From: Mathieu Baudier Date: Mon, 24 Nov 2014 12:43:18 +0000 (+0000) Subject: Move to the root the bundles which will be part of v1.4 and v2.2 X-Git-Tag: argeo-commons-2.1.30~544 X-Git-Url: http://git.argeo.org/?a=commitdiff_plain;h=1df1bf64759d35d3d72b9d96b26b71118fdbe031;p=lgpl%2Fargeo-commons.git Move to the root the bundles which will be part of v1.4 and v2.2 git-svn-id: https://svn.argeo.org/commons/trunk@7493 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- diff --git a/base/dep/org.argeo.dep.jackrabbit/pom.xml b/base/dep/org.argeo.dep.jackrabbit/pom.xml deleted file mode 100644 index d355e93a5..000000000 --- a/base/dep/org.argeo.dep.jackrabbit/pom.xml +++ /dev/null @@ -1,110 +0,0 @@ - - 4.0.0 - - org.argeo.commons.base - 2.1.12-SNAPSHOT - dep - .. - - org.argeo.dep.jackrabbit - pom - Commons Minimal Jackrabbit - - - - org.argeo.tp - org.apache.jackrabbit - - - - - org.argeo.tp - org.h2 - - - - - org.argeo.tp - javax.jcr - - - org.argeo.tp - org.apache.lucene - - - org.argeo.commons.base - org.argeo.dep.log4j - 2.1.12-SNAPSHOT - pom - - - - - org.argeo.tp - org.apache.commons.collections - - - org.argeo.tp - org.apache.commons.io - - - org.argeo.tp - org.apache.commons.httpclient - - - org.argeo.tp - org.apache.commons.fileupload - - - org.argeo.tp - org.apache.commons.compress - - - org.argeo.tp - org.apache.commons.pool - - - org.argeo.tp - org.apache.commons.dbcp - - - - - org.argeo.tp - edu.oswego.cs.dl.util.concurrent - - - - - org.argeo.tp - javax.servlet - - - - - org.argeo.tp - org.apache.tika - - - - org.argeo.tp - org.dom4j - - - org.argeo.tp - org.jdom - - - org.argeo.tp - org.objectweb.asm - - - org.argeo.tp - org.jaxen - - - org.argeo.tp - org.xmlpull - - - \ No newline at end of file diff --git a/base/dep/org.argeo.dep.log4j/pom.xml b/base/dep/org.argeo.dep.log4j/pom.xml deleted file mode 100644 index 5686f41fc..000000000 --- a/base/dep/org.argeo.dep.log4j/pom.xml +++ /dev/null @@ -1,55 +0,0 @@ - - 4.0.0 - - org.argeo.commons.base - 2.1.12-SNAPSHOT - dep - .. - - org.argeo.dep.log4j - pom - Commons Apache Log4j (SLF4J) Dependencies - - - org.argeo.tp - slf4j.org.apache.commons.logging - - - org.argeo.tp - org.apache.log4j - - - org.argeo.tp - slf4j.log4j - - - org.argeo.tp - slf4j.api - - - - \ No newline at end of file diff --git a/base/dep/org.argeo.eclipse.dep.rap/p2.inf b/base/dep/org.argeo.eclipse.dep.rap/p2.inf deleted file mode 100644 index 0423aa509..000000000 --- a/base/dep/org.argeo.eclipse.dep.rap/p2.inf +++ /dev/null @@ -1,2 +0,0 @@ -properties.1.name=org.eclipse.equinox.p2.type.category -properties.1.value=true \ No newline at end of file diff --git a/base/dep/org.argeo.eclipse.dep.rap/pom.xml b/base/dep/org.argeo.eclipse.dep.rap/pom.xml deleted file mode 100644 index 6ce432b4a..000000000 --- a/base/dep/org.argeo.eclipse.dep.rap/pom.xml +++ /dev/null @@ -1,238 +0,0 @@ - - - 4.0.0 - - org.argeo.commons.base - dep - 2.1.12-SNAPSHOT - .. - - org.argeo.eclipse.dep.rap - Commons Eclipse RAP Dependencies - - - - org.argeo.maven.plugins - maven-argeo-osgi-plugin - - - - - - - - - - - org.argeo.tp.rap.addons - binaries - ${version.rap.addons} - pom - - - - org.argeo.tp.rap.addons - org.eclipse.osgi - - - - - - org.argeo.tp.rap.platform - binaries - ${version.rap} - pom - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - org.argeo.tp.rap.platform - org.eclipse.rap.demo - - - org.argeo.tp.rap.platform - org.eclipse.rap.demo.databinding - - - org.argeo.tp.rap.platform - org.eclipse.rap.design.example - - - - - org.argeo.tp.rap.platform - org.eclipse.jdt.junit.runtime - - - org.argeo.tp.rap.platform - org.eclipse.rap.junit.runtime - - - org.argeo.tp.rap.platform - org.eclipse.rap.rwt.testfixture - - - - - - - - - - - - org.argeo.tp - org.apache.commons.io - - - org.argeo.tp - org.apache.commons.fileupload - - - - - org.argeo.tp - javax.servlet - - - - - org.argeo.tp.rap - org.eclipse.equinox.security - - - - - - - - - - - - check-osgi - - - - org.argeo.maven.plugins - maven-argeo-osgi-plugin - - - check-osgi - test - - equinox - - - true - - - - - - - - - rpmbuild-tp - - - - org.codehaus.mojo - rpm-maven-plugin - - - rpm-rap - package - - rpm - - - eclipse-rap - ${version.rap} - - - /usr/share/eclipse-rap - root - root - 644 - false - - - - - - - - - maven-antrun-plugin - - - install - - run - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/base/dep/org.argeo.eclipse.dep.rcp/p2.inf b/base/dep/org.argeo.eclipse.dep.rcp/p2.inf deleted file mode 100644 index 0423aa509..000000000 --- a/base/dep/org.argeo.eclipse.dep.rcp/p2.inf +++ /dev/null @@ -1,2 +0,0 @@ -properties.1.name=org.eclipse.equinox.p2.type.category -properties.1.value=true \ No newline at end of file diff --git a/base/dep/org.argeo.eclipse.dep.rcp/pom.xml b/base/dep/org.argeo.eclipse.dep.rcp/pom.xml deleted file mode 100644 index 7142395e3..000000000 --- a/base/dep/org.argeo.eclipse.dep.rcp/pom.xml +++ /dev/null @@ -1,261 +0,0 @@ - - - 4.0.0 - - org.argeo.commons.base - dep - 2.1.12-SNAPSHOT - .. - - org.argeo.eclipse.dep.rcp - Commons Eclipse RCP Dependencies - - - - - org.argeo.maven.plugins - maven-argeo-osgi-plugin - - - - - - org.argeo.tp - org.eclipse.osgi - - - - org.argeo.tp.rcp.platform - binaries - ${version.argeo-distribution} - pom - - - - org.argeo.tp.rcp.platform - org.eclipse.update.configurator - - - - org.argeo.tp.rcp.platform - org.eclipse.swt.win32.win32.x86_64 - - - org.argeo.tp.rcp.platform - org.eclipse.swt.carbon.macosx - - - org.argeo.tp.rcp.platform - org.eclipse.swt.cocoa.macosx.x86_64 - - - org.argeo.tp.rcp.platform - org.eclipse.swt.gtk.solaris.sparc - - - org.argeo.tp.rcp.platform - org.eclipse.swt.gtk.solaris.x86 - - - org.argeo.tp.rcp.platform - org.eclipse.swt.motif.solaris.sparc - - - org.argeo.tp.rcp.platform - org.eclipse.swt.gtk.linux.s390 - - - org.argeo.tp.rcp.platform - org.eclipse.swt.gtk.linux.s390x - - - org.argeo.tp.rcp.platform - org.eclipse.swt.gtk.linux.ppc64 - - - org.argeo.tp.rcp.platform - org.eclipse.swt.motif.linux.x86 - - - org.argeo.tp.rcp.platform - org.eclipse.swt.gtk.linux.ppc - - - org.argeo.tp.rcp.platform - org.eclipse.swt.photon.qnx.x86 - - - org.argeo.tp.rcp.platform - org.eclipse.swt.motif.aix.ppc - - - org.argeo.tp.rcp.platform - org.eclipse.swt.motif.aix.ppc64 - - - org.argeo.tp.rcp.platform - org.eclipse.swt.motif.hpux.ia64_32 - - - - - org.argeo.tp.rcp.platform - org.eclipse.equinox.launcher.win32.win32.x86_64 - - - org.argeo.tp.rcp.platform - org.eclipse.equinox.launcher.carbon.macosx - - - org.argeo.tp.rcp.platform - org.eclipse.equinox.launcher.cocoa.macosx.x86_64 - - - org.argeo.tp.rcp.platform - org.eclipse.equinox.launcher.gtk.solaris.sparc - - - org.argeo.tp.rcp.platform - org.eclipse.equinox.launcher.gtk.solaris.x86 - - - org.argeo.tp.rcp.platform - org.eclipse.equinox.launcher.motif.solaris.sparc - - - org.argeo.tp.rcp.platform - org.eclipse.equinox.launcher.gtk.linux.s390 - - - org.argeo.tp.rcp.platform - org.eclipse.equinox.launcher.gtk.linux.s390x - - - org.argeo.tp.rcp.platform - org.eclipse.equinox.launcher.gtk.linux.ppc64 - - - org.argeo.tp.rcp.platform - org.eclipse.equinox.launcher.motif.linux.x86 - - - org.argeo.tp.rcp.platform - org.eclipse.equinox.launcher.gtk.linux.ppc - - - org.argeo.tp.rcp.platform - org.eclipse.equinox.launcher.photon.qnx.x86 - - - org.argeo.tp.rcp.platform - org.eclipse.equinox.launcher.motif.aix.ppc - - - org.argeo.tp.rcp.platform - org.eclipse.equinox.launcher.motif.aix.ppc64 - - - org.argeo.tp.rcp.platform - org.eclipse.equinox.launcher.motif.hpux.ia64_32 - - - - - org.argeo.tp.rcp.platform - org.eclipse.ui.carbon - - - - - - - org.argeo.tp.rcp - org.eclipse.equinox.security - - - - - - org.argeo.tp.rcp - binaries - ${version.argeo-distribution} - pom - import - - - org.argeo.tp.rcp.platform - binaries - ${version.argeo-distribution} - pom - import - - - - - - check-osgi - - - - org.argeo.maven.plugins - maven-argeo-osgi-plugin - - - check-osgi - test - - equinox - - - true - - - - - - - - - \ No newline at end of file diff --git a/base/dep/pom.xml b/base/dep/pom.xml deleted file mode 100644 index 3ef6c4a52..000000000 --- a/base/dep/pom.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - 4.0.0 - - org.argeo.commons - base - 2.1.12-SNAPSHOT - .. - - org.argeo.commons.base - dep - Commons Base Dependencies - pom - - org.argeo.dep.log4j - org.argeo.dep.jackrabbit - org.argeo.eclipse.dep.rap - org.argeo.eclipse.dep.rcp - - - - - org.apache.felix - maven-bundle-plugin - - - - - - org.argeo.maven.plugins - maven-argeo-osgi-plugin - - - generate-descriptors - - descriptors - - generate-resources - - - - - - - - - check-osgi - - - org.argeo.commons.base - org.argeo.osgi.boot - 2.1.12-SNAPSHOT - test - - - - - \ No newline at end of file diff --git a/base/dist/osgi-boot/pom.xml b/base/dist/osgi-boot/pom.xml deleted file mode 100644 index b2b97e1a6..000000000 --- a/base/dist/osgi-boot/pom.xml +++ /dev/null @@ -1,188 +0,0 @@ - - 4.0.0 - - org.argeo.commons.base - 2.1.12-SNAPSHOT - dist - .. - - osgi-boot - pom - Commons OSGi Boot Distribution - - - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-dependencies - package - - copy-dependencies - - - jar - true - ${project.build.directory}/lib - - - - - - - - - org.argeo.commons.base - org.argeo.osgi.boot - 2.1.12-SNAPSHOT - - - - - rpmbuild - - - - org.codehaus.mojo - rpm-maven-plugin - - - rpm-osgi-boot - package - - rpm - - - osgi-boot - - - /etc/osgiboot - root - root - 644 - noreplace - false - - - src/main/rpm/etc/osgiboot - - *-settings.sh - - - - - - /etc/osgiboot - root - root - 644 - false - - - src/main/rpm/etc/osgiboot - - *-functions.sh - - - - - - /usr/sbin - root - root - 755 - - - src/main/rpm/usr/sbin - - - - - /usr/share/osgi/boot - root - root - 644 - false - - - ${project.build.directory}/lib - - org.argeo.osgi.boot.jar - - - - - - - osgi-boot-equinox - - - - - - - maven-antrun-plugin - - - install - - run - - - - - - - - - - - - - - - - - rpmbuild-tp - - - - org.codehaus.mojo - rpm-maven-plugin - - - rpm-osgi-boot-equinox - package - - rpm - - - osgi-boot-equinox - ${version.argeo-distribution} - - - /usr/share/osgi/boot - root - root - 644 - false - - - ${project.build.directory}/lib - - org.eclipse.osgi.jar - - - - - - - - - - - - - - diff --git a/base/dist/osgi-boot/src/main/rpm/etc/osgiboot/osgi-service-init-functions.sh b/base/dist/osgi-boot/src/main/rpm/etc/osgiboot/osgi-service-init-functions.sh deleted file mode 100644 index 35bf9703f..000000000 --- a/base/dist/osgi-boot/src/main/rpm/etc/osgiboot/osgi-service-init-functions.sh +++ /dev/null @@ -1,59 +0,0 @@ -#!/bin/bash - -# Source function library. -. /etc/rc.d/init.d/functions - -RETVAL=0 - -osgi_service_start() { - APP=$1 - # create log an run directories writable by the application user - USER=$APP - GROUP=$APP - RUN_DIR=/var/run/$APP - LOG_DIR=/var/log/$APP - if [ ! -d $LOG_DIR ];then - mkdir -m 0750 $LOG_DIR - chown -R $USER.$GROUP $LOG_DIR - fi - if [ ! -d $RUN_DIR ];then - mkdir -m 0750 $RUN_DIR - chown -R $USER.$GROUP $RUN_DIR - fi - - # call Argeo Commons OSGi utilities as the application user - daemon --user $USER /usr/sbin/osgi-service $APP start - - RETVAL=$? - #action $"Start $APP" /bin/true - if [ $RETVAL -eq 0 ];then - PID=`cat $RUN_DIR/$APP.pid` - action $"Started $APP with pid $PID" /bin/true - else - action $"Could not start $APP" /bin/false - fi - return $RETVAL -} - -osgi_service_stop() { - APP=$1 - USER=$APP - # call Argeo Commons OSGi utilities as the application user - runuser -s /bin/bash $USER -c "/usr/sbin/osgi-service $APP stop" - RETVAL=$? - if [ $RETVAL -eq 0 ];then - action $"Stopped $APP" /bin/true - else - action $"Could not stop $APP" /bin/false - fi - return $RETVAL -} - -osgi_service_status() { - APP=$1 - USER=$APP - # call Argeo Commons OSGi utilities as the application user - runuser -s /bin/bash $USER -c "/usr/sbin/osgi-service $APP status" - RETVAL=$? - return $RETVAL -} diff --git a/base/dist/osgi-boot/src/main/rpm/etc/osgiboot/osgi-service-settings.sh b/base/dist/osgi-boot/src/main/rpm/etc/osgiboot/osgi-service-settings.sh deleted file mode 100644 index f5504f811..000000000 --- a/base/dist/osgi-boot/src/main/rpm/etc/osgiboot/osgi-service-settings.sh +++ /dev/null @@ -1 +0,0 @@ -#JAVA_OPTS=-Xmx256m \ No newline at end of file diff --git a/base/dist/osgi-boot/src/main/rpm/usr/sbin/osgi-service b/base/dist/osgi-boot/src/main/rpm/usr/sbin/osgi-service deleted file mode 100644 index 5c37f9c82..000000000 --- a/base/dist/osgi-boot/src/main/rpm/usr/sbin/osgi-service +++ /dev/null @@ -1,153 +0,0 @@ -#!/bin/sh - -JVM=java -. /etc/osgiboot/osgi-service-settings.sh - -APP=$1 - -CONF_DIR=/etc/$APP -if [ -f $CONF_DIR/settings.sh ];then - . $CONF_DIR/settings.sh -fi - -LIB_DIR=/usr/share/$APP/lib - -# read/write -EXEC_DIR=/var/lib/$APP -DATA_DIR=$EXEC_DIR/data -CONF_RW=$EXEC_DIR/conf - -LOG_DIR=/var/log/$APP -LOG_FILE=$LOG_DIR/$APP.log - -RUN_DIR=/var/run/$APP -PID_FILE=$RUN_DIR/$APP.pid -SHUTDOWN_FILE=$RUN_DIR/$APP.shutdown - -OSGI_INSTALL_AREA=/usr/share/osgi/boot -OSGI_FRAMEWORK=$OSGI_INSTALL_AREA/org.eclipse.osgi.jar - -RETVAL=0 - -start() { - if [ -f $PID_FILE ];then - PID=`cat $PID_FILE` - kill -0 $PID &> /dev/null - PID_EXISTS=$? - if [ $PID_EXISTS -eq 0 ]; then - echo $APP already running with pid $PID - RETVAL=1 - return $RETVAL - else - echo Old $APP process with pid $PID is dead, removing $PID_FILE - rm -f $PID_FILE - fi - fi - - cp --preserve $CONF_DIR/config.ini $CONF_RW/config.ini - touch $SHUTDOWN_FILE - cd $EXEC_DIR - $JVM \ - -Dargeo.osgi.shutdownFile="$SHUTDOWN_FILE" \ - -Dlog4j.configuration="file:$CONF_DIR/log4j.properties" \ - $JAVA_OPTS -jar $OSGI_FRAMEWORK \ - -clean \ - -configuration "$CONF_RW" \ - -data "$DATA_DIR" \ - >> $LOG_FILE 2>&1 & - # (above) stderr redirected to stdout, then stdout to log file - # see http://tldp.org/LDP/abs/html/io-redirection.html - PID=$! - echo $PID > $PID_FILE - #echo Started $APP with pid $PID - return $RETVAL -} - -stop() { - if [ -f $PID_FILE ];then - PID=`cat $PID_FILE` - kill -0 $PID &> /dev/null - PID_EXISTS=$? - if [ $PID_EXISTS -ne 0 ]; then - echo Dead $APP process with pid $PID, removing $PID_FILE - rm -f $PID_FILE - RETVAL=1 - return $RETVAL - fi - else - echo $APP is not running - RETVAL=1 - return $RETVAL - fi - - # notifies application by removing the shutdown file - rm -f $SHUTDOWN_FILE - - # wait 5 min for application to shutdown, then kill it - TIMEOUT=$((5*60)) - BEGIN=$(date +%s) - while kill -0 $PID &> /dev/null - do - sleep 1 - NOW=$(date +%s) - DURATION=$(($NOW-$BEGIN)) - if [ $DURATION -gt $TIMEOUT ]; then - kill -9 $PID - echo Forcibly killed $APP with pid $PID - RETVAL=1 - fi - done - - # remove pid file - rm -f $PID_FILE - return $RETVAL - -# timeout is only available in EL6 -# timeout 5m sh << EOF -#while kill -0 $PID &> /dev/null; do sleep 1; done -#EOF -# TIMEOUT_EXIT=$? -# if [ $TIMEOUT_EXIT -eq 124 ];then -# kill -9 $PID -# RETVAL=1 -# echo Killed $APP with pid $PID -# else -# echo Stopped $APP with pid $PID -# fi -# rm -f $PID_FILE -# return $RETVAL -} - -status() { - if [ -f $PID_FILE ];then - PID=`cat $PID_FILE` - else - echo $APP is not running - return $RETVAL - fi - kill -0 $PID &> /dev/null - PID_EXISTS=$? - if [ $PID_EXISTS -eq 0 ]; then - echo $APP is running with pid $PID ... - else - echo No $APP process with pid $PID, removing $PID_FILE - rm -f $PID_FILE - fi - return $RETVAL -} - -# main -case "$2" in - start) - start - ;; - stop) - stop - ;; - status) - status - ;; - *) - echo $"Usage: $0 {start|stop|status}" - exit 1 -esac \ No newline at end of file diff --git a/base/dist/pom.xml b/base/dist/pom.xml deleted file mode 100644 index 5d33b1e46..000000000 --- a/base/dist/pom.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - 4.0.0 - - org.argeo.commons - base - 2.1.12-SNAPSHOT - .. - - org.argeo.commons.base - dist - Commons Base Distributions - pom - - osgi-boot - - \ No newline at end of file diff --git a/base/plugins/org.argeo.osgi.ui.explorer/.classpath b/base/plugins/org.argeo.osgi.ui.explorer/.classpath deleted file mode 100644 index c5931a083..000000000 --- a/base/plugins/org.argeo.osgi.ui.explorer/.classpath +++ /dev/null @@ -1,7 +0,0 @@ - - - >> - - - - diff --git a/base/plugins/org.argeo.osgi.ui.explorer/.project b/base/plugins/org.argeo.osgi.ui.explorer/.project deleted file mode 100644 index 1a4f4d3bd..000000000 --- a/base/plugins/org.argeo.osgi.ui.explorer/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - org.argeo.osgi.ui.explorer - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - - diff --git a/base/plugins/org.argeo.osgi.ui.explorer/.settings/org.eclipse.jdt.core.prefs b/base/plugins/org.argeo.osgi.ui.explorer/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 9916a2282..000000000 --- a/base/plugins/org.argeo.osgi.ui.explorer/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,8 +0,0 @@ -#Sun Sep 04 16:04:00 CEST 2011 -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 -org.eclipse.jdt.core.compiler.compliance=1.5 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.5 diff --git a/base/plugins/org.argeo.osgi.ui.explorer/build.properties b/base/plugins/org.argeo.osgi.ui.explorer/build.properties deleted file mode 100644 index 4f799f2d3..000000000 --- a/base/plugins/org.argeo.osgi.ui.explorer/build.properties +++ /dev/null @@ -1,6 +0,0 @@ -source.. = src/main/java/ -output.. = target/classes/ -bin.includes = META-INF/,\ - .,\ - icons/,\ - plugin.xml diff --git a/base/plugins/org.argeo.osgi.ui.explorer/icons/active.gif b/base/plugins/org.argeo.osgi.ui.explorer/icons/active.gif deleted file mode 100644 index 7d24707ee..000000000 Binary files a/base/plugins/org.argeo.osgi.ui.explorer/icons/active.gif and /dev/null differ diff --git a/base/plugins/org.argeo.osgi.ui.explorer/icons/bundles.gif b/base/plugins/org.argeo.osgi.ui.explorer/icons/bundles.gif deleted file mode 100644 index e9a6bd966..000000000 Binary files a/base/plugins/org.argeo.osgi.ui.explorer/icons/bundles.gif and /dev/null differ diff --git a/base/plugins/org.argeo.osgi.ui.explorer/icons/installed.gif b/base/plugins/org.argeo.osgi.ui.explorer/icons/installed.gif deleted file mode 100644 index 298871653..000000000 Binary files a/base/plugins/org.argeo.osgi.ui.explorer/icons/installed.gif and /dev/null differ diff --git a/base/plugins/org.argeo.osgi.ui.explorer/icons/osgi_explorer.gif b/base/plugins/org.argeo.osgi.ui.explorer/icons/osgi_explorer.gif deleted file mode 100644 index e9a6bd966..000000000 Binary files a/base/plugins/org.argeo.osgi.ui.explorer/icons/osgi_explorer.gif and /dev/null differ diff --git a/base/plugins/org.argeo.osgi.ui.explorer/icons/resolved.gif b/base/plugins/org.argeo.osgi.ui.explorer/icons/resolved.gif deleted file mode 100644 index f4a1ea150..000000000 Binary files a/base/plugins/org.argeo.osgi.ui.explorer/icons/resolved.gif and /dev/null differ diff --git a/base/plugins/org.argeo.osgi.ui.explorer/icons/starting.gif b/base/plugins/org.argeo.osgi.ui.explorer/icons/starting.gif deleted file mode 100644 index 563743d39..000000000 Binary files a/base/plugins/org.argeo.osgi.ui.explorer/icons/starting.gif and /dev/null differ diff --git a/base/plugins/org.argeo.osgi.ui.explorer/plugin.xml b/base/plugins/org.argeo.osgi.ui.explorer/plugin.xml deleted file mode 100644 index c0815cad4..000000000 --- a/base/plugins/org.argeo.osgi.ui.explorer/plugin.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/base/plugins/org.argeo.osgi.ui.explorer/pom.xml b/base/plugins/org.argeo.osgi.ui.explorer/pom.xml deleted file mode 100644 index 2c380895d..000000000 --- a/base/plugins/org.argeo.osgi.ui.explorer/pom.xml +++ /dev/null @@ -1,56 +0,0 @@ - - 4.0.0 - - org.argeo.commons.base - 2.1.12-SNAPSHOT - plugins - .. - - org.argeo.osgi.ui.explorer - Commons OSGi Explorer - - - - org.apache.felix - maven-bundle-plugin - - - lazy - org.argeo.osgi.ui.explorer.OsgiExplorerPlugin - org.eclipse.ui;resolution:=optional, - org.eclipse.rap.ui;resolution:=optional, - org.eclipse.core.runtime - org.argeo.osgi.ui.explorer.* - - - - - - - - org.argeo.tp - org.eclipse.osgi - provided - - - - org.argeo.commons.base - org.argeo.eclipse.ui - 2.1.12-SNAPSHOT - - - - - org.argeo.commons.base - org.argeo.eclipse.dep.rcp - 2.1.12-SNAPSHOT - provided - - - org.argeo.commons.base - org.argeo.eclipse.ui.rcp - 2.1.12-SNAPSHOT - provided - - - diff --git a/base/plugins/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/OsgiExplorerImages.java b/base/plugins/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/OsgiExplorerImages.java deleted file mode 100644 index 77bdfe946..000000000 --- a/base/plugins/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/OsgiExplorerImages.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.osgi.ui.explorer; - -import org.eclipse.swt.graphics.Image; - -/** Shared icons. */ -public class OsgiExplorerImages { - public final static Image INSTALLED = OsgiExplorerPlugin - .getImageDescriptor("icons/installed.gif").createImage(); - public final static Image RESOLVED = OsgiExplorerPlugin.getImageDescriptor( - "icons/resolved.gif").createImage(); - public final static Image STARTING = OsgiExplorerPlugin.getImageDescriptor( - "icons/starting.gif").createImage(); - public final static Image ACTIVE = OsgiExplorerPlugin.getImageDescriptor( - "icons/active.gif").createImage(); -} diff --git a/base/plugins/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/OsgiExplorerPerspective.java b/base/plugins/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/OsgiExplorerPerspective.java deleted file mode 100644 index 153abcda2..000000000 --- a/base/plugins/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/OsgiExplorerPerspective.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.osgi.ui.explorer; - -import org.eclipse.ui.IPageLayout; -import org.eclipse.ui.IPerspectiveFactory; - -/** OSGi explorer perspective (to be enriched declaratively) */ -public class OsgiExplorerPerspective implements IPerspectiveFactory { - - public void createInitialLayout(IPageLayout layout) { - layout.setEditorAreaVisible(true); - layout.setFixed(false); - - } - -} diff --git a/base/plugins/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/OsgiExplorerPlugin.java b/base/plugins/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/OsgiExplorerPlugin.java deleted file mode 100644 index 80146d198..000000000 --- a/base/plugins/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/OsgiExplorerPlugin.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.osgi.ui.explorer; - -import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.ui.plugin.AbstractUIPlugin; -import org.osgi.framework.BundleContext; - -/** - * The activator class controls the plug-in life cycle - */ -public class OsgiExplorerPlugin extends AbstractUIPlugin { - - // The plug-in ID - public static final String PLUGIN_ID = "org.argeo.osgi.ui.explorer"; //$NON-NLS-1$ - - // The shared instance - private static OsgiExplorerPlugin plugin; - - /** - * The constructor - */ - public OsgiExplorerPlugin() { - } - - /* - * (non-Javadoc) - * - * @see - * org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext - * ) - */ - public void start(BundleContext context) throws Exception { - super.start(context); - plugin = this; - } - - /* - * (non-Javadoc) - * - * @see - * org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext - * ) - */ - public void stop(BundleContext context) throws Exception { - plugin = null; - super.stop(context); - } - - /** - * Returns the shared instance - * - * @return the shared instance - */ - public static OsgiExplorerPlugin getDefault() { - return plugin; - } - - public static ImageDescriptor getImageDescriptor(String path) { - return imageDescriptorFromPlugin(PLUGIN_ID, path); - } - -} diff --git a/base/plugins/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/views/BundlesView.java b/base/plugins/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/views/BundlesView.java deleted file mode 100644 index 98d74a6a7..000000000 --- a/base/plugins/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/views/BundlesView.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.osgi.ui.explorer.views; - -import java.util.Comparator; - -import org.argeo.eclipse.ui.ColumnViewerComparator; -import org.argeo.eclipse.ui.specific.EclipseUiSpecificUtils; -import org.argeo.osgi.ui.explorer.OsgiExplorerImages; -import org.argeo.osgi.ui.explorer.OsgiExplorerPlugin; -import org.eclipse.jface.viewers.ColumnLabelProvider; -import org.eclipse.jface.viewers.IStructuredContentProvider; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.jface.viewers.TableViewerColumn; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.ui.part.ViewPart; -import org.osgi.framework.Bundle; -import org.osgi.framework.BundleContext; -import org.osgi.framework.Constants; - -/** - * Overview of the bundles as a table. Equivalent to Equinox 'ss' console - * command. - */ -public class BundlesView extends ViewPart { - private TableViewer viewer; - - @Override - public void createPartControl(Composite parent) { - viewer = new TableViewer(parent); - viewer.setContentProvider(new BundleContentProvider()); - viewer.getTable().setHeaderVisible(true); - - EclipseUiSpecificUtils.enableToolTipSupport(viewer); - - // ID - TableViewerColumn column = new TableViewerColumn(viewer, SWT.NONE); - column.getColumn().setWidth(30); - column.getColumn().setText("ID"); - column.getColumn().setAlignment(SWT.RIGHT); - column.setLabelProvider(new ColumnLabelProvider() { - public String getText(Object element) { - return Long.toString(((Bundle) element).getBundleId()); - } - }); - new ColumnViewerComparator(column, new Comparator() { - public int compare(Bundle o1, Bundle o2) { - return (int) (o1.getBundleId() - o2.getBundleId()); - } - }); - - // State - column = new TableViewerColumn(viewer, SWT.NONE); - column.getColumn().setWidth(18); - column.getColumn().setText("State"); - column.setLabelProvider(new StateLabelProvider()); - new ColumnViewerComparator(column, new Comparator() { - public int compare(Bundle o1, Bundle o2) { - return o1.getState() - o2.getState(); - } - }); - - // Symbolic name - column = new TableViewerColumn(viewer, SWT.NONE); - column.getColumn().setWidth(300); - column.getColumn().setText("Symbolic Name"); - column.setLabelProvider(new ColumnLabelProvider() { - public String getText(Object element) { - return ((Bundle) element).getSymbolicName(); - } - }); - new ColumnViewerComparator(column, new Comparator() { - public int compare(Bundle o1, Bundle o2) { - return o1.getSymbolicName().compareTo(o2.getSymbolicName()); - } - }); - - // Version - column = new TableViewerColumn(viewer, SWT.NONE); - column.getColumn().setWidth(150); - column.getColumn().setText("Version"); - column.setLabelProvider(new ColumnLabelProvider() { - public String getText(Object element) { - return ((Bundle) element).getVersion().toString(); - } - }); - new ColumnViewerComparator(column, new Comparator() { - public int compare(Bundle o1, Bundle o2) { - return o1.getVersion().compareTo(o2.getVersion()); - } - }); - - viewer.setInput(OsgiExplorerPlugin.getDefault().getBundle() - .getBundleContext()); - - } - - @Override - public void setFocus() { - if (viewer != null) - viewer.getControl().setFocus(); - } - - /** Content provider managing the array of bundles */ - private static class BundleContentProvider implements - IStructuredContentProvider { - public Object[] getElements(Object inputElement) { - if (inputElement instanceof BundleContext) { - BundleContext bc = (BundleContext) inputElement; - return bc.getBundles(); - } - return null; - } - - public void dispose() { - } - - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - } - - } - - /** Label provider for the state column */ - private static class StateLabelProvider extends ColumnLabelProvider { - @Override - public Image getImage(Object element) { - Integer state = ((Bundle) element).getState(); - switch (state) { - case Bundle.UNINSTALLED: - return OsgiExplorerImages.INSTALLED; - case Bundle.INSTALLED: - return OsgiExplorerImages.INSTALLED; - case Bundle.RESOLVED: - return OsgiExplorerImages.RESOLVED; - case Bundle.STARTING: - return OsgiExplorerImages.STARTING; - case Bundle.STOPPING: - return OsgiExplorerImages.STARTING; - case Bundle.ACTIVE: - return OsgiExplorerImages.ACTIVE; - default: - return null; - } - } - - @Override - public String getText(Object element) { - return null; - } - - @Override - public String getToolTipText(Object element) { - Bundle bundle = (Bundle) element; - Integer state = bundle.getState(); - switch (state) { - case Bundle.UNINSTALLED: - return "UNINSTALLED"; - case Bundle.INSTALLED: - return "INSTALLED"; - case Bundle.RESOLVED: - return "RESOLVED"; - case Bundle.STARTING: - String activationPolicy = bundle.getHeaders() - .get(Constants.BUNDLE_ACTIVATIONPOLICY).toString(); - if (activationPolicy != null - && activationPolicy.equals(Constants.ACTIVATION_LAZY)) - return "<>"; - return "STARTING"; - case Bundle.STOPPING: - return "STOPPING"; - case Bundle.ACTIVE: - return "ACTIVE"; - default: - return null; - } - } - - } -} diff --git a/base/plugins/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/views/ModulesView.java b/base/plugins/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/views/ModulesView.java deleted file mode 100644 index 5d67bd458..000000000 --- a/base/plugins/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/views/ModulesView.java +++ /dev/null @@ -1,379 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.osgi.ui.explorer.views; - -import java.util.Comparator; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; -import java.util.TreeSet; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.eclipse.ui.TreeParent; -import org.argeo.osgi.ui.explorer.OsgiExplorerPlugin; -import org.eclipse.jface.viewers.ITableLabelProvider; -import org.eclipse.jface.viewers.ITreeContentProvider; -import org.eclipse.jface.viewers.LabelProvider; -import org.eclipse.jface.viewers.TreeViewer; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.ui.part.ViewPart; -import org.osgi.framework.Bundle; -import org.osgi.framework.BundleContext; -import org.osgi.framework.ServiceReference; -import org.osgi.service.packageadmin.ExportedPackage; -import org.osgi.service.packageadmin.PackageAdmin; - -/** Experimental The OSGi runtime from a module perspective. */ -public class ModulesView extends ViewPart { - private final static Log log = LogFactory.getLog(ModulesView.class); - - private TreeViewer viewer; - - private PackageAdmin packageAdmin; - - private Comparator exportedPackageComparator = new Comparator() { - - public int compare(ExportedPackage o1, ExportedPackage o2) { - if (!o1.getName().equals(o2.getName())) - return o1.getName().compareTo(o2.getName()); - else - return o1.getVersion().compareTo(o2.getVersion()); - } - }; - - @Override - public void createPartControl(Composite parent) { - viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); - viewer.setContentProvider(new ModulesContentProvider()); - viewer.setLabelProvider(new ModulesLabelProvider()); - viewer.setInput(OsgiExplorerPlugin.getDefault().getBundle() - .getBundleContext()); - } - - @Override - public void setFocus() { - viewer.getTree().setFocus(); - } - - private class ModulesContentProvider implements ITreeContentProvider { - - public Object[] getElements(Object inputElement) { - return getChildren(inputElement); - } - - public Object[] getChildren(Object parentElement) { - if (parentElement instanceof BundleContext) { - BundleContext bundleContext = (BundleContext) parentElement; - Bundle[] bundles = bundleContext.getBundles(); - - TreeParent bundlesNode = new TreeParent("Bundles"); - for (Bundle bundle : bundles) { - if (bundle.getState() == Bundle.ACTIVE) - bundlesNode.addChild(new BundleNode(bundle)); - } - - // scan packages - ServiceReference paSr = bundleContext - .getServiceReference(PackageAdmin.class.getName()); - // TODO: make a cleaner referencing - packageAdmin = (PackageAdmin) bundleContext.getService(paSr); - - Bundle bundle1 = null; - Bundle bundle2 = null; - - Map> importedPackages = new HashMap>(); - Map> packages = new TreeMap>(); - for (Bundle bundle : bundles) { - if (bundle.getSymbolicName() - .equals("org.argeo.security.ui")) - bundle1 = bundle; - if (bundle.getSymbolicName().equals( - "org.argeo.security.equinox")) - bundle2 = bundle; - - ExportedPackage[] pkgs = packageAdmin - .getExportedPackages(bundle); - if (pkgs != null) - for (ExportedPackage pkg : pkgs) { - if (!packages.containsKey(pkg.getName())) - packages.put(pkg.getName(), - new TreeSet( - exportedPackageComparator)); - Set expPackages = (Set) packages - .get(pkg.getName()); - expPackages.add(pkg); - - // imported - for (Bundle b : pkg.getImportingBundles()) { - if (bundle.getBundleId() != b.getBundleId()) { - if (!importedPackages.containsKey(b)) - importedPackages - .put(b, - new TreeSet( - exportedPackageComparator)); - Set impPackages = (Set) importedPackages - .get(b); - impPackages.add(pkg); - } - } - } - } - - TreeParent mPackageNode = new TreeParent("Multiple Packages"); - // TreeParent aPackageNode = new TreeParent("All Packages"); - for (String packageName : packages.keySet()) { - Set pkgs = packages.get(packageName); - if (pkgs.size() > 1) { - MultiplePackagesNode mpn = new MultiplePackagesNode( - packageName, pkgs); - mPackageNode.addChild(mpn); - // aPackageNode.addChild(mpn); - } else { - // aPackageNode.addChild(new ExportedPackageNode(pkgs - // .iterator().next())); - } - } - - return new Object[] { bundlesNode, mPackageNode };// , - // aPackageNode - // }; - } else if (parentElement instanceof TreeParent) { - return ((TreeParent) parentElement).getChildren(); - } else { - return null; - } - } - - public Object getParent(Object element) { - // TODO Auto-generated method stub - return null; - } - - public boolean hasChildren(Object element) { - if (element instanceof TreeParent) { - return ((TreeParent) element).hasChildren(); - } - return false; - } - - public void dispose() { - // TODO Auto-generated method stub - - } - - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - // TODO Auto-generated method stub - - } - - } - - protected Map dependencySpace(Bundle bundle, - Map> importedPackages, - Map> traces) { - log.debug("Dependency space for " + bundle.getSymbolicName()); - Map space = new TreeMap(); - fillDependencySpace(space, bundle, importedPackages, - bundle.getSymbolicName(), traces); - return space; - } - - /** Recursive */ - protected void fillDependencySpace(Map space, - Bundle bundle, Map> importedPackages, - String currTrace, Map> traces) { - if (importedPackages.containsKey(bundle)) { - Set imports = importedPackages.get(bundle); - // log.debug("## Fill dependency space for " + bundle + " : "); - for (ExportedPackage pkg : imports) { - if (!traces.containsKey(pkg.getName())) - traces.put(pkg.getName(), new TreeSet()); - traces.get(pkg.getName()).add(currTrace); - if (!space.containsKey(pkg.getName())) { - space.put(pkg.getName(), pkg); - Bundle exportingBundle = pkg.getExportingBundle(); - // if (bundle.getBundleId() != - // exportingBundle.getBundleId()) - fillDependencySpace(space, exportingBundle, - importedPackages, currTrace + " > " - + exportingBundle.getSymbolicName(), traces); - } - } - } - } - - private class ModulesLabelProvider extends LabelProvider implements - ITableLabelProvider { - - public Image getColumnImage(Object element, int columnIndex) { - // TODO Auto-generated method stub - return null; - } - - public String getColumnText(Object element, int columnIndex) { - return getText(element); - } - - } - - class BundleNode extends TreeParent { - private final Bundle bundle; - - public BundleNode(Bundle bundle) { - super(bundle.getSymbolicName()); - this.bundle = bundle; - - // Registered services - ServiceReference[] registeredServices = bundle - .getRegisteredServices(); - if (registeredServices != null) { - TreeParent registeredServicesNode = new TreeParent( - "Registered Services"); - addChild(registeredServicesNode); - for (ServiceReference sr : registeredServices) { - if (sr != null) - registeredServicesNode - .addChild(new ServiceReferenceNode(sr)); - } - } - - // Used services - ServiceReference[] usedServices = bundle.getRegisteredServices(); - if (usedServices != null) { - TreeParent usedServicesNode = new TreeParent("Used Services"); - addChild(usedServicesNode); - for (ServiceReference sr : usedServices) { - if (sr != null) - usedServicesNode.addChild(new ServiceReferenceNode(sr)); - } - } - } - - public Bundle getBundle() { - return bundle; - } - - } - - class ServiceReferenceNode extends TreeParent { - private final ServiceReference serviceReference; - - public ServiceReferenceNode(ServiceReference serviceReference) { - super(serviceReference.toString()); - this.serviceReference = serviceReference; - - Bundle[] usedBundles = serviceReference.getUsingBundles(); - if (usedBundles != null) { - TreeParent usingBundles = new TreeParent("Using Bundles"); - addChild(usingBundles); - for (Bundle b : usedBundles) { - if (b != null) - usingBundles.addChild(new TreeParent(b - .getSymbolicName())); - } - } - - TreeParent properties = new TreeParent("Properties"); - addChild(properties); - for (String key : serviceReference.getPropertyKeys()) { - properties.addChild(new TreeParent(key + "=" - + serviceReference.getProperty(key))); - } - - } - - public ServiceReference getServiceReference() { - return serviceReference; - } - - } - - class MultiplePackagesNode extends TreeParent { - private String packageName; - private Set exportedPackages; - - public MultiplePackagesNode(String packageName, - Set exportedPackages) { - super(packageName); - this.packageName = packageName; - this.exportedPackages = exportedPackages; - for (ExportedPackage pkg : exportedPackages) { - addChild(new ExportedPackageNode(pkg)); - } - } - - } - - class ConflictingPackageNode extends TreeParent { - private ExportedPackage exportedPackage; - - public ConflictingPackageNode(ExportedPackage exportedPackage) { - super(exportedPackage.getName() + " - " - + exportedPackage.getVersion() + " (" - + exportedPackage.getExportingBundle() + ")"); - this.exportedPackage = exportedPackage; - - TreeParent bundlesNode = new TreeParent("Dependent Bundles"); - this.addChild(bundlesNode); - Map bundles = new TreeMap(); - for (Bundle b : exportedPackage.getImportingBundles()) { - bundles.put(b.getSymbolicName(), b); - } - for (String key : bundles.keySet()) { - addDependentBundles(bundlesNode, bundles.get(key)); - } - } - } - - protected void addDependentBundles(TreeParent parent, Bundle bundle) { - TreeParent bundleNode = new TreeParent(bundle.toString()); - parent.addChild(bundleNode); - Map bundles = new TreeMap(); - ExportedPackage[] pkgs = packageAdmin.getExportedPackages(bundle); - if (pkgs != null) - for (ExportedPackage pkg : pkgs) { - for (Bundle b : pkg.getImportingBundles()) { - if (!bundles.containsKey(b.getSymbolicName()) - && b.getBundleId() != bundle.getBundleId()) { - bundles.put(b.getSymbolicName(), b); - } - } - } - - for (String key : bundles.keySet()) { - addDependentBundles(bundleNode, bundles.get(key)); - } - } - - class ExportedPackageNode extends TreeParent { - private ExportedPackage exportedPackage; - - public ExportedPackageNode(ExportedPackage exportedPackage) { - super(exportedPackage.getName() + " - " - + exportedPackage.getVersion() + " (" - + exportedPackage.getExportingBundle() + ")"); - this.exportedPackage = exportedPackage; - for (Bundle bundle : exportedPackage.getImportingBundles()) { - addChild(new BundleNode(bundle)); - } - } - } -} diff --git a/base/plugins/pom.xml b/base/plugins/pom.xml index 967c50194..4eb1ec8ad 100644 --- a/base/plugins/pom.xml +++ b/base/plugins/pom.xml @@ -6,8 +6,8 @@ 2.1.12-SNAPSHOT .. - org.argeo.commons.base - plugins + org.argeo.commons + argeo-commons Commons OSGi Eclipse Plugins pom diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/.classpath b/base/runtime/org.argeo.eclipse.ui.jcr/.classpath deleted file mode 100644 index cf1efe7e4..000000000 --- a/base/runtime/org.argeo.eclipse.ui.jcr/.classpath +++ /dev/null @@ -1,8 +0,0 @@ - - - >> - - - - - diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/.project b/base/runtime/org.argeo.eclipse.ui.jcr/.project deleted file mode 100644 index d15268372..000000000 --- a/base/runtime/org.argeo.eclipse.ui.jcr/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - org.argeo.eclipse.ui.jcr - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - - diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/.settings/org.eclipse.jdt.core.prefs b/base/runtime/org.argeo.eclipse.ui.jcr/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 57d3f0066..000000000 --- a/base/runtime/org.argeo.eclipse.ui.jcr/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,8 +0,0 @@ -#Sat Jan 22 14:25:47 CET 2011 -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 -org.eclipse.jdt.core.compiler.compliance=1.5 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.5 diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/.settings/org.eclipse.pde.core.prefs b/base/runtime/org.argeo.eclipse.ui.jcr/.settings/org.eclipse.pde.core.prefs deleted file mode 100644 index 81635e90f..000000000 --- a/base/runtime/org.argeo.eclipse.ui.jcr/.settings/org.eclipse.pde.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -#Sat Jan 22 14:25:47 CET 2011 -eclipse.preferences.version=1 -pluginProject.extensions=false -resolve.requirebundle=false diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/build.properties b/base/runtime/org.argeo.eclipse.ui.jcr/build.properties deleted file mode 100644 index 0f2736b3a..000000000 --- a/base/runtime/org.argeo.eclipse.ui.jcr/build.properties +++ /dev/null @@ -1,6 +0,0 @@ -source.. = src/main/java/,\ - src/main/resources -output.. = target/classes/ -bin.includes = META-INF/,\ - .,\ - icons/ diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/icons/binary.png b/base/runtime/org.argeo.eclipse.ui.jcr/icons/binary.png deleted file mode 100644 index fdf4f82be..000000000 Binary files a/base/runtime/org.argeo.eclipse.ui.jcr/icons/binary.png and /dev/null differ diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/icons/file.gif b/base/runtime/org.argeo.eclipse.ui.jcr/icons/file.gif deleted file mode 100644 index ef3028807..000000000 Binary files a/base/runtime/org.argeo.eclipse.ui.jcr/icons/file.gif and /dev/null differ diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/icons/folder.gif b/base/runtime/org.argeo.eclipse.ui.jcr/icons/folder.gif deleted file mode 100644 index 42e027c93..000000000 Binary files a/base/runtime/org.argeo.eclipse.ui.jcr/icons/folder.gif and /dev/null differ diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/icons/home.gif b/base/runtime/org.argeo.eclipse.ui.jcr/icons/home.gif deleted file mode 100644 index fd0c66950..000000000 Binary files a/base/runtime/org.argeo.eclipse.ui.jcr/icons/home.gif and /dev/null differ diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/icons/node.gif b/base/runtime/org.argeo.eclipse.ui.jcr/icons/node.gif deleted file mode 100644 index 364c0e70b..000000000 Binary files a/base/runtime/org.argeo.eclipse.ui.jcr/icons/node.gif and /dev/null differ diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/icons/remote_connected.gif b/base/runtime/org.argeo.eclipse.ui.jcr/icons/remote_connected.gif deleted file mode 100644 index 1492b4efa..000000000 Binary files a/base/runtime/org.argeo.eclipse.ui.jcr/icons/remote_connected.gif and /dev/null differ diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/icons/remote_disconnected.gif b/base/runtime/org.argeo.eclipse.ui.jcr/icons/remote_disconnected.gif deleted file mode 100644 index 6c54da9ad..000000000 Binary files a/base/runtime/org.argeo.eclipse.ui.jcr/icons/remote_disconnected.gif and /dev/null differ diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/icons/repositories.gif b/base/runtime/org.argeo.eclipse.ui.jcr/icons/repositories.gif deleted file mode 100644 index c13bea1ca..000000000 Binary files a/base/runtime/org.argeo.eclipse.ui.jcr/icons/repositories.gif and /dev/null differ diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/icons/repository_connected.gif b/base/runtime/org.argeo.eclipse.ui.jcr/icons/repository_connected.gif deleted file mode 100644 index a15fa5538..000000000 Binary files a/base/runtime/org.argeo.eclipse.ui.jcr/icons/repository_connected.gif and /dev/null differ diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/icons/repository_disconnected.gif b/base/runtime/org.argeo.eclipse.ui.jcr/icons/repository_disconnected.gif deleted file mode 100644 index 4576dc563..000000000 Binary files a/base/runtime/org.argeo.eclipse.ui.jcr/icons/repository_disconnected.gif and /dev/null differ diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/icons/sort.gif b/base/runtime/org.argeo.eclipse.ui.jcr/icons/sort.gif deleted file mode 100644 index 23c5d0b11..000000000 Binary files a/base/runtime/org.argeo.eclipse.ui.jcr/icons/sort.gif and /dev/null differ diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/icons/workspace_connected.png b/base/runtime/org.argeo.eclipse.ui.jcr/icons/workspace_connected.png deleted file mode 100644 index 0430baaf5..000000000 Binary files a/base/runtime/org.argeo.eclipse.ui.jcr/icons/workspace_connected.png and /dev/null differ diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/icons/workspace_disconnected.png b/base/runtime/org.argeo.eclipse.ui.jcr/icons/workspace_disconnected.png deleted file mode 100644 index fddcb8c4e..000000000 Binary files a/base/runtime/org.argeo.eclipse.ui.jcr/icons/workspace_disconnected.png and /dev/null differ diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/pom.xml b/base/runtime/org.argeo.eclipse.ui.jcr/pom.xml deleted file mode 100644 index 540812813..000000000 --- a/base/runtime/org.argeo.eclipse.ui.jcr/pom.xml +++ /dev/null @@ -1,89 +0,0 @@ - - 4.0.0 - - org.argeo.commons.base - 2.1.12-SNAPSHOT - runtime - .. - - org.argeo.eclipse.ui.jcr - Commons Eclipse UI JCR - jar - - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-source-plugin - - - org.apache.maven.plugins - maven-jar-plugin - - - org.apache.felix - maven-bundle-plugin - - - - lazy - org.eclipse.ui;resolution:=optional,org.eclipse.rap.ui;resolution:=optional,org.eclipse.core.runtime - - org.eclipse.swt, - org.argeo.eclipse.ui.specific, - * - - - - - - - - - org.argeo.commons.base - org.argeo.eclipse.ui - 2.1.12-SNAPSHOT - - - - - org.argeo.tp - javax.jcr - - - org.argeo.commons.server - org.argeo.server.jcr - 2.1.12-SNAPSHOT - - - - - org.argeo.commons.base - org.argeo.eclipse.dep.rcp - 2.1.12-SNAPSHOT - provided - - - org.argeo.commons.base - org.argeo.eclipse.ui.rcp - 2.1.12-SNAPSHOT - provided - - - - - org.argeo.commons.base - org.argeo.util - 2.1.12-SNAPSHOT - - - - - org.argeo.tp - slf4j.org.apache.commons.logging - - - \ No newline at end of file diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/AbstractNodeContentProvider.java b/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/AbstractNodeContentProvider.java deleted file mode 100644 index ef2b8a845..000000000 --- a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/AbstractNodeContentProvider.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.jcr; - -import java.util.ArrayList; -import java.util.List; - -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.ArgeoException; -import org.argeo.eclipse.ui.AbstractTreeContentProvider; - -/** Canonic implementation of tree content provider manipulating JCR nodes. */ -public abstract class AbstractNodeContentProvider extends - AbstractTreeContentProvider { - private final static Log log = LogFactory - .getLog(AbstractNodeContentProvider.class); - - private Session session; - - public AbstractNodeContentProvider(Session session) { - this.session = session; - } - - /** - * Whether this path is a base path (and thus has no parent). By default it - * returns true if path is '/' (root node) - */ - protected Boolean isBasePath(String path) { - // root node - return path.equals("/"); - } - - @Override - public Object[] getChildren(Object element) { - Object[] children; - if (element instanceof Node) { - try { - Node node = (Node) element; - children = getChildren(node); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot get children of " + element, e); - } - } else if (element instanceof WrappedNode) { - WrappedNode wrappedNode = (WrappedNode) element; - try { - children = getChildren(wrappedNode.getNode()); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot get children of " - + wrappedNode, e); - } - } else if (element instanceof NodesWrapper) { - NodesWrapper node = (NodesWrapper) element; - children = node.getChildren(); - } else { - children = super.getChildren(element); - } - - children = sort(element, children); - return children; - } - - /** Do not sort by default. To be overidden to provide custom sort. */ - protected Object[] sort(Object parent, Object[] children) { - return children; - } - - /** - * To be overridden in order to filter out some nodes. Does nothing by - * default. The provided list is a temporary one and can thus be modified - * directly . (e.g. via an iterator) - */ - protected List filterChildren(List children) - throws RepositoryException { - return children; - } - - protected Object[] getChildren(Node node) throws RepositoryException { - List nodes = new ArrayList(); - for (NodeIterator nit = node.getNodes(); nit.hasNext();) - nodes.add(nit.nextNode()); - nodes = filterChildren(nodes); - return nodes.toArray(); - } - - @Override - public Object getParent(Object element) { - if (element instanceof Node) { - Node node = (Node) element; - try { - String path = node.getPath(); - if (isBasePath(path)) - return null; - else - return node.getParent(); - } catch (RepositoryException e) { - log.warn("Cannot get parent of " + element + ": " + e); - return null; - } - } else if (element instanceof WrappedNode) { - WrappedNode wrappedNode = (WrappedNode) element; - return wrappedNode.getParent(); - } else if (element instanceof NodesWrapper) { - NodesWrapper nodesWrapper = (NodesWrapper) element; - return this.getParent(nodesWrapper.getNode()); - } - return super.getParent(element); - } - - @Override - public boolean hasChildren(Object element) { - try { - if (element instanceof Node) { - Node node = (Node) element; - return node.hasNodes(); - } else if (element instanceof WrappedNode) { - WrappedNode wrappedNode = (WrappedNode) element; - return wrappedNode.getNode().hasNodes(); - } else if (element instanceof NodesWrapper) { - NodesWrapper nodesWrapper = (NodesWrapper) element; - return nodesWrapper.hasChildren(); - } - - } catch (RepositoryException e) { - throw new ArgeoException("Cannot check whether " + element - + " has children", e); - } - return super.hasChildren(element); - } - - public Session getSession() { - return session; - } -} diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/AsyncUiEventListener.java b/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/AsyncUiEventListener.java deleted file mode 100644 index 100ceb444..000000000 --- a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/AsyncUiEventListener.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.jcr; - -import java.util.ArrayList; -import java.util.List; - -import javax.jcr.RepositoryException; -import javax.jcr.observation.Event; -import javax.jcr.observation.EventIterator; -import javax.jcr.observation.EventListener; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.ArgeoException; -import org.eclipse.swt.widgets.Display; - -/** {@link EventListener} which simplifies running actions within the UI thread. */ -public abstract class AsyncUiEventListener implements EventListener { -// private final static Log logSuper = LogFactory -// .getLog(AsyncUiEventListener.class); - private final Log logThis = LogFactory.getLog(getClass()); - - private final Display display; - - public AsyncUiEventListener(Display display) { - super(); - this.display = display; - } - - /** Called asynchronously in the UI thread. */ - protected abstract void onEventInUiThread(List events) - throws RepositoryException; - - /** - * Whether these events should be processed in the UI or skipped with no UI - * job created. - */ - protected Boolean willProcessInUiThread(List events) - throws RepositoryException { - return true; - } - - protected Log getLog() { - return logThis; - } - - public final void onEvent(final EventIterator eventIterator) { - final List events = new ArrayList(); - while (eventIterator.hasNext()) - events.add(eventIterator.nextEvent()); - - if (logThis.isTraceEnabled()) - logThis.trace("Received " + events.size() + " events"); - - try { - if (!willProcessInUiThread(events)) - return; - } catch (RepositoryException e) { - throw new ArgeoException("Cannot test skip events " + events, e); - } - -// Job job = new Job("JCR Events") { -// protected IStatus run(IProgressMonitor monitor) { -// if (display.isDisposed()) { -// logSuper.warn("Display is disposed cannot update UI"); -// return Status.CANCEL_STATUS; -// } - - display.asyncExec(new Runnable() { - public void run() { - try { - onEventInUiThread(events); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot process events " - + events, e); - } - } - }); - -// return Status.OK_STATUS; -// } -// }; -// job.schedule(); - } -} diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/DefaultNodeLabelProvider.java b/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/DefaultNodeLabelProvider.java deleted file mode 100644 index 76fac1256..000000000 --- a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/DefaultNodeLabelProvider.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.jcr; - -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.RepositoryException; -import javax.jcr.nodetype.NodeType; - -import org.argeo.ArgeoException; -import org.argeo.jcr.ArgeoTypes; -import org.eclipse.jface.viewers.ColumnLabelProvider; -import org.eclipse.swt.graphics.Image; - -/** Provides reasonable overridable defaults for know JCR types. */ -public class DefaultNodeLabelProvider extends ColumnLabelProvider { - // Images - /** - * @deprecated Use {@link JcrImages#NODE} instead - */ - public final static Image NODE = JcrImages.NODE; - /** - * @deprecated Use {@link JcrImages#FOLDER} instead - */ - public final static Image FOLDER = JcrImages.FOLDER; - /** - * @deprecated Use {@link JcrImages#FILE} instead - */ - public final static Image FILE = JcrImages.FILE; - /** - * @deprecated Use {@link JcrImages#BINARY} instead - */ - public final static Image BINARY = JcrImages.BINARY; - /** - * @deprecated Use {@link JcrImages#HOME} instead - */ - public final static Image HOME = JcrImages.HOME; - - public String getText(Object element) { - try { - if (element instanceof Node) { - return getText((Node) element); - } else if (element instanceof WrappedNode) { - return getText(((WrappedNode) element).getNode()); - } else if (element instanceof NodesWrapper) { - return getText(((NodesWrapper) element).getNode()); - } - return super.getText(element); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot get text for of " + element, e); - } - } - - protected String getText(Node node) throws RepositoryException { - if (node.isNodeType(NodeType.MIX_TITLE) - && node.hasProperty(Property.JCR_TITLE)) - return node.getProperty(Property.JCR_TITLE).getString(); - else - return node.getName(); - } - - @Override - public Image getImage(Object element) { - try { - if (element instanceof Node) { - return getImage((Node) element); - } else if (element instanceof WrappedNode) { - return getImage(((WrappedNode) element).getNode()); - } else if (element instanceof NodesWrapper) { - return getImage(((NodesWrapper) element).getNode()); - } - } catch (RepositoryException e) { - throw new ArgeoException("Cannot retrieve image for " + element, e); - } - return super.getImage(element); - } - - protected Image getImage(Node node) throws RepositoryException { - // optimized order - if (node.getPrimaryNodeType().isNodeType(NodeType.NT_FILE)) - return JcrImages.FILE; - else if (node.getPrimaryNodeType().isNodeType(NodeType.NT_FOLDER)) - return JcrImages.FOLDER; - else if (node.getPrimaryNodeType().isNodeType(NodeType.NT_RESOURCE)) - return JcrImages.BINARY; - else if (node.isNodeType(ArgeoTypes.ARGEO_USER_HOME)) - return JcrImages.HOME; - else - return JcrImages.NODE; - } - - @Override - public String getToolTipText(Object element) { - try { - if (element instanceof Node) { - return getToolTipText((Node) element); - } else if (element instanceof WrappedNode) { - return getToolTipText(((WrappedNode) element).getNode()); - } else if (element instanceof NodesWrapper) { - return getToolTipText(((NodesWrapper) element).getNode()); - } - } catch (RepositoryException e) { - throw new ArgeoException("Cannot get tooltip for " + element, e); - } - return super.getToolTipText(element); - } - - protected String getToolTipText(Node node) throws RepositoryException { - return null; - } - -} diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/JcrImages.java b/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/JcrImages.java deleted file mode 100644 index 255ea7a25..000000000 --- a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/JcrImages.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.jcr; - -import org.eclipse.swt.graphics.Image; - -/** Shared icons. */ -public class JcrImages { - public final static Image NODE = JcrUiPlugin.getImageDescriptor( - "icons/node.gif").createImage(); - public final static Image FOLDER = JcrUiPlugin.getImageDescriptor( - "icons/folder.gif").createImage(); - public final static Image FILE = JcrUiPlugin.getImageDescriptor( - "icons/file.gif").createImage(); - public final static Image BINARY = JcrUiPlugin.getImageDescriptor( - "icons/binary.png").createImage(); - public final static Image HOME = JcrUiPlugin.getImageDescriptor( - "icons/home.gif").createImage(); - public final static Image SORT = JcrUiPlugin.getImageDescriptor( - "icons/sort.gif").createImage(); - - public final static Image REPOSITORIES = JcrUiPlugin.getImageDescriptor( - "icons/repositories.gif").createImage(); - public final static Image REPOSITORY_DISCONNECTED = JcrUiPlugin - .getImageDescriptor("icons/repository_disconnected.gif") - .createImage(); - public final static Image REPOSITORY_CONNECTED = JcrUiPlugin - .getImageDescriptor("icons/repository_connected.gif").createImage(); - public final static Image REMOTE_DISCONNECTED = JcrUiPlugin - .getImageDescriptor("icons/remote_disconnected.gif").createImage(); - public final static Image REMOTE_CONNECTED = JcrUiPlugin - .getImageDescriptor("icons/remote_connected.gif").createImage(); - public final static Image WORKSPACE_DISCONNECTED = JcrUiPlugin - .getImageDescriptor("icons/workspace_disconnected.png") - .createImage(); - public final static Image WORKSPACE_CONNECTED = JcrUiPlugin - .getImageDescriptor("icons/workspace_connected.png").createImage(); - -} diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/JcrPreferenceStore.java b/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/JcrPreferenceStore.java deleted file mode 100644 index c9777cefd..000000000 --- a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/JcrPreferenceStore.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.jcr; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.Properties; - -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.PropertyIterator; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.version.VersionManager; - -import org.apache.commons.io.IOUtils; -import org.argeo.ArgeoException; -import org.argeo.jcr.ArgeoNames; -import org.argeo.jcr.ArgeoTypes; -import org.argeo.jcr.JcrUtils; -import org.argeo.jcr.UserJcrUtils; -import org.eclipse.jface.preference.PreferenceStore; -import org.eclipse.ui.preferences.ScopedPreferenceStore; -import org.osgi.framework.BundleContext; - -/** - * Persist preferences as key/value pairs under ~/argeo:preferences.
- * TODO: better integrate JCR and Eclipse:
- * - typing
- * - use eclipse preferences
- * - better integrate with {@link ScopedPreferenceStore} provided by RAP - */ -public class JcrPreferenceStore extends PreferenceStore implements ArgeoNames { - private Session session; - private BundleContext bundleContext; - - /** Retrieves the preference node */ - protected Node getPreferenceNode() { - try { - if (session.hasPendingChanges()) - session.save(); - Node userHome = UserJcrUtils.getUserHome(session); - if (userHome == null) - throw new ArgeoException("No user home for " - + session.getUserID()); - Node preferences; - if (!userHome.hasNode(ARGEO_PREFERENCES)) { - preferences = userHome.addNode(ARGEO_PREFERENCES); - preferences.addMixin(ArgeoTypes.ARGEO_PREFERENCE_NODE); - session.save(); - } else - preferences = userHome.getNode(ARGEO_PREFERENCES); - - String pluginPreferencesName = bundleContext.getBundle() - .getSymbolicName(); - Node pluginPreferences; - if (!preferences.hasNode(pluginPreferencesName)) { - VersionManager vm = session.getWorkspace().getVersionManager(); - vm.checkout(preferences.getPath()); - pluginPreferences = preferences.addNode(pluginPreferencesName); - pluginPreferences.addMixin(ArgeoTypes.ARGEO_PREFERENCE_NODE); - session.save(); - vm.checkin(preferences.getPath()); - } else - pluginPreferences = preferences.getNode(pluginPreferencesName); - return pluginPreferences; - } catch (RepositoryException e) { - e.printStackTrace(); - JcrUtils.discardQuietly(session); - throw new ArgeoException("Cannot retrieve preferences", e); - } - - } - - @Override - public void load() throws IOException { - ByteArrayOutputStream out = null; - ByteArrayInputStream in = null; - try { - Properties props = new Properties(); - PropertyIterator it = getPreferenceNode().getProperties(); - while (it.hasNext()) { - Property p = it.nextProperty(); - if (!p.isMultiple() && !p.getDefinition().isProtected()) { - props.setProperty(p.getName(), p.getValue().getString()); - } - } - out = new ByteArrayOutputStream(); - props.store(out, ""); - in = new ByteArrayInputStream(out.toByteArray()); - load(in); - } catch (Exception e) { - e.printStackTrace(); - throw new ArgeoException("Cannot load preferences", e); - } finally { - IOUtils.closeQuietly(in); - IOUtils.closeQuietly(out); - } - } - - @Override - public void save() throws IOException { - ByteArrayOutputStream out = null; - ByteArrayInputStream in = null; - Node pluginPreferences = null; - try { - out = new ByteArrayOutputStream(); - save(out, ""); - in = new ByteArrayInputStream(out.toByteArray()); - Properties props = new Properties(); - props.load(in); - pluginPreferences = getPreferenceNode(); - VersionManager vm = pluginPreferences.getSession().getWorkspace() - .getVersionManager(); - vm.checkout(pluginPreferences.getPath()); - for (Object key : props.keySet()) { - String name = key.toString(); - String value = props.getProperty(name); - pluginPreferences.setProperty(name, value); - } - JcrUtils.updateLastModified(pluginPreferences); - pluginPreferences.getSession().save(); - vm.checkin(pluginPreferences.getPath()); - } catch (Exception e) { - JcrUtils.discardUnderlyingSessionQuietly(pluginPreferences); - throw new ArgeoException("Cannot save preferences", e); - } finally { - IOUtils.closeQuietly(in); - IOUtils.closeQuietly(out); - } - } - - public void init() { - try { - load(); - } catch (IOException e) { - throw new ArgeoException("Cannot initialize preference store", e); - } - } - - public void setSession(Session session) { - this.session = session; - } - - public void setBundleContext(BundleContext bundleContext) { - this.bundleContext = bundleContext; - } - -} diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/JcrUiPlugin.java b/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/JcrUiPlugin.java deleted file mode 100644 index adfa1a4f4..000000000 --- a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/JcrUiPlugin.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.jcr; - -import java.util.ResourceBundle; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.ui.plugin.AbstractUIPlugin; -import org.osgi.framework.BundleContext; - -public class JcrUiPlugin extends AbstractUIPlugin { - private final static Log log = LogFactory.getLog(JcrUiPlugin.class); - - public final static String ID = "org.argeo.eclipse.ui.jcr"; - - private ResourceBundle messages; - - private static JcrUiPlugin plugin; - - public void start(BundleContext context) throws Exception { - super.start(context); - plugin = this; - messages = ResourceBundle.getBundle("org.argeo.eclipse.ui.jcr"); - } - - public static JcrUiPlugin getDefault() { - return plugin; - } - - public static ImageDescriptor getImageDescriptor(String path) { - return imageDescriptorFromPlugin(ID, path); - } - - /** Returns the internationalized label for the given key */ - public static String getMessage(String key) { - try { - return getDefault().messages.getString(key); - } catch (NullPointerException npe) { - log.warn(key + " not found."); - return key; - } - } - - /** - * Gives access to the internationalization message bundle. Returns null in - * case the ClientUiPlugin is not started (for JUnit tests, by instance) - */ - public static ResourceBundle getMessagesBundle() { - if (getDefault() != null) - // To avoid NPE - return getDefault().messages; - else - return null; - } -} diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/JcrUiUtils.java b/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/JcrUiUtils.java deleted file mode 100644 index 8ee13aab0..000000000 --- a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/JcrUiUtils.java +++ /dev/null @@ -1,146 +0,0 @@ -package org.argeo.eclipse.ui.jcr; - -import java.util.Calendar; - -import javax.jcr.Node; -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; - -import org.argeo.ArgeoException; -import org.argeo.eclipse.ui.jcr.lists.NodeViewerComparator; -import org.argeo.eclipse.ui.jcr.lists.RowViewerComparator; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.widgets.Table; - -/** Utility methods to simplify UI development using eclipse and JCR. */ -public class JcrUiUtils { - - /** - * Centralizes management of updating property value. Among other to avoid - * infinite loop when the new value is the same as the ones that is already - * stored in JCR. - * - * @return true if the value as changed - */ - public static boolean setJcrProperty(Node node, String propName, - int propertyType, Object value) { - try { - // int propertyType = getPic().getProperty(propName).getType(); - switch (propertyType) { - case PropertyType.STRING: - if ("".equals((String) value) - && (!node.hasProperty(propName) || node - .hasProperty(propName) - && "".equals(node.getProperty(propName) - .getString()))) - // workaround the fact that the Text widget value cannot be - // set to null - return false; - else if (node.hasProperty(propName) - && node.getProperty(propName).getString() - .equals((String) value)) - // nothing changed yet - return false; - else { - node.setProperty(propName, (String) value); - return true; - } - case PropertyType.BOOLEAN: - if (node.hasProperty(propName) - && node.getProperty(propName).getBoolean() == (Boolean) value) - // nothing changed yet - return false; - else { - node.setProperty(propName, (Boolean) value); - return true; - } - case PropertyType.DATE: - if (node.hasProperty(propName) - && node.getProperty(propName).getDate() - .equals((Calendar) value)) - // nothing changed yet - return false; - else { - node.setProperty(propName, (Calendar) value); - return true; - } - case PropertyType.LONG: - Long lgValue = (Long) value; - - if (lgValue == null) - lgValue = 0L; - - if (node.hasProperty(propName) - && node.getProperty(propName).getLong() == lgValue) - // nothing changed yet - return false; - else { - node.setProperty(propName, lgValue); - return true; - } - - default: - throw new ArgeoException("Unimplemented property save"); - } - } catch (RepositoryException re) { - throw new ArgeoException("Unexpected error while setting property", - re); - } - } - - /** - * Creates a new selection adapter in order to provide sorting abitily on a - * swt table that display a row list - **/ - public static SelectionAdapter getRowSelectionAdapter(final int index, - final int propertyType, final String selectorName, - final String propertyName, final RowViewerComparator comparator, - final TableViewer viewer) { - SelectionAdapter selectionAdapter = new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - Table table = viewer.getTable(); - comparator.setColumn(propertyType, selectorName, propertyName); - int dir = table.getSortDirection(); - if (table.getSortColumn() == table.getColumn(index)) { - dir = dir == SWT.UP ? SWT.DOWN : SWT.UP; - } else { - dir = SWT.DOWN; - } - table.setSortDirection(dir); - table.setSortColumn(table.getColumn(index)); - viewer.refresh(); - } - }; - return selectionAdapter; - } - - /** - * Creates a new selection adapter in order to provide sorting abitily on a - * swt table that display a row list - **/ - public static SelectionAdapter getNodeSelectionAdapter(final int index, - final int propertyType, final String propertyName, - final NodeViewerComparator comparator, final TableViewer viewer) { - SelectionAdapter selectionAdapter = new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - Table table = viewer.getTable(); - comparator.setColumn(propertyType, propertyName); - int dir = table.getSortDirection(); - if (table.getSortColumn() == table.getColumn(index)) { - dir = dir == SWT.UP ? SWT.DOWN : SWT.UP; - } else { - dir = SWT.DOWN; - } - table.setSortDirection(dir); - table.setSortColumn(table.getColumn(index)); - viewer.refresh(); - } - }; - return selectionAdapter; - } -} diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/NodeElementComparer.java b/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/NodeElementComparer.java deleted file mode 100644 index f284b9c13..000000000 --- a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/NodeElementComparer.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.jcr; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.argeo.ArgeoException; -import org.eclipse.jface.viewers.IElementComparer; - -/** Element comparer for JCR node, to be used in JFace viewers. */ -public class NodeElementComparer implements IElementComparer { - - public boolean equals(Object a, Object b) { - try { - if ((a instanceof Node) && (b instanceof Node)) { - Node nodeA = (Node) a; - Node nodeB = (Node) b; - return nodeA.getIdentifier().equals(nodeB.getIdentifier()); - } else { - return a.equals(b); - } - } catch (RepositoryException e) { - throw new ArgeoException("Cannot compare nodes", e); - } - } - - public int hashCode(Object element) { - try { - if (element instanceof Node) - return ((Node) element).getIdentifier().hashCode(); - return element.hashCode(); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot get hash code", e); - } - } - -} diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/NodesWrapper.java b/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/NodesWrapper.java deleted file mode 100644 index dcd3b42f6..000000000 --- a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/NodesWrapper.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.jcr; - -import java.util.ArrayList; -import java.util.List; - -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.RepositoryException; - -import org.argeo.ArgeoException; - -/** - * Element of tree which is based on a node, but whose children are not - * necessarily this node children. - */ -public class NodesWrapper { - private final Node node; - - public NodesWrapper(Node node) { - super(); - this.node = node; - } - - protected NodeIterator getNodeIterator() throws RepositoryException { - return node.getNodes(); - } - - protected List getWrappedNodes() throws RepositoryException { - List nodes = new ArrayList(); - for (NodeIterator nit = getNodeIterator(); nit.hasNext();) - nodes.add(new WrappedNode(this, nit.nextNode())); - return nodes; - } - - public Object[] getChildren() { - try { - return getWrappedNodes().toArray(); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot get wrapped children", e); - } - } - - /** - * @return true by default because we don't want to compute the wrapped - * nodes twice - */ - public Boolean hasChildren() { - return true; - } - - public Node getNode() { - return node; - } - - @Override - public int hashCode() { - return node.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof NodesWrapper) - return node.equals(((NodesWrapper) obj).getNode()); - else - return false; - } - - public String toString() { - return "nodes wrapper based on " + node; - } -} diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/SimpleNodeContentProvider.java b/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/SimpleNodeContentProvider.java deleted file mode 100644 index 0dad19cfe..000000000 --- a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/SimpleNodeContentProvider.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.jcr; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.argeo.ArgeoException; -import org.argeo.jcr.JcrUtils; - -/** Simple JCR node content provider taking a list of String as base path. */ -public class SimpleNodeContentProvider extends AbstractNodeContentProvider { - private final List basePaths; - private Boolean mkdirs = false; - - public SimpleNodeContentProvider(Session session, String... basePaths) { - this(session, Arrays.asList(basePaths)); - } - - public SimpleNodeContentProvider(Session session, List basePaths) { - super(session); - this.basePaths = basePaths; - } - - @Override - protected Boolean isBasePath(String path) { - if (basePaths.contains(path)) - return true; - return super.isBasePath(path); - } - - public Object[] getElements(Object inputElement) { - try { - List baseNodes = new ArrayList(); - for (String basePath : basePaths) - if (mkdirs && !getSession().itemExists(basePath)) - baseNodes.add(JcrUtils.mkdirs(getSession(), basePath)); - else - baseNodes.add(getSession().getNode(basePath)); - return baseNodes.toArray(); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot get base nodes for " + basePaths, - e); - } - } - - public List getBasePaths() { - return basePaths; - } - - public void setMkdirs(Boolean mkdirs) { - this.mkdirs = mkdirs; - } - -} diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/WrappedNode.java b/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/WrappedNode.java deleted file mode 100644 index c0e197336..000000000 --- a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/WrappedNode.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.jcr; - -import javax.jcr.Node; - -/** Wraps a node (created from a {@link NodesWrapper}) */ -public class WrappedNode { - private final NodesWrapper parent; - private final Node node; - - public WrappedNode(NodesWrapper parent, Node node) { - super(); - this.parent = parent; - this.node = node; - } - - public NodesWrapper getParent() { - return parent; - } - - public Node getNode() { - return node; - } - - public String toString() { - return "wrapped " + node; - } - - @Override - public int hashCode() { - return node.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof WrappedNode) - return node.equals(((WrappedNode) obj).getNode()); - else - return false; - } - -} diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/commands/AddFileFolder.java b/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/commands/AddFileFolder.java deleted file mode 100644 index 5fc7db031..000000000 --- a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/commands/AddFileFolder.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.jcr.commands; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.nodetype.NodeType; - -import org.argeo.eclipse.ui.ErrorFeedback; -import org.argeo.eclipse.ui.dialogs.SingleValue; -import org.argeo.eclipse.ui.jcr.JcrUiPlugin; -import org.argeo.eclipse.ui.jcr.views.AbstractJcrBrowser; -import org.eclipse.core.commands.AbstractHandler; -import org.eclipse.core.commands.ExecutionEvent; -import org.eclipse.core.commands.ExecutionException; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.ui.handlers.HandlerUtil; - -/** Adds a node of type nt:folder */ -public class AddFileFolder extends AbstractHandler { - - public Object execute(ExecutionEvent event) throws ExecutionException { - ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event) - .getActivePage().getSelection(); - AbstractJcrBrowser view = (AbstractJcrBrowser) HandlerUtil - .getActiveWorkbenchWindow(event).getActivePage() - .findView(HandlerUtil.getActivePartId(event)); - if (selection != null && !selection.isEmpty() - && selection instanceof IStructuredSelection) { - Object obj = ((IStructuredSelection) selection).getFirstElement(); - - if (obj instanceof Node) { - String folderName = SingleValue.ask("Folder name", - "Enter folder name"); - if (folderName != null) { - Node parentNode = (Node) obj; - try { - Node newNode = parentNode.addNode(folderName, - NodeType.NT_FOLDER); - view.nodeAdded(parentNode, newNode); - parentNode.getSession().save(); - } catch (RepositoryException e) { - ErrorFeedback.show("Cannot create folder " + folderName - + " under " + parentNode, e); - } - } - } else { - ErrorFeedback.show(JcrUiPlugin - .getMessage("errorUnvalidNtFolderNodeType")); - } - } - return null; - } - -} diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/commands/DeleteNodes.java b/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/commands/DeleteNodes.java deleted file mode 100644 index 168674806..000000000 --- a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/commands/DeleteNodes.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.jcr.commands; - -import java.util.Iterator; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.argeo.ArgeoException; -import org.argeo.eclipse.ui.ErrorFeedback; -import org.argeo.eclipse.ui.jcr.views.AbstractJcrBrowser; -import org.eclipse.core.commands.AbstractHandler; -import org.eclipse.core.commands.ExecutionEvent; -import org.eclipse.core.commands.ExecutionException; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.ui.handlers.HandlerUtil; - -/** - * Deletes the selected nodes and refresh the corresponding AbstractJcrView. - * Note that no model specific check is done to see if the node can be removed - * or not. Extend or override to implement specific behaviour. - */ -public class DeleteNodes extends AbstractHandler { - public final static String ID = "org.argeo.eclipse.ui.jcr.deleteNodes"; - public final static String DEFAULT_LABEL = "Delete selected nodes"; - - public Object execute(ExecutionEvent event) throws ExecutionException { - ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event) - .getActivePage().getSelection(); - AbstractJcrBrowser view = (AbstractJcrBrowser) HandlerUtil - .getActiveWorkbenchWindow(event).getActivePage() - .findView(HandlerUtil.getActivePartId(event)); - - if (selection != null && selection instanceof IStructuredSelection) { - Iterator it = ((IStructuredSelection) selection).iterator(); - Object obj = null; - Node ancestor = null; - try { - while (it.hasNext()) { - obj = it.next(); - if (obj instanceof Node) { - Node node = (Node) obj; - Node parentNode = node.getParent(); - node.remove(); - node.getSession().save(); - ancestor = getOlder(ancestor, parentNode); - } - } - if (ancestor != null) - view.nodeRemoved(ancestor); - } catch (Exception e) { - ErrorFeedback.show("Cannot delete node " + obj, e); - } - } - return null; - } - - protected Node getOlder(Node A, Node B) { - try { - - if (A == null) - return B == null ? null : B; - // Todo enhanced this method - else - return A.getDepth() <= B.getDepth() ? A : B; - } catch (RepositoryException re) { - throw new ArgeoException("Cannot find ancestor", re); - } - } -} diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/commands/OpenGenericJcrQueryEditor.java b/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/commands/OpenGenericJcrQueryEditor.java deleted file mode 100644 index ce42266cc..000000000 --- a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/commands/OpenGenericJcrQueryEditor.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.jcr.commands; - -import org.argeo.eclipse.ui.jcr.editors.JcrQueryEditorInput; -import org.eclipse.core.commands.AbstractHandler; -import org.eclipse.core.commands.ExecutionEvent; -import org.eclipse.core.commands.ExecutionException; -import org.eclipse.ui.IWorkbenchPage; -import org.eclipse.ui.handlers.HandlerUtil; - -/** Open a JCR query editor. */ -public class OpenGenericJcrQueryEditor extends AbstractHandler { - private String editorId; - - public Object execute(ExecutionEvent event) throws ExecutionException { - try { - JcrQueryEditorInput editorInput = new JcrQueryEditorInput("", null); - IWorkbenchPage activePage = HandlerUtil.getActiveWorkbenchWindow( - event).getActivePage(); - activePage.openEditor(editorInput, editorId); - } catch (Exception e) { - throw new ExecutionException("Cannot open editor", e); - } - return null; - } - - public void setEditorId(String editorId) { - this.editorId = editorId; - } - -} diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/commands/Refresh.java b/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/commands/Refresh.java deleted file mode 100644 index f62be37eb..000000000 --- a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/commands/Refresh.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.jcr.commands; - -import java.util.Iterator; - -import org.argeo.eclipse.ui.jcr.views.AbstractJcrBrowser; -import org.eclipse.core.commands.AbstractHandler; -import org.eclipse.core.commands.ExecutionEvent; -import org.eclipse.core.commands.ExecutionException; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.ui.handlers.HandlerUtil; - -/** - * Call the refresh method of the active AbstractJcrBrowser instance. - * - * Warning: this method only refreshes the viewer, if the model is "stale", e.g. - * if some changes in the underlying data have not yet been propagated to the - * model, the view will not display up-to-date information. - */ -@Deprecated -public class Refresh extends AbstractHandler { - - public Object execute(ExecutionEvent event) throws ExecutionException { - ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event) - .getActivePage().getSelection(); - AbstractJcrBrowser view = (AbstractJcrBrowser) HandlerUtil - .getActiveWorkbenchWindow(event).getActivePage() - .findView(HandlerUtil.getActivePartId(event)); - if (selection != null && selection instanceof IStructuredSelection) { - Iterator it = ((IStructuredSelection) selection).iterator(); - while (it.hasNext()) { - Object obj = it.next(); - view.refresh(obj); - } - } - return null; - } -} diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/editors/AbstractJcrQueryEditor.java b/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/editors/AbstractJcrQueryEditor.java deleted file mode 100644 index 5e7d69644..000000000 --- a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/editors/AbstractJcrQueryEditor.java +++ /dev/null @@ -1,354 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.jcr.editors; - -import java.util.ArrayList; -import java.util.List; - -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.query.QueryResult; -import javax.jcr.query.Row; -import javax.jcr.query.RowIterator; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.ArgeoException; -import org.argeo.eclipse.ui.GenericTableComparator; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.jface.dialogs.ErrorDialog; -import org.eclipse.jface.viewers.ColumnLabelProvider; -import org.eclipse.jface.viewers.IDoubleClickListener; -import org.eclipse.jface.viewers.IStructuredContentProvider; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.jface.viewers.TableViewerColumn; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.swt.SWT; -import org.eclipse.swt.custom.SashForm; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.layout.FillLayout; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.TableColumn; -import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.IEditorSite; -import org.eclipse.ui.PartInitException; -import org.eclipse.ui.part.EditorPart; - -/** Executes any JCR query. */ -public abstract class AbstractJcrQueryEditor extends EditorPart { - private final static Log log = LogFactory - .getLog(AbstractJcrQueryEditor.class); - - protected String initialQuery; - protected String initialQueryType; - - /* DEPENDENCY INJECTION */ - private Session session; - - // Widgets - private TableViewer viewer; - private List tableViewerColumns = new ArrayList(); - private GenericTableComparator comparator; - - /** Override to layout a form enabling the end user to build his query */ - protected abstract void createQueryForm(Composite parent); - - @Override - public void init(IEditorSite site, IEditorInput input) - throws PartInitException { - JcrQueryEditorInput editorInput = (JcrQueryEditorInput) input; - initialQuery = editorInput.getQuery(); - initialQueryType = editorInput.getQueryType(); - setSite(site); - setInput(editorInput); - } - - @Override - public final void createPartControl(final Composite parent) { - parent.setLayout(new FillLayout()); - - SashForm sashForm = new SashForm(parent, SWT.VERTICAL); - sashForm.setSashWidth(4); - sashForm.setLayout(new FillLayout()); - - Composite top = new Composite(sashForm, SWT.NONE); - GridLayout gl = new GridLayout(1, false); - top.setLayout(gl); - - createQueryForm(top); - - Composite bottom = new Composite(sashForm, SWT.NONE); - bottom.setLayout(new GridLayout(1, false)); - sashForm.setWeights(getWeights()); - - viewer = new TableViewer(bottom); - viewer.getTable().setLayoutData( - new GridData(SWT.FILL, SWT.FILL, true, true)); - viewer.getTable().setHeaderVisible(true); - viewer.setContentProvider(getQueryResultContentProvider()); - viewer.setInput(getEditorSite()); - - if (getComparator() != null) { - comparator = getComparator(); - viewer.setComparator(comparator); - } - if (getTableDoubleClickListener() != null) - viewer.addDoubleClickListener(getTableDoubleClickListener()); - - } - - protected void executeQuery(String statement) { - try { - if (log.isDebugEnabled()) - log.debug("Query : " + statement); - - QueryResult qr = session.getWorkspace().getQueryManager() - .createQuery(statement, initialQueryType).execute(); - - // remove previous columns - for (TableViewerColumn tvc : tableViewerColumns) - tvc.getColumn().dispose(); - - int i = 0; - for (final String columnName : qr.getColumnNames()) { - TableViewerColumn tvc = new TableViewerColumn(viewer, SWT.NONE); - configureColumn(columnName, tvc, i); - tvc.setLabelProvider(getLabelProvider(columnName)); - tableViewerColumns.add(tvc); - i++; - } - - // Must create a local list: QueryResults can only be read once. - try { - List rows = new ArrayList(); - RowIterator rit = qr.getRows(); - while (rit.hasNext()) { - rows.add(rit.nextRow()); - } - viewer.setInput(rows); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot read query result", e); - } - - } catch (RepositoryException e) { - ErrorDialog.openError(null, "Error", "Cannot execute JCR query: " - + statement, new Status(IStatus.ERROR, - "org.argeo.eclipse.ui.jcr", e.getMessage())); - } - } - - /** - * To be overidden to adapt size of form and result frames. - * - * @return - */ - protected int[] getWeights() { - return new int[] { 30, 70 }; - } - - /** - * To be overidden to implement a doubleclick Listener on one of the rows of - * the table. - * - * @return - */ - protected IDoubleClickListener getTableDoubleClickListener() { - return null; - } - - /** - * To be overiden in order to implement a specific - * QueryResultContentProvider - */ - protected IStructuredContentProvider getQueryResultContentProvider() { - return new QueryResultContentProvider(); - } - - /** - * Enable specific implementation for columns - */ - protected List getTableViewerColumns() { - return tableViewerColumns; - } - - /** - * Enable specific implementation for columns - */ - protected TableViewer getTableViewer() { - return viewer; - } - - /** - * To be overridden in order to configure column label providers . - */ - protected ColumnLabelProvider getLabelProvider(final String columnName) { - return new ColumnLabelProvider() { - public String getText(Object element) { - Row row = (Row) element; - try { - return row.getValue(columnName).getString(); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot display row " + row, e); - } - } - - public Image getImage(Object element) { - return null; - } - }; - } - - /** - * To be overridden in order to configure the columns. - * - * @deprecated use {@link - * org.argeo.eclipse.ui.jcr.editors.AbstractJcrQueryEditor. - * configureColumn(String jcrColumnName, TableViewerColumn - * column, int columnIndex)} instead - */ - protected void configureColumn(String jcrColumnName, - TableViewerColumn column) { - column.getColumn().setWidth(50); - column.getColumn().setText(jcrColumnName); - } - - /** To be overridden in order to configure the columns. */ - protected void configureColumn(String jcrColumnName, - TableViewerColumn column, int columnIndex) { - column.getColumn().setWidth(50); - column.getColumn().setText(jcrColumnName); - } - - private class QueryResultContentProvider implements - IStructuredContentProvider { - - public void dispose() { - } - - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - } - - public Object[] getElements(Object inputElement) { - - if (inputElement instanceof List) - return ((List) inputElement).toArray(); - - // Never reached might be deleted in future release - if (!(inputElement instanceof QueryResult)) - return new String[] {}; - - try { - QueryResult queryResult = (QueryResult) inputElement; - List rows = new ArrayList(); - RowIterator rit = queryResult.getRows(); - while (rit.hasNext()) { - rows.add(rit.nextRow()); - } - - // List elems = new ArrayList(); - // NodeIterator nit = queryResult.getNodes(); - // while (nit.hasNext()) { - // elems.add(nit.nextNode()); - // } - return rows.toArray(); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot read query result", e); - } - } - - } - - /** - * Might be used by children classes to sort columns. - * - * @param column - * @param index - * @return - */ - protected SelectionAdapter getSelectionAdapter(final TableColumn column, - final int index) { - - // A comparator must be define - if (comparator == null) - return null; - - SelectionAdapter selectionAdapter = new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - - try { - - comparator.setColumn(index); - int dir = viewer.getTable().getSortDirection(); - if (viewer.getTable().getSortColumn() == column) { - dir = dir == SWT.UP ? SWT.DOWN : SWT.UP; - } else { - - dir = SWT.DOWN; - } - viewer.getTable().setSortDirection(dir); - viewer.getTable().setSortColumn(column); - viewer.refresh(); - } catch (Exception exc) { - exc.printStackTrace(); - } - } - }; - return selectionAdapter; - } - - /** - * To be overridden to enable sorting. - */ - protected GenericTableComparator getComparator() { - return null; - } - - @Override - public boolean isDirty() { - return false; - } - - @Override - public void doSave(IProgressMonitor monitor) { - // TODO save the query in JCR? - } - - @Override - public void doSaveAs() { - } - - @Override - public boolean isSaveAsAllowed() { - return false; - } - - /** Returns the injected current session */ - protected Session getSession() { - return session; - } - - /* DEPENDENCY INJECTION */ - public void setSession(Session session) { - this.session = session; - } -} diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/editors/JcrQueryEditorInput.java b/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/editors/JcrQueryEditorInput.java deleted file mode 100644 index eedccc85b..000000000 --- a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/editors/JcrQueryEditorInput.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.jcr.editors; - -import javax.jcr.query.Query; - -import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.IPersistableElement; - -public class JcrQueryEditorInput implements IEditorInput { - private final String query; - private final String queryType; - - public JcrQueryEditorInput(String query, String queryType) { - this.query = query; - if (queryType == null) - this.queryType = Query.JCR_SQL2; - else - this.queryType = queryType; - } - - public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) { - return null; - } - - public boolean exists() { - return true; - } - - public ImageDescriptor getImageDescriptor() { - return null; - } - - public String getName() { - return query; - } - - public IPersistableElement getPersistable() { - return null; - } - - public String getToolTipText() { - return query; - } - - public String getQuery() { - return query; - } - - public String getQueryType() { - return queryType; - } - -} diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/editors/NodeEditorInput.java b/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/editors/NodeEditorInput.java deleted file mode 100644 index a55884f2e..000000000 --- a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/editors/NodeEditorInput.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.jcr.editors; - -import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.IPersistableElement; - -/** - * A canonical editor input based on a path to a node. In a multirepository - * environment, path can be enriched with Repository Alias and workspace - */ - -public class NodeEditorInput implements IEditorInput { - private final String path; - - public NodeEditorInput(String path) { - this.path = path; - } - - public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) { - return null; - } - - public boolean exists() { - return true; - } - - public ImageDescriptor getImageDescriptor() { - return null; - } - - public String getName() { - return path; - } - - public IPersistableElement getPersistable() { - return null; - } - - public String getToolTipText() { - return path; - } - - public String getPath() { - return path; - } -} diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/lists/ColumnDefinition.java b/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/lists/ColumnDefinition.java deleted file mode 100644 index 9e338276a..000000000 --- a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/lists/ColumnDefinition.java +++ /dev/null @@ -1,88 +0,0 @@ -package org.argeo.eclipse.ui.jcr.lists; - -/** - * Utility object to manage column in various tables and extracts displaying - * data from JCR - */ -public class ColumnDefinition { - private final static int DEFAULT_COLUMN_SIZE = 120; - - private String selectorName; - private String propertyName; - private String headerLabel; - private int propertyType; - private int columnSize = DEFAULT_COLUMN_SIZE; - - /** - * new column using default width - * - * @param selectorName - * @param propertyName - * @param propertyType - * @param headerLabel - */ - public ColumnDefinition(String selectorName, String propertyName, - int propertyType, String headerLabel) { - this.selectorName = selectorName; - this.propertyName = propertyName; - this.propertyType = propertyType; - this.headerLabel = headerLabel; - } - - /** - * - * @param selectorName - * @param propertyName - * @param propertyType - * @param headerLabel - * @param columnSize - */ - public ColumnDefinition(String selectorName, String propertyName, - int propertyType, String headerLabel, int columnSize) { - this.selectorName = selectorName; - this.propertyName = propertyName; - this.propertyType = propertyType; - this.headerLabel = headerLabel; - this.columnSize = columnSize; - } - - public String getSelectorName() { - return selectorName; - } - - public void setSelectorName(String selectorName) { - this.selectorName = selectorName; - } - - public String getPropertyName() { - return propertyName; - } - - public void setPropertyName(String propertyName) { - this.propertyName = propertyName; - } - - public String getHeaderLabel() { - return headerLabel; - } - - public void setHeaderLabel(String headerLabel) { - this.headerLabel = headerLabel; - } - - public int getPropertyType() { - return propertyType; - } - - public void setPropertyType(int propertyType) { - this.propertyType = propertyType; - } - - public int getColumnSize() { - return columnSize; - } - - public void setColumnSize(int columnSize) { - this.columnSize = columnSize; - } -} diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/lists/IListProvider.java b/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/lists/IListProvider.java deleted file mode 100644 index 622e2e259..000000000 --- a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/lists/IListProvider.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.argeo.eclipse.ui.jcr.lists; - -import java.util.List; - -/** - * Views and editors can implement this interface so that one of the row list - * that is displayed in the part (For instance in a Table or a Tree Viewer) can - * be rebuilt externally. typically to generate csv or calc extract. - */ -public interface IListProvider { - /** - * Returns an array of current and relevant elements - */ - public Object[] getElements(String extractId); - - /** - * Returns the column definition for passed ID - */ - public List getColumnDefinition(String extractId); -} diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/lists/NodeViewerComparator.java b/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/lists/NodeViewerComparator.java deleted file mode 100644 index 11f12e6f5..000000000 --- a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/lists/NodeViewerComparator.java +++ /dev/null @@ -1,192 +0,0 @@ -package org.argeo.eclipse.ui.jcr.lists; - -import java.math.BigDecimal; -import java.util.Calendar; - -import javax.jcr.Node; -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; -import javax.jcr.Value; -import javax.jcr.ValueFormatException; - -import org.argeo.ArgeoException; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.jface.viewers.ViewerComparator; - -/** - * Base comparator to enable ordering on Table or Tree viewer that display Jcr - * Nodes. - * - * Note that the following snippet must be added before setting the comparator - * to the corresponding control: - * // IMPORTANT: initialize comparator before setting it - * ColumnDefinition firstCol = colDefs.get(0); - * comparator.setColumn(firstCol.getPropertyType(), - * firstCol.getPropertyName()); - * viewer.setComparator(comparator); - */ -public class NodeViewerComparator extends ViewerComparator { - - protected String propertyName; - - protected int propertyType; - public static final int ASCENDING = 0, DESCENDING = 1; - protected int direction = DESCENDING; - - public NodeViewerComparator() { - } - - /** - * e1 and e2 must both be Jcr nodes. - * - * @param viewer - * @param e1 - * @param e2 - * @return - */ - @Override - public int compare(Viewer viewer, Object e1, Object e2) { - int rc = 0; - long lc = 0; - - try { - - Node n1 = (Node) e1; - Node n2 = (Node) e2; - - Value v1 = null; - Value v2 = null; - if (n1.hasProperty(propertyName)) - v1 = n1.getProperty(propertyName).getValue(); - if (n2.hasProperty(propertyName)) - v2 = n2.getProperty(propertyName).getValue(); - - if (v2 == null && v1 == null) - return 0; - else if (v2 == null) - return -1; - else if (v1 == null) - return 1; - - switch (propertyType) { - case PropertyType.STRING: - rc = v1.getString().compareTo(v2.getString()); - break; - case PropertyType.BOOLEAN: - boolean b1 = v1.getBoolean(); - boolean b2 = v2.getBoolean(); - if (b1 == b2) - rc = 0; - else - // we assume true is greater than false - rc = b1 ? 1 : -1; - break; - case PropertyType.DATE: - Calendar c1 = v1.getDate(); - Calendar c2 = v2.getDate(); - if (c1 == null || c2 == null) - // log.trace("undefined date"); - ; - lc = c1.getTimeInMillis() - c2.getTimeInMillis(); - if (lc < Integer.MIN_VALUE) - // rc = Integer.MIN_VALUE; - rc = -1; - else if (lc > Integer.MAX_VALUE) - // rc = Integer.MAX_VALUE; - rc = 1; - else - rc = (int) lc; - break; - case PropertyType.LONG: - long l1; - long l2; - // FIXME sometimes an empty string is set instead of a long - try { - l1 = v1.getLong(); - } catch (ValueFormatException ve) { - l1 = 0; - } - try { - l2 = v2.getLong(); - } catch (ValueFormatException ve) { - l2 = 0; - } - - lc = l1 - l2; - if (lc < Integer.MIN_VALUE) - rc = -1; - else if (lc > Integer.MAX_VALUE) - rc = 1; - else - rc = (int) lc; - break; - case PropertyType.DECIMAL: - BigDecimal bd1 = v1.getDecimal(); - BigDecimal bd2 = v2.getDecimal(); - rc = bd1.compareTo(bd2); - break; - case PropertyType.DOUBLE: - Double d1 = v1.getDouble(); - Double d2 = v2.getDouble(); - rc = d1.compareTo(d2); - break; - default: - throw new ArgeoException( - "Unimplemented comparaison for PropertyType " - + propertyType); - } - // If descending order, flip the direction - if (direction == DESCENDING) { - rc = -rc; - } - - } catch (RepositoryException re) { - throw new ArgeoException("Unexpected error " - + "while comparing nodes", re); - } - return rc; - } - - /** - * @param propertyType - * Corresponding JCR type - * @param propertyName - * name of the property to use. - */ - public void setColumn(int propertyType, String propertyName) { - if (this.propertyName != null && this.propertyName.equals(propertyName)) { - // Same column as last sort; toggle the direction - direction = 1 - direction; - } else { - // New column; do an ascending sort - this.propertyType = propertyType; - this.propertyName = propertyName; - direction = ASCENDING; - } - } - - // Getters and setters - protected String getPropertyName() { - return propertyName; - } - - protected void setPropertyName(String propertyName) { - this.propertyName = propertyName; - } - - protected int getPropertyType() { - return propertyType; - } - - protected void setPropertyType(int propertyType) { - this.propertyType = propertyType; - } - - protected int getDirection() { - return direction; - } - - protected void setDirection(int direction) { - this.direction = direction; - } -} \ No newline at end of file diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/lists/RowViewerComparator.java b/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/lists/RowViewerComparator.java deleted file mode 100644 index 509f72324..000000000 --- a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/lists/RowViewerComparator.java +++ /dev/null @@ -1,62 +0,0 @@ -package org.argeo.eclipse.ui.jcr.lists; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.query.Row; - -import org.argeo.ArgeoException; -import org.eclipse.jface.viewers.Viewer; - -/** - * Base comparator to enable ordering on Table or Tree viewer that display Jcr - * rows - */ -public class RowViewerComparator extends NodeViewerComparator { - - protected String selectorName; - - public RowViewerComparator() { - } - - /** - * e1 and e2 must both be Jcr rows. - * - * @param viewer - * @param e1 - * @param e2 - * @return - */ - @Override - public int compare(Viewer viewer, Object e1, Object e2) { - try { - Node n1 = ((Row) e1).getNode(selectorName); - Node n2 = ((Row) e2).getNode(selectorName); - return super.compare(viewer, n1, n2); - } catch (RepositoryException re) { - throw new ArgeoException("Unexpected error " - + "while comparing nodes", re); - } - } - - /** - * @param propertyType - * Corresponding JCR type - * @param propertyName - * name of the property to use. - */ - public void setColumn(int propertyType, String selectorName, - String propertyName) { - if (this.selectorName != null && getPropertyName() != null - && this.selectorName.equals(selectorName) - && this.getPropertyName().equals(propertyName)) { - // Same column as last sort; toggle the direction - setDirection(1 - getDirection()); - } else { - // New column; do a descending sort - setPropertyType(propertyType); - setPropertyName(propertyName); - this.selectorName = selectorName; - setDirection(NodeViewerComparator.ASCENDING); - } - } -} \ No newline at end of file diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/lists/SimpleJcrNodeLabelProvider.java b/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/lists/SimpleJcrNodeLabelProvider.java deleted file mode 100644 index 88585c343..000000000 --- a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/lists/SimpleJcrNodeLabelProvider.java +++ /dev/null @@ -1,122 +0,0 @@ -package org.argeo.eclipse.ui.jcr.lists; - -import java.text.DateFormat; -import java.text.DecimalFormat; -import java.text.NumberFormat; -import java.text.SimpleDateFormat; - -import javax.jcr.Node; -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; -import javax.jcr.Value; - -import org.argeo.ArgeoException; -import org.eclipse.jface.viewers.ColumnLabelProvider; - -/** - * Base implementation of a label provider for widgets that display JCR Rows. - */ -public class SimpleJcrNodeLabelProvider extends ColumnLabelProvider { - private static final long serialVersionUID = -5215787695436221993L; - - private final static String DEFAULT_DATE_FORMAT = "EEE, dd MMM yyyy"; - private final static String DEFAULT_NUMBER_FORMAT = "#,##0.0"; - - private DateFormat dateFormat; - private NumberFormat numberFormat; - - final private String propertyName; - - /** - * Default Label provider for a given property of a node. Using default - * pattern for date and number formating - */ - public SimpleJcrNodeLabelProvider(String propertyName) { - this.propertyName = propertyName; - dateFormat = new SimpleDateFormat(DEFAULT_DATE_FORMAT); - numberFormat = DecimalFormat.getInstance(); - ((DecimalFormat) numberFormat).applyPattern(DEFAULT_NUMBER_FORMAT); - } - - /** - * Label provider for a given property of a node optionally precising date - * and/or number format patterns - */ - public SimpleJcrNodeLabelProvider(String propertyName, - String dateFormatPattern, String numberFormatPattern) { - this.propertyName = propertyName; - dateFormat = new SimpleDateFormat( - dateFormatPattern == null ? DEFAULT_DATE_FORMAT - : dateFormatPattern); - numberFormat = DecimalFormat.getInstance(); - ((DecimalFormat) numberFormat) - .applyPattern(numberFormatPattern == null ? DEFAULT_NUMBER_FORMAT - : numberFormatPattern); - } - - @Override - public String getText(Object element) { - try { - Node currNode = (Node) element; - - if (currNode.hasProperty(propertyName)) { - if (currNode.getProperty(propertyName).isMultiple()) { - StringBuilder builder = new StringBuilder(); - for (Value value : currNode.getProperty(propertyName) - .getValues()) { - String currStr = getSingleValueAsString(value); - if (notEmptyString(currStr)) - builder.append(currStr).append("; "); - } - if (builder.length() > 0) - builder.deleteCharAt(builder.length() - 2); - - return builder.toString(); - } else - return getSingleValueAsString(currNode.getProperty( - propertyName).getValue()); - } else - return ""; - } catch (RepositoryException re) { - throw new ArgeoException("Unable to get text from row", re); - } - } - - private String getSingleValueAsString(Value value) - throws RepositoryException { - switch (value.getType()) { - case PropertyType.STRING: - return value.getString(); - case PropertyType.BOOLEAN: - return "" + value.getBoolean(); - case PropertyType.DATE: - return dateFormat.format(value.getDate().getTime()); - case PropertyType.LONG: - return "" + value.getLong(); - case PropertyType.DECIMAL: - return numberFormat.format(value.getDecimal()); - case PropertyType.DOUBLE: - return numberFormat.format(value.getDouble()); - case PropertyType.NAME: - return value.getString(); - default: - throw new ArgeoException("Unimplemented label provider " - + "for property type " + value.getType() - + " while getting property " + propertyName + " - value: " - + value.getString()); - - } - } - - private boolean notEmptyString(String string) { - return string != null && !"".equals(string.trim()); - } - - public void setDateFormat(String dateFormatPattern) { - dateFormat = new SimpleDateFormat(dateFormatPattern); - } - - public void setNumberFormat(String numberFormatPattern) { - ((DecimalFormat) numberFormat).applyPattern(numberFormatPattern); - } -} \ No newline at end of file diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/lists/SimpleJcrRowLabelProvider.java b/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/lists/SimpleJcrRowLabelProvider.java deleted file mode 100644 index bb55f187d..000000000 --- a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/lists/SimpleJcrRowLabelProvider.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.argeo.eclipse.ui.jcr.lists; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.query.Row; - -import org.argeo.ArgeoException; - -/** - * Base implementation of a label provider for widgets that display JCR Rows. - */ -public class SimpleJcrRowLabelProvider extends SimpleJcrNodeLabelProvider { - private static final long serialVersionUID = -3414654948197181740L; - - final private String selectorName; - - /** - * Default Label provider for a given property of a row. Using default - * pattern for date and number formating - */ - public SimpleJcrRowLabelProvider(String selectorName, String propertyName) { - super(propertyName); - this.selectorName = selectorName; - } - - /** - * Label provider for a given property of a node optionally precising date - * and/or number format patterns - */ - public SimpleJcrRowLabelProvider(String selectorName, String propertyName, - String dateFormatPattern, String numberFormatPattern) { - super(propertyName, dateFormatPattern, numberFormatPattern); - this.selectorName = selectorName; - } - - @Override - public String getText(Object element) { - try { - Row currRow = (Row) element; - Node currNode = currRow.getNode(selectorName); - return super.getText(currNode); - } catch (RepositoryException re) { - throw new ArgeoException("Unable to get Node " + selectorName - + " from row " + element, re); - } - } -} \ No newline at end of file diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/utils/JcrFileProvider.java b/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/utils/JcrFileProvider.java deleted file mode 100644 index 47cab6d6a..000000000 --- a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/utils/JcrFileProvider.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.jcr.utils; - -import java.io.InputStream; - -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.RepositoryException; -import javax.jcr.nodetype.NodeType; - -import org.apache.commons.io.IOUtils; -import org.argeo.ArgeoException; -import org.argeo.eclipse.ui.specific.FileProvider; - -/** - * Implements a FileProvider for UI purposes. Note that it might not be very - * reliable as long as we have not fixed login & multi repository issues that - * will be addressed in the next version. - * - * NOTE: id used here is the real id of the JCR Node, not the JCR Path - * - * Relies on common approach for JCR file handling implementation. - * - */ - -public class JcrFileProvider implements FileProvider { - - // private Object[] rootNodes; - private Node refNode; - - /** - * Must be set in order for the provider to be able to get current session - * and thus have the ability to get the file node corresponding to a given - * file ID - * - * FIXME : this introduces some concurrences ISSUES. - * - * @param repositoryNode - */ - public void setReferenceNode(Node refNode) { - this.refNode = refNode; - } - - /** - * Must be set in order for the provider to be able to search the repository - * Provided object might be either JCR Nodes or UI RepositoryNode for the - * time being. - * - * @param repositoryNode - */ - // public void setRootNodes(Object[] rootNodes) { - // List tmpNodes = new ArrayList(); - // for (int i = 0; i < rootNodes.length; i++) { - // Object obj = rootNodes[i]; - // if (obj instanceof Node) { - // tmpNodes.add(obj); - // } else if (obj instanceof RepositoryRegister) { - // RepositoryRegister repositoryRegister = (RepositoryRegister) obj; - // Map repositories = repositoryRegister - // .getRepositories(); - // for (String name : repositories.keySet()) { - // // tmpNodes.add(new RepositoryNode(name, repositories - // // .get(name))); - // } - // - // } - // } - // this.rootNodes = tmpNodes.toArray(); - // } - - public byte[] getByteArrayFileFromId(String fileId) { - InputStream fis = null; - byte[] ba = null; - Node child = getFileNodeFromId(fileId); - try { - fis = (InputStream) child.getProperty(Property.JCR_DATA) - .getBinary().getStream(); - ba = IOUtils.toByteArray(fis); - - } catch (Exception e) { - throw new ArgeoException("Stream error while opening file", e); - } finally { - IOUtils.closeQuietly(fis); - } - return ba; - } - - public InputStream getInputStreamFromFileId(String fileId) { - try { - InputStream fis = null; - - Node child = getFileNodeFromId(fileId); - fis = (InputStream) child.getProperty(Property.JCR_DATA) - .getBinary().getStream(); - return fis; - } catch (RepositoryException re) { - throw new ArgeoException("Cannot get stream from file node for Id " - + fileId, re); - } - } - - /** - * Throws an exception if the node is not found in the current repository (a - * bit like a FileNotFoundException) - * - * @param fileId - * @return Returns the child node of the nt:file node. It is the child node - * that have the jcr:data property where actual file is stored. - * never null - */ - private Node getFileNodeFromId(String fileId) { - try { - Node result = refNode.getSession().getNodeByIdentifier(fileId); - - // rootNodes: for (int j = 0; j < rootNodes.length; j++) { - // // in case we have a classic JCR Node - // if (rootNodes[j] instanceof Node) { - // Node curNode = (Node) rootNodes[j]; - // if (result != null) - // break rootNodes; - // } // Case of a repository Node - // else if (rootNodes[j] instanceof RepositoryNode) { - // Object[] nodes = ((RepositoryNode) rootNodes[j]) - // .getChildren(); - // for (int i = 0; i < nodes.length; i++) { - // Node node = (Node) nodes[i]; - // result = node.getSession().getNodeByIdentifier(fileId); - // if (result != null) - // break rootNodes; - // } - // } - // } - - // Sanity checks - if (result == null) - throw new ArgeoException("File node not found for ID" + fileId); - - Node child = null; - - boolean isValid = true; - if (!result.isNodeType(NodeType.NT_FILE)) - // useless: mandatory child node - // || !result.hasNode(Property.JCR_CONTENT)) - isValid = false; - else { - child = result.getNode(Property.JCR_CONTENT); - if (!(child.isNodeType(NodeType.NT_RESOURCE) || child - .hasProperty(Property.JCR_DATA))) - isValid = false; - } - - if (!isValid) - throw new ArgeoException( - "ERROR: In the current implemented model, '" - + NodeType.NT_FILE - + "' file node must have a child node named jcr:content " - + "that has a BINARY Property named jcr:data " - + "where the actual data is stored"); - return child; - - } catch (RepositoryException re) { - throw new ArgeoException("Erreur while getting file node of ID " - + fileId, re); - } - } -} diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/utils/JcrItemsComparator.java b/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/utils/JcrItemsComparator.java deleted file mode 100644 index 2d36bf28a..000000000 --- a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/utils/JcrItemsComparator.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.jcr.utils; - -import java.util.Comparator; - -import javax.jcr.Item; -import javax.jcr.RepositoryException; - -import org.argeo.ArgeoException; - -/** Compares two JCR items (node or properties) based on their names. */ -public class JcrItemsComparator implements Comparator { - public int compare(Item o1, Item o2) { - try { - // TODO: put folder before files - return o1.getName().compareTo(o2.getName()); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot compare " + o1 + " and " + o2, e); - } - } - -} diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/utils/NodeViewerComparer.java b/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/utils/NodeViewerComparer.java deleted file mode 100644 index 5a94ee76a..000000000 --- a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/utils/NodeViewerComparer.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.jcr.utils; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.argeo.ArgeoException; -import org.eclipse.jface.viewers.IElementComparer; - -/** Compare JCR nodes based on their JCR identifiers, for use in JFace viewers. */ -public class NodeViewerComparer implements IElementComparer { - - // force comparison on Node IDs only. - public boolean equals(Object elementA, Object elementB) { - if (!(elementA instanceof Node) || !(elementB instanceof Node)) { - return elementA == null ? elementB == null : elementA - .equals(elementB); - } else { - - boolean result = false; - try { - String idA = ((Node) elementA).getIdentifier(); - String idB = ((Node) elementB).getIdentifier(); - result = idA == null ? idB == null : idA.equals(idB); - } catch (RepositoryException re) { - throw new ArgeoException("cannot compare nodes", re); - } - - return result; - } - } - - public int hashCode(Object element) { - // TODO enhanced this method. - return element.getClass().toString().hashCode(); - } -} \ No newline at end of file diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/utils/SingleSessionFileProvider.java b/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/utils/SingleSessionFileProvider.java deleted file mode 100644 index f0c378024..000000000 --- a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/utils/SingleSessionFileProvider.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.jcr.utils; - -import java.io.InputStream; - -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.nodetype.NodeType; - -import org.apache.commons.io.IOUtils; -import org.argeo.ArgeoException; -import org.argeo.eclipse.ui.specific.FileProvider; - -/** - * Implements a FileProvider for UI purposes. Unlike the - * JcrFileProvider , it relies on a single session and manages - * nodes with path only. - * - * Note that considered id is the JCR path - * - * Relies on common approach for JCR file handling implementation. - * - * @author bsinou - * - */ - -public class SingleSessionFileProvider implements FileProvider { - - private Session session; - - public SingleSessionFileProvider(Session session) { - this.session = session; - } - - public byte[] getByteArrayFileFromId(String fileId) { - InputStream fis = null; - byte[] ba = null; - Node child = getFileNodeFromId(fileId); - try { - fis = (InputStream) child.getProperty(Property.JCR_DATA) - .getBinary().getStream(); - ba = IOUtils.toByteArray(fis); - - } catch (Exception e) { - throw new ArgeoException("Stream error while opening file", e); - } finally { - IOUtils.closeQuietly(fis); - } - return ba; - } - - public InputStream getInputStreamFromFileId(String fileId) { - try { - InputStream fis = null; - - Node child = getFileNodeFromId(fileId); - fis = (InputStream) child.getProperty(Property.JCR_DATA) - .getBinary().getStream(); - return fis; - } catch (RepositoryException re) { - throw new ArgeoException("Cannot get stream from file node for Id " - + fileId, re); - } - } - - /** - * - * @param fileId - * @return Returns the child node of the nt:file node. It is the child node - * that have the jcr:data property where actual file is stored. - * never null - */ - private Node getFileNodeFromId(String fileId) { - try { - Node result = null; - result = session.getNode(fileId); - - // Sanity checks - if (result == null) - throw new ArgeoException("File node not found for ID" + fileId); - - // Ensure that the node have the correct type. - if (!result.isNodeType(NodeType.NT_FILE)) - throw new ArgeoException( - "Cannot open file children Node that are not of " - + NodeType.NT_RESOURCE + " type."); - - Node child = result.getNodes().nextNode(); - if (child == null || !child.isNodeType(NodeType.NT_RESOURCE)) - throw new ArgeoException( - "ERROR: IN the current implemented model, " - + NodeType.NT_FILE - + " file node must have one and only one child of the nt:ressource, where actual data is stored"); - return child; - } catch (RepositoryException re) { - throw new ArgeoException("Erreur while getting file node of ID " - + fileId, re); - } - } -} diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/views/AbstractJcrBrowser.java b/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/views/AbstractJcrBrowser.java deleted file mode 100644 index 133a65fd1..000000000 --- a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/views/AbstractJcrBrowser.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.jcr.views; - -import javax.jcr.Node; - -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.viewers.ITreeContentProvider; -import org.eclipse.jface.viewers.StructuredSelection; -import org.eclipse.jface.viewers.TreeViewer; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.ui.part.ViewPart; - -public abstract class AbstractJcrBrowser extends ViewPart { - - @Override - public abstract void createPartControl(Composite parent); - - /** - * To be overridden to adapt size of form and result frames. - */ - abstract protected int[] getWeights(); - - /** - * To be overridden to provide an adapted size nodeViewer - */ - abstract protected TreeViewer createNodeViewer(Composite parent, - ITreeContentProvider nodeContentProvider); - - /** - * To be overridden to retrieve the current nodeViewer - */ - abstract protected TreeViewer getNodeViewer(); - - /* - * Enables the refresh of the tree. - */ - @Override - public void setFocus() { - getNodeViewer().getTree().setFocus(); - } - - public void refresh(Object obj) { - // getNodeViewer().update(obj, null); - getNodeViewer().refresh(obj); - // getNodeViewer().expandToLevel(obj, 1); - } - - public void nodeAdded(Node parentNode, Node newNode) { - getNodeViewer().refresh(parentNode); - getNodeViewer().expandToLevel(newNode, 0); - } - - public void nodeRemoved(Node parentNode) { - IStructuredSelection newSel = new StructuredSelection(parentNode); - getNodeViewer().setSelection(newSel, true); - // Force refresh - IStructuredSelection tmpSel = (IStructuredSelection) getNodeViewer() - .getSelection(); - getNodeViewer().refresh(tmpSel.getFirstElement()); - } -} diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/resources/org/argeo/eclipse/ui/jcr/messages.properties b/base/runtime/org.argeo.eclipse.ui.jcr/src/main/resources/org/argeo/eclipse/ui/jcr/messages.properties deleted file mode 100644 index a24aa3861..000000000 --- a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/resources/org/argeo/eclipse/ui/jcr/messages.properties +++ /dev/null @@ -1,7 +0,0 @@ -## English labels for Agreo base JCR UI application - -## Generic labels - -## Errors -errorUnvalidNtFolderNodeType= Error: folder can only be created on a Jcr Node - diff --git a/base/runtime/org.argeo.eclipse.ui.rap/.classpath b/base/runtime/org.argeo.eclipse.ui.rap/.classpath deleted file mode 100644 index 8cf7f48a0..000000000 --- a/base/runtime/org.argeo.eclipse.ui.rap/.classpath +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/base/runtime/org.argeo.eclipse.ui.rap/.project b/base/runtime/org.argeo.eclipse.ui.rap/.project deleted file mode 100644 index df496c27d..000000000 --- a/base/runtime/org.argeo.eclipse.ui.rap/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - org.argeo.eclipse.ui.rap - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - - diff --git a/base/runtime/org.argeo.eclipse.ui.rap/.settings/org.eclipse.jdt.core.prefs b/base/runtime/org.argeo.eclipse.ui.rap/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index ffba01eed..000000000 --- a/base/runtime/org.argeo.eclipse.ui.rap/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,8 +0,0 @@ -#Wed Mar 02 13:27:08 CET 2011 -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.6 diff --git a/base/runtime/org.argeo.eclipse.ui.rap/build.properties b/base/runtime/org.argeo.eclipse.ui.rap/build.properties deleted file mode 100644 index 7cc98e7f8..000000000 --- a/base/runtime/org.argeo.eclipse.ui.rap/build.properties +++ /dev/null @@ -1,4 +0,0 @@ -source.. = src/main/java/ -output.. = target/classes/ -bin.includes = META-INF/,\ - .,\ \ No newline at end of file diff --git a/base/runtime/org.argeo.eclipse.ui.rap/pom.xml b/base/runtime/org.argeo.eclipse.ui.rap/pom.xml deleted file mode 100644 index 8a340474a..000000000 --- a/base/runtime/org.argeo.eclipse.ui.rap/pom.xml +++ /dev/null @@ -1,78 +0,0 @@ - - 4.0.0 - - org.argeo.commons.base - 2.1.12-SNAPSHOT - runtime - .. - - org.argeo.eclipse.ui.rap - Commons Eclipse UI RAP - jar - - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-source-plugin - - - org.apache.maven.plugins - maven-jar-plugin - - - org.apache.felix - maven-bundle-plugin - - - - lazy - org.argeo.eclipse.ui.ArgeoUiPlugin - org.eclipse.rap.ui,org.eclipse.core.runtime - - - org.apache.commons.io, - org.argeo, - org.springframework.beans.factory, - org.springframework.core.io.support, - !org.eclipse.rwt.widgets, - !org.eclipse.core.runtime, - !org.eclipse.core.commands, - !org.eclipse.ui.plugin, - * - - - - - - - - - - - org.argeo.commons.base - org.argeo.util - 2.1.12-SNAPSHOT - - - - - org.argeo.commons.base - org.argeo.eclipse.dep.rap - 2.1.12-SNAPSHOT - - - - - org.argeo.tp - slf4j.org.apache.commons.logging - - - \ No newline at end of file diff --git a/base/runtime/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/DownloadServiceHandler.java b/base/runtime/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/DownloadServiceHandler.java deleted file mode 100644 index b28229695..000000000 --- a/base/runtime/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/DownloadServiceHandler.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.specific; - -import java.io.IOException; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.argeo.ArgeoException; -import org.eclipse.rap.rwt.service.ServiceHandler; - -@Deprecated -public class DownloadServiceHandler implements ServiceHandler { - - private FileProvider provider; - - public DownloadServiceHandler(FileProvider provider) { - this.provider = provider; - } - - public void service(HttpServletRequest request, HttpServletResponse response) - throws IOException, ServletException { - // Which file to download? - String fileName = request.getParameter("filename"); - String fileId = request.getParameter("fileid"); - - // Get the file content - byte[] download = provider.getByteArrayFileFromId(fileId); - - // Send the file in the response - response.setContentType("application/octet-stream"); - response.setContentLength(download.length); - String contentDisposition = "attachment; filename=\"" + fileName + "\""; - response.setHeader("Content-Disposition", contentDisposition); - - // Various header fields that can be set to solve some issues with some - // old browsers. - // Unused. - // String contentType = "application/force-download; name=\"" + fileName - // + "\""; - // response.setContentType(contentType); - // response.setHeader("Content-Transfer-Encoding", "binary"); - // response.setHeader("Pragma", "no-cache"); - // response.setHeader("Cache-Control", "no-cache, must-revalidate"); - // response.setHeader("Expires", "0"); - // response.setHeader("Connection", "Keep-Alive"); - // response.setHeader("Keep-Alive", "timeout=5, max=86"); - // response.setHeader("transfer-Encoding", "chunked"); - - try { - response.getOutputStream().write(download); - } catch (IOException ioe) { - throw new ArgeoException("Error while writing the file " + fileName - + " to the servlet response", ioe); - } - } -} diff --git a/base/runtime/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/EclipseUiSpecificUtils.java b/base/runtime/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/EclipseUiSpecificUtils.java deleted file mode 100644 index c7ab28aaf..000000000 --- a/base/runtime/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/EclipseUiSpecificUtils.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.specific; - -import org.eclipse.jface.viewers.AbstractTableViewer; -import org.eclipse.jface.viewers.ColumnViewerToolTipSupport; -import org.eclipse.jface.viewers.Viewer; - -/** Static utilities to bridge differences between RCP and RAP */ -public class EclipseUiSpecificUtils { - /** - * TootlTip support is supported only for {@link AbstractTableViewer} in RAP - * - * @see ColumnViewerToolTipSupport#enableFor(AbstractTableViewer) - */ - public static void enableToolTipSupport(Viewer viewer) { - if (viewer instanceof AbstractTableViewer) - ColumnViewerToolTipSupport.enableFor((AbstractTableViewer) viewer); - } - - private EclipseUiSpecificUtils() { - } - -} diff --git a/base/runtime/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/FileHandler.java b/base/runtime/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/FileHandler.java deleted file mode 100644 index 927747e62..000000000 --- a/base/runtime/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/FileHandler.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.specific; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.ArgeoException; -import org.eclipse.rap.rwt.RWT; -import org.eclipse.rap.rwt.client.service.UrlLauncher; -import org.eclipse.rap.rwt.service.ServiceHandler; - -/** - * RAP SPECIFIC handler to enable the opening of a download dialog box triggered - * by whatever action in the UI - * - * Manages the registration of the effective DownloadServiceHandler at - * instantiation time. - * - * Manages the process of forwarding the request to the handler at runtime to - * open the dialog box encodedURL - */ -@Deprecated -public class FileHandler { - public final static String DOWNLOAD_SERVICE_NAME = "argeo.rap.download.service"; - private final static Log log = LogFactory.getLog(FileHandler.class); - - public FileHandler(FileProvider provider) { - ServiceHandler handler = new DownloadServiceHandler(provider); - try { - RWT.getServiceManager().registerServiceHandler( - DOWNLOAD_SERVICE_NAME, handler); - } catch (IllegalArgumentException iae) { - log.warn("Handler is already registered, clean this registering process"); - } - } - - public void openFile(String fileName, String fileId) { - try { - String downloadUrl = RWT.getServiceManager().getServiceHandlerUrl( - DOWNLOAD_SERVICE_NAME) - + createParamUrl(fileName, fileId); - if (log.isTraceEnabled()) - log.debug("URL : " + downloadUrl); - UrlLauncher launcher = RWT.getClient() - .getService(UrlLauncher.class); - launcher.openURL(downloadUrl); - } catch (Exception e) { - throw new ArgeoException("Unable to open file " + fileName, e); - } - // These lines are useless in the current use case but might be - // necessary with new browsers. Stored here for memo - // response.setContentType("application/force-download"); - // response.setHeader("Content-Disposition", contentDisposition); - // response.setHeader("Content-Transfer-Encoding", "binary"); - // response.setHeader("Pragma", "no-cache"); - // response.setHeader("Cache-Control", "no-cache, must-revalidate"); - } - - private String createParamUrl(String filename, String fileId) { - StringBuilder url = new StringBuilder(); - url.append("&filename="); - url.append(filename); - url.append("&fileid="); - url.append(fileId); - return url.toString(); - } -} \ No newline at end of file diff --git a/base/runtime/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/FileProvider.java b/base/runtime/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/FileProvider.java deleted file mode 100644 index ae959fb6d..000000000 --- a/base/runtime/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/FileProvider.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.specific; - -import java.io.InputStream; - -/** - * Used for file download : subclasses must implement model specific methods to - * get a byte array representing a file given is ID. - */ -@Deprecated -public interface FileProvider { - - public byte[] getByteArrayFileFromId(String fileId); - - public InputStream getInputStreamFromFileId(String fileId); - -} diff --git a/base/runtime/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/GenericUploadControl.java b/base/runtime/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/GenericUploadControl.java deleted file mode 100644 index e3b319862..000000000 --- a/base/runtime/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/GenericUploadControl.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.specific; - -import java.io.InputStream; - -import org.apache.commons.io.IOUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.ArgeoException; -//import org.eclipse.rap.rwt.widgets.Upload; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; - -public class GenericUploadControl extends Composite { - private final static Log log = LogFactory - .getLog(GenericUploadControl.class); - - //private Upload upload; - - public GenericUploadControl(Composite parent, int style, String browseLabel) { - super(parent, style); - createControl(this, browseLabel); - - } - - private void createControl(Composite parent, String browseLabel) { - parent.setLayout(new GridLayout(1, false)); - parent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); - -// upload = new Upload(parent, SWT.BORDER); -// upload.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); -// upload.setBrowseButtonText(browseLabel); - // upload.addModifyListener(new UploadListener()); - parent.pack(); - } - - /** - * Wrap upload.getLastFileUploaded(). Gets the name of the last uploaded - * file. This method can be called even if the upload has not finished yet. - */ - public String getLastFileUploadedName() { - return ""; - } - - public boolean isControlEmpty() { - String path = ""; - if (log.isTraceEnabled()) - log.trace("UploadControl chosen path : " + path); - if (path == null || "".equals(path.trim())) - return true; - else - return false; - } - - public byte[] performUpload() { -// boolean success = upload.performUpload(); -// if (success) { -// if (upload.getUploadItem().getFileSize() == -1) -// throw new ArgeoException("File " -// + upload.getUploadItem().getFileName() -// + " has not been uploaded, its size is -1"); -// -// InputStream inStream = null; -// byte[] fileBA = null; -// try { -// inStream = upload.getUploadItem().getFileInputStream(); -// fileBA = IOUtils.toByteArray(inStream); -// } catch (Exception e) { -// throw new ArgeoException("Cannot read uploaded data", e); -// } finally { -// IOUtils.closeQuietly(inStream); -// } -// return fileBA; -// } - return null; - } - - public void addModifyListener(ModifyListener listener) { -// upload.addModifyListener(listener); - } - - // private class UploadManager extends UploadAdapter { - // private Upload upload; - // - // public UploadManager(Upload upload) { - // super(); - // this.upload = upload; - // } - // - // public void uploadFinished(UploadEvent uploadEvent) { - // handleUploadFinished(upload); - // } - // - // public void uploadInProgress(UploadEvent uploadEvent) { - // } - // - // public void uploadException(UploadEvent uploadEvent) { - // Exception exc = uploadEvent.getUploadException(); - // if (exc != null) { - // MessageDialog.openError(Display.getCurrent().getActiveShell(), - // "Error", exc.getMessage()); - // } - // } - // - // } - // - -} diff --git a/base/runtime/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/ImportToServerWizardPage.java b/base/runtime/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/ImportToServerWizardPage.java deleted file mode 100644 index f66a279c6..000000000 --- a/base/runtime/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/ImportToServerWizardPage.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.specific; - -import java.io.InputStream; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.ArgeoException; -import org.eclipse.jface.wizard.WizardPage; -//import org.eclipse.rap.rwt.widgets.Upload; -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Label; - -public class ImportToServerWizardPage extends WizardPage { - private final static Log log = LogFactory - .getLog(ImportToServerWizardPage.class); - - public final static String FILE_ITEM_TYPE = "FILE"; - public final static String FOLDER_ITEM_TYPE = "FOLDER"; - - //private Upload uploadFile; - - public ImportToServerWizardPage() { - super("Import from file system"); - setDescription("Import files from the local file system to the server"); - } - - public void createControl(Composite parent) { - Composite composite = new Composite(parent, SWT.NONE); - composite.setLayout(new GridLayout(2, false)); - composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); - new Label(composite, SWT.NONE).setText("Pick up a file"); -// uploadFile = new Upload(composite, SWT.BORDER); -// uploadFile.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); -// uploadFile.setBrowseButtonText("Open..."); - setControl(composite); - } - - public String getObjectPath() { - // NOTE Returns the full file name of the last uploaded file including - // the file path as selected by the user on his local machine. - // The full path including the directory and file drive are only - // returned, if the browser supports reading this properties. In Firefox - // 3, only the filename is returned. - return null; - } - - public String getObjectName() { - return null; - } - - public String getObjectType() { - return FILE_ITEM_TYPE; - } - - public void performFinish() { -// boolean success = uploadFile.performUpload(); -// if (!success) -// throw new ArgeoException("Cannot upload file named " -// + uploadFile.getPath()); - } - -// protected void handleUploadFinished(final Upload upload) { -// } - - public InputStream getFileInputStream() { - return null; - } - - public boolean getNeedsProgressMonitor() { - return false; - } - -} diff --git a/base/runtime/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/OpenFile.java b/base/runtime/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/OpenFile.java deleted file mode 100644 index b55521b12..000000000 --- a/base/runtime/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/OpenFile.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.specific; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.eclipse.core.commands.AbstractHandler; -import org.eclipse.core.commands.ExecutionEvent; -import org.eclipse.core.commands.ExecutionException; -import org.eclipse.rap.rwt.RWT; -import org.eclipse.rap.rwt.client.service.UrlLauncher; - -/** - * Rap specific command handler to open a file retrieved from the server. It - * forwards the request to the correct service after encoding file name and path - * in the request URI. - * - * The parameter "URI" is used to determine the correct file service, the path - * and the file name. An optional file name can be precised to present a - * different file name as the one used to retrieve it to the end user/ - * - * Various instances of this handler with different command ID might coexist in - * order to provide context specific download service. - * - * The instance specific service is called by its ID and must have been - * externally created - */ -public class OpenFile extends AbstractHandler { - private final static Log log = LogFactory.getLog(OpenFile.class); - - /* DEPENDENCY INJECTION */ - private String openFileServiceId; - - public final static String PARAM_FILE_NAME = OpenFileService.PARAM_FILE_NAME; - public final static String PARAM_FILE_URI = OpenFileService.PARAM_FILE_URI; // "param.fileURI"; - - public Object execute(ExecutionEvent event) throws ExecutionException { - String fileName = event.getParameter(PARAM_FILE_NAME); - String fileUri = event.getParameter(PARAM_FILE_URI); - - // sanity check - if (fileUri == null || "".equals(fileUri.trim()) - || openFileServiceId == null - || "".equals(openFileServiceId.trim())) - return null; - - StringBuilder url = new StringBuilder(); - url.append(RWT.getServiceManager().getServiceHandlerUrl( - openFileServiceId)); - - url.append("&").append(PARAM_FILE_NAME).append("="); - url.append(fileName); - url.append("&").append(PARAM_FILE_URI).append("="); - url.append(fileUri); - - String downloadUrl = url.toString(); - if (log.isTraceEnabled()) - log.debug("URL : " + downloadUrl); - - UrlLauncher launcher = RWT.getClient().getService(UrlLauncher.class); - launcher.openURL(downloadUrl); - - // These lines are useless in the current use case but might be - // necessary with new browsers. Stored here for memo - // response.setContentType("application/force-download"); - // response.setHeader("Content-Disposition", contentDisposition); - // response.setHeader("Content-Transfer-Encoding", "binary"); - // response.setHeader("Pragma", "no-cache"); - // response.setHeader("Cache-Control", "no-cache, must-revalidate"); - return null; - } - - /* DEPENDENCY INJECTION */ - public void setOpenFileServiceId(String openFileServiceId) { - this.openFileServiceId = openFileServiceId; - } -} \ No newline at end of file diff --git a/base/runtime/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/OpenFileService.java b/base/runtime/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/OpenFileService.java deleted file mode 100644 index e48babf0b..000000000 --- a/base/runtime/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/OpenFileService.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.specific; - -import java.io.File; -import java.io.IOException; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.io.FileUtils; -import org.argeo.ArgeoException; -import org.eclipse.rap.rwt.service.ServiceHandler; - -/** - * Basic Default service handler that retrieves a file on the server file system - * using its absolute path and forwards it to the end user browser. Rap - * specific. - * - * Clients might extend to provide context specific services (to open files from - * a JCR repository for instance) - */ -public class OpenFileService implements ServiceHandler { - public final static String PARAM_FILE_NAME = "param.fileName"; - public final static String PARAM_FILE_URI = "param.fileURI"; - - public final static String SCHEME_HOST_SEPARATOR = "://"; - public final static String FILE_SCHEME = "file"; - - public OpenFileService() { - } - - public void service(HttpServletRequest request, HttpServletResponse response) - throws IOException, ServletException { - String fileName = request.getParameter(PARAM_FILE_NAME); - String uri = request.getParameter(PARAM_FILE_URI); - - // Set the Metadata - response.setContentType("application/octet-stream"); - response.setContentLength((int) getFileLength(uri)); - if (fileName == null || "".equals(fileName.trim())) - fileName = getFileName(uri); - String contentDisposition = "attachment; filename=\"" + fileName + "\""; - response.setHeader("Content-Disposition", contentDisposition); - - response.getOutputStream().write(getFileAsByteArray(uri)); - // FileUtils.readFileToByteArray(new File(path)) - } - - protected byte[] getFileAsByteArray(String uri) { - if (uri.startsWith(FILE_SCHEME)) { - try { - return FileUtils.readFileToByteArray(new File( - getFilePathFromUri(uri))); - } catch (IOException ioe) { - throw new ArgeoException("Error while getting the file at " - + uri, ioe); - } - } - return null; - } - - protected long getFileLength(String uri) { - if (uri.startsWith(FILE_SCHEME)) { - return new File(getFilePathFromUri(uri)).length(); - } - return -1l; - } - - protected String getFileName(String uri) { - if (uri.startsWith(FILE_SCHEME)) { - return new File(getFilePathFromUri(uri)).getName(); - } - return null; - } - - private String getFilePathFromUri(String uri) { - return uri.substring((FILE_SCHEME + SCHEME_HOST_SEPARATOR).length()); - } - -} \ No newline at end of file diff --git a/base/runtime/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/ThreadNLS.java b/base/runtime/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/ThreadNLS.java deleted file mode 100644 index 8b8837f2e..000000000 --- a/base/runtime/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/ThreadNLS.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.specific; - -import org.eclipse.osgi.util.NLS; -import org.eclipse.rap.rwt.RWT; - -/** NLS attached to a given thread */ -public class ThreadNLS extends InheritableThreadLocal { - public final static String DEFAULT_BUNDLE_LOCATION = "/properties/plugin"; - - private final String bundleLocation; - - private Class type; - private Boolean utf8 = false; - - public ThreadNLS(String bundleLocation, Class type, Boolean utf8) { - this.bundleLocation = bundleLocation; - this.type = type; - this.utf8 = utf8; - } - - public ThreadNLS(Class type) { - this(DEFAULT_BUNDLE_LOCATION, type, false); - } - - @SuppressWarnings("unchecked") - @Override - protected T initialValue() { - if (utf8) - return (T) RWT.NLS.getUTF8Encoded(bundleLocation, type); - else - return (T) RWT.NLS.getISO8859_1Encoded(bundleLocation, type); - } -} diff --git a/base/runtime/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/UploadFileWizardPage.java b/base/runtime/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/UploadFileWizardPage.java deleted file mode 100644 index 17d4e22f3..000000000 --- a/base/runtime/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/UploadFileWizardPage.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.specific; - -import java.io.InputStream; - -import org.eclipse.jface.wizard.WizardPage; -import org.eclipse.rap.rwt.widgets.FileUpload; -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Label; - -public class UploadFileWizardPage extends WizardPage { - // private final static Log log = LogFactory - // .getLog(UploadFileWizardPage.class); - private static final long serialVersionUID = 8251354244542973179L; - public final static String FILE_ITEM_TYPE = "FILE"; - public final static String FOLDER_ITEM_TYPE = "FOLDER"; - - private FileUpload fileUpload; - - public UploadFileWizardPage() { - super("Import from file system"); - setDescription("Import files from the local file system to the server"); - } - - public void createControl(Composite parent) { - Composite composite = new Composite(parent, SWT.NONE); - composite.setLayout(new GridLayout(2, false)); - composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); - new Label(composite, SWT.NONE).setText("Pick up a file"); - fileUpload = new FileUpload(composite, SWT.BORDER); - fileUpload.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); - fileUpload.setText("Browse"); - setControl(composite); - } - - public String getObjectPath() { - // NOTE Returns the full file name of the last uploaded file including - // the file path as selected by the user on his local machine. - // The full path including the directory and file drive are only - // returned, if the browser supports reading this properties. In Firefox - // 3, only the filename is returned. - return null; - } - - public String getObjectName() { - return fileUpload.getFileName(); - } - - public String getObjectType() { - return FILE_ITEM_TYPE; - } - - public void performFinish() { - // boolean success = uploadFile.performUpload(); - // if (!success) - // throw new ArgeoException("Cannot upload file named " - // + uploadFile.getPath()); - } - - // protected void handleUploadFinished(final Upload upload) { - // } - - public InputStream getFileInputStream() { - return null; - } - - public boolean getNeedsProgressMonitor() { - return false; - } - -} diff --git a/base/runtime/org.argeo.eclipse.ui.rcp/.classpath b/base/runtime/org.argeo.eclipse.ui.rcp/.classpath deleted file mode 100644 index 8cf7f48a0..000000000 --- a/base/runtime/org.argeo.eclipse.ui.rcp/.classpath +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/base/runtime/org.argeo.eclipse.ui.rcp/.project b/base/runtime/org.argeo.eclipse.ui.rcp/.project deleted file mode 100644 index ef2dc2dbb..000000000 --- a/base/runtime/org.argeo.eclipse.ui.rcp/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - org.argeo.eclipse.ui.rcp - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - - diff --git a/base/runtime/org.argeo.eclipse.ui.rcp/.settings/org.eclipse.jdt.core.prefs b/base/runtime/org.argeo.eclipse.ui.rcp/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index b06d92e45..000000000 --- a/base/runtime/org.argeo.eclipse.ui.rcp/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,8 +0,0 @@ -#Tue Mar 01 19:20:51 CET 2011 -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.6 diff --git a/base/runtime/org.argeo.eclipse.ui.rcp/build.properties b/base/runtime/org.argeo.eclipse.ui.rcp/build.properties deleted file mode 100644 index 886a20027..000000000 --- a/base/runtime/org.argeo.eclipse.ui.rcp/build.properties +++ /dev/null @@ -1,4 +0,0 @@ -source.. = src/main/java/ -output.. = target/classes/ -bin.includes = META-INF/,\ - .,\ diff --git a/base/runtime/org.argeo.eclipse.ui.rcp/pom.xml b/base/runtime/org.argeo.eclipse.ui.rcp/pom.xml deleted file mode 100644 index 94da11781..000000000 --- a/base/runtime/org.argeo.eclipse.ui.rcp/pom.xml +++ /dev/null @@ -1,84 +0,0 @@ - - 4.0.0 - - org.argeo.commons.base - 2.1.12-SNAPSHOT - runtime - .. - - org.argeo.eclipse.ui.rcp - Commons Eclipse UI RCP - jar - - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-source-plugin - - - org.apache.maven.plugins - maven-jar-plugin - - - org.apache.felix - maven-bundle-plugin - - - - lazy - org.argeo.eclipse.ui.ArgeoUiPlugin - org.eclipse.ui,org.eclipse.core.runtime - - org.springframework.beans.factory, - org.springframework.core.io.support, - org.apache.commons.io, - org.argeo, - !org.eclipse.core.runtime, - !org.eclipse.core.commands, - !org.eclipse.ui.plugin, - * - - - - - - - - - - org.argeo.commons.base - org.argeo.eclipse.ui - 2.1.12-SNAPSHOT - - - - - org.argeo.commons.base - org.argeo.eclipse.dep.rcp - 2.1.12-SNAPSHOT - - - - - org.argeo.commons.base - org.argeo.util - 2.1.12-SNAPSHOT - - - - - org.argeo.tp - org.apache.commons.io - - - - - org.argeo.tp - slf4j.org.apache.commons.logging - - - \ No newline at end of file diff --git a/base/runtime/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/DefaultNLS.java b/base/runtime/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/DefaultNLS.java deleted file mode 100644 index 71a0c898d..000000000 --- a/base/runtime/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/DefaultNLS.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.specific; - -import org.eclipse.osgi.util.NLS; - -/** RCP specific {@link NLS} to be extended */ -public class DefaultNLS extends NLS { - public final static String DEFAULT_BUNDLE_LOCATION = "/properties/plugin"; - - public DefaultNLS() { - this(DEFAULT_BUNDLE_LOCATION); - } - - public DefaultNLS(String bundleName) { - NLS.initializeMessages(bundleName, getClass()); - } -} diff --git a/base/runtime/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/EclipseUiSpecificUtils.java b/base/runtime/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/EclipseUiSpecificUtils.java deleted file mode 100644 index 2642a35a1..000000000 --- a/base/runtime/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/EclipseUiSpecificUtils.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.specific; - -import org.eclipse.jface.viewers.ColumnViewer; -import org.eclipse.jface.viewers.ColumnViewerToolTipSupport; -import org.eclipse.jface.viewers.Viewer; - -/** Static utilities to bridge differences between RCP and RAP */ -public class EclipseUiSpecificUtils { - /** - * TootlTip support is supported for {@link ColumnViewer} in RCP - * - * @see ColumnViewerToolTipSupport#enableFor(Viewer) - */ - public static void enableToolTipSupport(Viewer viewer) { - if (viewer instanceof ColumnViewer) - ColumnViewerToolTipSupport.enableFor((ColumnViewer) viewer); - } - - private EclipseUiSpecificUtils() { - } - -} diff --git a/base/runtime/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/FileHandler.java b/base/runtime/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/FileHandler.java deleted file mode 100644 index 5da49736d..000000000 --- a/base/runtime/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/FileHandler.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.specific; - -import java.awt.Desktop; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -import org.apache.commons.io.IOUtils; -import org.argeo.ArgeoException; - -/** - * Abstraction that enable to implement runtime environment specific (typically - * RCP or RAP) methods while dealing with files in the UI. - * - */ -public class FileHandler { - - private FileProvider provider; - - public FileHandler(FileProvider provider) { - this.provider = provider; - } - - public void openFile(String fileName, String fileId) { - String tmpFileName = fileName; - String prefix = "", extension = ""; - if (fileName != null) { - int ind = fileName.lastIndexOf('.'); - if (ind > 0) { - prefix = fileName.substring(0, ind); - extension = fileName.substring(ind); - } - } - - InputStream is = null; - try { - is = provider.getInputStreamFromFileId(fileId); - File file = createTmpFile(prefix, extension, is); - tmpFileName = file.getName(); - Desktop desktop = null; - if (Desktop.isDesktopSupported()) { - desktop = Desktop.getDesktop(); - } - desktop.open(file); - } catch (IOException e) { - // Note : tmpFileName = fileName if the error has been thrown while - // creating the tmpFile. - throw new ArgeoException("Cannot open file " + tmpFileName, e); - } finally { - IOUtils.closeQuietly(is); - } - } - - private File createTmpFile(String prefix, String suffix, InputStream is) { - File tmpFile = null; - OutputStream os = null; - try { - tmpFile = File.createTempFile(prefix, suffix); - os = new FileOutputStream(tmpFile); - IOUtils.copy(is, os); - } catch (IOException e) { - throw new ArgeoException("Cannot open file " + prefix + "." - + suffix, e); - } finally { - IOUtils.closeQuietly(os); - } - return tmpFile; - } -} diff --git a/base/runtime/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/FileProvider.java b/base/runtime/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/FileProvider.java deleted file mode 100644 index 5c92260d7..000000000 --- a/base/runtime/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/FileProvider.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.specific; - -import java.io.InputStream; - -/** - * Used for file download : subclasses must implement model specific methods to - * get a byte array representing a file given is ID. - * - * @author bsinou - * - */ -public interface FileProvider { - - public byte[] getByteArrayFileFromId(String fileId); - - public InputStream getInputStreamFromFileId(String fileId); - -} diff --git a/base/runtime/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/GenericUploadControl.java b/base/runtime/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/GenericUploadControl.java deleted file mode 100644 index 80e1e539c..000000000 --- a/base/runtime/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/GenericUploadControl.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.specific; - -import java.io.File; -import java.io.IOException; - -import org.apache.commons.io.FileUtils; -import org.argeo.ArgeoException; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.FileDialog; -import org.eclipse.swt.widgets.Listener; -import org.eclipse.swt.widgets.Text; - -/** - * RCP specific composite that provides a control to upload a file. WARNING: for - * the time being we set a GridLayout(2, false) on th eparent control. - */ -public class GenericUploadControl extends Composite { - // private final static Log log = LogFactory - // .getLog(GenericUploadControl.class); - - private FileDialog dialog; - private Text filePath; - - public GenericUploadControl(Composite parent, int style, String browseLabel) { - super(parent, style); - createControl(this, browseLabel); - - } - - private void createControl(final Composite parent, String browseLabel) { - parent.setLayout(new GridLayout(2, false)); - - filePath = new Text(parent, SWT.BORDER | SWT.SINGLE); - GridData gd = new GridData(GridData.GRAB_HORIZONTAL - | GridData.FILL_HORIZONTAL); - filePath.setEditable(false); - filePath.setLayoutData(gd); - - // Execute button - Button execute = new Button(parent, SWT.PUSH); - GridData gridData = new GridData(); - gridData.horizontalAlignment = GridData.BEGINNING; - execute.setLayoutData(gridData); - execute.setText(browseLabel); - - // Button listener - Listener executeListener = new Listener() { - public void handleEvent(Event event) { - dialog = new FileDialog(parent.getShell()); - filePath.setText(dialog.open()); - } - }; - parent.layout(); - execute.addListener(SWT.Selection, executeListener); - } - - public boolean isControlEmpty() { - String path = filePath.getText(); - if (path == null || "".equals(path.trim())) - return true; - else - return false; - } - - public byte[] performUpload() { - String path = filePath.getText(); - if (path != null) { - try { - File file = new File(path); - byte[] fileBA = FileUtils.readFileToByteArray(file); - return fileBA; - } catch (IOException e) { - throw new ArgeoException("Unexpected error while " - + "reading file at path " + path, e); - } - } - return null; - } - - public void addModifyListener(ModifyListener listener) { - filePath.addModifyListener(listener); - } - - /** - * Always returns null in an RCP environment - */ - public String getLastFileUploadedName() { - return null; - } -} diff --git a/base/runtime/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/ImportToServerWizardPage.java b/base/runtime/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/ImportToServerWizardPage.java deleted file mode 100644 index 55065bfa0..000000000 --- a/base/runtime/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/ImportToServerWizardPage.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.specific; - -import java.io.InputStream; - -import org.eclipse.jface.preference.DirectoryFieldEditor; -import org.eclipse.jface.wizard.WizardPage; -import org.eclipse.swt.widgets.Composite; - -public class ImportToServerWizardPage extends WizardPage { - - public final static String FILE_ITEM_TYPE = "FILE"; - public final static String FOLDER_ITEM_TYPE = "FOLDER"; - - private DirectoryFieldEditor dfe; - - public ImportToServerWizardPage() { - super("Import from file system"); - setDescription("Import files from the local file system into the JCR repository"); - } - - public void createControl(Composite parent) { - dfe = new DirectoryFieldEditor("directory", "From", parent); - setControl(dfe.getTextControl(parent)); - } - - public String getObjectPath() { - return dfe.getStringValue(); - } - - public String getObjectType() { - return FOLDER_ITEM_TYPE; - } - - public boolean getNeedsProgressMonitor() { - return true; - } - - // Dummy methods : useless in RCP context but useful for RAP - /** WARNING : always return null in RCP context */ - public String getObjectName() { - return null; - } - - /** WARNING : do nothing in RCP context */ - public void performFinish() { - } - - /** WARNING : always return null in RCP context */ - public InputStream getFileInputStream() { - return null; - } -} \ No newline at end of file diff --git a/base/runtime/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/OpenFile.java b/base/runtime/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/OpenFile.java deleted file mode 100644 index 610020dd1..000000000 --- a/base/runtime/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/OpenFile.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.specific; - -import java.awt.Desktop; -import java.io.File; -import java.io.IOException; - -import org.argeo.ArgeoException; -import org.eclipse.core.commands.AbstractHandler; -import org.eclipse.core.commands.ExecutionEvent; -import org.eclipse.core.commands.ExecutionException; - -/** - * RCP specific command handler to open a file. - * - * The parameter "URI" is used to determine the correct method to open it. - * - * Various instances of this handler with different command ID might coexist in - * order to provide context specific open file service. - * - */ -public class OpenFile extends AbstractHandler { - // private final static Log log = LogFactory.getLog(OpenFile.class); - - public final static String PARAM_FILE_NAME = "param.fileName"; - public final static String PARAM_FILE_URI = "param.fileURI"; - - private final static String FILE_SCHEME = "file"; - - public Object execute(ExecutionEvent event) throws ExecutionException { - @SuppressWarnings("unused") - @Deprecated - String fileName = event.getParameter(PARAM_FILE_NAME); - String fileUri = event.getParameter(PARAM_FILE_URI); - - // sanity check - if (fileUri == null || "".equals(fileUri.trim())) - return null; - - Desktop desktop = null; - if (Desktop.isDesktopSupported()) { - desktop = Desktop.getDesktop(); - } - - File file = getFileFromUri(fileUri); - if (file != null) - try { - desktop.open(file); - } catch (IOException e) { - throw new ArgeoException("Unable to open file with URI: " - + fileUri, e); - } - - return null; - } - - protected File getFileFromUri(String uri) { - if (uri.startsWith(FILE_SCHEME)) { - String path = uri.substring((FILE_SCHEME + "://").length()); - return new File(path); - } - return null; - } -} \ No newline at end of file diff --git a/base/runtime/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/ThreadNLS.java b/base/runtime/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/ThreadNLS.java deleted file mode 100644 index c87f6e54f..000000000 --- a/base/runtime/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/ThreadNLS.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.specific; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.MissingResourceException; -import java.util.ResourceBundle; - -import org.argeo.util.LocaleUtils; -import org.eclipse.osgi.util.NLS; - -/** NLS attached to a given thread */ -public class ThreadNLS extends InheritableThreadLocal { - public final static String DEFAULT_BUNDLE_LOCATION = "/properties/plugin"; - - private final String bundleLocation; - - private Class type; - private Boolean utf8 = false; - - public ThreadNLS(String bundleLocation, Class type, Boolean utf8) { - this.bundleLocation = bundleLocation; - this.type = type; - this.utf8 = utf8; - } - - public ThreadNLS(Class type) { - this(DEFAULT_BUNDLE_LOCATION, type, false); - } - - @Override - protected T initialValue() { - ResourceBundle bundle = ResourceBundle.getBundle(bundleLocation, - LocaleUtils.threadLocale.get(), type.getClassLoader()); - T result; - try { - NLS.initializeMessages(bundleLocation, type); - Constructor constructor = type.getConstructor(); - constructor.setAccessible(true); - result = constructor.newInstance(); - final Field[] fieldArray = type.getDeclaredFields(); - for (int i = 0; i < fieldArray.length; i++) { - int modifiers = fieldArray[i].getModifiers(); - if (String.class.isAssignableFrom(fieldArray[i].getType()) - && Modifier.isPublic(modifiers) - && !Modifier.isStatic(modifiers)) { - try { - String value = bundle - .getString(fieldArray[i].getName()); - byte[] bytes = value.getBytes(); - - String forcedValue; - if (utf8) - forcedValue = new String(bytes, "UTF8"); - else - forcedValue = value; - if (value != null) { - fieldArray[i].setAccessible(true); - fieldArray[i].set(result, forcedValue); - } - } catch (final MissingResourceException mre) { - fieldArray[i].setAccessible(true); - fieldArray[i].set(result, ""); - mre.printStackTrace(); - } - } - } - return result; - } catch (final Exception ex) { - throw new IllegalStateException(ex.getMessage()); - } - } - -} diff --git a/base/runtime/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/UploadFileWizardPage.java b/base/runtime/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/UploadFileWizardPage.java deleted file mode 100644 index 5bdaeceb5..000000000 --- a/base/runtime/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/UploadFileWizardPage.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.specific; - -import java.io.InputStream; - -import org.eclipse.jface.preference.DirectoryFieldEditor; -import org.eclipse.jface.wizard.WizardPage; -import org.eclipse.swt.widgets.Composite; - -public class UploadFileWizardPage extends WizardPage { - - public final static String FILE_ITEM_TYPE = "FILE"; - public final static String FOLDER_ITEM_TYPE = "FOLDER"; - - private DirectoryFieldEditor dfe; - - public UploadFileWizardPage() { - super("Import from file system"); - setDescription("Import files from the local file system into the JCR repository"); - } - - public void createControl(Composite parent) { - dfe = new DirectoryFieldEditor("directory", "From", parent); - setControl(dfe.getTextControl(parent)); - } - - public String getObjectPath() { - return dfe.getStringValue(); - } - - public String getObjectType() { - return FOLDER_ITEM_TYPE; - } - - public boolean getNeedsProgressMonitor() { - return true; - } - - // Dummy methods : useless in RCP context but useful for RAP - /** WARNING : always return null in RCP context */ - public String getObjectName() { - return null; - } - - /** WARNING : do nothing in RCP context */ - public void performFinish() { - } - - /** WARNING : always return null in RCP context */ - public InputStream getFileInputStream() { - return null; - } -} \ No newline at end of file diff --git a/base/runtime/org.argeo.eclipse.ui/.classpath b/base/runtime/org.argeo.eclipse.ui/.classpath deleted file mode 100644 index a50743442..000000000 --- a/base/runtime/org.argeo.eclipse.ui/.classpath +++ /dev/null @@ -1,7 +0,0 @@ - - - - > - - - diff --git a/base/runtime/org.argeo.eclipse.ui/.project b/base/runtime/org.argeo.eclipse.ui/.project deleted file mode 100644 index 53e9b324c..000000000 --- a/base/runtime/org.argeo.eclipse.ui/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - org.argeo.eclipse.ui - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - - diff --git a/base/runtime/org.argeo.eclipse.ui/.settings/org.eclipse.jdt.core.prefs b/base/runtime/org.argeo.eclipse.ui/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index f441c9045..000000000 --- a/base/runtime/org.argeo.eclipse.ui/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,8 +0,0 @@ -#Thu Jul 29 10:54:11 CEST 2010 -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 -org.eclipse.jdt.core.compiler.compliance=1.5 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.5 diff --git a/base/runtime/org.argeo.eclipse.ui/.settings/org.eclipse.pde.core.prefs b/base/runtime/org.argeo.eclipse.ui/.settings/org.eclipse.pde.core.prefs deleted file mode 100644 index 8e36e3304..000000000 --- a/base/runtime/org.argeo.eclipse.ui/.settings/org.eclipse.pde.core.prefs +++ /dev/null @@ -1,3 +0,0 @@ -#Thu Jul 29 11:00:39 CEST 2010 -eclipse.preferences.version=1 -resolve.requirebundle=false diff --git a/base/runtime/org.argeo.eclipse.ui/build.properties b/base/runtime/org.argeo.eclipse.ui/build.properties deleted file mode 100644 index 5fc538bc8..000000000 --- a/base/runtime/org.argeo.eclipse.ui/build.properties +++ /dev/null @@ -1,4 +0,0 @@ -source.. = src/main/java/ -output.. = target/classes/ -bin.includes = META-INF/,\ - . diff --git a/base/runtime/org.argeo.eclipse.ui/pom.xml b/base/runtime/org.argeo.eclipse.ui/pom.xml deleted file mode 100644 index 53c87d6a8..000000000 --- a/base/runtime/org.argeo.eclipse.ui/pom.xml +++ /dev/null @@ -1,88 +0,0 @@ - - 4.0.0 - - org.argeo.commons.base - 2.1.12-SNAPSHOT - runtime - .. - - org.argeo.eclipse.ui - Commons Eclipse UI - jar - - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-source-plugin - - - org.apache.maven.plugins - maven-jar-plugin - - - org.apache.felix - maven-bundle-plugin - - - - ${project.artifactId};singleton:=true - lazy - org.argeo.eclipse.ui.ArgeoUiPlugin - org.eclipse.ui;resolution:=optional,org.eclipse.rap.ui;resolution:=optional,org.eclipse.core.runtime - - org.springframework.beans.factory, - org.springframework.core.io.support, - !org.eclipse.core.runtime, - !org.eclipse.core.commands, - !org.eclipse.ui.plugin, - * - - - - - - - - - - org.argeo.tp - javax.jcr - - - - - org.argeo.commons.base - org.argeo.eclipse.dep.rcp - 2.1.12-SNAPSHOT - provided - - - - - org.argeo.commons.base - org.argeo.util - 2.1.12-SNAPSHOT - - - - - org.argeo.tp - org.springframework.context - - - org.argeo.tp - org.springframework.osgi.extender - - - - - org.argeo.tp - slf4j.org.apache.commons.logging - - - - \ No newline at end of file diff --git a/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/spring/ApplicationContextTracker.java b/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/spring/ApplicationContextTracker.java deleted file mode 100644 index 070c70826..000000000 --- a/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/spring/ApplicationContextTracker.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.spring; - -import static java.text.MessageFormat.format; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.eclipse.core.runtime.Platform; -import org.osgi.framework.Bundle; -import org.osgi.framework.BundleContext; -import org.osgi.framework.BundleException; -import org.osgi.framework.FrameworkUtil; -import org.osgi.framework.InvalidSyntaxException; -import org.osgi.util.tracker.ServiceTracker; -import org.springframework.context.ApplicationContext; - -/** - * Tracks Spring application context published as services. - * - * @author Heiko Seeberger - * @author Mathieu Baudier - */ -class ApplicationContextTracker { - private final static Log log = LogFactory - .getLog(ApplicationContextTracker.class); - - private static final String FILTER = "(&(objectClass=org.springframework.context.ApplicationContext)" //$NON-NLS-1$ - + "(org.springframework.context.service.name={0}))"; //$NON-NLS-1$ - - public final static String APPLICATION_CONTEXT_TRACKER_TIMEOUT = "org.argeo.eclipse.spring.applicationContextTrackerTimeout"; - - private static Long defaultTimeout = Long.parseLong(System.getProperty( - APPLICATION_CONTEXT_TRACKER_TIMEOUT, "30000")); - - private ServiceTracker applicationContextServiceTracker; - - /** - * @param contributorBundle - * OSGi bundle for which the Spring application context is to be - * tracked. Must not be null! - * @param factoryBundleContext - * BundleContext object which can be used to track services - * @throws IllegalArgumentException - * if the given bundle is null. - */ - public ApplicationContextTracker(final Bundle contributorBundle, - final BundleContext factoryBundleContext) { - final String filter = format(FILTER, - contributorBundle.getSymbolicName()); - try { - applicationContextServiceTracker = new ServiceTracker( - factoryBundleContext, FrameworkUtil.createFilter(filter), - null); - // applicationContextServiceTracker.open(); - } catch (final InvalidSyntaxException e) { - e.printStackTrace(); - } - } - - public void open() { - if (applicationContextServiceTracker != null) { - applicationContextServiceTracker.open(); - } - } - - public void close() { - if (applicationContextServiceTracker != null) { - applicationContextServiceTracker.close(); - } - } - - public ApplicationContext getApplicationContext() { - ApplicationContext applicationContext = null; - if (applicationContextServiceTracker != null) { - try { - applicationContext = (ApplicationContext) applicationContextServiceTracker - .waitForService(defaultTimeout); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - return applicationContext; - } - - @Override - protected void finalize() throws Throwable { - close(); - super.finalize(); - } - - static ApplicationContext getApplicationContext(String bundleSymbolicName) { - Bundle contributorBundle = Platform.getBundle(bundleSymbolicName); - return getApplicationContext(contributorBundle); - } - - static ApplicationContext getApplicationContext( - final Bundle contributorBundle) { - if (log.isTraceEnabled()) - log.trace("Get application context for bundle " + contributorBundle); - - // Start if not yet started (also if in STARTING state, may be lazy) - if (contributorBundle.getState() != Bundle.ACTIVE) { - if (log.isTraceEnabled()) - log.trace("Starting bundle: " - + contributorBundle.getSymbolicName()); - // Thread startBundle = new Thread("Start bundle " - // + contributorBundle.getSymbolicName()) { - // public void run() { - try { - contributorBundle.start(); - } catch (BundleException e) { - log.error("Cannot start bundle " + contributorBundle, e); - } - // } - // }; - // startBundle.start(); - // try { - // startBundle.join(10 * 1000l); - // } catch (InterruptedException e) { - // // silent - // } - } - - final ApplicationContextTracker applicationContextTracker = new ApplicationContextTracker( - contributorBundle, contributorBundle.getBundleContext()); - ApplicationContext applicationContext = null; - try { - applicationContextTracker.open(); - applicationContext = applicationContextTracker - .getApplicationContext(); - } finally { - applicationContextTracker.close(); - } - return applicationContext; - } -} diff --git a/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/spring/SpringCommandHandler.java b/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/spring/SpringCommandHandler.java deleted file mode 100644 index 4c7a152df..000000000 --- a/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/spring/SpringCommandHandler.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.spring; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.ArgeoException; -import org.eclipse.core.commands.ExecutionEvent; -import org.eclipse.core.commands.ExecutionException; -import org.eclipse.core.commands.IHandler; -import org.eclipse.core.commands.IHandlerListener; -import org.springframework.context.ApplicationContext; - -/** Allows to declare Eclipse commands as Spring beans */ -public class SpringCommandHandler implements IHandler { - private final static Log log = LogFactory - .getLog(SpringCommandHandler.class); - - public void addHandlerListener(IHandlerListener handlerListener) { - } - - public void dispose() { - } - - public Object execute(ExecutionEvent event) throws ExecutionException { - String commandId = event.getCommand().getId(); - String bundleSymbolicName = commandId.substring(0, - commandId.lastIndexOf('.')); - try { - if (log.isTraceEnabled()) - log.trace("Execute " + event + " via spring command handler " - + this); - // TODO: make it more flexible and robust - ApplicationContext applicationContext = ApplicationContextTracker - .getApplicationContext(bundleSymbolicName); - if (applicationContext == null) - throw new ArgeoException("No application context found for " - + bundleSymbolicName); - - // retrieve the command via its id - String beanName = event.getCommand().getId(); - - if (!applicationContext.containsBean(beanName)) { - if (beanName.startsWith(bundleSymbolicName)) - beanName = beanName - .substring(bundleSymbolicName.length() + 1); - } - - if (!applicationContext.containsBean(beanName)) - throw new ExecutionException("No bean found with name " - + beanName + " in bundle " + bundleSymbolicName); - Object bean = applicationContext.getBean(beanName); - - if (!(bean instanceof IHandler)) - throw new ExecutionException("Bean with name " + beanName - + " and class " + bean.getClass() - + " does not implement the IHandler interface."); - - IHandler handler = (IHandler) bean; - return handler.execute(event); - } catch (Exception e) { - // TODO: use eclipse error management - // log.error(e); - throw new ExecutionException("Cannot execute Spring command " - + commandId + " in bundle " + bundleSymbolicName, e); - } - } - - public boolean isEnabled() { - return true; - } - - public boolean isHandled() { - return true; - } - - public void removeHandlerListener(IHandlerListener handlerListener) { - } - -} diff --git a/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/spring/SpringExtensionFactory.java b/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/spring/SpringExtensionFactory.java deleted file mode 100644 index 7a0486fd2..000000000 --- a/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/spring/SpringExtensionFactory.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.spring; - -import org.argeo.ArgeoException; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IConfigurationElement; -import org.eclipse.core.runtime.IExecutableExtension; -import org.eclipse.core.runtime.IExecutableExtensionFactory; -import org.eclipse.core.runtime.IExtension; -import org.springframework.context.ApplicationContext; - -/** - * The Spring Extension Factory builds a bridge between the Eclipse Extension - * Registry and the Spring Framework (especially Spring Dynamic Modules). - * - * It allows you to define your extension as a spring bean within the spring - * application context of your bundle. If you would like to use this bean as an - * instance of an extension (an Eclipse RCP view, for example) you define the - * extension with this spring extension factory as the class to be created. - * - * To let the spring extension factory pick the right bean from your application - * context you need to set the bean id to the same value as the id of the view - * within the view definition, for example. This is important if your extension - * definition contains more than one element, where each element has its own id. - * - * If the extension definition elements themselves have no id attribute the - * spring extension factory uses the id of the extension itself to identify the - * bean. - * - * original code from: Blog entry - * - * @author Martin Lippert - * @author mbaudier - */ -public class SpringExtensionFactory implements IExecutableExtensionFactory, - IExecutableExtension { - - private Object bean; - - public Object create() throws CoreException { - if (bean == null) - throw new ArgeoException("No underlying bean for extension"); - return bean; - } - - public void setInitializationData(IConfigurationElement config, - String propertyName, Object data) throws CoreException { - String bundleSymbolicName = config.getContributor().getName(); - ApplicationContext applicationContext = ApplicationContextTracker - .getApplicationContext(bundleSymbolicName); - if (applicationContext == null) - throw new ArgeoException( - "Cannot find application context for bundle " - + bundleSymbolicName); - - String beanName = getBeanName(data, config); - if (beanName == null) - throw new ArgeoException("Cannot find bean name for extension " - + config); - - if (!applicationContext.containsBean(beanName)) { - if (beanName.startsWith(bundleSymbolicName)) - beanName = beanName.substring(bundleSymbolicName.length() + 1); - } - - if (!applicationContext.containsBean(beanName)) - throw new ArgeoException("No bean with name '" + beanName + "'"); - - this.bean = applicationContext.getBean(beanName); - if (this.bean instanceof IExecutableExtension) { - ((IExecutableExtension) this.bean).setInitializationData(config, - propertyName, data); - } - } - - private String getBeanName(Object data, IConfigurationElement config) { - - // try the specific bean id the extension defines - if (data != null && data.toString().length() > 0) { - return data.toString(); - } - - // try the id of the config element - if (config.getAttribute("id") != null) { - return config.getAttribute("id"); - } - - // try the id of the extension element itself - if (config.getParent() != null - && config.getParent() instanceof IExtension) { - IExtension extensionDefinition = (IExtension) config.getParent(); - return extensionDefinition.getSimpleIdentifier(); - } - - return null; - } - -} diff --git a/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/AbstractTreeContentProvider.java b/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/AbstractTreeContentProvider.java deleted file mode 100644 index 6b86676b4..000000000 --- a/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/AbstractTreeContentProvider.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui; - -import org.eclipse.jface.viewers.ITreeContentProvider; -import org.eclipse.jface.viewers.Viewer; - -/** - * Tree content provider dealing with tree objects and providing reasonable - * defaults. - */ -public abstract class AbstractTreeContentProvider implements - ITreeContentProvider { - private static final long serialVersionUID = 8246126401957763868L; - - /** Does nothing */ - public void dispose() { - } - - /** Does nothing */ - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - } - - public Object[] getChildren(Object element) { - if (element instanceof TreeParent) { - return ((TreeParent) element).getChildren(); - } - return new Object[0]; - } - - public Object getParent(Object element) { - if (element instanceof TreeParent) { - return ((TreeParent) element).getParent(); - } - return null; - } - - public boolean hasChildren(Object element) { - if (element instanceof TreeParent) { - return ((TreeParent) element).hasChildren(); - } - return false; - } - -} diff --git a/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/ArgeoUiPlugin.java b/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/ArgeoUiPlugin.java deleted file mode 100644 index 6befdf7d4..000000000 --- a/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/ArgeoUiPlugin.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.eclipse.core.runtime.ILogListener; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Platform; -import org.eclipse.ui.plugin.AbstractUIPlugin; -import org.osgi.framework.BundleContext; - -/** - * The activator class controls the plug-in life cycle - */ -public class ArgeoUiPlugin extends AbstractUIPlugin implements ILogListener { - public static final String PLUGIN_ID = "org.argeo.eclipse.ui"; - private final static Log log = LogFactory.getLog(ArgeoUiPlugin.class); - // The shared instance - private static ArgeoUiPlugin plugin; - - public void start(BundleContext context) throws Exception { - super.start(context); - // weirdly, the start method is called twice... - if (plugin == null) { - plugin = this; - Platform.addLogListener(this); - log.debug("Eclipse logging now directed to standard logging"); - } - } - - public void stop(BundleContext context) throws Exception { - try { - // weirdly, the stop method is called twice... - if (plugin != null) { - Platform.removeLogListener(this); - log.debug("Eclipse logging not directed anymore to standard logging"); - plugin = null; - } - } finally { - super.stop(context); - } - } - - /** Returns the shared instance */ - public static ArgeoUiPlugin getDefault() { - return plugin; - } - - public void logging(IStatus status, String plugin) { - Log pluginLog = LogFactory.getLog(plugin); - Integer severity = status.getSeverity(); - if (severity == IStatus.ERROR) - pluginLog.error(status.getMessage(), status.getException()); - else if (severity == IStatus.WARNING) - pluginLog.warn(status.getMessage(), status.getException()); - else if (severity == IStatus.INFO) - pluginLog.info(status.getMessage(), status.getException()); - else if (severity == IStatus.CANCEL) - if (pluginLog.isDebugEnabled()) - pluginLog.debug(status.getMessage(), status.getException()); - - } - -} diff --git a/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/ColumnViewerComparator.java b/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/ColumnViewerComparator.java deleted file mode 100644 index 8db5d4fe8..000000000 --- a/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/ColumnViewerComparator.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui; - -import java.util.Comparator; - -import org.eclipse.jface.viewers.ColumnViewer; -import org.eclipse.jface.viewers.TableViewerColumn; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.jface.viewers.ViewerComparator; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; - -/** Generic column viewer sorter */ -public class ColumnViewerComparator extends ViewerComparator { - private static final long serialVersionUID = -2266218906355859909L; - - public static final int ASC = 1; - - public static final int NONE = 0; - - public static final int DESC = -1; - - private int direction = 0; - - private TableViewerColumn column; - - private ColumnViewer viewer; - - public ColumnViewerComparator(TableViewerColumn column, - Comparator comparator) { - super(comparator); - this.column = column; - this.viewer = column.getViewer(); - this.column.getColumn().addSelectionListener(new SelectionAdapter() { - private static final long serialVersionUID = 7586796298965472189L; - - public void widgetSelected(SelectionEvent e) { - if (ColumnViewerComparator.this.viewer.getComparator() != null) { - if (ColumnViewerComparator.this.viewer.getComparator() == ColumnViewerComparator.this) { - int tdirection = ColumnViewerComparator.this.direction; - - if (tdirection == ASC) { - setSortDirection(DESC); - } else if (tdirection == DESC) { - setSortDirection(NONE); - } - } else { - setSortDirection(ASC); - } - } else { - setSortDirection(ASC); - } - } - }); - } - - private void setSortDirection(int direction) { - if (direction == NONE) { - column.getColumn().getParent().setSortColumn(null); - column.getColumn().getParent().setSortDirection(SWT.NONE); - viewer.setComparator(null); - } else { - column.getColumn().getParent().setSortColumn(column.getColumn()); - this.direction = direction; - - if (direction == ASC) { - column.getColumn().getParent().setSortDirection(SWT.DOWN); - } else { - column.getColumn().getParent().setSortDirection(SWT.UP); - } - - if (viewer.getComparator() == this) { - viewer.refresh(); - } else { - viewer.setComparator(this); - } - - } - } - - @SuppressWarnings("unchecked") - public int compare(Viewer viewer, Object e1, Object e2) { - return direction * getComparator().compare((T) e1, (T) e2); - } -} diff --git a/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/EclipseArgeoMonitor.java b/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/EclipseArgeoMonitor.java deleted file mode 100644 index 7c0b39884..000000000 --- a/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/EclipseArgeoMonitor.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui; - -import org.argeo.ArgeoMonitor; -import org.eclipse.core.runtime.IProgressMonitor; - -/** - * Wraps an Eclipse {@link IProgressMonitor} so that it can be passed to - * framework agnostic Argeo routines. - */ -public class EclipseArgeoMonitor implements ArgeoMonitor { - private final IProgressMonitor progressMonitor; - - public EclipseArgeoMonitor(IProgressMonitor progressMonitor) { - this.progressMonitor = progressMonitor; - } - - public void beginTask(String name, int totalWork) { - progressMonitor.beginTask(name, totalWork); - } - - public void done() { - progressMonitor.done(); - } - - public boolean isCanceled() { - return progressMonitor.isCanceled(); - } - - public void setCanceled(boolean value) { - progressMonitor.setCanceled(value); - } - - public void setTaskName(String name) { - progressMonitor.setTaskName(name); - } - - public void subTask(String name) { - progressMonitor.subTask(name); - } - - public void worked(int work) { - progressMonitor.worked(work); - } -} diff --git a/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/EclipseUiUtils.java b/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/EclipseUiUtils.java deleted file mode 100644 index 8e1c7e632..000000000 --- a/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/EclipseUiUtils.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui; - -import org.eclipse.jface.resource.JFaceResources; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.graphics.Font; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Text; - -/** Utilities to simplify UI development. */ -public class EclipseUiUtils { - /** - * Create a label and a text field for a grid layout, the text field grabing - * excess horizontal - * - * @param parent - * the parent composite - * @param label - * the lable to display - * @param modifyListener - * a {@link ModifyListener} to listen on events on the text, can - * be null - * @return the created text - * - */ - // FIXME why was this deprecated. - // * @ deprecated use { @ link #createGridLT(Composite, String)} instead - // @ Deprecated - public static Text createGridLT(Composite parent, String label, - ModifyListener modifyListener) { - Label lbl = new Label(parent, SWT.LEAD); - lbl.setText(label); - lbl.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false)); - Text txt = new Text(parent, SWT.LEAD | SWT.BORDER); - txt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); - if (modifyListener != null) - txt.addModifyListener(modifyListener); - return txt; - } - - /** - * Create a label and a text field for a grid layout, the text field - * grabbing excess horizontal - */ - public static Text createGridLT(Composite parent, String label) { - return createGridLT(parent, label, null); - } - - /** - * Creates one label and a text field not editable with background color of - * the parent (like a label but with selectable text) - */ - public static Text createGridLL(Composite parent, String label, String text) { - Text txt = createGridLT(parent, label); - txt.setText(text); - txt.setEditable(false); - txt.setBackground(parent.getBackground()); - return txt; - } - - /** - * Create a label and a text field with password display for a grid layout, - * the text field grabbing excess horizontal - */ - public static Text createGridLP(Composite parent, String label, - ModifyListener modifyListener) { - Label lbl = new Label(parent, SWT.LEAD); - lbl.setText(label); - lbl.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false)); - Text txt = new Text(parent, SWT.LEAD | SWT.BORDER | SWT.PASSWORD); - txt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); - if (txt != null) - txt.addModifyListener(modifyListener); - return txt; - } - - /** Shortcut to retrieve default italic font from display */ - public static Font getItalicFont(Composite parent) { - return JFaceResources.getFontRegistry().defaultFontDescriptor() - .setStyle(SWT.ITALIC).createFont(parent.getDisplay()); - } - - /** Shortcut to retrieve default bold font from display */ - public static Font getBoldFont(Composite parent) { - return JFaceResources.getFontRegistry().defaultFontDescriptor() - .setStyle(SWT.BOLD).createFont(parent.getDisplay()); - } - - /** Shortcut to retrieve default bold italic font from display */ - public static Font getBoldItalicFont(Composite parent) { - return JFaceResources.getFontRegistry().defaultFontDescriptor() - .setStyle(SWT.BOLD | SWT.ITALIC) - .createFont(parent.getDisplay()); - } -} \ No newline at end of file diff --git a/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/Error.java b/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/Error.java deleted file mode 100644 index 03b047001..000000000 --- a/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/Error.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui; - -import org.eclipse.swt.widgets.Shell; - -/** - * @deprecated deprecated because of poor naming, use {@link ErrorFeedback} - * instead - */ -@SuppressWarnings("serial") -@Deprecated -public class Error extends ErrorFeedback { - - public Error(Shell parentShell, String message, Throwable e) { - super(parentShell, message, e); - // TODO Auto-generated constructor stub - } - -} diff --git a/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/ErrorFeedback.java b/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/ErrorFeedback.java deleted file mode 100644 index 895e8b866..000000000 --- a/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/ErrorFeedback.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui; - -import java.io.PrintWriter; -import java.io.StringWriter; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.eclipse.jface.dialogs.IMessageProvider; -import org.eclipse.jface.dialogs.TitleAreaDialog; -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Text; -import org.eclipse.ui.PlatformUI; - -/** Generic error dialog to be used in try/catch blocks */ -@SuppressWarnings("serial") -public class ErrorFeedback extends TitleAreaDialog { - private final static Log log = LogFactory.getLog(ErrorFeedback.class); - - private final String message; - private final Throwable exception; - - public static void show(String message, Throwable e) { - // rethrow ThreaDeath in order to make sure that RAP will properly clean - // up the UI thread - if (e instanceof ThreadDeath) - throw (ThreadDeath) e; - - new ErrorFeedback(getDisplay().getActiveShell(), message, e).open(); - } - - public static void show(String message) { - new ErrorFeedback(getDisplay().getActiveShell(), message, null).open(); - } - - /** Tries to find a display */ - private static Display getDisplay() { - try { - Display display = PlatformUI.getWorkbench().getDisplay(); - if (display != null) - return display; - else - return Display.getDefault(); - } catch (Exception e) { - return Display.getCurrent(); - } - } - - public ErrorFeedback(Shell parentShell, String message, Throwable e) { - super(parentShell); - this.message = message; - this.exception = e; - log.error(message, e); - } - - protected Point getInitialSize() { - if (exception != null) - return new Point(800, 600); - else - return new Point(400, 300); - } - - @Override - protected Control createDialogArea(Composite parent) { - Composite dialogarea = (Composite) super.createDialogArea(parent); - dialogarea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - Composite composite = new Composite(dialogarea, SWT.NONE); - composite.setLayout(new GridLayout(2, false)); - composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - - setMessage(message != null ? message - + (exception != null ? ": " + exception.getMessage() : "") - : exception != null ? exception.getMessage() : "Unkown Error", - IMessageProvider.ERROR); - - if (exception != null) { - Text stack = new Text(composite, SWT.MULTI | SWT.LEAD | SWT.BORDER - | SWT.V_SCROLL | SWT.H_SCROLL); - stack.setEditable(false); - stack.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - StringWriter sw = new StringWriter(); - exception.printStackTrace(new PrintWriter(sw)); - stack.setText(sw.toString()); - } - - parent.pack(); - return composite; - } - - protected void configureShell(Shell shell) { - super.configureShell(shell); - shell.setText("Error"); - } -} \ No newline at end of file diff --git a/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/GenericTableComparator.java b/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/GenericTableComparator.java deleted file mode 100644 index a4179cbee..000000000 --- a/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/GenericTableComparator.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui; - -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.jface.viewers.ViewerComparator; - -public abstract class GenericTableComparator extends ViewerComparator { - private static final long serialVersionUID = -1175894935075325810L; - protected int propertyIndex; - public static final int ASCENDING = 0, DESCENDING = 1; - protected int direction = DESCENDING; - - /** - * Creates an instance of a sorter for TableViewer. - * - * @param defaultColumn - * the default sorter column - */ - - public GenericTableComparator(int defaultColumnIndex, int direction) { - propertyIndex = defaultColumnIndex; - this.direction = direction; - } - - public void setColumn(int column) { - if (column == this.propertyIndex) { - // Same column as last sort; toggle the direction - direction = 1 - direction; - } else { - // New column; do a descending sort - this.propertyIndex = column; - direction = DESCENDING; - } - } - - /** - * Must be Overriden in each view. - */ - public abstract int compare(Viewer viewer, Object e1, Object e2); -} diff --git a/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/TreeParent.java b/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/TreeParent.java deleted file mode 100644 index 2dfd2e60c..000000000 --- a/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/TreeParent.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui; - -import java.util.ArrayList; -import java.util.List; - -/** Parent / children semantic to be used for simple UI Tree structure */ -public class TreeParent { - private String name; - private TreeParent parent; - - private List children; - - /** - * Unique id within the context of a tree display. If set, equals() and - * hashCode() methods will be based on it - */ - private String path = null; - - /** False until at least one child has been added, then true until cleared */ - private boolean loaded = false; - - public TreeParent(String name) { - this.name = name; - children = new ArrayList(); - } - - public synchronized void addChild(Object child) { - loaded = true; - children.add(child); - if (child instanceof TreeParent) - ((TreeParent) child).setParent(this); - } - - /** - * Remove this child. The child is disposed. - */ - public synchronized void removeChild(Object child) { - children.remove(child); - if (child instanceof TreeParent) { - ((TreeParent) child).dispose(); - } - } - - public synchronized void clearChildren() { - for (Object obj : children) { - if (obj instanceof TreeParent) - ((TreeParent) obj).dispose(); - } - loaded = false; - children.clear(); - } - - /** - * If overridden, super.dispose() must be called, typically - * after custom cleaning. - */ - public synchronized void dispose() { - clearChildren(); - parent = null; - children = null; - } - - public synchronized Object[] getChildren() { - return children.toArray(new Object[children.size()]); - } - - @SuppressWarnings("unchecked") - public synchronized List getChildrenOfType(Class clss) { - List lst = new ArrayList(); - for (Object obj : children) { - if (clss.isAssignableFrom(obj.getClass())) - lst.add((T) obj); - } - return lst; - } - - public synchronized boolean hasChildren() { - return children.size() > 0; - } - - public Object getChildByName(String name) { - for (Object child : children) { - if (child.toString().equals(name)) - return child; - } - return null; - } - - public synchronized Boolean isLoaded() { - return loaded; - } - - public String getName() { - return name; - } - - public void setParent(TreeParent parent) { - this.parent = parent; - if (parent != null && parent.path != null) - this.path = parent.path + '/' + name; - else - this.path = '/' + name; - } - - public TreeParent getParent() { - return parent; - } - - public String toString() { - return getName(); - } - - public int compareTo(TreeParent o) { - return name.compareTo(o.name); - } - - @Override - public int hashCode() { - if (path != null) - return path.hashCode(); - else - return name.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (path != null && obj instanceof TreeParent) - return path.equals(((TreeParent) obj).path); - else - return name.equals(obj.toString()); - } - -} diff --git a/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/dialogs/Error.java b/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/dialogs/Error.java deleted file mode 100644 index 918bfd244..000000000 --- a/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/dialogs/Error.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.dialogs; - -import org.eclipse.swt.widgets.Shell; - -/** - * Generic error dialog to be used in try/catch blocks - * - * @deprecated use {@link org.argeo.eclipse.ui.ErrorFeedback} instead. - */ -public class Error extends org.argeo.eclipse.ui.ErrorFeedback { - private static final long serialVersionUID = -93864960090248736L; - - public Error(Shell parentShell, String message, Throwable e) { - super(parentShell, message, e); - } -} diff --git a/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/dialogs/SingleValue.java b/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/dialogs/SingleValue.java deleted file mode 100644 index b58f44694..000000000 --- a/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/dialogs/SingleValue.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.dialogs; - -import org.eclipse.jface.dialogs.Dialog; -import org.eclipse.jface.dialogs.IMessageProvider; -import org.eclipse.jface.dialogs.TitleAreaDialog; -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Text; - -/** Dialog retrieve a single value. */ -public class SingleValue extends TitleAreaDialog { - private static final long serialVersionUID = 2843538207460082349L; - - private Text valueT; - private String value; - private final String title, message, label; - private final Boolean multiline; - - public static String ask(String label, String message) { - SingleValue svd = new SingleValue(label, message); - if (svd.open() == Dialog.OK) - return svd.getString(); - else - return null; - } - - public static Long askLong(String label, String message) { - SingleValue svd = new SingleValue(label, message); - if (svd.open() == Dialog.OK) - return svd.getLong(); - else - return null; - } - - public static Double askDouble(String label, String message) { - SingleValue svd = new SingleValue(label, message); - if (svd.open() == Dialog.OK) - return svd.getDouble(); - else - return null; - } - - public SingleValue(String label, String message) { - this(Display.getDefault().getActiveShell(), label, message, label, - false); - } - - public SingleValue(Shell parentShell, String title, String message, - String label, Boolean multiline) { - super(parentShell); - this.title = title; - this.message = message; - this.label = label; - this.multiline = multiline; - } - - protected Point getInitialSize() { - return new Point(300, 250); - } - - protected Control createDialogArea(Composite parent) { - Composite dialogarea = (Composite) super.createDialogArea(parent); - dialogarea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - Composite composite = new Composite(dialogarea, SWT.NONE); - composite.setLayout(new GridLayout(2, false)); - composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); - valueT = createLT(composite, label); - - setMessage(message, IMessageProvider.NONE); - - parent.pack(); - return composite; - } - - @Override - protected void okPressed() { - value = valueT.getText(); - super.okPressed(); - } - - /** Creates label and text. */ - protected Text createLT(Composite parent, String label) { - new Label(parent, SWT.NONE).setText(label); - Text text = new Text(parent, SWT.SINGLE | SWT.LEAD | SWT.BORDER - | (multiline ? SWT.MULTI : SWT.NONE)); - text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - return text; - } - - protected void configureShell(Shell shell) { - super.configureShell(shell); - shell.setText(title); - } - - public String getString() { - return value; - } - - public Long getLong() { - return Long.valueOf(getString()); - } - - public Double getDouble() { - return Double.valueOf(getString()); - } -} diff --git a/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/utils/CommandUtils.java b/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/utils/CommandUtils.java deleted file mode 100644 index 22a139f13..000000000 --- a/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/utils/CommandUtils.java +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.utils; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; - -import org.argeo.ArgeoException; -import org.argeo.eclipse.ui.ArgeoUiPlugin; -import org.eclipse.core.commands.Command; -import org.eclipse.core.commands.IParameter; -import org.eclipse.core.commands.Parameterization; -import org.eclipse.core.commands.ParameterizedCommand; -import org.eclipse.jface.action.IContributionItem; -import org.eclipse.jface.action.IMenuManager; -import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.swt.SWT; -import org.eclipse.ui.IWorkbench; -import org.eclipse.ui.IWorkbenchWindow; -import org.eclipse.ui.commands.ICommandService; -import org.eclipse.ui.handlers.IHandlerService; -import org.eclipse.ui.menus.CommandContributionItem; -import org.eclipse.ui.menus.CommandContributionItemParameter; -import org.eclipse.ui.services.IServiceLocator; - -/** - * Centralises useful and generic methods when dealing with commands in an - * Eclipse Workbench context - */ -public class CommandUtils { - - /** - * Commodities the refresh of a single command with no parameter in a - * Menu.aboutToShow method to simplify further development - * - * Note: that this method should be called with a false show command flag to - * remove a contribution that have been previously contributed - * - * @param menuManager - * @param locator - * @param cmdId - * @param label - * @param icon - * @param showCommand - */ - public static void refreshCommand(IMenuManager menuManager, - IServiceLocator locator, String cmdId, String label, - ImageDescriptor icon, boolean showCommand) { - refreshParameterizedCommand(menuManager, locator, cmdId, label, icon, - showCommand, null); - } - - /** - * Commodities the refresh the contribution of a command with a map of - * parameters in a context menu - * - * The command ID is used has contribution item ID - * - * @param menuManager - * @param locator - * @param cmdId - * @param label - * @param iconPath - * @param showCommand - */ - public static void refreshParameterizedCommand(IMenuManager menuManager, - IServiceLocator locator, String cmdId, String label, - ImageDescriptor icon, boolean showCommand, - Map params) { - refreshParameterizedCommand(menuManager, locator, cmdId, cmdId, label, - icon, showCommand, params); - } - - /** - * Commodities the refresh the contribution of a command with a map of - * parameters in a context menu - * - * @param menuManager - * @param locator - * @param contributionId - * @param commandId - * @param label - * @param icon - * @param showCommand - * @param params - */ - public static void refreshParameterizedCommand(IMenuManager menuManager, - IServiceLocator locator, String contributionId, String commandId, - String label, ImageDescriptor icon, boolean showCommand, - Map params) { - IContributionItem ici = menuManager.find(contributionId); - if (ici != null) - menuManager.remove(ici); - if (showCommand) { - CommandContributionItemParameter contributionItemParameter = new CommandContributionItemParameter( - locator, null, commandId, SWT.PUSH); - - // Set Params - contributionItemParameter.label = label; - contributionItemParameter.icon = icon; - - if (params != null) - contributionItemParameter.parameters = params; - - CommandContributionItem cci = new CommandContributionItem( - contributionItemParameter); - cci.setId(contributionId); - menuManager.add(cci); - } - } - - /** Helper to call a command without parameter easily */ - public static void callCommand(String commandID) { - callCommand(commandID, null); - } - - /** Helper to call a command with a single parameter easily */ - public static void callCommand(String commandID, String parameterID, - String parameterValue) { - Map params = new HashMap(); - params.put(parameterID, parameterValue); - callCommand(commandID, params); - } - - /** - * Helper to call a command with a map of parameters easily - * - * @param paramMap - * a map that links various command IDs with corresponding String - * values. - */ - public static void callCommand(String commandID, - Map paramMap) { - try { - IWorkbench iw = ArgeoUiPlugin.getDefault().getWorkbench(); - IHandlerService handlerService = (IHandlerService) iw - .getService(IHandlerService.class); - ICommandService cmdService = (ICommandService) iw - .getActiveWorkbenchWindow().getService( - ICommandService.class); - Command cmd = cmdService.getCommand(commandID); - - ArrayList parameters = null; - ParameterizedCommand pc; - - if (paramMap != null) { - // Set parameters of the command to launch : - parameters = new ArrayList(); - Parameterization parameterization; - - for (String id : paramMap.keySet()) { - parameterization = new Parameterization( - cmd.getParameter(id), paramMap.get(id)); - parameters.add(parameterization); - } - pc = new ParameterizedCommand(cmd, - parameters.toArray(new Parameterization[parameters - .size()])); - } else - pc = new ParameterizedCommand(cmd, null); - - // execute the command - handlerService.executeCommand(pc, null); - } catch (Exception e) { - throw new ArgeoException("Unexpected error while" - + " calling the command " + commandID, e); - } - } - - // legacy methods. Should be removed soon - - /** - * Shortcut to call a command with a single parameter. - * - * WARNING: none of the parameter can be null - * - * @deprecated rather use callCommand(commandID,parameterID, - parameterValue) - */ - public static void CallCommandWithOneParameter(String commandId, - String paramId, String paramValue) { - try { - IWorkbench iw = ArgeoUiPlugin.getDefault().getWorkbench(); - IHandlerService handlerService = (IHandlerService) iw - .getService(IHandlerService.class); - - // Gets a command that must have been previously registered - IWorkbenchWindow window = iw.getActiveWorkbenchWindow(); - ICommandService cmdService = (ICommandService) window - .getService(ICommandService.class); - Command cmd = cmdService.getCommand(commandId); - - // Manages the single parameter - ArrayList parameters = new ArrayList(); - IParameter iparam = cmd.getParameter(paramId); - Parameterization params = new Parameterization(iparam, paramValue); - parameters.add(params); - - // Create and execute the command - ParameterizedCommand pc = new ParameterizedCommand(cmd, - parameters.toArray(new Parameterization[parameters.size()])); - handlerService = (IHandlerService) window - .getService(IHandlerService.class); - handlerService.executeCommand(pc, null); - } catch (Exception e) { - throw new ArgeoException( - "Error calling command of id:" + commandId, e); - } - } - - /** - * Commodities the refresh of a single command with a map of parameters in a - * Menu.aboutToShow method to simplify further development Rather use - * {@link refreshParameterizedCommand()} - */ - @Deprecated - public static void refreshParametrizedCommand(IMenuManager menuManager, - IServiceLocator locator, String cmdId, String label, - ImageDescriptor icon, boolean showCommand, - Map params) { - refreshParameterizedCommand(menuManager, locator, cmdId, label, icon, - showCommand, params); - } -} \ No newline at end of file diff --git a/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/utils/ViewerUtils.java b/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/utils/ViewerUtils.java deleted file mode 100644 index 42e9fab99..000000000 --- a/base/runtime/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/utils/ViewerUtils.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.eclipse.ui.utils; - -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.jface.viewers.TableViewerColumn; -import org.eclipse.jface.viewers.TreeViewer; -import org.eclipse.jface.viewers.TreeViewerColumn; -import org.eclipse.swt.widgets.Table; -import org.eclipse.swt.widgets.TableColumn; -import org.eclipse.swt.widgets.TreeColumn; - -/** - * Centralizes useful methods to manage Jface Table, Tree and TreeColumn - * viewers. - */ -public class ViewerUtils { - - /** - * Creates a basic column for the given table. For the time being, we do not - * support moveable columns. - */ - public static TableColumn createColumn(Table parent, String name, - int style, int width) { - TableColumn result = new TableColumn(parent, style); - result.setText(name); - result.setWidth(width); - result.setResizable(true); - return result; - } - - /** - * Creates a TableViewerColumn for the given viewer. For the time being, we - * do not support moveable columns. - */ - public static TableViewerColumn createTableViewerColumn(TableViewer parent, - String name, int style, int width) { - TableViewerColumn tvc = new TableViewerColumn(parent, style); - final TableColumn column = tvc.getColumn(); - column.setText(name); - column.setWidth(width); - column.setResizable(true); - return tvc; - } - - /** - * Creates a TreeViewerColumn for the given viewer. For the time being, we - * do not support moveable columns. - */ - public static TreeViewerColumn createTreeViewerColumn(TreeViewer parent, - String name, int style, int width) { - TreeViewerColumn tvc = new TreeViewerColumn(parent, style); - final TreeColumn column = tvc.getColumn(); - column.setText(name); - column.setWidth(width); - column.setResizable(true); - return tvc; - } -} diff --git a/base/runtime/org.argeo.osgi.boot/.classpath b/base/runtime/org.argeo.osgi.boot/.classpath deleted file mode 100644 index 2f7e966c4..000000000 --- a/base/runtime/org.argeo.osgi.boot/.classpath +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/base/runtime/org.argeo.osgi.boot/.project b/base/runtime/org.argeo.osgi.boot/.project deleted file mode 100644 index e145e9691..000000000 --- a/base/runtime/org.argeo.osgi.boot/.project +++ /dev/null @@ -1,23 +0,0 @@ - - - org.argeo.osgi.boot - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - - org.eclipse.jdt.core.javanature - org.eclipse.pde.PluginNature - - diff --git a/base/runtime/org.argeo.osgi.boot/.settings/org.eclipse.jdt.core.prefs b/base/runtime/org.argeo.osgi.boot/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index ba812fb90..000000000 --- a/base/runtime/org.argeo.osgi.boot/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,12 +0,0 @@ -#Fri Jun 26 11:15:56 CEST 2009 -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.4 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.assertIdentifier=warning -org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning -org.eclipse.jdt.core.compiler.source=1.3 diff --git a/base/runtime/org.argeo.osgi.boot/build.properties b/base/runtime/org.argeo.osgi.boot/build.properties deleted file mode 100644 index f17a5821b..000000000 --- a/base/runtime/org.argeo.osgi.boot/build.properties +++ /dev/null @@ -1 +0,0 @@ -additional.bundles = junit diff --git a/base/runtime/org.argeo.osgi.boot/pom.xml b/base/runtime/org.argeo.osgi.boot/pom.xml deleted file mode 100644 index 1f91093b0..000000000 --- a/base/runtime/org.argeo.osgi.boot/pom.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - 4.0.0 - - org.argeo.commons.base - 2.1.12-SNAPSHOT - runtime - .. - - org.argeo.osgi.boot - jar - Commons OSGi Boot - - - - org.apache.maven.plugins - maven-compiler-plugin - - 1.4 - 1.4 - - - - org.apache.felix - maven-bundle-plugin - - - - org.argeo.osgi.boot.Activator - J2SE-1.4 - org.eclipse.*;resolution:=optional,* - - - - - - - - org.argeo.tp.rap.platform - org.eclipse.osgi - provided - - - - - org.argeo.tp - junit - test - - - - - \ No newline at end of file diff --git a/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/Activator.java b/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/Activator.java deleted file mode 100644 index cd9f3583d..000000000 --- a/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/Activator.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.osgi.boot; - -import org.osgi.framework.BundleActivator; -import org.osgi.framework.BundleContext; - -/** - * An OSGi configurator. See http: - * //wiki.eclipse.org/Configurator - */ -public class Activator implements BundleActivator { - - public void start(final BundleContext bundleContext) throws Exception { - // admin thread - Thread adminThread = new AdminThread(bundleContext); - adminThread.start(); - - // bootstrap - OsgiBoot osgiBoot = new OsgiBoot(bundleContext); - osgiBoot.bootstrap(); - } - - public void stop(BundleContext context) throws Exception { - } -} diff --git a/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/AdminThread.java b/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/AdminThread.java deleted file mode 100644 index 6f01b89bb..000000000 --- a/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/AdminThread.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.osgi.boot; - -import java.io.File; - -import org.osgi.framework.BundleContext; -import org.osgi.framework.launch.Framework; - -/** Monitors the runtime and can shut it down. */ -public class AdminThread extends Thread { - public final static String PROP_ARGEO_OSGI_SHUTDOWN_FILE = "argeo.osgi.shutdownFile"; - private File shutdownFile; - private final BundleContext bundleContext; - - public AdminThread(BundleContext bundleContext) { - super("OSGi Boot Admin"); - this.bundleContext = bundleContext; - if (System.getProperty(PROP_ARGEO_OSGI_SHUTDOWN_FILE) != null) { - shutdownFile = new File( - System.getProperty(PROP_ARGEO_OSGI_SHUTDOWN_FILE)); - if (!shutdownFile.exists()) { - shutdownFile = null; - OsgiBootUtils.warn("Shutdown file " + shutdownFile - + " not found, feature deactivated"); - } - } - } - - public void run() { - if (shutdownFile != null) { - // wait for file to be removed - while (shutdownFile.exists()) { - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - Framework framework = (Framework) bundleContext.getBundle(0); - try { - // shutdown framework - framework.stop(); - // wait 10 mins for shutdown - framework.waitForStop(10 * 60 * 1000); - // close VM - System.exit(0); - } catch (Exception e) { - e.printStackTrace(); - System.exit(1); - } - } - } -} diff --git a/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/DistributionBundle.java b/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/DistributionBundle.java deleted file mode 100644 index e6c04281f..000000000 --- a/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/DistributionBundle.java +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.osgi.boot; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.URL; -import java.util.ArrayList; -import java.util.List; -import java.util.StringTokenizer; -import java.util.jar.JarEntry; -import java.util.jar.JarInputStream; -import java.util.jar.Manifest; - -import org.osgi.framework.Constants; - -/** - * A distribution bundle is a bundle within a maven-like distribution - * groupId:Bundle-SymbolicName:Bundle-Version which references others OSGi - * bundle. It is not required to be OSGi complete also it will generally be - * expected that it is. The root of the repository is computed based on the file - * name of the URL and of the content of the index. - */ -public class DistributionBundle { - private final static String INDEX_FILE_NAME = "modularDistribution.csv"; - - private final String url; - - private Manifest manifest; - private String symbolicName; - private String version; - - /** can be null */ - private String baseUrl; - /** can be null */ - private String relativeUrl; - - private List/* */artifacts; - - private String separator = ","; - - public DistributionBundle(String url) { - this.url = url; - } - - public DistributionBundle(String baseUrl, String relativeUrl) { - if (baseUrl == null || !baseUrl.endsWith("/")) - throw new OsgiBootException("Base url " + baseUrl - + " badly formatted"); - if (relativeUrl.startsWith("http") || relativeUrl.startsWith("file:")) - throw new OsgiBootException("Relative URL " + relativeUrl - + " badly formatted"); - this.url = baseUrl + relativeUrl; - this.baseUrl = baseUrl; - this.relativeUrl = relativeUrl; - } - - public void processUrl() { - JarInputStream jarIn = null; - try { - URL u = new URL(url); - jarIn = new JarInputStream(u.openStream()); - - // meta data - manifest = jarIn.getManifest(); - symbolicName = manifest.getMainAttributes().getValue( - Constants.BUNDLE_SYMBOLICNAME); - version = manifest.getMainAttributes().getValue( - Constants.BUNDLE_VERSION); - - JarEntry indexEntry; - while ((indexEntry = jarIn.getNextJarEntry()) != null) { - String entryName = indexEntry.getName(); - if (entryName.equals(INDEX_FILE_NAME)) { - break; - } - jarIn.closeEntry(); - } - - // list artifacts - if (indexEntry == null) - throw new OsgiBootException("No index " + INDEX_FILE_NAME - + " in " + url); - artifacts = listArtifacts(jarIn); - jarIn.closeEntry(); - - // find base URL - // won't work if distribution artifact is not listed - for (int i = 0; i < artifacts.size(); i++) { - OsgiArtifact osgiArtifact = (OsgiArtifact) artifacts.get(i); - if (osgiArtifact.getSymbolicName().equals(symbolicName) - && osgiArtifact.getVersion().equals(version)) { - String relativeUrl = osgiArtifact.getRelativeUrl(); - if (url.endsWith(relativeUrl)) { - baseUrl = url.substring(0, url.length() - - osgiArtifact.getRelativeUrl().length()); - break; - } - } - } - } catch (Exception e) { - throw new OsgiBootException("Cannot list URLs from " + url, e); - } finally { - if (jarIn != null) - try { - jarIn.close(); - } catch (IOException e) { - // silent - } - } - } - - protected List/* */listArtifacts(InputStream in) { - List osgiArtifacts = new ArrayList(); - BufferedReader reader = null; - try { - reader = new BufferedReader(new InputStreamReader(in)); - String line = null; - while ((line = reader.readLine()) != null) { - StringTokenizer st = new StringTokenizer(line, separator); - String moduleName = st.nextToken(); - String moduleVersion = st.nextToken(); - String relativeUrl = st.nextToken(); - osgiArtifacts.add(new OsgiArtifact(moduleName, moduleVersion, - relativeUrl)); - } - } catch (Exception e) { - throw new OsgiBootException("Cannot list artifacts", e); - } - return osgiArtifacts; - } - - /** Convenience method */ - public static DistributionBundle processUrl(String baseUrl, - String realtiveUrl) { - DistributionBundle distributionBundle = new DistributionBundle(baseUrl, - realtiveUrl); - distributionBundle.processUrl(); - return distributionBundle; - } - - /** - * List full URLs of the bunmdles, based on base URL, usable directly for - * download. - */ - public List/* */listUrls() { - if (baseUrl == null) - throw new OsgiBootException("Base URL is not set"); - - if (artifacts == null) - throw new OsgiBootException("Artifact list not initialized"); - - List/* */urls = new ArrayList(); - for (int i = 0; i < artifacts.size(); i++) { - OsgiArtifact osgiArtifact = (OsgiArtifact) artifacts.get(i); - urls.add(baseUrl + osgiArtifact.getRelativeUrl()); - } - return urls; - } - - public void setBaseUrl(String baseUrl) { - this.baseUrl = baseUrl; - } - - /** Separator used to parse the tabular file */ - public void setSeparator(String modulesUrlSeparator) { - this.separator = modulesUrlSeparator; - } - - public String getRelativeUrl() { - return relativeUrl; - } - - /** One of the listed artifact */ - protected static class OsgiArtifact { - private final String symbolicName; - private final String version; - private final String relativeUrl; - - public OsgiArtifact(String symbolicName, String version, - String relativeUrl) { - super(); - this.symbolicName = symbolicName; - this.version = version; - this.relativeUrl = relativeUrl; - } - - public String getSymbolicName() { - return symbolicName; - } - - public String getVersion() { - return version; - } - - public String getRelativeUrl() { - return relativeUrl; - } - - } -} diff --git a/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/Launcher.java b/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/Launcher.java deleted file mode 100644 index 6af1a7184..000000000 --- a/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/Launcher.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.osgi.boot; - -import java.io.FileInputStream; -import java.io.IOException; -import java.lang.reflect.Method; -import java.util.List; -import java.util.Vector; - -import org.eclipse.core.runtime.adaptor.EclipseStarter; -import org.osgi.framework.BundleContext; - -/** Command line interface. */ -public class Launcher { - - public static void main(String[] args) { - // Try to load system properties - String systemPropertiesFilePath = OsgiBootUtils - .getProperty(OsgiBoot.PROP_ARGEO_OSGI_BOOT_SYSTEM_PROPERTIES_FILE); - if (systemPropertiesFilePath != null) { - FileInputStream in; - try { - in = new FileInputStream(systemPropertiesFilePath); - System.getProperties().load(in); - } catch (IOException e1) { - throw new RuntimeException( - "Cannot load system properties from " - + systemPropertiesFilePath, e1); - } - if (in != null) { - try { - in.close(); - } catch (Exception e) { - // silent - } - } - } - - // Start main class - startMainClass(); - - // Start Equinox - BundleContext bundleContext = null; - try { - bundleContext = EclipseStarter.startup(args, null); - } catch (Exception e) { - throw new RuntimeException("Cannot start Equinox.", e); - } - - // OSGi bootstrap - OsgiBoot osgiBoot = new OsgiBoot(bundleContext); - osgiBoot.bootstrap(); - } - - protected static void startMainClass() { - String className = OsgiBootUtils - .getProperty(OsgiBoot.PROP_ARGEO_OSGI_BOOT_APPCLASS); - if (className == null) - return; - - String line = System.getProperty(OsgiBoot.PROP_ARGEO_OSGI_BOOT_APPARGS, - ""); - - String[] uiArgs = readArgumentsFromLine(line); - - try { - // Launch main method using reflection - Class clss = Class.forName(className); - Class[] mainArgsClasses = new Class[] { uiArgs.getClass() }; - Object[] mainArgs = { uiArgs }; - Method mainMethod = clss.getMethod("main", mainArgsClasses); - mainMethod.invoke(null, mainArgs); - } catch (Exception e) { - throw new RuntimeException("Cannot start main class.", e); - } - - } - - /** - * Transform a line into an array of arguments, taking "" as single - * arguments. (nested \" are not supported) - */ - private static String[] readArgumentsFromLine(String lineOrig) { - String line = lineOrig.trim();// remove trailing spaces - List args = new Vector(); - StringBuffer curr = new StringBuffer(""); - boolean inQuote = false; - char[] arr = line.toCharArray(); - for (int i = 0; i < arr.length; i++) { - char c = arr[i]; - switch (c) { - case '\"': - inQuote = !inQuote; - break; - case ' ': - if (!inQuote) {// otherwise, no break: goes to default - if (curr.length() > 0) { - args.add(curr.toString()); - curr = new StringBuffer(""); - } - break; - } - default: - curr.append(c); - break; - } - } - - // Add last arg - if (curr.length() > 0) { - args.add(curr.toString()); - curr = null; - } - - String[] res = new String[args.size()]; - for (int i = 0; i < args.size(); i++) { - res[i] = args.get(i).toString(); - } - return res; - } - -} diff --git a/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/OsgiBoot.java b/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/OsgiBoot.java deleted file mode 100644 index 300ebb82d..000000000 --- a/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/OsgiBoot.java +++ /dev/null @@ -1,1036 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.osgi.boot; - -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.URL; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.Set; -import java.util.SortedMap; -import java.util.StringTokenizer; -import java.util.TreeMap; -import java.util.TreeSet; - -import org.argeo.osgi.boot.internal.springutil.AntPathMatcher; -import org.argeo.osgi.boot.internal.springutil.PathMatcher; -import org.argeo.osgi.boot.internal.springutil.SystemPropertyUtils; -import org.osgi.framework.Bundle; -import org.osgi.framework.BundleContext; -import org.osgi.framework.BundleException; -import org.osgi.framework.Constants; -import org.osgi.framework.ServiceReference; -import org.osgi.service.packageadmin.ExportedPackage; -import org.osgi.service.packageadmin.PackageAdmin; - -/** - * Basic provisioning of an OSGi runtime via file path patterns and system - * properties. Java 1.4 compatible.
- * The approach is to generate list of URLs based on various methods, configured - * via system properties. - */ -public class OsgiBoot { - public final static String SYMBOLIC_NAME_OSGI_BOOT = "org.argeo.osgi.boot"; - public final static String SYMBOLIC_NAME_EQUINOX = "org.eclipse.osgi"; - - public final static String PROP_OSGI_STARTLEVEL = "osgi.startLevel"; - public final static String PROP_OSGI_BUNDLES_DEFAULTSTARTLEVEL = "osgi.bundles.defaultStartLevel"; - - public final static String PROP_ARGEO_OSGI_DATA_DIR = "argeo.osgi.data.dir"; - - public final static String PROP_ARGEO_OSGI_START = "argeo.osgi.start"; - public final static String PROP_ARGEO_OSGI_BUNDLES = "argeo.osgi.bundles"; - public final static String PROP_ARGEO_OSGI_LOCATIONS = "argeo.osgi.locations"; - public final static String PROP_ARGEO_OSGI_BASE_URL = "argeo.osgi.baseUrl"; - /** @deprecated */ - public final static String PROP_ARGEO_OSGI_MODULES_URL = "argeo.osgi.modulesUrl"; - public final static String PROP_ARGEO_OSGI_DISTRIBUTION_URL = "argeo.osgi.distributionUrl"; - - // booleans - public final static String PROP_ARGEO_OSGI_BOOT_DEBUG = "argeo.osgi.boot.debug"; - public final static String PROP_ARGEO_OSGI_BOOT_EXCLUDE_SVN = "argeo.osgi.boot.excludeSvn"; - public final static String PROP_ARGEO_OSGI_BOOT_INSTALL_IN_LEXICOGRAPHIC_ORDER = "argeo.osgi.boot.installInLexicographicOrder"; - - public final static String PROP_ARGEO_OSGI_BOOT_DEFAULT_TIMEOUT = "argeo.osgi.boot.defaultTimeout"; - public final static String PROP_ARGEO_OSGI_BOOT_MODULES_URL_SEPARATOR = "argeo.osgi.boot.modulesUrlSeparator"; - public final static String PROP_ARGEO_OSGI_BOOT_SYSTEM_PROPERTIES_FILE = "argeo.osgi.boot.systemPropertiesFile"; - public final static String PROP_ARGEO_OSGI_BOOT_APPCLASS = "argeo.osgi.boot.appclass"; - public final static String PROP_ARGEO_OSGI_BOOT_APPARGS = "argeo.osgi.boot.appargs"; - - public final static String DEFAULT_BASE_URL = "reference:file:"; - public final static String EXCLUDES_SVN_PATTERN = "**/.svn/**"; - - // OSGi system properties - public final static String INSTANCE_AREA_PROP = "osgi.instance.area"; - public final static String INSTANCE_AREA_DEFAULT_PROP = "osgi.instance.area.default"; - - private boolean debug = Boolean.valueOf( - System.getProperty(PROP_ARGEO_OSGI_BOOT_DEBUG, "false")) - .booleanValue(); - /** Exclude svn metadata implicitely(a bit costly) */ - private boolean excludeSvn = Boolean.valueOf( - System.getProperty(PROP_ARGEO_OSGI_BOOT_EXCLUDE_SVN, "false")) - .booleanValue(); - - /** - * The {@link #installUrls(List)} methods won't follow the list order but - * order the urls according to the alphabetical order of the file names - * (last part of the URL). The goal is to stay closer from Eclipse PDE way - * of installing target platform bundles. - */ - private boolean installInLexicographicOrder = Boolean - .valueOf( - System.getProperty( - PROP_ARGEO_OSGI_BOOT_INSTALL_IN_LEXICOGRAPHIC_ORDER, - "true")).booleanValue();; - - /** Default is 10s (set in constructor) */ - private long defaultTimeout; - - /** Default is ',' (set in constructor) */ - private String modulesUrlSeparator = ","; - - private final BundleContext bundleContext; - - /* - * INITIALIZATION - */ - /** Constructor */ - public OsgiBoot(BundleContext bundleContext) { - this.bundleContext = bundleContext; - defaultTimeout = Long.parseLong(OsgiBootUtils.getProperty( - PROP_ARGEO_OSGI_BOOT_DEFAULT_TIMEOUT, "10000")); - modulesUrlSeparator = OsgiBootUtils.getProperty( - PROP_ARGEO_OSGI_BOOT_MODULES_URL_SEPARATOR, ","); - initSystemProperties(); - } - - /** - * Set additional system properties, especially ${argeo.osgi.data.dir} as an - * OS file path (and not a file:// URL) - */ - protected void initSystemProperties() { - String osgiInstanceArea = System.getProperty(INSTANCE_AREA_PROP); - String osgiInstanceAreaDefault = System - .getProperty(INSTANCE_AREA_DEFAULT_PROP); - String tempDir = System.getProperty("java.io.tmpdir"); - - File dataDir = null; - if (osgiInstanceArea != null) { - // within OSGi with -data specified - osgiInstanceArea = removeFilePrefix(osgiInstanceArea); - dataDir = new File(osgiInstanceArea); - } else if (osgiInstanceAreaDefault != null) { - // within OSGi without -data specified - osgiInstanceAreaDefault = removeFilePrefix(osgiInstanceAreaDefault); - dataDir = new File(osgiInstanceAreaDefault); - } else {// outside OSGi - dataDir = new File(tempDir + File.separator + "argeoOsgiData"); - } - System.setProperty(PROP_ARGEO_OSGI_DATA_DIR, dataDir.getAbsolutePath()); - } - - /* - * HIGH-LEVEL METHODS - */ - /** Bootstraps the OSGi runtime */ - public void bootstrap() { - long begin = System.currentTimeMillis(); - System.out.println(); - OsgiBootUtils.info("OSGi bootstrap starting..."); - OsgiBootUtils.info("Writable data directory : " - + System.getProperty(PROP_ARGEO_OSGI_DATA_DIR) - + " (set as system property " + PROP_ARGEO_OSGI_DATA_DIR + ")"); - installUrls(getBundlesUrls()); - installUrls(getLocationsUrls()); - installUrls(getModulesUrls()); - installUrls(getDistributionUrls()); - checkUnresolved(); - startBundles(); - long duration = System.currentTimeMillis() - begin; - OsgiBootUtils.info("OSGi bootstrap completed in " - + Math.round(((double) duration) / 1000) + "s (" + duration - + "ms), " + bundleContext.getBundles().length + " bundles"); - - // display packages exported twice - if (debug) { - Map /* > */duplicatePackages = findPackagesExportedTwice(); - if (duplicatePackages.size() > 0) { - OsgiBootUtils.info("Packages exported twice:"); - Iterator it = duplicatePackages.keySet().iterator(); - while (it.hasNext()) { - String pkgName = it.next().toString(); - OsgiBootUtils.info(pkgName); - Set bdles = (Set) duplicatePackages.get(pkgName); - Iterator bdlesIt = bdles.iterator(); - while (bdlesIt.hasNext()) - OsgiBootUtils.info(" " + bdlesIt.next()); - } - } - } - - System.out.println(); - } - - /* - * INSTALLATION - */ - /** Install a single url. Convenience method. */ - public Bundle installUrl(String url) { - List urls = new ArrayList(); - urls.add(url); - installUrls(urls); - return (Bundle) getBundlesByLocation().get(url); - } - - /** Install the bundles at this URL list. */ - public void installUrls(List urls) { - Map installedBundles = getBundlesByLocation(); - - if (installInLexicographicOrder) { - SortedMap map = new TreeMap(); - // reorder - for (int i = 0; i < urls.size(); i++) { - String url = (String) urls.get(i); - int index = url.lastIndexOf('/'); - String fileName; - if (index >= 0) - fileName = url.substring(index + 1); - else - fileName = url; - map.put(fileName, url); - } - - // install - Iterator keys = map.keySet().iterator(); - while (keys.hasNext()) { - Object key = keys.next(); - String url = map.get(key).toString(); - installUrl(url, installedBundles); - } - } else { - for (int i = 0; i < urls.size(); i++) { - String url = (String) urls.get(i); - installUrl(url, installedBundles); - } - } - - } - - /** Actually install the provided URL */ - protected void installUrl(String url, Map installedBundles) { - try { - if (installedBundles.containsKey(url)) { - Bundle bundle = (Bundle) installedBundles.get(url); - // bundle.update(); - if (debug) - debug("Bundle " + bundle.getSymbolicName() - + " already installed from " + url); - } else { - Bundle bundle = bundleContext.installBundle(url); - if (debug) - debug("Installed bundle " + bundle.getSymbolicName() - + " from " + url); - } - } catch (BundleException e) { - String message = e.getMessage(); - if ((message.contains("Bundle \"" + SYMBOLIC_NAME_OSGI_BOOT + "\"") || message - .contains("Bundle \"" + SYMBOLIC_NAME_EQUINOX + "\"")) - && message.contains("has already been installed")) { - // silent, in order to avoid warnings: we know that both - // have already been installed... - } else { - OsgiBootUtils.warn("Could not install bundle from " + url - + ": " + message); - } - if (debug) - e.printStackTrace(); - } - } - - /* - * START - */ - public void startBundles() { - // default and active start levels from System properties - Integer defaultStartLevel = new Integer(Integer.parseInt(OsgiBootUtils - .getProperty(PROP_OSGI_BUNDLES_DEFAULTSTARTLEVEL, "4"))); - Integer activeStartLevel = new Integer(OsgiBootUtils.getProperty( - PROP_OSGI_STARTLEVEL, "6")); - - SortedMap/* > */startLevels = new TreeMap(); - computeStartLevels(startLevels, System.getProperties(), - defaultStartLevel); - - Iterator/* */levels = startLevels.keySet().iterator(); - while (levels.hasNext()) { - Integer level = (Integer) levels.next(); - boolean allStarted = startBundles((List) startLevels.get(level)); - if (!allStarted) - OsgiBootUtils - .warn("Not all bundles started for level " + level); - if (level.equals(activeStartLevel)) - break;// active start level reached - } - - } - - public static void computeStartLevels( - SortedMap/* > */startLevels, - Properties properties, Integer defaultStartLevel) { - - // default (and previously, only behaviour) - appendToStartLevels(startLevels, defaultStartLevel, - properties.getProperty(PROP_ARGEO_OSGI_START, "")); - - // list argeo.osgi.start.* system properties - Iterator/* */keys = properties.keySet().iterator(); - final String prefix = PROP_ARGEO_OSGI_START + "."; - while (keys.hasNext()) { - String key = (String) keys.next(); - if (key.startsWith(prefix)) { - Integer startLevel; - String suffix = key.substring(prefix.length()); - String[] tokens = suffix.split("\\."); - if (tokens.length > 0 && !tokens[0].trim().equals("")) - try { - // first token is start level - startLevel = new Integer(tokens[0]); - } catch (NumberFormatException e) { - startLevel = defaultStartLevel; - } - else - startLevel = defaultStartLevel; - - // append bundle names - String bundleNames = properties.getProperty(key); - appendToStartLevels(startLevels, startLevel, bundleNames); - } - } - } - - /** Append a comma-separated list of bundles to the start levels. */ - private static void appendToStartLevels( - SortedMap/* > */startLevels, - Integer startLevel, String str) { - if (str == null || str.trim().equals("")) - return; - - if (!startLevels.containsKey(startLevel)) - startLevels.put(startLevel, new ArrayList()); - String[] bundleNames = str.split(","); - for (int i = 0; i < bundleNames.length; i++) { - if (bundleNames[i] != null && !bundleNames[i].trim().equals("")) - ((List) startLevels.get(startLevel)).add(bundleNames[i]); - } - } - - /** - * Convenience method accepting a comma-separated list of bundle to start - * - * @deprecated - */ - public void startBundles(String bundlesToStartStr) { - if (bundlesToStartStr == null) - return; - - StringTokenizer st = new StringTokenizer(bundlesToStartStr, ","); - List bundlesToStart = new ArrayList(); - while (st.hasMoreTokens()) { - String name = st.nextToken().trim(); - bundlesToStart.add(name); - } - startBundles(bundlesToStart); - } - - /** - * Start the provided list of bundles - * - * @return whether all bundlesa are now in active state - */ - public boolean startBundles(List bundlesToStart) { - if (bundlesToStart.size() == 0) - return true; - - // used to monitor ACTIVE states - List/* */startedBundles = new ArrayList(); - // used to log the bundles not found - List/* */notFoundBundles = new ArrayList(bundlesToStart); - - Bundle[] bundles = bundleContext.getBundles(); - long startBegin = System.currentTimeMillis(); - for (int i = 0; i < bundles.length; i++) { - Bundle bundle = bundles[i]; - String symbolicName = bundle.getSymbolicName(); - if (bundlesToStart.contains(symbolicName)) - try { - try { - bundle.start(); - if (debug) - debug("Bundle " + symbolicName + " started"); - } catch (Exception e) { - OsgiBootUtils.warn("Start of bundle " + symbolicName - + " failed because of " + e - + ", maybe bundle is not yet resolved," - + " waiting and trying again."); - waitForBundleResolvedOrActive(startBegin, bundle); - bundle.start(); - startedBundles.add(bundle); - } - notFoundBundles.remove(symbolicName); - } catch (Exception e) { - OsgiBootUtils.warn("Bundle " + symbolicName - + " cannot be started: " + e.getMessage()); - if (debug) - e.printStackTrace(); - // was found even if start failed - notFoundBundles.remove(symbolicName); - } - } - - for (int i = 0; i < notFoundBundles.size(); i++) - OsgiBootUtils.warn("Bundle '" + notFoundBundles.get(i) - + "' not started because it was not found."); - - // monitors that all bundles are started - long beginMonitor = System.currentTimeMillis(); - boolean allStarted = !(startedBundles.size() > 0); - List/* */notStarted = new ArrayList(); - while (!allStarted - && (System.currentTimeMillis() - beginMonitor) < defaultTimeout) { - notStarted = new ArrayList(); - allStarted = true; - for (int i = 0; i < startedBundles.size(); i++) { - Bundle bundle = (Bundle) startedBundles.get(i); - // TODO check behaviour of lazs bundles - if (bundle.getState() != Bundle.ACTIVE) { - allStarted = false; - notStarted.add(bundle.getSymbolicName()); - } - } - try { - Thread.sleep(100); - } catch (InterruptedException e) { - // silent - } - } - long duration = System.currentTimeMillis() - beginMonitor; - - if (!allStarted) - for (int i = 0; i < notStarted.size(); i++) - OsgiBootUtils.warn("Bundle '" + notStarted.get(i) - + "' not ACTIVE after " + (duration / 1000) + "s"); - - return allStarted; - } - - /* - * DIAGNOSTICS - */ - /** Check unresolved bundles */ - protected void checkUnresolved() { - // Refresh - ServiceReference packageAdminRef = bundleContext - .getServiceReference(PackageAdmin.class.getName()); - PackageAdmin packageAdmin = (PackageAdmin) bundleContext - .getService(packageAdminRef); - packageAdmin.resolveBundles(null); - - Bundle[] bundles = bundleContext.getBundles(); - List /* Bundle */unresolvedBundles = new ArrayList(); - for (int i = 0; i < bundles.length; i++) { - int bundleState = bundles[i].getState(); - if (!(bundleState == Bundle.ACTIVE - || bundleState == Bundle.RESOLVED || bundleState == Bundle.STARTING)) - unresolvedBundles.add(bundles[i]); - } - - if (unresolvedBundles.size() != 0) { - OsgiBootUtils.warn("Unresolved bundles " + unresolvedBundles); - } - } - - /** List packages exported twice. */ - public Map findPackagesExportedTwice() { - ServiceReference paSr = bundleContext - .getServiceReference(PackageAdmin.class.getName()); - PackageAdmin packageAdmin = (PackageAdmin) bundleContext - .getService(paSr); - - // find packages exported twice - Bundle[] bundles = bundleContext.getBundles(); - Map /* > */exportedPackages = new TreeMap(); - for (int i = 0; i < bundles.length; i++) { - Bundle bundle = bundles[i]; - ExportedPackage[] pkgs = packageAdmin.getExportedPackages(bundle); - if (pkgs != null) - for (int j = 0; j < pkgs.length; j++) { - String pkgName = pkgs[j].getName(); - if (!exportedPackages.containsKey(pkgName)) { - exportedPackages.put(pkgName, new TreeSet()); - } - ((Set) exportedPackages.get(pkgName)).add(bundle - .getSymbolicName() + "_" + bundle.getVersion()); - } - } - Map /* > */duplicatePackages = new TreeMap(); - Iterator it = exportedPackages.keySet().iterator(); - while (it.hasNext()) { - String pkgName = it.next().toString(); - Set bdles = (Set) exportedPackages.get(pkgName); - if (bdles.size() > 1) - duplicatePackages.put(pkgName, bdles); - } - return duplicatePackages; - } - - /** Waits for a bundle to become active or resolved */ - protected void waitForBundleResolvedOrActive(long startBegin, Bundle bundle) - throws Exception { - int originalState = bundle.getState(); - if ((originalState == Bundle.RESOLVED) - || (originalState == Bundle.ACTIVE)) - return; - - String originalStateStr = OsgiBootUtils.stateAsString(originalState); - - int currentState = bundle.getState(); - while (!(currentState == Bundle.RESOLVED || currentState == Bundle.ACTIVE)) { - long now = System.currentTimeMillis(); - if ((now - startBegin) > defaultTimeout * 10) - throw new Exception("Bundle " + bundle.getSymbolicName() - + " was not RESOLVED or ACTIVE after " - + (now - startBegin) + "ms (originalState=" - + originalStateStr + ", currentState=" - + OsgiBootUtils.stateAsString(currentState) + ")"); - - try { - Thread.sleep(100l); - } catch (InterruptedException e) { - // silent - } - currentState = bundle.getState(); - } - } - - /* - * EXPLICIT LOCATIONS INSTALLATION - */ - /** Gets the list of resolved explicit URL locations. */ - public List getLocationsUrls() { - String baseUrl = OsgiBootUtils.getProperty(PROP_ARGEO_OSGI_BASE_URL, - DEFAULT_BASE_URL); - String bundleLocations = OsgiBootUtils - .getProperty(PROP_ARGEO_OSGI_LOCATIONS); - return getLocationsUrls(baseUrl, bundleLocations); - } - - /** - * Gets a list of URLs based on explicit locations, resolving placeholder - * ${...} containing system properties, e.g. ${user.home}. - */ - public List getLocationsUrls(String baseUrl, String bundleLocations) { - List urls = new ArrayList(); - - if (bundleLocations == null) - return urls; - bundleLocations = SystemPropertyUtils - .resolvePlaceholders(bundleLocations); - if (debug) - debug(PROP_ARGEO_OSGI_LOCATIONS + "=" + bundleLocations); - - StringTokenizer st = new StringTokenizer(bundleLocations, - File.pathSeparator); - while (st.hasMoreTokens()) { - urls.add(locationToUrl(baseUrl, st.nextToken().trim())); - } - return urls; - } - - /* - * BUNDLE PATTERNS INSTALLATION - */ - /** - * Computes a list of URLs based on Ant-like incluide/exclude patterns - * defined by ${argeo.osgi.bundles} with the following format:
- * /base/directory;in=*.jar;in=**;ex=org.eclipse.osgi_*;jar
- * WARNING: /base/directory;in=*.jar,\ at the end of a file, - * without a new line causes a '.' to be appended with unexpected side - * effects. - */ - public List getBundlesUrls() { - String bundlePatterns = OsgiBootUtils - .getProperty(PROP_ARGEO_OSGI_BUNDLES); - return getBundlesUrls(bundlePatterns); - } - - /** - * Compute alist of URLs to install based on the provided patterns, with - * default base url - */ - public List getBundlesUrls(String bundlePatterns) { - String baseUrl = OsgiBootUtils.getProperty(PROP_ARGEO_OSGI_BASE_URL, - DEFAULT_BASE_URL); - return getBundlesUrls(baseUrl, bundlePatterns); - } - - /** Implements the path matching logic */ - List getBundlesUrls(String baseUrl, String bundlePatterns) { - List urls = new ArrayList(); - if (bundlePatterns == null) - return urls; - - bundlePatterns = SystemPropertyUtils - .resolvePlaceholders(bundlePatterns); - if (debug) - debug(PROP_ARGEO_OSGI_BUNDLES + "=" + bundlePatterns - + " (excludeSvn=" + excludeSvn + ")"); - - StringTokenizer st = new StringTokenizer(bundlePatterns, ","); - List bundlesSets = new ArrayList(); - while (st.hasMoreTokens()) { - bundlesSets.add(new BundlesSet(st.nextToken())); - } - - // find included - List included = new ArrayList(); - PathMatcher matcher = new AntPathMatcher(); - for (int i = 0; i < bundlesSets.size(); i++) { - BundlesSet bundlesSet = (BundlesSet) bundlesSets.get(i); - for (int j = 0; j < bundlesSet.getIncludes().size(); j++) { - String pattern = (String) bundlesSet.getIncludes().get(j); - match(matcher, included, bundlesSet.getDir(), null, pattern); - } - } - - // find excluded - List excluded = new ArrayList(); - for (int i = 0; i < bundlesSets.size(); i++) { - BundlesSet bundlesSet = (BundlesSet) bundlesSets.get(i); - for (int j = 0; j < bundlesSet.getExcludes().size(); j++) { - String pattern = (String) bundlesSet.getExcludes().get(j); - match(matcher, excluded, bundlesSet.getDir(), null, pattern); - } - } - - // construct list - for (int i = 0; i < included.size(); i++) { - String fullPath = (String) included.get(i); - if (!excluded.contains(fullPath)) - urls.add(locationToUrl(baseUrl, fullPath)); - } - - return urls; - } - - /* - * DISTRIBUTION JAR INSTALLATION - */ - public List getDistributionUrls() { - List urls = new ArrayList(); - String distributionUrl = OsgiBootUtils - .getProperty(PROP_ARGEO_OSGI_DISTRIBUTION_URL); - if (distributionUrl == null) - return urls; - String baseUrl = OsgiBootUtils.getProperty(PROP_ARGEO_OSGI_BASE_URL); - - DistributionBundle distributionBundle; - if (baseUrl != null - && !(distributionUrl.startsWith("http") || distributionUrl - .startsWith("file"))) { - // relative url - distributionBundle = new DistributionBundle(baseUrl, - distributionUrl); - } else { - distributionBundle = new DistributionBundle(distributionUrl); - if (baseUrl != null) - distributionBundle.setBaseUrl(baseUrl); - - } - distributionBundle.processUrl(); - return distributionBundle.listUrls(); - } - - /* - * MODULES LIST INSTALLATION (${argeo.osgi.modulesUrl}) - */ - /** - * Downloads a list of URLs in CSV format from ${argeo.osgi.modulesUrl}:
- * Bundle-SymbolicName,Bundle-Version,url)
- * If ${argeo.osgi.baseUrl} is set, URLs will be considered relative paths - * and be concatenated with the base URL, typically the root of a Maven - * repository. - * - * @deprecated - */ - public List getModulesUrls() { - List urls = new ArrayList(); - String modulesUrlStr = OsgiBootUtils - .getProperty(PROP_ARGEO_OSGI_MODULES_URL); - if (modulesUrlStr == null) - return urls; - - String baseUrl = OsgiBootUtils.getProperty(PROP_ARGEO_OSGI_BASE_URL); - - Map installedBundles = getBundlesBySymbolicName(); - - BufferedReader reader = null; - try { - URL modulesUrl = new URL(modulesUrlStr); - reader = new BufferedReader(new InputStreamReader( - modulesUrl.openStream())); - String line = null; - while ((line = reader.readLine()) != null) { - StringTokenizer st = new StringTokenizer(line, - modulesUrlSeparator); - String moduleName = st.nextToken(); - String moduleVersion = st.nextToken(); - String url = st.nextToken(); - if (baseUrl != null) - url = baseUrl + url; - - if (installedBundles.containsKey(moduleName)) { - Bundle bundle = (Bundle) installedBundles.get(moduleName); - String bundleVersion = bundle.getHeaders() - .get(Constants.BUNDLE_VERSION).toString(); - int comp = OsgiBootUtils.compareVersions(bundleVersion, - moduleVersion); - if (comp > 0) { - OsgiBootUtils.warn("Installed version " + bundleVersion - + " of bundle " + moduleName - + " is newer than provided version " - + moduleVersion); - } else if (comp < 0) { - urls.add(url); - OsgiBootUtils.info("Updated bundle " + moduleName - + " with version " + moduleVersion - + " (old version was " + bundleVersion + ")"); - } else { - // do nothing - } - } else { - urls.add(url); - } - } - } catch (Exception e1) { - throw new RuntimeException("Cannot read url " + modulesUrlStr, e1); - } finally { - if (reader != null) - try { - reader.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - return urls; - } - - /* - * HIGH LEVEL UTILITIES - */ - /** Actually performs the matching logic. */ - protected void match(PathMatcher matcher, List matched, String base, - String currentPath, String pattern) { - if (currentPath == null) { - // Init - File baseDir = new File(base.replace('/', File.separatorChar)); - File[] files = baseDir.listFiles(); - - if (files == null) { - if (debug) - OsgiBootUtils.warn("Base dir " + baseDir - + " has no children, exists=" + baseDir.exists() - + ", isDirectory=" + baseDir.isDirectory()); - return; - } - - for (int i = 0; i < files.length; i++) - match(matcher, matched, base, files[i].getName(), pattern); - } else { - String fullPath = base + '/' + currentPath; - if (matched.contains(fullPath)) - return;// don't try deeper if already matched - - boolean ok = matcher.match(pattern, currentPath); - // if (debug) - // debug(currentPath + " " + (ok ? "" : " not ") - // + " matched with " + pattern); - if (ok) { - matched.add(fullPath); - return; - } else { - String newFullPath = relativeToFullPath(base, currentPath); - File newFile = new File(newFullPath); - File[] files = newFile.listFiles(); - if (files != null) { - for (int i = 0; i < files.length; i++) { - String newCurrentPath = currentPath + '/' - + files[i].getName(); - if (files[i].isDirectory()) { - if (matcher.matchStart(pattern, newCurrentPath)) { - // recurse only if start matches - match(matcher, matched, base, newCurrentPath, - pattern); - } else { - if (debug) - debug(newCurrentPath - + " does not start match with " - + pattern); - - } - } else { - boolean nonDirectoryOk = matcher.match(pattern, - newCurrentPath); - if (debug) - debug(currentPath + " " + (ok ? "" : " not ") - + " matched with " + pattern); - if (nonDirectoryOk) - matched.add(relativeToFullPath(base, - newCurrentPath)); - } - } - } - } - } - } - - protected void matchFile() { - - } - - /* - * LOW LEVEL UTILITIES - */ - /** - * The bundles already installed. Key is location (String) , value is a - * {@link Bundle} - */ - public Map getBundlesByLocation() { - Map installedBundles = new HashMap(); - Bundle[] bundles = bundleContext.getBundles(); - for (int i = 0; i < bundles.length; i++) { - installedBundles.put(bundles[i].getLocation(), bundles[i]); - } - return installedBundles; - } - - /** - * The bundles already installed. Key is symbolic name (String) , value is a - * {@link Bundle} - */ - public Map getBundlesBySymbolicName() { - Map namedBundles = new HashMap(); - Bundle[] bundles = bundleContext.getBundles(); - for (int i = 0; i < bundles.length; i++) { - namedBundles.put(bundles[i].getSymbolicName(), bundles[i]); - } - return namedBundles; - } - - /** Creates an URL from a location */ - protected String locationToUrl(String baseUrl, String location) { - // int extInd = location.lastIndexOf('.'); - // String ext = null; - // if (extInd > 0) - // ext = location.substring(extInd); - // - // if (baseUrl.startsWith("reference:") && ".jar".equals(ext)) - // return "file:" + location; - // else - return baseUrl + location; - } - - /** Transforms a relative path in a full system path. */ - protected String relativeToFullPath(String basePath, String relativePath) { - return (basePath + '/' + relativePath).replace('/', File.separatorChar); - } - - private String removeFilePrefix(String url) { - if (url.startsWith("file:")) - return url.substring("file:".length()); - else if (url.startsWith("reference:file:")) - return url.substring("reference:file:".length()); - else - return url; - } - - /** - * Convenience method to avoid cluttering the code with - * OsgiBootUtils.debug() - */ - protected void debug(Object obj) { - OsgiBootUtils.debug(obj); - } - - /* - * BEAN METHODS - */ - - public boolean getDebug() { - return debug; - } - - public void setDebug(boolean debug) { - this.debug = debug; - } - - public BundleContext getBundleContext() { - return bundleContext; - } - - public void setInstallInLexicographicOrder( - boolean installInAlphabeticalOrder) { - this.installInLexicographicOrder = installInAlphabeticalOrder; - } - - public boolean isInstallInLexicographicOrder() { - return installInLexicographicOrder; - } - - public void setDefaultTimeout(long defaultTimeout) { - this.defaultTimeout = defaultTimeout; - } - - public void setModulesUrlSeparator(String modulesUrlSeparator) { - this.modulesUrlSeparator = modulesUrlSeparator; - } - - public boolean isExcludeSvn() { - return excludeSvn; - } - - public void setExcludeSvn(boolean excludeSvn) { - this.excludeSvn = excludeSvn; - } - - /* - * INTERNAL CLASSES - */ - - /** Intermediary structure used by path matching */ - protected class BundlesSet { - private String baseUrl = "reference:file";// not used yet - private final String dir; - private List includes = new ArrayList(); - private List excludes = new ArrayList(); - - public BundlesSet(String def) { - StringTokenizer st = new StringTokenizer(def, ";"); - - if (!st.hasMoreTokens()) - throw new RuntimeException("Base dir not defined."); - try { - String dirPath = st.nextToken(); - - if (dirPath.startsWith("file:")) - dirPath = dirPath.substring("file:".length()); - - dir = new File(dirPath.replace('/', File.separatorChar)) - .getCanonicalPath(); - if (debug) - debug("Base dir: " + dir); - } catch (IOException e) { - throw new RuntimeException("Cannot convert to absolute path", e); - } - - while (st.hasMoreTokens()) { - String tk = st.nextToken(); - StringTokenizer stEq = new StringTokenizer(tk, "="); - String type = stEq.nextToken(); - String pattern = stEq.nextToken(); - if ("in".equals(type) || "include".equals(type)) { - includes.add(pattern); - } else if ("ex".equals(type) || "exclude".equals(type)) { - excludes.add(pattern); - } else if ("baseUrl".equals(type)) { - baseUrl = pattern; - } else { - System.err.println("Unkown bundles pattern type " + type); - } - } - - if (excludeSvn && !excludes.contains(EXCLUDES_SVN_PATTERN)) { - excludes.add(EXCLUDES_SVN_PATTERN); - } - } - - public String getDir() { - return dir; - } - - public List getIncludes() { - return includes; - } - - public List getExcludes() { - return excludes; - } - - public String getBaseUrl() { - return baseUrl; - } - - } - - /* @deprecated Doesn't seem to be used anymore. */ - // public void installOrUpdateUrls(Map urls) { - // Map installedBundles = getBundles(); - // - // for (Iterator modules = urls.keySet().iterator(); modules.hasNext();) { - // String moduleName = (String) modules.next(); - // String urlStr = (String) urls.get(moduleName); - // if (installedBundles.containsKey(moduleName)) { - // Bundle bundle = (Bundle) installedBundles.get(moduleName); - // InputStream in; - // try { - // URL url = new URL(urlStr); - // in = url.openStream(); - // bundle.update(in); - // OsgiBootUtils.info("Updated bundle " + moduleName - // + " from " + urlStr); - // } catch (Exception e) { - // throw new RuntimeException("Cannot update " + moduleName - // + " from " + urlStr); - // } - // if (in != null) - // try { - // in.close(); - // } catch (IOException e) { - // e.printStackTrace(); - // } - // } else { - // try { - // Bundle bundle = bundleContext.installBundle(urlStr); - // if (debug) - // debug("Installed bundle " + bundle.getSymbolicName() - // + " from " + urlStr); - // } catch (BundleException e) { - // OsgiBootUtils.warn("Could not install bundle from " - // + urlStr + ": " + e.getMessage()); - // } - // } - // } - // - // } - -} diff --git a/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/OsgiBootException.java b/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/OsgiBootException.java deleted file mode 100644 index 9a75f1766..000000000 --- a/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/OsgiBootException.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.osgi.boot; - -/** OsgiBoot specific exceptions */ -public class OsgiBootException extends RuntimeException { - private static final long serialVersionUID = 2414011711711425353L; - - public OsgiBootException() { - } - - public OsgiBootException(String message) { - super(message); - } - - public OsgiBootException(String message, Throwable cause) { - super(message, cause); - } - -} diff --git a/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/OsgiBootUtils.java b/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/OsgiBootUtils.java deleted file mode 100644 index 20891c7f9..000000000 --- a/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/OsgiBootUtils.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.osgi.boot; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.StringTokenizer; - -import org.osgi.framework.Bundle; - -/** Utilities, mostly related to logging. */ -public class OsgiBootUtils { - /** ISO8601 (as per log4j) and difference to UTC */ - private static DateFormat dateFormat = new SimpleDateFormat( - "yyyy-MM-dd HH:mm:ss,SSS Z"); - - public static void info(Object obj) { - System.out.println("# OSGiBOOT # " + dateFormat.format(new Date()) - + " # " + obj); - } - - public static void debug(Object obj) { - System.out.println("# OSGiBOOT DBG # " + dateFormat.format(new Date()) - + " # " + obj); - } - - public static void warn(Object obj) { - System.out.println("# OSGiBOOT WARN # " + dateFormat.format(new Date()) - + " # " + obj); - } - - /** - * Gets a property value - * - * @return null when defaultValue is "" - */ - public static String getProperty(String name, String defaultValue) { - final String value; - if (defaultValue != null) - value = System.getProperty(name, defaultValue); - else - value = System.getProperty(name); - - if (value == null || value.equals("")) - return null; - else - return value; - } - - public static String getProperty(String name) { - return getProperty(name, null); - } - - public static String stateAsString(int state) { - switch (state) { - case Bundle.UNINSTALLED: - return "UNINSTALLED"; - case Bundle.INSTALLED: - return "INSTALLED"; - case Bundle.RESOLVED: - return "RESOLVED"; - case Bundle.STARTING: - return "STARTING"; - case Bundle.ACTIVE: - return "ACTIVE"; - case Bundle.STOPPING: - return "STOPPING"; - default: - return Integer.toString(state); - } - } - - /** - * @return ==0: versions are identical, <0: tested version is newer, >0: - * currentVersion is newer. - */ - public static int compareVersions(String currentVersion, - String testedVersion) { - List cToks = new ArrayList(); - StringTokenizer cSt = new StringTokenizer(currentVersion, "."); - while (cSt.hasMoreTokens()) - cToks.add(cSt.nextToken()); - List tToks = new ArrayList(); - StringTokenizer tSt = new StringTokenizer(currentVersion, "."); - while (tSt.hasMoreTokens()) - tToks.add(tSt.nextToken()); - - int comp = 0; - comp: for (int i = 0; i < cToks.size(); i++) { - if (tToks.size() <= i) { - // equals until then, tested shorter - comp = 1; - break comp; - } - - String c = (String) cToks.get(i); - String t = (String) tToks.get(i); - - try { - int cInt = Integer.parseInt(c); - int tInt = Integer.parseInt(t); - if (cInt == tInt) - continue comp; - else { - comp = (cInt - tInt); - break comp; - } - } catch (NumberFormatException e) { - if (c.equals(t)) - continue comp; - else { - comp = c.compareTo(t); - break comp; - } - } - } - - if (comp == 0 && tToks.size() > cToks.size()) { - // equals until then, current shorter - comp = -1; - } - - return comp; - } - -} diff --git a/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/internal/springutil/AntPathMatcher.java b/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/internal/springutil/AntPathMatcher.java deleted file mode 100644 index 0b9ad1a23..000000000 --- a/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/internal/springutil/AntPathMatcher.java +++ /dev/null @@ -1,411 +0,0 @@ -/* - * Copyright 2002-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.argeo.osgi.boot.internal.springutil; - -/** - * PathMatcher implementation for Ant-style path patterns. - * Examples are provided below. - * - *

Part of this mapping code has been kindly borrowed from - * Apache Ant. - * - *

The mapping matches URLs using the following rules:
- *

    - *
  • ? matches one character
  • - *
  • * matches zero or more characters
  • - *
  • ** matches zero or more 'directories' in a path
  • - *
- * - *

Some examples:
- *

    - *
  • com/t?st.jsp - matches com/test.jsp but also - * com/tast.jsp or com/txst.jsp
  • - *
  • com/*.jsp - matches all .jsp files in the - * com directory
  • - *
  • com/**/test.jsp - matches all test.jsp - * files underneath the com path
  • - *
  • org/springframework/**/*.jsp - matches all .jsp - * files underneath the org/springframework path
  • - *
  • org/**/servlet/bla.jsp - matches - * org/springframework/servlet/bla.jsp but also - * org/springframework/testing/servlet/bla.jsp and - * org/servlet/bla.jsp
  • - *
- * - * @author Alef Arendsen - * @author Juergen Hoeller - * @author Rob Harrop - * @since 16.07.2003 - */ -public class AntPathMatcher implements PathMatcher { - - /** Default path separator: "/" */ - public static final String DEFAULT_PATH_SEPARATOR = "/"; - - private String pathSeparator = DEFAULT_PATH_SEPARATOR; - - - /** - * Set the path separator to use for pattern parsing. - * Default is "/", as in Ant. - */ - public void setPathSeparator(String pathSeparator) { - this.pathSeparator = (pathSeparator != null ? pathSeparator : DEFAULT_PATH_SEPARATOR); - } - - - public boolean isPattern(String path) { - return (path.indexOf('*') != -1 || path.indexOf('?') != -1); - } - - public boolean match(String pattern, String path) { - return doMatch(pattern, path, true); - } - - public boolean matchStart(String pattern, String path) { - return doMatch(pattern, path, false); - } - - - /** - * Actually match the given path against the given pattern. - * @param pattern the pattern to match against - * @param path the path String to test - * @param fullMatch whether a full pattern match is required - * (else a pattern match as far as the given base path goes is sufficient) - * @return true if the supplied path matched, - * false if it didn't - */ - protected boolean doMatch(String pattern, String path, boolean fullMatch) { - if (path.startsWith(this.pathSeparator) != pattern.startsWith(this.pathSeparator)) { - return false; - } - - String[] pattDirs = StringUtils.tokenizeToStringArray(pattern, this.pathSeparator); - String[] pathDirs = StringUtils.tokenizeToStringArray(path, this.pathSeparator); - - int pattIdxStart = 0; - int pattIdxEnd = pattDirs.length - 1; - int pathIdxStart = 0; - int pathIdxEnd = pathDirs.length - 1; - - // Match all elements up to the first ** - while (pattIdxStart <= pattIdxEnd && pathIdxStart <= pathIdxEnd) { - String patDir = pattDirs[pattIdxStart]; - if ("**".equals(patDir)) { - break; - } - if (!matchStrings(patDir, pathDirs[pathIdxStart])) { - return false; - } - pattIdxStart++; - pathIdxStart++; - } - - if (pathIdxStart > pathIdxEnd) { - // Path is exhausted, only match if rest of pattern is * or **'s - if (pattIdxStart > pattIdxEnd) { - return (pattern.endsWith(this.pathSeparator) ? - path.endsWith(this.pathSeparator) : !path.endsWith(this.pathSeparator)); - } - if (!fullMatch) { - return true; - } - if (pattIdxStart == pattIdxEnd && pattDirs[pattIdxStart].equals("*") && - path.endsWith(this.pathSeparator)) { - return true; - } - for (int i = pattIdxStart; i <= pattIdxEnd; i++) { - if (!pattDirs[i].equals("**")) { - return false; - } - } - return true; - } - else if (pattIdxStart > pattIdxEnd) { - // String not exhausted, but pattern is. Failure. - return false; - } - else if (!fullMatch && "**".equals(pattDirs[pattIdxStart])) { - // Path start definitely matches due to "**" part in pattern. - return true; - } - - // up to last '**' - while (pattIdxStart <= pattIdxEnd && pathIdxStart <= pathIdxEnd) { - String patDir = pattDirs[pattIdxEnd]; - if (patDir.equals("**")) { - break; - } - if (!matchStrings(patDir, pathDirs[pathIdxEnd])) { - return false; - } - pattIdxEnd--; - pathIdxEnd--; - } - if (pathIdxStart > pathIdxEnd) { - // String is exhausted - for (int i = pattIdxStart; i <= pattIdxEnd; i++) { - if (!pattDirs[i].equals("**")) { - return false; - } - } - return true; - } - - while (pattIdxStart != pattIdxEnd && pathIdxStart <= pathIdxEnd) { - int patIdxTmp = -1; - for (int i = pattIdxStart + 1; i <= pattIdxEnd; i++) { - if (pattDirs[i].equals("**")) { - patIdxTmp = i; - break; - } - } - if (patIdxTmp == pattIdxStart + 1) { - // '**/**' situation, so skip one - pattIdxStart++; - continue; - } - // Find the pattern between padIdxStart & padIdxTmp in str between - // strIdxStart & strIdxEnd - int patLength = (patIdxTmp - pattIdxStart - 1); - int strLength = (pathIdxEnd - pathIdxStart + 1); - int foundIdx = -1; - - strLoop: - for (int i = 0; i <= strLength - patLength; i++) { - for (int j = 0; j < patLength; j++) { - String subPat = (String) pattDirs[pattIdxStart + j + 1]; - String subStr = (String) pathDirs[pathIdxStart + i + j]; - if (!matchStrings(subPat, subStr)) { - continue strLoop; - } - } - foundIdx = pathIdxStart + i; - break; - } - - if (foundIdx == -1) { - return false; - } - - pattIdxStart = patIdxTmp; - pathIdxStart = foundIdx + patLength; - } - - for (int i = pattIdxStart; i <= pattIdxEnd; i++) { - if (!pattDirs[i].equals("**")) { - return false; - } - } - - return true; - } - - /** - * Tests whether or not a string matches against a pattern. - * The pattern may contain two special characters:
- * '*' means zero or more characters
- * '?' means one and only one character - * @param pattern pattern to match against. - * Must not be null. - * @param str string which must be matched against the pattern. - * Must not be null. - * @return true if the string matches against the - * pattern, or false otherwise. - */ - private boolean matchStrings(String pattern, String str) { - char[] patArr = pattern.toCharArray(); - char[] strArr = str.toCharArray(); - int patIdxStart = 0; - int patIdxEnd = patArr.length - 1; - int strIdxStart = 0; - int strIdxEnd = strArr.length - 1; - char ch; - - boolean containsStar = false; - for (int i = 0; i < patArr.length; i++) { - if (patArr[i] == '*') { - containsStar = true; - break; - } - } - - if (!containsStar) { - // No '*'s, so we make a shortcut - if (patIdxEnd != strIdxEnd) { - return false; // Pattern and string do not have the same size - } - for (int i = 0; i <= patIdxEnd; i++) { - ch = patArr[i]; - if (ch != '?') { - if (ch != strArr[i]) { - return false;// Character mismatch - } - } - } - return true; // String matches against pattern - } - - - if (patIdxEnd == 0) { - return true; // Pattern contains only '*', which matches anything - } - - // Process characters before first star - while ((ch = patArr[patIdxStart]) != '*' && strIdxStart <= strIdxEnd) { - if (ch != '?') { - if (ch != strArr[strIdxStart]) { - return false;// Character mismatch - } - } - patIdxStart++; - strIdxStart++; - } - if (strIdxStart > strIdxEnd) { - // All characters in the string are used. Check if only '*'s are - // left in the pattern. If so, we succeeded. Otherwise failure. - for (int i = patIdxStart; i <= patIdxEnd; i++) { - if (patArr[i] != '*') { - return false; - } - } - return true; - } - - // Process characters after last star - while ((ch = patArr[patIdxEnd]) != '*' && strIdxStart <= strIdxEnd) { - if (ch != '?') { - if (ch != strArr[strIdxEnd]) { - return false;// Character mismatch - } - } - patIdxEnd--; - strIdxEnd--; - } - if (strIdxStart > strIdxEnd) { - // All characters in the string are used. Check if only '*'s are - // left in the pattern. If so, we succeeded. Otherwise failure. - for (int i = patIdxStart; i <= patIdxEnd; i++) { - if (patArr[i] != '*') { - return false; - } - } - return true; - } - - // process pattern between stars. padIdxStart and patIdxEnd point - // always to a '*'. - while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd) { - int patIdxTmp = -1; - for (int i = patIdxStart + 1; i <= patIdxEnd; i++) { - if (patArr[i] == '*') { - patIdxTmp = i; - break; - } - } - if (patIdxTmp == patIdxStart + 1) { - // Two stars next to each other, skip the first one. - patIdxStart++; - continue; - } - // Find the pattern between padIdxStart & padIdxTmp in str between - // strIdxStart & strIdxEnd - int patLength = (patIdxTmp - patIdxStart - 1); - int strLength = (strIdxEnd - strIdxStart + 1); - int foundIdx = -1; - strLoop: - for (int i = 0; i <= strLength - patLength; i++) { - for (int j = 0; j < patLength; j++) { - ch = patArr[patIdxStart + j + 1]; - if (ch != '?') { - if (ch != strArr[strIdxStart + i + j]) { - continue strLoop; - } - } - } - - foundIdx = strIdxStart + i; - break; - } - - if (foundIdx == -1) { - return false; - } - - patIdxStart = patIdxTmp; - strIdxStart = foundIdx + patLength; - } - - // All characters in the string are used. Check if only '*'s are left - // in the pattern. If so, we succeeded. Otherwise failure. - for (int i = patIdxStart; i <= patIdxEnd; i++) { - if (patArr[i] != '*') { - return false; - } - } - - return true; - } - - /** - * Given a pattern and a full path, determine the pattern-mapped part. - *

For example: - *

    - *
  • '/docs/cvs/commit.html' and '/docs/cvs/commit.html -> ''
  • - *
  • '/docs/*' and '/docs/cvs/commit -> 'cvs/commit'
  • - *
  • '/docs/cvs/*.html' and '/docs/cvs/commit.html -> 'commit.html'
  • - *
  • '/docs/**' and '/docs/cvs/commit -> 'cvs/commit'
  • - *
  • '/docs/**\/*.html' and '/docs/cvs/commit.html -> 'cvs/commit.html'
  • - *
  • '/*.html' and '/docs/cvs/commit.html -> 'docs/cvs/commit.html'
  • - *
  • '*.html' and '/docs/cvs/commit.html -> '/docs/cvs/commit.html'
  • - *
  • '*' and '/docs/cvs/commit.html -> '/docs/cvs/commit.html'
  • - *
- *

Assumes that {@link #match} returns true for 'pattern' - * and 'path', but does not enforce this. - */ - public String extractPathWithinPattern(String pattern, String path) { - String[] patternParts = StringUtils.tokenizeToStringArray(pattern, this.pathSeparator); - String[] pathParts = StringUtils.tokenizeToStringArray(path, this.pathSeparator); - - StringBuffer buffer = new StringBuffer(); - - // Add any path parts that have a wildcarded pattern part. - int puts = 0; - for (int i = 0; i < patternParts.length; i++) { - String patternPart = patternParts[i]; - if ((patternPart.indexOf('*') > -1 || patternPart.indexOf('?') > -1) && pathParts.length >= i + 1) { - if (puts > 0 || (i == 0 && !pattern.startsWith(this.pathSeparator))) { - buffer.append(this.pathSeparator); - } - buffer.append(pathParts[i]); - puts++; - } - } - - // Append any trailing path parts. - for (int i = patternParts.length; i < pathParts.length; i++) { - if (puts > 0 || i > 0) { - buffer.append(this.pathSeparator); - } - buffer.append(pathParts[i]); - } - - return buffer.toString(); - } - -} diff --git a/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/internal/springutil/CollectionUtils.java b/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/internal/springutil/CollectionUtils.java deleted file mode 100644 index ad0154293..000000000 --- a/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/internal/springutil/CollectionUtils.java +++ /dev/null @@ -1,275 +0,0 @@ -/* - * Copyright 2002-2008 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.argeo.osgi.boot.internal.springutil; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Enumeration; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Properties; - -/** - * Miscellaneous collection utility methods. - * Mainly for internal use within the framework. - * - * @author Juergen Hoeller - * @author Rob Harrop - * @since 1.1.3 - */ -public abstract class CollectionUtils { - - /** - * Return true if the supplied Collection is null - * or empty. Otherwise, return false. - * @param collection the Collection to check - * @return whether the given Collection is empty - */ - public static boolean isEmpty(Collection collection) { - return (collection == null || collection.isEmpty()); - } - - /** - * Return true if the supplied Map is null - * or empty. Otherwise, return false. - * @param map the Map to check - * @return whether the given Map is empty - */ - public static boolean isEmpty(Map map) { - return (map == null || map.isEmpty()); - } - - /** - * Convert the supplied array into a List. A primitive array gets - * converted into a List of the appropriate wrapper type. - *

A null source value will be converted to an - * empty List. - * @param source the (potentially primitive) array - * @return the converted List result - * @see ObjectUtils#toObjectArray(Object) - */ - public static List arrayToList(Object source) { - return Arrays.asList(ObjectUtils.toObjectArray(source)); - } - - /** - * Merge the given array into the given Collection. - * @param array the array to merge (may be null) - * @param collection the target Collection to merge the array into - */ - public static void mergeArrayIntoCollection(Object array, Collection collection) { - if (collection == null) { - throw new IllegalArgumentException("Collection must not be null"); - } - Object[] arr = ObjectUtils.toObjectArray(array); - for (int i = 0; i < arr.length; i++) { - collection.add(arr[i]); - } - } - - /** - * Merge the given Properties instance into the given Map, - * copying all properties (key-value pairs) over. - *

Uses Properties.propertyNames() to even catch - * default properties linked into the original Properties instance. - * @param props the Properties instance to merge (may be null) - * @param map the target Map to merge the properties into - */ - public static void mergePropertiesIntoMap(Properties props, Map map) { - if (map == null) { - throw new IllegalArgumentException("Map must not be null"); - } - if (props != null) { - for (Enumeration en = props.propertyNames(); en.hasMoreElements();) { - String key = (String) en.nextElement(); - map.put(key, props.getProperty(key)); - } - } - } - - - /** - * Check whether the given Iterator contains the given element. - * @param iterator the Iterator to check - * @param element the element to look for - * @return true if found, false else - */ - public static boolean contains(Iterator iterator, Object element) { - if (iterator != null) { - while (iterator.hasNext()) { - Object candidate = iterator.next(); - if (ObjectUtils.nullSafeEquals(candidate, element)) { - return true; - } - } - } - return false; - } - - /** - * Check whether the given Enumeration contains the given element. - * @param enumeration the Enumeration to check - * @param element the element to look for - * @return true if found, false else - */ - public static boolean contains(Enumeration enumeration, Object element) { - if (enumeration != null) { - while (enumeration.hasMoreElements()) { - Object candidate = enumeration.nextElement(); - if (ObjectUtils.nullSafeEquals(candidate, element)) { - return true; - } - } - } - return false; - } - - /** - * Check whether the given Collection contains the given element instance. - *

Enforces the given instance to be present, rather than returning - * true for an equal element as well. - * @param collection the Collection to check - * @param element the element to look for - * @return true if found, false else - */ - public static boolean containsInstance(Collection collection, Object element) { - if (collection != null) { - for (Iterator it = collection.iterator(); it.hasNext();) { - Object candidate = it.next(); - if (candidate == element) { - return true; - } - } - } - return false; - } - - /** - * Return true if any element in 'candidates' is - * contained in 'source'; otherwise returns false. - * @param source the source Collection - * @param candidates the candidates to search for - * @return whether any of the candidates has been found - */ - public static boolean containsAny(Collection source, Collection candidates) { - if (isEmpty(source) || isEmpty(candidates)) { - return false; - } - for (Iterator it = candidates.iterator(); it.hasNext();) { - if (source.contains(it.next())) { - return true; - } - } - return false; - } - - /** - * Return the first element in 'candidates' that is contained in - * 'source'. If no element in 'candidates' is present in - * 'source' returns null. Iteration order is - * {@link Collection} implementation specific. - * @param source the source Collection - * @param candidates the candidates to search for - * @return the first present object, or null if not found - */ - public static Object findFirstMatch(Collection source, Collection candidates) { - if (isEmpty(source) || isEmpty(candidates)) { - return null; - } - for (Iterator it = candidates.iterator(); it.hasNext();) { - Object candidate = it.next(); - if (source.contains(candidate)) { - return candidate; - } - } - return null; - } - - /** - * Find a single value of the given type in the given Collection. - * @param collection the Collection to search - * @param type the type to look for - * @return a value of the given type found if there is a clear match, - * or null if none or more than one such value found - */ - public static Object findValueOfType(Collection collection, Class type) { - if (isEmpty(collection)) { - return null; - } - Object value = null; - for (Iterator it = collection.iterator(); it.hasNext();) { - Object obj = it.next(); - if (type == null || type.isInstance(obj)) { - if (value != null) { - // More than one value found... no clear single value. - return null; - } - value = obj; - } - } - return value; - } - - /** - * Find a single value of one of the given types in the given Collection: - * searching the Collection for a value of the first type, then - * searching for a value of the second type, etc. - * @param collection the collection to search - * @param types the types to look for, in prioritized order - * @return a value of one of the given types found if there is a clear match, - * or null if none or more than one such value found - */ - public static Object findValueOfType(Collection collection, Class[] types) { - if (isEmpty(collection) || ObjectUtils.isEmpty(types)) { - return null; - } - for (int i = 0; i < types.length; i++) { - Object value = findValueOfType(collection, types[i]); - if (value != null) { - return value; - } - } - return null; - } - - /** - * Determine whether the given Collection only contains a single unique object. - * @param collection the Collection to check - * @return true if the collection contains a single reference or - * multiple references to the same instance, false else - */ - public static boolean hasUniqueObject(Collection collection) { - if (isEmpty(collection)) { - return false; - } - boolean hasCandidate = false; - Object candidate = null; - for (Iterator it = collection.iterator(); it.hasNext();) { - Object elem = it.next(); - if (!hasCandidate) { - hasCandidate = true; - candidate = elem; - } - else if (candidate != elem) { - return false; - } - } - return true; - } - -} diff --git a/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/internal/springutil/ObjectUtils.java b/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/internal/springutil/ObjectUtils.java deleted file mode 100644 index 223b2a1c1..000000000 --- a/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/internal/springutil/ObjectUtils.java +++ /dev/null @@ -1,833 +0,0 @@ -/* - * Copyright 2002-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.argeo.osgi.boot.internal.springutil; - -import java.lang.reflect.Array; -import java.util.Arrays; - -/** - * Miscellaneous object utility methods. Mainly for internal use within the - * framework; consider Jakarta's Commons Lang for a more comprehensive suite - * of object utilities. - * - * @author Juergen Hoeller - * @author Keith Donald - * @author Rod Johnson - * @author Rob Harrop - * @author Alex Ruiz - * @since 19.03.2004 - * @see org.apache.commons.lang.ObjectUtils - */ -public abstract class ObjectUtils { - - private static final int INITIAL_HASH = 7; - private static final int MULTIPLIER = 31; - - private static final String EMPTY_STRING = ""; - private static final String NULL_STRING = "null"; - private static final String ARRAY_START = "{"; - private static final String ARRAY_END = "}"; - private static final String EMPTY_ARRAY = ARRAY_START + ARRAY_END; - private static final String ARRAY_ELEMENT_SEPARATOR = ", "; - - - /** - * Return whether the given throwable is a checked exception: - * that is, neither a RuntimeException nor an Error. - * @param ex the throwable to check - * @return whether the throwable is a checked exception - * @see java.lang.Exception - * @see java.lang.RuntimeException - * @see java.lang.Error - */ - public static boolean isCheckedException(Throwable ex) { - return !(ex instanceof RuntimeException || ex instanceof Error); - } - - /** - * Check whether the given exception is compatible with the exceptions - * declared in a throws clause. - * @param ex the exception to checked - * @param declaredExceptions the exceptions declared in the throws clause - * @return whether the given exception is compatible - */ - public static boolean isCompatibleWithThrowsClause(Throwable ex, Class[] declaredExceptions) { - if (!isCheckedException(ex)) { - return true; - } - if (declaredExceptions != null) { - for (int i = 0; i < declaredExceptions.length; i++) { - if (declaredExceptions[i].isAssignableFrom(ex.getClass())) { - return true; - } - } - } - return false; - } - - /** - * Return whether the given array is empty: that is, null - * or of zero length. - * @param array the array to check - * @return whether the given array is empty - */ - public static boolean isEmpty(Object[] array) { - return (array == null || array.length == 0); - } - - /** - * Check whether the given array contains the given element. - * @param array the array to check (may be null, - * in which case the return value will always be false) - * @param element the element to check for - * @return whether the element has been found in the given array - */ - public static boolean containsElement(Object[] array, Object element) { - if (array == null) { - return false; - } - for (int i = 0; i < array.length; i++) { - if (nullSafeEquals(array[i], element)) { - return true; - } - } - return false; - } - - /** - * Append the given Object to the given array, returning a new array - * consisting of the input array contents plus the given Object. - * @param array the array to append to (can be null) - * @param obj the Object to append - * @return the new array (of the same component type; never null) - */ - public static Object[] addObjectToArray(Object[] array, Object obj) { - Class compType = Object.class; - if (array != null) { - compType = array.getClass().getComponentType(); - } - else if (obj != null) { - compType = obj.getClass(); - } - int newArrLength = (array != null ? array.length + 1 : 1); - Object[] newArr = (Object[]) Array.newInstance(compType, newArrLength); - if (array != null) { - System.arraycopy(array, 0, newArr, 0, array.length); - } - newArr[newArr.length - 1] = obj; - return newArr; - } - - /** - * Convert the given array (which may be a primitive array) to an - * object array (if necessary of primitive wrapper objects). - *

A null source value will be converted to an - * empty Object array. - * @param source the (potentially primitive) array - * @return the corresponding object array (never null) - * @throws IllegalArgumentException if the parameter is not an array - */ - public static Object[] toObjectArray(Object source) { - if (source instanceof Object[]) { - return (Object[]) source; - } - if (source == null) { - return new Object[0]; - } - if (!source.getClass().isArray()) { - throw new IllegalArgumentException("Source is not an array: " + source); - } - int length = Array.getLength(source); - if (length == 0) { - return new Object[0]; - } - Class wrapperType = Array.get(source, 0).getClass(); - Object[] newArray = (Object[]) Array.newInstance(wrapperType, length); - for (int i = 0; i < length; i++) { - newArray[i] = Array.get(source, i); - } - return newArray; - } - - - //--------------------------------------------------------------------- - // Convenience methods for content-based equality/hash-code handling - //--------------------------------------------------------------------- - - /** - * Determine if the given objects are equal, returning true - * if both are null or false if only one is - * null. - *

Compares arrays with Arrays.equals, performing an equality - * check based on the array elements rather than the array reference. - * @param o1 first Object to compare - * @param o2 second Object to compare - * @return whether the given objects are equal - * @see java.util.Arrays#equals - */ - public static boolean nullSafeEquals(Object o1, Object o2) { - if (o1 == o2) { - return true; - } - if (o1 == null || o2 == null) { - return false; - } - if (o1.equals(o2)) { - return true; - } - if (o1.getClass().isArray() && o2.getClass().isArray()) { - if (o1 instanceof Object[] && o2 instanceof Object[]) { - return Arrays.equals((Object[]) o1, (Object[]) o2); - } - if (o1 instanceof boolean[] && o2 instanceof boolean[]) { - return Arrays.equals((boolean[]) o1, (boolean[]) o2); - } - if (o1 instanceof byte[] && o2 instanceof byte[]) { - return Arrays.equals((byte[]) o1, (byte[]) o2); - } - if (o1 instanceof char[] && o2 instanceof char[]) { - return Arrays.equals((char[]) o1, (char[]) o2); - } - if (o1 instanceof double[] && o2 instanceof double[]) { - return Arrays.equals((double[]) o1, (double[]) o2); - } - if (o1 instanceof float[] && o2 instanceof float[]) { - return Arrays.equals((float[]) o1, (float[]) o2); - } - if (o1 instanceof int[] && o2 instanceof int[]) { - return Arrays.equals((int[]) o1, (int[]) o2); - } - if (o1 instanceof long[] && o2 instanceof long[]) { - return Arrays.equals((long[]) o1, (long[]) o2); - } - if (o1 instanceof short[] && o2 instanceof short[]) { - return Arrays.equals((short[]) o1, (short[]) o2); - } - } - return false; - } - - /** - * Return as hash code for the given object; typically the value of - * {@link Object#hashCode()}. If the object is an array, - * this method will delegate to any of the nullSafeHashCode - * methods for arrays in this class. If the object is null, - * this method returns 0. - * @see #nullSafeHashCode(Object[]) - * @see #nullSafeHashCode(boolean[]) - * @see #nullSafeHashCode(byte[]) - * @see #nullSafeHashCode(char[]) - * @see #nullSafeHashCode(double[]) - * @see #nullSafeHashCode(float[]) - * @see #nullSafeHashCode(int[]) - * @see #nullSafeHashCode(long[]) - * @see #nullSafeHashCode(short[]) - */ - public static int nullSafeHashCode(Object obj) { - if (obj == null) { - return 0; - } - if (obj.getClass().isArray()) { - if (obj instanceof Object[]) { - return nullSafeHashCode((Object[]) obj); - } - if (obj instanceof boolean[]) { - return nullSafeHashCode((boolean[]) obj); - } - if (obj instanceof byte[]) { - return nullSafeHashCode((byte[]) obj); - } - if (obj instanceof char[]) { - return nullSafeHashCode((char[]) obj); - } - if (obj instanceof double[]) { - return nullSafeHashCode((double[]) obj); - } - if (obj instanceof float[]) { - return nullSafeHashCode((float[]) obj); - } - if (obj instanceof int[]) { - return nullSafeHashCode((int[]) obj); - } - if (obj instanceof long[]) { - return nullSafeHashCode((long[]) obj); - } - if (obj instanceof short[]) { - return nullSafeHashCode((short[]) obj); - } - } - return obj.hashCode(); - } - - /** - * Return a hash code based on the contents of the specified array. - * If array is null, this method returns 0. - */ - public static int nullSafeHashCode(Object[] array) { - if (array == null) { - return 0; - } - int hash = INITIAL_HASH; - int arraySize = array.length; - for (int i = 0; i < arraySize; i++) { - hash = MULTIPLIER * hash + nullSafeHashCode(array[i]); - } - return hash; - } - - /** - * Return a hash code based on the contents of the specified array. - * If array is null, this method returns 0. - */ - public static int nullSafeHashCode(boolean[] array) { - if (array == null) { - return 0; - } - int hash = INITIAL_HASH; - int arraySize = array.length; - for (int i = 0; i < arraySize; i++) { - hash = MULTIPLIER * hash + hashCode(array[i]); - } - return hash; - } - - /** - * Return a hash code based on the contents of the specified array. - * If array is null, this method returns 0. - */ - public static int nullSafeHashCode(byte[] array) { - if (array == null) { - return 0; - } - int hash = INITIAL_HASH; - int arraySize = array.length; - for (int i = 0; i < arraySize; i++) { - hash = MULTIPLIER * hash + array[i]; - } - return hash; - } - - /** - * Return a hash code based on the contents of the specified array. - * If array is null, this method returns 0. - */ - public static int nullSafeHashCode(char[] array) { - if (array == null) { - return 0; - } - int hash = INITIAL_HASH; - int arraySize = array.length; - for (int i = 0; i < arraySize; i++) { - hash = MULTIPLIER * hash + array[i]; - } - return hash; - } - - /** - * Return a hash code based on the contents of the specified array. - * If array is null, this method returns 0. - */ - public static int nullSafeHashCode(double[] array) { - if (array == null) { - return 0; - } - int hash = INITIAL_HASH; - int arraySize = array.length; - for (int i = 0; i < arraySize; i++) { - hash = MULTIPLIER * hash + hashCode(array[i]); - } - return hash; - } - - /** - * Return a hash code based on the contents of the specified array. - * If array is null, this method returns 0. - */ - public static int nullSafeHashCode(float[] array) { - if (array == null) { - return 0; - } - int hash = INITIAL_HASH; - int arraySize = array.length; - for (int i = 0; i < arraySize; i++) { - hash = MULTIPLIER * hash + hashCode(array[i]); - } - return hash; - } - - /** - * Return a hash code based on the contents of the specified array. - * If array is null, this method returns 0. - */ - public static int nullSafeHashCode(int[] array) { - if (array == null) { - return 0; - } - int hash = INITIAL_HASH; - int arraySize = array.length; - for (int i = 0; i < arraySize; i++) { - hash = MULTIPLIER * hash + array[i]; - } - return hash; - } - - /** - * Return a hash code based on the contents of the specified array. - * If array is null, this method returns 0. - */ - public static int nullSafeHashCode(long[] array) { - if (array == null) { - return 0; - } - int hash = INITIAL_HASH; - int arraySize = array.length; - for (int i = 0; i < arraySize; i++) { - hash = MULTIPLIER * hash + hashCode(array[i]); - } - return hash; - } - - /** - * Return a hash code based on the contents of the specified array. - * If array is null, this method returns 0. - */ - public static int nullSafeHashCode(short[] array) { - if (array == null) { - return 0; - } - int hash = INITIAL_HASH; - int arraySize = array.length; - for (int i = 0; i < arraySize; i++) { - hash = MULTIPLIER * hash + array[i]; - } - return hash; - } - - /** - * Return the same value as {@link Boolean#hashCode()}. - * @see Boolean#hashCode() - */ - public static int hashCode(boolean bool) { - return bool ? 1231 : 1237; - } - - /** - * Return the same value as {@link Double#hashCode()}. - * @see Double#hashCode() - */ - public static int hashCode(double dbl) { - long bits = Double.doubleToLongBits(dbl); - return hashCode(bits); - } - - /** - * Return the same value as {@link Float#hashCode()}. - * @see Float#hashCode() - */ - public static int hashCode(float flt) { - return Float.floatToIntBits(flt); - } - - /** - * Return the same value as {@link Long#hashCode()}. - * @see Long#hashCode() - */ - public static int hashCode(long lng) { - return (int) (lng ^ (lng >>> 32)); - } - - - //--------------------------------------------------------------------- - // Convenience methods for toString output - //--------------------------------------------------------------------- - - /** - * Return a String representation of an object's overall identity. - * @param obj the object (may be null) - * @return the object's identity as String representation, - * or an empty String if the object was null - */ - public static String identityToString(Object obj) { - if (obj == null) { - return EMPTY_STRING; - } - return obj.getClass().getName() + "@" + getIdentityHexString(obj); - } - - /** - * Return a hex String form of an object's identity hash code. - * @param obj the object - * @return the object's identity code in hex notation - */ - public static String getIdentityHexString(Object obj) { - return Integer.toHexString(System.identityHashCode(obj)); - } - - /** - * Return a content-based String representation if obj is - * not null; otherwise returns an empty String. - *

Differs from {@link #nullSafeToString(Object)} in that it returns - * an empty String rather than "null" for a null value. - * @param obj the object to build a display String for - * @return a display String representation of obj - * @see #nullSafeToString(Object) - */ - public static String getDisplayString(Object obj) { - if (obj == null) { - return EMPTY_STRING; - } - return nullSafeToString(obj); - } - - /** - * Determine the class name for the given object. - *

Returns "null" if obj is null. - * @param obj the object to introspect (may be null) - * @return the corresponding class name - */ - public static String nullSafeClassName(Object obj) { - return (obj != null ? obj.getClass().getName() : NULL_STRING); - } - - /** - * Return a String representation of the specified Object. - *

Builds a String representation of the contents in case of an array. - * Returns "null" if obj is null. - * @param obj the object to build a String representation for - * @return a String representation of obj - */ - public static String nullSafeToString(Object obj) { - if (obj == null) { - return NULL_STRING; - } - if (obj instanceof String) { - return (String) obj; - } - if (obj instanceof Object[]) { - return nullSafeToString((Object[]) obj); - } - if (obj instanceof boolean[]) { - return nullSafeToString((boolean[]) obj); - } - if (obj instanceof byte[]) { - return nullSafeToString((byte[]) obj); - } - if (obj instanceof char[]) { - return nullSafeToString((char[]) obj); - } - if (obj instanceof double[]) { - return nullSafeToString((double[]) obj); - } - if (obj instanceof float[]) { - return nullSafeToString((float[]) obj); - } - if (obj instanceof int[]) { - return nullSafeToString((int[]) obj); - } - if (obj instanceof long[]) { - return nullSafeToString((long[]) obj); - } - if (obj instanceof short[]) { - return nullSafeToString((short[]) obj); - } - String str = obj.toString(); - return (str != null ? str : EMPTY_STRING); - } - - /** - * Return a String representation of the contents of the specified array. - *

The String representation consists of a list of the array's elements, - * enclosed in curly braces ("{}"). Adjacent elements are separated - * by the characters ", " (a comma followed by a space). Returns - * "null" if array is null. - * @param array the array to build a String representation for - * @return a String representation of array - */ - public static String nullSafeToString(Object[] array) { - if (array == null) { - return NULL_STRING; - } - int length = array.length; - if (length == 0) { - return EMPTY_ARRAY; - } - StringBuffer buffer = new StringBuffer(); - for (int i = 0; i < length; i++) { - if (i == 0) { - buffer.append(ARRAY_START); - } - else { - buffer.append(ARRAY_ELEMENT_SEPARATOR); - } - buffer.append(String.valueOf(array[i])); - } - buffer.append(ARRAY_END); - return buffer.toString(); - } - - /** - * Return a String representation of the contents of the specified array. - *

The String representation consists of a list of the array's elements, - * enclosed in curly braces ("{}"). Adjacent elements are separated - * by the characters ", " (a comma followed by a space). Returns - * "null" if array is null. - * @param array the array to build a String representation for - * @return a String representation of array - */ - public static String nullSafeToString(boolean[] array) { - if (array == null) { - return NULL_STRING; - } - int length = array.length; - if (length == 0) { - return EMPTY_ARRAY; - } - StringBuffer buffer = new StringBuffer(); - for (int i = 0; i < length; i++) { - if (i == 0) { - buffer.append(ARRAY_START); - } - else { - buffer.append(ARRAY_ELEMENT_SEPARATOR); - } - - buffer.append(array[i]); - } - buffer.append(ARRAY_END); - return buffer.toString(); - } - - /** - * Return a String representation of the contents of the specified array. - *

The String representation consists of a list of the array's elements, - * enclosed in curly braces ("{}"). Adjacent elements are separated - * by the characters ", " (a comma followed by a space). Returns - * "null" if array is null. - * @param array the array to build a String representation for - * @return a String representation of array - */ - public static String nullSafeToString(byte[] array) { - if (array == null) { - return NULL_STRING; - } - int length = array.length; - if (length == 0) { - return EMPTY_ARRAY; - } - StringBuffer buffer = new StringBuffer(); - for (int i = 0; i < length; i++) { - if (i == 0) { - buffer.append(ARRAY_START); - } - else { - buffer.append(ARRAY_ELEMENT_SEPARATOR); - } - buffer.append(array[i]); - } - buffer.append(ARRAY_END); - return buffer.toString(); - } - - /** - * Return a String representation of the contents of the specified array. - *

The String representation consists of a list of the array's elements, - * enclosed in curly braces ("{}"). Adjacent elements are separated - * by the characters ", " (a comma followed by a space). Returns - * "null" if array is null. - * @param array the array to build a String representation for - * @return a String representation of array - */ - public static String nullSafeToString(char[] array) { - if (array == null) { - return NULL_STRING; - } - int length = array.length; - if (length == 0) { - return EMPTY_ARRAY; - } - StringBuffer buffer = new StringBuffer(); - for (int i = 0; i < length; i++) { - if (i == 0) { - buffer.append(ARRAY_START); - } - else { - buffer.append(ARRAY_ELEMENT_SEPARATOR); - } - buffer.append("'").append(array[i]).append("'"); - } - buffer.append(ARRAY_END); - return buffer.toString(); - } - - /** - * Return a String representation of the contents of the specified array. - *

The String representation consists of a list of the array's elements, - * enclosed in curly braces ("{}"). Adjacent elements are separated - * by the characters ", " (a comma followed by a space). Returns - * "null" if array is null. - * @param array the array to build a String representation for - * @return a String representation of array - */ - public static String nullSafeToString(double[] array) { - if (array == null) { - return NULL_STRING; - } - int length = array.length; - if (length == 0) { - return EMPTY_ARRAY; - } - StringBuffer buffer = new StringBuffer(); - for (int i = 0; i < length; i++) { - if (i == 0) { - buffer.append(ARRAY_START); - } - else { - buffer.append(ARRAY_ELEMENT_SEPARATOR); - } - - buffer.append(array[i]); - } - buffer.append(ARRAY_END); - return buffer.toString(); - } - - /** - * Return a String representation of the contents of the specified array. - *

The String representation consists of a list of the array's elements, - * enclosed in curly braces ("{}"). Adjacent elements are separated - * by the characters ", " (a comma followed by a space). Returns - * "null" if array is null. - * @param array the array to build a String representation for - * @return a String representation of array - */ - public static String nullSafeToString(float[] array) { - if (array == null) { - return NULL_STRING; - } - int length = array.length; - if (length == 0) { - return EMPTY_ARRAY; - } - StringBuffer buffer = new StringBuffer(); - for (int i = 0; i < length; i++) { - if (i == 0) { - buffer.append(ARRAY_START); - } - else { - buffer.append(ARRAY_ELEMENT_SEPARATOR); - } - - buffer.append(array[i]); - } - buffer.append(ARRAY_END); - return buffer.toString(); - } - - /** - * Return a String representation of the contents of the specified array. - *

The String representation consists of a list of the array's elements, - * enclosed in curly braces ("{}"). Adjacent elements are separated - * by the characters ", " (a comma followed by a space). Returns - * "null" if array is null. - * @param array the array to build a String representation for - * @return a String representation of array - */ - public static String nullSafeToString(int[] array) { - if (array == null) { - return NULL_STRING; - } - int length = array.length; - if (length == 0) { - return EMPTY_ARRAY; - } - StringBuffer buffer = new StringBuffer(); - for (int i = 0; i < length; i++) { - if (i == 0) { - buffer.append(ARRAY_START); - } - else { - buffer.append(ARRAY_ELEMENT_SEPARATOR); - } - buffer.append(array[i]); - } - buffer.append(ARRAY_END); - return buffer.toString(); - } - - /** - * Return a String representation of the contents of the specified array. - *

The String representation consists of a list of the array's elements, - * enclosed in curly braces ("{}"). Adjacent elements are separated - * by the characters ", " (a comma followed by a space). Returns - * "null" if array is null. - * @param array the array to build a String representation for - * @return a String representation of array - */ - public static String nullSafeToString(long[] array) { - if (array == null) { - return NULL_STRING; - } - int length = array.length; - if (length == 0) { - return EMPTY_ARRAY; - } - StringBuffer buffer = new StringBuffer(); - for (int i = 0; i < length; i++) { - if (i == 0) { - buffer.append(ARRAY_START); - } - else { - buffer.append(ARRAY_ELEMENT_SEPARATOR); - } - buffer.append(array[i]); - } - buffer.append(ARRAY_END); - return buffer.toString(); - } - - /** - * Return a String representation of the contents of the specified array. - *

The String representation consists of a list of the array's elements, - * enclosed in curly braces ("{}"). Adjacent elements are separated - * by the characters ", " (a comma followed by a space). Returns - * "null" if array is null. - * @param array the array to build a String representation for - * @return a String representation of array - */ - public static String nullSafeToString(short[] array) { - if (array == null) { - return NULL_STRING; - } - int length = array.length; - if (length == 0) { - return EMPTY_ARRAY; - } - StringBuffer buffer = new StringBuffer(); - for (int i = 0; i < length; i++) { - if (i == 0) { - buffer.append(ARRAY_START); - } - else { - buffer.append(ARRAY_ELEMENT_SEPARATOR); - } - buffer.append(array[i]); - } - buffer.append(ARRAY_END); - return buffer.toString(); - } - -} diff --git a/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/internal/springutil/PathMatcher.java b/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/internal/springutil/PathMatcher.java deleted file mode 100644 index d7a23221b..000000000 --- a/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/internal/springutil/PathMatcher.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2002-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.argeo.osgi.boot.internal.springutil; - -/** - * Strategy interface for String-based path matching. - * - *

Used by {@link org.springframework.core.io.support.PathMatchingResourcePatternResolver}, - * {@link org.springframework.web.servlet.handler.AbstractUrlHandlerMapping}, - * {@link org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver}, - * and {@link org.springframework.web.servlet.mvc.WebContentInterceptor}. - * - *

The default implementation is {@link AntPathMatcher}, supporting the - * Ant-style pattern syntax. - * - * @author Juergen Hoeller - * @since 1.2 - * @see AntPathMatcher - */ -public interface PathMatcher { - - /** - * Does the given path represent a pattern that can be matched - * by an implementation of this interface? - *

If the return value is false, then the {@link #match} - * method does not have to be used because direct equality comparisons - * on the static path Strings will lead to the same result. - * @param path the path String to check - * @return true if the given path represents a pattern - */ - boolean isPattern(String path); - - /** - * Match the given path against the given pattern, - * according to this PathMatcher's matching strategy. - * @param pattern the pattern to match against - * @param path the path String to test - * @return true if the supplied path matched, - * false if it didn't - */ - boolean match(String pattern, String path); - - /** - * Match the given path against the corresponding part of the given - * pattern, according to this PathMatcher's matching strategy. - *

Determines whether the pattern at least matches as far as the given base - * path goes, assuming that a full path may then match as well. - * @param pattern the pattern to match against - * @param path the path String to test - * @return true if the supplied path matched, - * false if it didn't - */ - boolean matchStart(String pattern, String path); - - /** - * Given a pattern and a full path, determine the pattern-mapped part. - *

This method is supposed to find out which part of the path is matched - * dynamically through an actual pattern, that is, it strips off a statically - * defined leading path from the given full path, returning only the actually - * pattern-matched part of the path. - *

For example: For "myroot/*.html" as pattern and "myroot/myfile.html" - * as full path, this method should return "myfile.html". The detailed - * determination rules are specified to this PathMatcher's matching strategy. - *

A simple implementation may return the given full path as-is in case - * of an actual pattern, and the empty String in case of the pattern not - * containing any dynamic parts (i.e. the pattern parameter being - * a static path that wouldn't qualify as an actual {@link #isPattern pattern}). - * A sophisticated implementation will differentiate between the static parts - * and the dynamic parts of the given path pattern. - * @param pattern the path pattern - * @param path the full path to introspect - * @return the pattern-mapped part of the given path - * (never null) - */ - String extractPathWithinPattern(String pattern, String path); - -} diff --git a/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/internal/springutil/StringUtils.java b/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/internal/springutil/StringUtils.java deleted file mode 100644 index 262659044..000000000 --- a/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/internal/springutil/StringUtils.java +++ /dev/null @@ -1,1113 +0,0 @@ -/* - * Copyright 2002-2008 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.argeo.osgi.boot.internal.springutil; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Enumeration; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Locale; -import java.util.Properties; -import java.util.Set; -import java.util.StringTokenizer; -import java.util.TreeSet; - -/** - * Miscellaneous {@link String} utility methods. - * - *

Mainly for internal use within the framework; consider - * Jakarta's Commons Lang - * for a more comprehensive suite of String utilities. - * - *

This class delivers some simple functionality that should really - * be provided by the core Java String and {@link StringBuffer} - * classes, such as the ability to {@link #replace} all occurrences of a given - * substring in a target string. It also provides easy-to-use methods to convert - * between delimited strings, such as CSV strings, and collections and arrays. - * - * @author Rod Johnson - * @author Juergen Hoeller - * @author Keith Donald - * @author Rob Harrop - * @author Rick Evans - * @since 16 April 2001 - * @see org.apache.commons.lang.StringUtils - */ -public abstract class StringUtils { - - private static final String FOLDER_SEPARATOR = "/"; - - private static final String WINDOWS_FOLDER_SEPARATOR = "\\"; - - private static final String TOP_PATH = ".."; - - private static final String CURRENT_PATH = "."; - - private static final char EXTENSION_SEPARATOR = '.'; - - - //--------------------------------------------------------------------- - // General convenience methods for working with Strings - //--------------------------------------------------------------------- - - /** - * Check that the given CharSequence is neither null nor of length 0. - * Note: Will return true for a CharSequence that purely consists of whitespace. - *

-	 * StringUtils.hasLength(null) = false
-	 * StringUtils.hasLength("") = false
-	 * StringUtils.hasLength(" ") = true
-	 * StringUtils.hasLength("Hello") = true
-	 * 
- * @param str the CharSequence to check (may be null) - * @return true if the CharSequence is not null and has length - * @see #hasText(String) - */ - public static boolean hasLength(CharSequence str) { - return (str != null && str.length() > 0); - } - - /** - * Check that the given String is neither null nor of length 0. - * Note: Will return true for a String that purely consists of whitespace. - * @param str the String to check (may be null) - * @return true if the String is not null and has length - * @see #hasLength(CharSequence) - */ - public static boolean hasLength(String str) { - return hasLength((CharSequence) str); - } - - /** - * Check whether the given CharSequence has actual text. - * More specifically, returns true if the string not null, - * its length is greater than 0, and it contains at least one non-whitespace character. - *

-	 * StringUtils.hasText(null) = false
-	 * StringUtils.hasText("") = false
-	 * StringUtils.hasText(" ") = false
-	 * StringUtils.hasText("12345") = true
-	 * StringUtils.hasText(" 12345 ") = true
-	 * 
- * @param str the CharSequence to check (may be null) - * @return true if the CharSequence is not null, - * its length is greater than 0, and it does not contain whitespace only - * @see java.lang.Character#isWhitespace - */ - public static boolean hasText(CharSequence str) { - if (!hasLength(str)) { - return false; - } - int strLen = str.length(); - for (int i = 0; i < strLen; i++) { - if (!Character.isWhitespace(str.charAt(i))) { - return true; - } - } - return false; - } - - /** - * Check whether the given String has actual text. - * More specifically, returns true if the string not null, - * its length is greater than 0, and it contains at least one non-whitespace character. - * @param str the String to check (may be null) - * @return true if the String is not null, its length is - * greater than 0, and it does not contain whitespace only - * @see #hasText(CharSequence) - */ - public static boolean hasText(String str) { - return hasText((CharSequence) str); - } - - /** - * Check whether the given CharSequence contains any whitespace characters. - * @param str the CharSequence to check (may be null) - * @return true if the CharSequence is not empty and - * contains at least 1 whitespace character - * @see java.lang.Character#isWhitespace - */ - public static boolean containsWhitespace(CharSequence str) { - if (!hasLength(str)) { - return false; - } - int strLen = str.length(); - for (int i = 0; i < strLen; i++) { - if (Character.isWhitespace(str.charAt(i))) { - return true; - } - } - return false; - } - - /** - * Check whether the given String contains any whitespace characters. - * @param str the String to check (may be null) - * @return true if the String is not empty and - * contains at least 1 whitespace character - * @see #containsWhitespace(CharSequence) - */ - public static boolean containsWhitespace(String str) { - return containsWhitespace((CharSequence) str); - } - - /** - * Trim leading and trailing whitespace from the given String. - * @param str the String to check - * @return the trimmed String - * @see java.lang.Character#isWhitespace - */ - public static String trimWhitespace(String str) { - if (!hasLength(str)) { - return str; - } - StringBuffer buf = new StringBuffer(str); - while (buf.length() > 0 && Character.isWhitespace(buf.charAt(0))) { - buf.deleteCharAt(0); - } - while (buf.length() > 0 && Character.isWhitespace(buf.charAt(buf.length() - 1))) { - buf.deleteCharAt(buf.length() - 1); - } - return buf.toString(); - } - - /** - * Trim all whitespace from the given String: - * leading, trailing, and inbetween characters. - * @param str the String to check - * @return the trimmed String - * @see java.lang.Character#isWhitespace - */ - public static String trimAllWhitespace(String str) { - if (!hasLength(str)) { - return str; - } - StringBuffer buf = new StringBuffer(str); - int index = 0; - while (buf.length() > index) { - if (Character.isWhitespace(buf.charAt(index))) { - buf.deleteCharAt(index); - } - else { - index++; - } - } - return buf.toString(); - } - - /** - * Trim leading whitespace from the given String. - * @param str the String to check - * @return the trimmed String - * @see java.lang.Character#isWhitespace - */ - public static String trimLeadingWhitespace(String str) { - if (!hasLength(str)) { - return str; - } - StringBuffer buf = new StringBuffer(str); - while (buf.length() > 0 && Character.isWhitespace(buf.charAt(0))) { - buf.deleteCharAt(0); - } - return buf.toString(); - } - - /** - * Trim trailing whitespace from the given String. - * @param str the String to check - * @return the trimmed String - * @see java.lang.Character#isWhitespace - */ - public static String trimTrailingWhitespace(String str) { - if (!hasLength(str)) { - return str; - } - StringBuffer buf = new StringBuffer(str); - while (buf.length() > 0 && Character.isWhitespace(buf.charAt(buf.length() - 1))) { - buf.deleteCharAt(buf.length() - 1); - } - return buf.toString(); - } - - /** - * Trim all occurences of the supplied leading character from the given String. - * @param str the String to check - * @param leadingCharacter the leading character to be trimmed - * @return the trimmed String - */ - public static String trimLeadingCharacter(String str, char leadingCharacter) { - if (!hasLength(str)) { - return str; - } - StringBuffer buf = new StringBuffer(str); - while (buf.length() > 0 && buf.charAt(0) == leadingCharacter) { - buf.deleteCharAt(0); - } - return buf.toString(); - } - - /** - * Trim all occurences of the supplied trailing character from the given String. - * @param str the String to check - * @param trailingCharacter the trailing character to be trimmed - * @return the trimmed String - */ - public static String trimTrailingCharacter(String str, char trailingCharacter) { - if (!hasLength(str)) { - return str; - } - StringBuffer buf = new StringBuffer(str); - while (buf.length() > 0 && buf.charAt(buf.length() - 1) == trailingCharacter) { - buf.deleteCharAt(buf.length() - 1); - } - return buf.toString(); - } - - - /** - * Test if the given String starts with the specified prefix, - * ignoring upper/lower case. - * @param str the String to check - * @param prefix the prefix to look for - * @see java.lang.String#startsWith - */ - public static boolean startsWithIgnoreCase(String str, String prefix) { - if (str == null || prefix == null) { - return false; - } - if (str.startsWith(prefix)) { - return true; - } - if (str.length() < prefix.length()) { - return false; - } - String lcStr = str.substring(0, prefix.length()).toLowerCase(); - String lcPrefix = prefix.toLowerCase(); - return lcStr.equals(lcPrefix); - } - - /** - * Test if the given String ends with the specified suffix, - * ignoring upper/lower case. - * @param str the String to check - * @param suffix the suffix to look for - * @see java.lang.String#endsWith - */ - public static boolean endsWithIgnoreCase(String str, String suffix) { - if (str == null || suffix == null) { - return false; - } - if (str.endsWith(suffix)) { - return true; - } - if (str.length() < suffix.length()) { - return false; - } - - String lcStr = str.substring(str.length() - suffix.length()).toLowerCase(); - String lcSuffix = suffix.toLowerCase(); - return lcStr.equals(lcSuffix); - } - - /** - * Test whether the given string matches the given substring - * at the given index. - * @param str the original string (or StringBuffer) - * @param index the index in the original string to start matching against - * @param substring the substring to match at the given index - */ - public static boolean substringMatch(CharSequence str, int index, CharSequence substring) { - for (int j = 0; j < substring.length(); j++) { - int i = index + j; - if (i >= str.length() || str.charAt(i) != substring.charAt(j)) { - return false; - } - } - return true; - } - - /** - * Count the occurrences of the substring in string s. - * @param str string to search in. Return 0 if this is null. - * @param sub string to search for. Return 0 if this is null. - */ - public static int countOccurrencesOf(String str, String sub) { - if (str == null || sub == null || str.length() == 0 || sub.length() == 0) { - return 0; - } - int count = 0, pos = 0, idx = 0; - while ((idx = str.indexOf(sub, pos)) != -1) { - ++count; - pos = idx + sub.length(); - } - return count; - } - - /** - * Replace all occurences of a substring within a string with - * another string. - * @param inString String to examine - * @param oldPattern String to replace - * @param newPattern String to insert - * @return a String with the replacements - */ - public static String replace(String inString, String oldPattern, String newPattern) { - if (!hasLength(inString) || !hasLength(oldPattern) || newPattern == null) { - return inString; - } - StringBuffer sbuf = new StringBuffer(); - // output StringBuffer we'll build up - int pos = 0; // our position in the old string - int index = inString.indexOf(oldPattern); - // the index of an occurrence we've found, or -1 - int patLen = oldPattern.length(); - while (index >= 0) { - sbuf.append(inString.substring(pos, index)); - sbuf.append(newPattern); - pos = index + patLen; - index = inString.indexOf(oldPattern, pos); - } - sbuf.append(inString.substring(pos)); - // remember to append any characters to the right of a match - return sbuf.toString(); - } - - /** - * Delete all occurrences of the given substring. - * @param inString the original String - * @param pattern the pattern to delete all occurrences of - * @return the resulting String - */ - public static String delete(String inString, String pattern) { - return replace(inString, pattern, ""); - } - - /** - * Delete any character in a given String. - * @param inString the original String - * @param charsToDelete a set of characters to delete. - * E.g. "az\n" will delete 'a's, 'z's and new lines. - * @return the resulting String - */ - public static String deleteAny(String inString, String charsToDelete) { - if (!hasLength(inString) || !hasLength(charsToDelete)) { - return inString; - } - StringBuffer out = new StringBuffer(); - for (int i = 0; i < inString.length(); i++) { - char c = inString.charAt(i); - if (charsToDelete.indexOf(c) == -1) { - out.append(c); - } - } - return out.toString(); - } - - - //--------------------------------------------------------------------- - // Convenience methods for working with formatted Strings - //--------------------------------------------------------------------- - - /** - * Quote the given String with single quotes. - * @param str the input String (e.g. "myString") - * @return the quoted String (e.g. "'myString'"), - * or null if the input was null - */ - public static String quote(String str) { - return (str != null ? "'" + str + "'" : null); - } - - /** - * Turn the given Object into a String with single quotes - * if it is a String; keeping the Object as-is else. - * @param obj the input Object (e.g. "myString") - * @return the quoted String (e.g. "'myString'"), - * or the input object as-is if not a String - */ - public static Object quoteIfString(Object obj) { - return (obj instanceof String ? quote((String) obj) : obj); - } - - /** - * Unqualify a string qualified by a '.' dot character. For example, - * "this.name.is.qualified", returns "qualified". - * @param qualifiedName the qualified name - */ - public static String unqualify(String qualifiedName) { - return unqualify(qualifiedName, '.'); - } - - /** - * Unqualify a string qualified by a separator character. For example, - * "this:name:is:qualified" returns "qualified" if using a ':' separator. - * @param qualifiedName the qualified name - * @param separator the separator - */ - public static String unqualify(String qualifiedName, char separator) { - return qualifiedName.substring(qualifiedName.lastIndexOf(separator) + 1); - } - - /** - * Capitalize a String, changing the first letter to - * upper case as per {@link Character#toUpperCase(char)}. - * No other letters are changed. - * @param str the String to capitalize, may be null - * @return the capitalized String, null if null - */ - public static String capitalize(String str) { - return changeFirstCharacterCase(str, true); - } - - /** - * Uncapitalize a String, changing the first letter to - * lower case as per {@link Character#toLowerCase(char)}. - * No other letters are changed. - * @param str the String to uncapitalize, may be null - * @return the uncapitalized String, null if null - */ - public static String uncapitalize(String str) { - return changeFirstCharacterCase(str, false); - } - - private static String changeFirstCharacterCase(String str, boolean capitalize) { - if (str == null || str.length() == 0) { - return str; - } - StringBuffer buf = new StringBuffer(str.length()); - if (capitalize) { - buf.append(Character.toUpperCase(str.charAt(0))); - } - else { - buf.append(Character.toLowerCase(str.charAt(0))); - } - buf.append(str.substring(1)); - return buf.toString(); - } - - /** - * Extract the filename from the given path, - * e.g. "mypath/myfile.txt" -> "myfile.txt". - * @param path the file path (may be null) - * @return the extracted filename, or null if none - */ - public static String getFilename(String path) { - if (path == null) { - return null; - } - int separatorIndex = path.lastIndexOf(FOLDER_SEPARATOR); - return (separatorIndex != -1 ? path.substring(separatorIndex + 1) : path); - } - - /** - * Extract the filename extension from the given path, - * e.g. "mypath/myfile.txt" -> "txt". - * @param path the file path (may be null) - * @return the extracted filename extension, or null if none - */ - public static String getFilenameExtension(String path) { - if (path == null) { - return null; - } - int sepIndex = path.lastIndexOf(EXTENSION_SEPARATOR); - return (sepIndex != -1 ? path.substring(sepIndex + 1) : null); - } - - /** - * Strip the filename extension from the given path, - * e.g. "mypath/myfile.txt" -> "mypath/myfile". - * @param path the file path (may be null) - * @return the path with stripped filename extension, - * or null if none - */ - public static String stripFilenameExtension(String path) { - if (path == null) { - return null; - } - int sepIndex = path.lastIndexOf(EXTENSION_SEPARATOR); - return (sepIndex != -1 ? path.substring(0, sepIndex) : path); - } - - /** - * Apply the given relative path to the given path, - * assuming standard Java folder separation (i.e. "/" separators); - * @param path the path to start from (usually a full file path) - * @param relativePath the relative path to apply - * (relative to the full file path above) - * @return the full file path that results from applying the relative path - */ - public static String applyRelativePath(String path, String relativePath) { - int separatorIndex = path.lastIndexOf(FOLDER_SEPARATOR); - if (separatorIndex != -1) { - String newPath = path.substring(0, separatorIndex); - if (!relativePath.startsWith(FOLDER_SEPARATOR)) { - newPath += FOLDER_SEPARATOR; - } - return newPath + relativePath; - } - else { - return relativePath; - } - } - - /** - * Normalize the path by suppressing sequences like "path/.." and - * inner simple dots. - *

The result is convenient for path comparison. For other uses, - * notice that Windows separators ("\") are replaced by simple slashes. - * @param path the original path - * @return the normalized path - */ - public static String cleanPath(String path) { - if (path == null) { - return null; - } - String pathToUse = replace(path, WINDOWS_FOLDER_SEPARATOR, FOLDER_SEPARATOR); - - // Strip prefix from path to analyze, to not treat it as part of the - // first path element. This is necessary to correctly parse paths like - // "file:core/../core/io/Resource.class", where the ".." should just - // strip the first "core" directory while keeping the "file:" prefix. - int prefixIndex = pathToUse.indexOf(":"); - String prefix = ""; - if (prefixIndex != -1) { - prefix = pathToUse.substring(0, prefixIndex + 1); - pathToUse = pathToUse.substring(prefixIndex + 1); - } - if (pathToUse.startsWith(FOLDER_SEPARATOR)) { - prefix = prefix + FOLDER_SEPARATOR; - pathToUse = pathToUse.substring(1); - } - - String[] pathArray = delimitedListToStringArray(pathToUse, FOLDER_SEPARATOR); - List pathElements = new LinkedList(); - int tops = 0; - - for (int i = pathArray.length - 1; i >= 0; i--) { - String element = pathArray[i]; - if (CURRENT_PATH.equals(element)) { - // Points to current directory - drop it. - } - else if (TOP_PATH.equals(element)) { - // Registering top path found. - tops++; - } - else { - if (tops > 0) { - // Merging path element with element corresponding to top path. - tops--; - } - else { - // Normal path element found. - pathElements.add(0, element); - } - } - } - - // Remaining top paths need to be retained. - for (int i = 0; i < tops; i++) { - pathElements.add(0, TOP_PATH); - } - - return prefix + collectionToDelimitedString(pathElements, FOLDER_SEPARATOR); - } - - /** - * Compare two paths after normalization of them. - * @param path1 first path for comparison - * @param path2 second path for comparison - * @return whether the two paths are equivalent after normalization - */ - public static boolean pathEquals(String path1, String path2) { - return cleanPath(path1).equals(cleanPath(path2)); - } - - /** - * Parse the given localeString into a {@link Locale}. - *

This is the inverse operation of {@link Locale#toString Locale's toString}. - * @param localeString the locale string, following Locale's - * toString() format ("en", "en_UK", etc); - * also accepts spaces as separators, as an alternative to underscores - * @return a corresponding Locale instance - */ - public static Locale parseLocaleString(String localeString) { - String[] parts = tokenizeToStringArray(localeString, "_ ", false, false); - String language = (parts.length > 0 ? parts[0] : ""); - String country = (parts.length > 1 ? parts[1] : ""); - String variant = ""; - if (parts.length >= 2) { - // There is definitely a variant, and it is everything after the country - // code sans the separator between the country code and the variant. - int endIndexOfCountryCode = localeString.indexOf(country) + country.length(); - // Strip off any leading '_' and whitespace, what's left is the variant. - variant = trimLeadingWhitespace(localeString.substring(endIndexOfCountryCode)); - if (variant.startsWith("_")) { - variant = trimLeadingCharacter(variant, '_'); - } - } - return (language.length() > 0 ? new Locale(language, country, variant) : null); - } - - /** - * Determine the RFC 3066 compliant language tag, - * as used for the HTTP "Accept-Language" header. - * @param locale the Locale to transform to a language tag - * @return the RFC 3066 compliant language tag as String - */ - public static String toLanguageTag(Locale locale) { - return locale.getLanguage() + (hasText(locale.getCountry()) ? "-" + locale.getCountry() : ""); - } - - - //--------------------------------------------------------------------- - // Convenience methods for working with String arrays - //--------------------------------------------------------------------- - - /** - * Append the given String to the given String array, returning a new array - * consisting of the input array contents plus the given String. - * @param array the array to append to (can be null) - * @param str the String to append - * @return the new array (never null) - */ - public static String[] addStringToArray(String[] array, String str) { - if (ObjectUtils.isEmpty(array)) { - return new String[] {str}; - } - String[] newArr = new String[array.length + 1]; - System.arraycopy(array, 0, newArr, 0, array.length); - newArr[array.length] = str; - return newArr; - } - - /** - * Concatenate the given String arrays into one, - * with overlapping array elements included twice. - *

The order of elements in the original arrays is preserved. - * @param array1 the first array (can be null) - * @param array2 the second array (can be null) - * @return the new array (null if both given arrays were null) - */ - public static String[] concatenateStringArrays(String[] array1, String[] array2) { - if (ObjectUtils.isEmpty(array1)) { - return array2; - } - if (ObjectUtils.isEmpty(array2)) { - return array1; - } - String[] newArr = new String[array1.length + array2.length]; - System.arraycopy(array1, 0, newArr, 0, array1.length); - System.arraycopy(array2, 0, newArr, array1.length, array2.length); - return newArr; - } - - /** - * Merge the given String arrays into one, with overlapping - * array elements only included once. - *

The order of elements in the original arrays is preserved - * (with the exception of overlapping elements, which are only - * included on their first occurence). - * @param array1 the first array (can be null) - * @param array2 the second array (can be null) - * @return the new array (null if both given arrays were null) - */ - public static String[] mergeStringArrays(String[] array1, String[] array2) { - if (ObjectUtils.isEmpty(array1)) { - return array2; - } - if (ObjectUtils.isEmpty(array2)) { - return array1; - } - List result = new ArrayList(); - result.addAll(Arrays.asList(array1)); - for (int i = 0; i < array2.length; i++) { - String str = array2[i]; - if (!result.contains(str)) { - result.add(str); - } - } - return toStringArray(result); - } - - /** - * Turn given source String array into sorted array. - * @param array the source array - * @return the sorted array (never null) - */ - public static String[] sortStringArray(String[] array) { - if (ObjectUtils.isEmpty(array)) { - return new String[0]; - } - Arrays.sort(array); - return array; - } - - /** - * Copy the given Collection into a String array. - * The Collection must contain String elements only. - * @param collection the Collection to copy - * @return the String array (null if the passed-in - * Collection was null) - */ - public static String[] toStringArray(Collection collection) { - if (collection == null) { - return null; - } - return (String[]) collection.toArray(new String[collection.size()]); - } - - /** - * Copy the given Enumeration into a String array. - * The Enumeration must contain String elements only. - * @param enumeration the Enumeration to copy - * @return the String array (null if the passed-in - * Enumeration was null) - */ - public static String[] toStringArray(Enumeration enumeration) { - if (enumeration == null) { - return null; - } - List list = Collections.list(enumeration); - return (String[]) list.toArray(new String[list.size()]); - } - - /** - * Trim the elements of the given String array, - * calling String.trim() on each of them. - * @param array the original String array - * @return the resulting array (of the same size) with trimmed elements - */ - public static String[] trimArrayElements(String[] array) { - if (ObjectUtils.isEmpty(array)) { - return new String[0]; - } - String[] result = new String[array.length]; - for (int i = 0; i < array.length; i++) { - String element = array[i]; - result[i] = (element != null ? element.trim() : null); - } - return result; - } - - /** - * Remove duplicate Strings from the given array. - * Also sorts the array, as it uses a TreeSet. - * @param array the String array - * @return an array without duplicates, in natural sort order - */ - public static String[] removeDuplicateStrings(String[] array) { - if (ObjectUtils.isEmpty(array)) { - return array; - } - Set set = new TreeSet(); - for (int i = 0; i < array.length; i++) { - set.add(array[i]); - } - return toStringArray(set); - } - - /** - * Split a String at the first occurrence of the delimiter. - * Does not include the delimiter in the result. - * @param toSplit the string to split - * @param delimiter to split the string up with - * @return a two element array with index 0 being before the delimiter, and - * index 1 being after the delimiter (neither element includes the delimiter); - * or null if the delimiter wasn't found in the given input String - */ - public static String[] split(String toSplit, String delimiter) { - if (!hasLength(toSplit) || !hasLength(delimiter)) { - return null; - } - int offset = toSplit.indexOf(delimiter); - if (offset < 0) { - return null; - } - String beforeDelimiter = toSplit.substring(0, offset); - String afterDelimiter = toSplit.substring(offset + delimiter.length()); - return new String[] {beforeDelimiter, afterDelimiter}; - } - - /** - * Take an array Strings and split each element based on the given delimiter. - * A Properties instance is then generated, with the left of the - * delimiter providing the key, and the right of the delimiter providing the value. - *

Will trim both the key and value before adding them to the - * Properties instance. - * @param array the array to process - * @param delimiter to split each element using (typically the equals symbol) - * @return a Properties instance representing the array contents, - * or null if the array to process was null or empty - */ - public static Properties splitArrayElementsIntoProperties(String[] array, String delimiter) { - return splitArrayElementsIntoProperties(array, delimiter, null); - } - - /** - * Take an array Strings and split each element based on the given delimiter. - * A Properties instance is then generated, with the left of the - * delimiter providing the key, and the right of the delimiter providing the value. - *

Will trim both the key and value before adding them to the - * Properties instance. - * @param array the array to process - * @param delimiter to split each element using (typically the equals symbol) - * @param charsToDelete one or more characters to remove from each element - * prior to attempting the split operation (typically the quotation mark - * symbol), or null if no removal should occur - * @return a Properties instance representing the array contents, - * or null if the array to process was null or empty - */ - public static Properties splitArrayElementsIntoProperties( - String[] array, String delimiter, String charsToDelete) { - - if (ObjectUtils.isEmpty(array)) { - return null; - } - Properties result = new Properties(); - for (int i = 0; i < array.length; i++) { - String element = array[i]; - if (charsToDelete != null) { - element = deleteAny(array[i], charsToDelete); - } - String[] splittedElement = split(element, delimiter); - if (splittedElement == null) { - continue; - } - result.setProperty(splittedElement[0].trim(), splittedElement[1].trim()); - } - return result; - } - - /** - * Tokenize the given String into a String array via a StringTokenizer. - * Trims tokens and omits empty tokens. - *

The given delimiters string is supposed to consist of any number of - * delimiter characters. Each of those characters can be used to separate - * tokens. A delimiter is always a single character; for multi-character - * delimiters, consider using delimitedListToStringArray - * @param str the String to tokenize - * @param delimiters the delimiter characters, assembled as String - * (each of those characters is individually considered as delimiter). - * @return an array of the tokens - * @see java.util.StringTokenizer - * @see java.lang.String#trim() - * @see #delimitedListToStringArray - */ - public static String[] tokenizeToStringArray(String str, String delimiters) { - return tokenizeToStringArray(str, delimiters, true, true); - } - - /** - * Tokenize the given String into a String array via a StringTokenizer. - *

The given delimiters string is supposed to consist of any number of - * delimiter characters. Each of those characters can be used to separate - * tokens. A delimiter is always a single character; for multi-character - * delimiters, consider using delimitedListToStringArray - * @param str the String to tokenize - * @param delimiters the delimiter characters, assembled as String - * (each of those characters is individually considered as delimiter) - * @param trimTokens trim the tokens via String's trim - * @param ignoreEmptyTokens omit empty tokens from the result array - * (only applies to tokens that are empty after trimming; StringTokenizer - * will not consider subsequent delimiters as token in the first place). - * @return an array of the tokens (null if the input String - * was null) - * @see java.util.StringTokenizer - * @see java.lang.String#trim() - * @see #delimitedListToStringArray - */ - public static String[] tokenizeToStringArray( - String str, String delimiters, boolean trimTokens, boolean ignoreEmptyTokens) { - - if (str == null) { - return null; - } - StringTokenizer st = new StringTokenizer(str, delimiters); - List tokens = new ArrayList(); - while (st.hasMoreTokens()) { - String token = st.nextToken(); - if (trimTokens) { - token = token.trim(); - } - if (!ignoreEmptyTokens || token.length() > 0) { - tokens.add(token); - } - } - return toStringArray(tokens); - } - - /** - * Take a String which is a delimited list and convert it to a String array. - *

A single delimiter can consists of more than one character: It will still - * be considered as single delimiter string, rather than as bunch of potential - * delimiter characters - in contrast to tokenizeToStringArray. - * @param str the input String - * @param delimiter the delimiter between elements (this is a single delimiter, - * rather than a bunch individual delimiter characters) - * @return an array of the tokens in the list - * @see #tokenizeToStringArray - */ - public static String[] delimitedListToStringArray(String str, String delimiter) { - return delimitedListToStringArray(str, delimiter, null); - } - - /** - * Take a String which is a delimited list and convert it to a String array. - *

A single delimiter can consists of more than one character: It will still - * be considered as single delimiter string, rather than as bunch of potential - * delimiter characters - in contrast to tokenizeToStringArray. - * @param str the input String - * @param delimiter the delimiter between elements (this is a single delimiter, - * rather than a bunch individual delimiter characters) - * @param charsToDelete a set of characters to delete. Useful for deleting unwanted - * line breaks: e.g. "\r\n\f" will delete all new lines and line feeds in a String. - * @return an array of the tokens in the list - * @see #tokenizeToStringArray - */ - public static String[] delimitedListToStringArray(String str, String delimiter, String charsToDelete) { - if (str == null) { - return new String[0]; - } - if (delimiter == null) { - return new String[] {str}; - } - List result = new ArrayList(); - if ("".equals(delimiter)) { - for (int i = 0; i < str.length(); i++) { - result.add(deleteAny(str.substring(i, i + 1), charsToDelete)); - } - } - else { - int pos = 0; - int delPos = 0; - while ((delPos = str.indexOf(delimiter, pos)) != -1) { - result.add(deleteAny(str.substring(pos, delPos), charsToDelete)); - pos = delPos + delimiter.length(); - } - if (str.length() > 0 && pos <= str.length()) { - // Add rest of String, but not in case of empty input. - result.add(deleteAny(str.substring(pos), charsToDelete)); - } - } - return toStringArray(result); - } - - /** - * Convert a CSV list into an array of Strings. - * @param str the input String - * @return an array of Strings, or the empty array in case of empty input - */ - public static String[] commaDelimitedListToStringArray(String str) { - return delimitedListToStringArray(str, ","); - } - - /** - * Convenience method to convert a CSV string list to a set. - * Note that this will suppress duplicates. - * @param str the input String - * @return a Set of String entries in the list - */ - public static Set commaDelimitedListToSet(String str) { - Set set = new TreeSet(); - String[] tokens = commaDelimitedListToStringArray(str); - for (int i = 0; i < tokens.length; i++) { - set.add(tokens[i]); - } - return set; - } - - /** - * Convenience method to return a Collection as a delimited (e.g. CSV) - * String. E.g. useful for toString() implementations. - * @param coll the Collection to display - * @param delim the delimiter to use (probably a ",") - * @param prefix the String to start each element with - * @param suffix the String to end each element with - * @return the delimited String - */ - public static String collectionToDelimitedString(Collection coll, String delim, String prefix, String suffix) { - if (CollectionUtils.isEmpty(coll)) { - return ""; - } - StringBuffer sb = new StringBuffer(); - Iterator it = coll.iterator(); - while (it.hasNext()) { - sb.append(prefix).append(it.next()).append(suffix); - if (it.hasNext()) { - sb.append(delim); - } - } - return sb.toString(); - } - - /** - * Convenience method to return a Collection as a delimited (e.g. CSV) - * String. E.g. useful for toString() implementations. - * @param coll the Collection to display - * @param delim the delimiter to use (probably a ",") - * @return the delimited String - */ - public static String collectionToDelimitedString(Collection coll, String delim) { - return collectionToDelimitedString(coll, delim, "", ""); - } - - /** - * Convenience method to return a Collection as a CSV String. - * E.g. useful for toString() implementations. - * @param coll the Collection to display - * @return the delimited String - */ - public static String collectionToCommaDelimitedString(Collection coll) { - return collectionToDelimitedString(coll, ","); - } - - /** - * Convenience method to return a String array as a delimited (e.g. CSV) - * String. E.g. useful for toString() implementations. - * @param arr the array to display - * @param delim the delimiter to use (probably a ",") - * @return the delimited String - */ - public static String arrayToDelimitedString(Object[] arr, String delim) { - if (ObjectUtils.isEmpty(arr)) { - return ""; - } - StringBuffer sb = new StringBuffer(); - for (int i = 0; i < arr.length; i++) { - if (i > 0) { - sb.append(delim); - } - sb.append(arr[i]); - } - return sb.toString(); - } - - /** - * Convenience method to return a String array as a CSV String. - * E.g. useful for toString() implementations. - * @param arr the array to display - * @return the delimited String - */ - public static String arrayToCommaDelimitedString(Object[] arr) { - return arrayToDelimitedString(arr, ","); - } - -} diff --git a/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/internal/springutil/SystemPropertyUtils.java b/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/internal/springutil/SystemPropertyUtils.java deleted file mode 100644 index f81adc25b..000000000 --- a/base/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/internal/springutil/SystemPropertyUtils.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2002-2008 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.argeo.osgi.boot.internal.springutil; - -/** - * Helper class for resolving placeholders in texts. Usually applied to file paths. - * - *

A text may contain ${...} placeholders, to be resolved as - * system properties: e.g. ${user.dir}. - * - * @author Juergen Hoeller - * @since 1.2.5 - * @see #PLACEHOLDER_PREFIX - * @see #PLACEHOLDER_SUFFIX - * @see System#getProperty(String) - */ -public abstract class SystemPropertyUtils { - - /** Prefix for system property placeholders: "${" */ - public static final String PLACEHOLDER_PREFIX = "${"; - - /** Suffix for system property placeholders: "}" */ - public static final String PLACEHOLDER_SUFFIX = "}"; - - - /** - * Resolve ${...} placeholders in the given text, - * replacing them with corresponding system property values. - * @param text the String to resolve - * @return the resolved String - * @see #PLACEHOLDER_PREFIX - * @see #PLACEHOLDER_SUFFIX - */ - public static String resolvePlaceholders(String text) { - StringBuffer buf = new StringBuffer(text); - - int startIndex = buf.indexOf(PLACEHOLDER_PREFIX); - while (startIndex != -1) { - int endIndex = buf.indexOf(PLACEHOLDER_SUFFIX, startIndex + PLACEHOLDER_PREFIX.length()); - if (endIndex != -1) { - String placeholder = buf.substring(startIndex + PLACEHOLDER_PREFIX.length(), endIndex); - int nextIndex = endIndex + PLACEHOLDER_SUFFIX.length(); - try { - String propVal = System.getProperty(placeholder); - if (propVal == null) { - // Fall back to searching the system environment. - //propVal = System.getenv(placeholder);// mbaudier - 2009-07-26 - throw new Error("getenv no longer supported, use properties and -D instead: " + placeholder); - } - if (propVal != null) { - buf.replace(startIndex, endIndex + PLACEHOLDER_SUFFIX.length(), propVal); - nextIndex = startIndex + propVal.length(); - } - else { - System.err.println("Could not resolve placeholder '" + placeholder + "' in [" + text + - "] as system property: neither system property nor environment variable found"); - } - } - catch (Throwable ex) { - System.err.println("Could not resolve placeholder '" + placeholder + "' in [" + text + - "] as system property: " + ex); - } - startIndex = buf.indexOf(PLACEHOLDER_PREFIX, nextIndex); - } - else { - startIndex = -1; - } - } - - return buf.toString(); - } - -} diff --git a/base/runtime/org.argeo.osgi.boot/src/test/bundles/jars/test.jar b/base/runtime/org.argeo.osgi.boot/src/test/bundles/jars/test.jar deleted file mode 100644 index e69de29bb..000000000 diff --git a/base/runtime/org.argeo.osgi.boot/src/test/bundles/others/subdir/org.argeo.osgi.boot.test.bundle3/META-INF/MANIFEST.MF b/base/runtime/org.argeo.osgi.boot/src/test/bundles/others/subdir/org.argeo.osgi.boot.test.bundle3/META-INF/MANIFEST.MF deleted file mode 100644 index f23da4422..000000000 --- a/base/runtime/org.argeo.osgi.boot/src/test/bundles/others/subdir/org.argeo.osgi.boot.test.bundle3/META-INF/MANIFEST.MF +++ /dev/null @@ -1,2 +0,0 @@ -Bundle-SymbolicName: org.argeo.osgi.boot.test.bundle3 -Bundle-Version: 0.1.0 diff --git a/base/runtime/org.argeo.osgi.boot/src/test/bundles/some/excluded/org.argeo.osgi.boot.test.bundle0/META-INF/MANIFEST.MF b/base/runtime/org.argeo.osgi.boot/src/test/bundles/some/excluded/org.argeo.osgi.boot.test.bundle0/META-INF/MANIFEST.MF deleted file mode 100644 index 9344d0735..000000000 --- a/base/runtime/org.argeo.osgi.boot/src/test/bundles/some/excluded/org.argeo.osgi.boot.test.bundle0/META-INF/MANIFEST.MF +++ /dev/null @@ -1,2 +0,0 @@ -Bundle-SymbolicName: org.argeo.osgi.boot.test.bundle0 -Bundle-Version: 0.1.0 diff --git a/base/runtime/org.argeo.osgi.boot/src/test/bundles/some/org.argeo.osgi.boot.test.bundle1/META-INF/MANIFEST.MF b/base/runtime/org.argeo.osgi.boot/src/test/bundles/some/org.argeo.osgi.boot.test.bundle1/META-INF/MANIFEST.MF deleted file mode 100644 index 0fb66dc00..000000000 --- a/base/runtime/org.argeo.osgi.boot/src/test/bundles/some/org.argeo.osgi.boot.test.bundle1/META-INF/MANIFEST.MF +++ /dev/null @@ -1,2 +0,0 @@ -Bundle-SymbolicName: org.argeo.osgi.boot.test.bundle1 -Bundle-Version: 0.1.0 diff --git a/base/runtime/org.argeo.osgi.boot/src/test/bundles/some/org.argeo.osgi.boot.test.bundle2/META-INF/MANIFEST.MF b/base/runtime/org.argeo.osgi.boot/src/test/bundles/some/org.argeo.osgi.boot.test.bundle2/META-INF/MANIFEST.MF deleted file mode 100644 index 97ecd31c9..000000000 --- a/base/runtime/org.argeo.osgi.boot/src/test/bundles/some/org.argeo.osgi.boot.test.bundle2/META-INF/MANIFEST.MF +++ /dev/null @@ -1,2 +0,0 @@ -Bundle-SymbolicName: org.argeo.osgi.boot.test.bundle2 -Bundle-Version: 0.1.0 diff --git a/base/runtime/org.argeo.osgi.boot/src/test/java/org/argeo/osgi/boot/OsgiBootNoRuntimeTest.java b/base/runtime/org.argeo.osgi.boot/src/test/java/org/argeo/osgi/boot/OsgiBootNoRuntimeTest.java deleted file mode 100644 index 638b13a6d..000000000 --- a/base/runtime/org.argeo.osgi.boot/src/test/java/org/argeo/osgi/boot/OsgiBootNoRuntimeTest.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.osgi.boot; - -import java.io.File; -import java.util.List; - -import junit.framework.TestCase; - -import org.argeo.osgi.boot.OsgiBoot; - -/** Tests which do not require a runtime. */ -public class OsgiBootNoRuntimeTest extends TestCase { - public final static String BUNDLES = "src/test/bundles/some;in=*;ex=excluded," - + "src/test/bundles/others;in=**/org.argeo.*"; - - /** Tests that location lists are properly parsed. */ - public void testLocations() { - String baseUrl = "file:"; - String locations = "/mydir/myfile" + File.pathSeparator - + "/myotherdir/myotherfile"; - - OsgiBoot osgiBoot = new OsgiBoot(null); - osgiBoot.setExcludeSvn(true); - List urls = osgiBoot.getLocationsUrls(baseUrl, locations); - assertEquals(2, urls.size()); - assertEquals("file:/mydir/myfile", urls.get(0)); - assertEquals("file:/myotherdir/myotherfile", urls.get(1)); - } - - /** Tests that bundle lists are properly parsed. */ - public void testBundles() { - String baseUrl = "file:"; - String bundles = BUNDLES; - OsgiBoot osgiBoot = new OsgiBoot(null); - osgiBoot.setExcludeSvn(true); - List urls = osgiBoot.getBundlesUrls(baseUrl, bundles); - for (int i = 0; i < urls.size(); i++) - System.out.println(urls.get(i)); - assertEquals(3, urls.size()); - - List jarUrls = osgiBoot.getBundlesUrls(baseUrl, - "src/test/bundles/jars;in=*.jar"); - for (int i = 0; i < jarUrls.size(); i++) - System.out.println(jarUrls.get(i)); - assertEquals(1, jarUrls.size()); - } -} diff --git a/base/runtime/org.argeo.osgi.boot/src/test/java/org/argeo/osgi/boot/OsgiBootRuntimeTest.java b/base/runtime/org.argeo.osgi.boot/src/test/java/org/argeo/osgi/boot/OsgiBootRuntimeTest.java deleted file mode 100644 index 32b72bceb..000000000 --- a/base/runtime/org.argeo.osgi.boot/src/test/java/org/argeo/osgi/boot/OsgiBootRuntimeTest.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.osgi.boot; - -import java.util.Iterator; -import java.util.Map; -import java.util.TreeMap; - -import junit.framework.TestCase; - -import org.eclipse.core.runtime.adaptor.EclipseStarter; -import org.osgi.framework.Bundle; -import org.osgi.framework.BundleContext; - -/** Starts an Equinox runtime and provision it with OSGi boot. */ -public class OsgiBootRuntimeTest extends TestCase { - protected OsgiBoot osgiBoot = null; - private boolean osgiRuntimeAlreadyRunning = false; - - public void testInstallAndStart() throws Exception { - if (osgiRuntimeAlreadyRunning) { - System.out - .println("OSGi runtime already running, skipping test..."); - return; - } - osgiBoot.installUrls(osgiBoot.getBundlesUrls(OsgiBoot.DEFAULT_BASE_URL, - OsgiBootNoRuntimeTest.BUNDLES)); - Map map = new TreeMap(osgiBoot.getBundlesBySymbolicName()); - for (Iterator keys = map.keySet().iterator(); keys.hasNext();) { - Object key = keys.next(); - Bundle bundle = (Bundle) map.get(key); - System.out.println(key + " : " + bundle.getLocation()); - } - assertEquals(4, map.size()); - Iterator keys = map.keySet().iterator(); - assertEquals("org.argeo.osgi.boot.test.bundle1", keys.next()); - assertEquals("org.argeo.osgi.boot.test.bundle2", keys.next()); - assertEquals("org.argeo.osgi.boot.test.bundle3", keys.next()); - assertEquals("org.eclipse.osgi", keys.next()); - - osgiBoot.startBundles("org.argeo.osgi.boot.test.bundle2"); - long begin = System.currentTimeMillis(); - while (System.currentTimeMillis() - begin < 10000) { - Map mapBundles = osgiBoot.getBundlesBySymbolicName(); - Bundle bundle = (Bundle) mapBundles - .get("org.argeo.osgi.boot.test.bundle2"); - if (bundle.getState() == Bundle.ACTIVE) { - System.out.println("Bundle " + bundle + " started."); - return; - } - } - fail("Bundle not started after timeout limit."); - } - - protected BundleContext startRuntime() throws Exception { - String[] args = { "-console", "-clean" }; - BundleContext bundleContext = EclipseStarter.startup(args, null); - return bundleContext; - } - - protected void stopRuntime() throws Exception { - EclipseStarter.shutdown(); - } - - public void setUp() throws Exception { - osgiRuntimeAlreadyRunning = EclipseStarter.isRunning(); - if (osgiRuntimeAlreadyRunning) - return; - BundleContext bundleContext = startRuntime(); - osgiBoot = new OsgiBoot(bundleContext); - } - - public void tearDown() throws Exception { - if (osgiRuntimeAlreadyRunning) - return; - osgiBoot = null; - stopRuntime(); - } - -} diff --git a/base/runtime/org.argeo.support.junit/.classpath b/base/runtime/org.argeo.support.junit/.classpath deleted file mode 100644 index 3bf3adef5..000000000 --- a/base/runtime/org.argeo.support.junit/.classpath +++ /dev/null @@ -1,7 +0,0 @@ - - - - >> - - - diff --git a/base/runtime/org.argeo.support.junit/.project b/base/runtime/org.argeo.support.junit/.project deleted file mode 100644 index cc37598f2..000000000 --- a/base/runtime/org.argeo.support.junit/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - org.argeo.support.junit - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - - diff --git a/base/runtime/org.argeo.support.junit/.settings/org.eclipse.jdt.core.prefs b/base/runtime/org.argeo.support.junit/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 383a4ec69..000000000 --- a/base/runtime/org.argeo.support.junit/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,5 +0,0 @@ -#Tue Oct 13 10:02:09 CEST 2009 -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 -org.eclipse.jdt.core.compiler.compliance=1.5 -org.eclipse.jdt.core.compiler.source=1.5 diff --git a/base/runtime/org.argeo.support.junit/.settings/org.maven.ide.eclipse.prefs b/base/runtime/org.argeo.support.junit/.settings/org.maven.ide.eclipse.prefs deleted file mode 100644 index 721e27ec2..000000000 --- a/base/runtime/org.argeo.support.junit/.settings/org.maven.ide.eclipse.prefs +++ /dev/null @@ -1,9 +0,0 @@ -#Tue Oct 13 10:01:59 CEST 2009 -activeProfiles= -eclipse.preferences.version=1 -fullBuildGoals=process-test-resources -includeModules=false -resolveWorkspaceProjects=true -resourceFilterGoals=process-resources resources\:testResources -skipCompilerPlugin=true -version=1 diff --git a/base/runtime/org.argeo.support.junit/pom.xml b/base/runtime/org.argeo.support.junit/pom.xml deleted file mode 100644 index ddc917442..000000000 --- a/base/runtime/org.argeo.support.junit/pom.xml +++ /dev/null @@ -1,64 +0,0 @@ - - 4.0.0 - - org.argeo.commons.base - runtime - 2.1.12-SNAPSHOT - .. - - org.argeo.support.junit - Commons Support JUnit - - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-source-plugin - - - org.apache.maven.plugins - maven-jar-plugin - - - org.apache.felix - maven-bundle-plugin - - - - - org.argeo.support.junit.* - - org.springframework.core.io,* - - - - - - - - org.argeo.tp - junit - - - org.argeo.tp - org.springframework.core - - - org.argeo.tp - org.springframework.context - - - org.argeo.tp - org.springframework.beans - - - - - org.argeo.tp - slf4j.org.apache.commons.logging - - - \ No newline at end of file diff --git a/base/runtime/org.argeo.support.junit/src/main/java/org/argeo/support/junit/AbstractSpringTestCase.java b/base/runtime/org.argeo.support.junit/src/main/java/org/argeo/support/junit/AbstractSpringTestCase.java deleted file mode 100644 index 11a93e9cd..000000000 --- a/base/runtime/org.argeo.support.junit/src/main/java/org/argeo/support/junit/AbstractSpringTestCase.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.support.junit; - -import java.util.Map; - -import junit.framework.TestCase; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.beans.factory.BeanFactoryUtils; -import org.springframework.beans.factory.ListableBeanFactory; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.support.ClassPathXmlApplicationContext; - - -/** Helper for tests using a Spring application context. */ -public abstract class AbstractSpringTestCase extends TestCase { - protected final Log log = LogFactory.getLog(getClass()); - private ConfigurableApplicationContext context; - - /** - * Gets (and creates if necessary) the application context to use. Default - * implementation uses a class path xml application context and calls - * {@link #getApplicationContextLocation()}. - */ - protected ConfigurableApplicationContext getContext() { - if (context == null) { - context = new ClassPathXmlApplicationContext( - getApplicationContextLocation()); - if (getIsStartContext()) - context.start(); - } - return context; - } - - /** Whether the context should be started after being created. */ - protected Boolean getIsStartContext() { - return false; - } - - /** Returns a bean from the underlying context */ - @SuppressWarnings(value = { "unchecked" }) - protected T getBean(String beanId) { - return (T) getContext().getBean(beanId); - } - - protected T getBean(Class clss) { - T bean = loadSingleFromContext(getContext(), clss); - if (bean == null) { - throw new RuntimeException("Cannot retrieve a unique bean of type " - + clss); - } else { - return bean; - } - } - - /** - * The location of the application to load. The default implementation - * returns applicationContext.xml found in the same package as the - * test. - */ - protected String getApplicationContextLocation() { - return inPackage("applicationContext.xml"); - } - - /** - * Prefixes the package of the class after converting the '.' to '/' in - * order to have a resource path. - */ - protected String inPackage(String suffix) { - String prefix = getClass().getPackage().getName().replace('.', '/'); - return prefix + '/' + suffix; - } - - @SuppressWarnings(value = { "unchecked" }) - protected T loadSingleFromContext(ListableBeanFactory context, - Class clss) { - Map beans = BeanFactoryUtils.beansOfTypeIncludingAncestors( - context, clss, false, false); - if (beans.size() == 1) { - return beans.values().iterator().next(); - } else if (beans.size() > 1) { - if (log.isDebugEnabled()) { - log - .debug(("Found more that one bean for type " + clss - + ": " + beans.keySet())); - } - return null; - } else { - return null; - } - } - -} diff --git a/base/runtime/org.argeo.util/.classpath b/base/runtime/org.argeo.util/.classpath deleted file mode 100644 index 8499fd0fa..000000000 --- a/base/runtime/org.argeo.util/.classpath +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/base/runtime/org.argeo.util/.project b/base/runtime/org.argeo.util/.project deleted file mode 100644 index 171ff88dc..000000000 --- a/base/runtime/org.argeo.util/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - org.argeo.util - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.jdt.core.javanature - org.eclipse.pde.PluginNature - - diff --git a/base/runtime/org.argeo.util/build.properties b/base/runtime/org.argeo.util/build.properties deleted file mode 100644 index fcffb0f5e..000000000 --- a/base/runtime/org.argeo.util/build.properties +++ /dev/null @@ -1,6 +0,0 @@ -source.. = src/main/java/,\ - src/test/resources/,\ - src/test/java/ -bin.includes = META-INF/,\ - . -additional.bundles = junit diff --git a/base/runtime/org.argeo.util/pom.xml b/base/runtime/org.argeo.util/pom.xml deleted file mode 100644 index b05152585..000000000 --- a/base/runtime/org.argeo.util/pom.xml +++ /dev/null @@ -1,33 +0,0 @@ - - 4.0.0 - - org.argeo.commons.base - runtime - 2.1.12-SNAPSHOT - .. - - org.argeo.util - Commons Util (no third party dependencies) - - - - org.apache.felix - maven-bundle-plugin - - - - org.argeo.* - - - - - - - - - org.argeo.tp - junit - test - - - \ No newline at end of file diff --git a/base/runtime/org.argeo.util/src/main/java/org/argeo/ArgeoException.java b/base/runtime/org.argeo.util/src/main/java/org/argeo/ArgeoException.java deleted file mode 100644 index 9cf918667..000000000 --- a/base/runtime/org.argeo.util/src/main/java/org/argeo/ArgeoException.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo; - -/** Argeo Commons specific exception. */ -public class ArgeoException extends RuntimeException { - private static final long serialVersionUID = 1L; - - /** Creates an exception with a message. */ - public ArgeoException(String message) { - super(message); - } - - /** Creates an exception with a message and a root cause. */ - public ArgeoException(String message, Throwable e) { - super(message, e); - } - - /** - * Chain the messages of all causes (one per line, starts with a line - * return) without all the stack - */ - public static String chainCausesMessages(Throwable t) { - StringBuffer buf = new StringBuffer(); - chainCauseMessage(buf, t); - return buf.toString(); - } - - /** Recursive chaining of messages */ - private static void chainCauseMessage(StringBuffer buf, Throwable t) { - buf.append('\n').append(' ').append(t.getClass().getCanonicalName()) - .append(": ").append(t.getMessage()); - if (t.getCause() != null) - chainCauseMessage(buf, t.getCause()); - } -} diff --git a/base/runtime/org.argeo.util/src/main/java/org/argeo/ArgeoLogListener.java b/base/runtime/org.argeo.util/src/main/java/org/argeo/ArgeoLogListener.java deleted file mode 100644 index bac8a9820..000000000 --- a/base/runtime/org.argeo.util/src/main/java/org/argeo/ArgeoLogListener.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo; - -/** Framework agnostic interface for log notifications */ -public interface ArgeoLogListener { - /** - * Appends a log - * - * @param username - * authentified user, null for anonymous - * @param level - * INFO, DEBUG, WARN, etc. (logging framework specific) - * @param category - * hierarchy (logging framework specific) - * @param thread - * name of the thread which logged this message - * @param msg - * any object as long as its toString() method returns the - * message - * @param the - * exception in log4j ThrowableStrRep format - */ - public void appendLog(String username, Long timestamp, String level, - String category, String thread, Object msg, String[] exception); -} diff --git a/base/runtime/org.argeo.util/src/main/java/org/argeo/ArgeoLogger.java b/base/runtime/org.argeo.util/src/main/java/org/argeo/ArgeoLogger.java deleted file mode 100644 index 0657c29dd..000000000 --- a/base/runtime/org.argeo.util/src/main/java/org/argeo/ArgeoLogger.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo; - -/** - * Logging framework agnostic identifying a logging service, to which one can - * register - */ -public interface ArgeoLogger { - /** - * Register for events by threads with the same authentication (or all - * threads if admin) - */ - public void register(ArgeoLogListener listener, - Integer numberOfPreviousEvents); - - /** - * For admin use only: register for all users - * - * @param listener - * the log listener - * @param numberOfPreviousEvents - * the number of previous events to notify - * @param everything - * if true even anonymous is logged - */ - public void registerForAll(ArgeoLogListener listener, - Integer numberOfPreviousEvents, boolean everything); - - public void unregister(ArgeoLogListener listener); - - public void unregisterForAll(ArgeoLogListener listener); -} diff --git a/base/runtime/org.argeo.util/src/main/java/org/argeo/ArgeoMonitor.java b/base/runtime/org.argeo.util/src/main/java/org/argeo/ArgeoMonitor.java deleted file mode 100644 index 9ef23cc8b..000000000 --- a/base/runtime/org.argeo.util/src/main/java/org/argeo/ArgeoMonitor.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo; - -/** - * Simple monitor abstraction. Inspired by Eclipse IProgressMOnitor, but without - * dependency to it. - */ -public interface ArgeoMonitor { - /** - * Constant indicating an unknown amount of work. - */ - public final static int UNKNOWN = -1; - - /** - * Notifies that the main task is beginning. This must only be called once - * on a given progress monitor instance. - * - * @param name - * the name (or description) of the main task - * @param totalWork - * the total number of work units into which the main task is - * been subdivided. If the value is UNKNOWN the - * implementation is free to indicate progress in a way which - * doesn't require the total number of work units in advance. - */ - public void beginTask(String name, int totalWork); - - /** - * Notifies that the work is done; that is, either the main task is - * completed or the user canceled it. This method may be called more than - * once (implementations should be prepared to handle this case). - */ - public void done(); - - /** - * Returns whether cancelation of current operation has been requested. - * Long-running operations should poll to see if cancelation has been - * requested. - * - * @return true if cancellation has been requested, and - * false otherwise - * @see #setCanceled(boolean) - */ - public boolean isCanceled(); - - /** - * Sets the cancel state to the given value. - * - * @param value - * true indicates that cancelation has been - * requested (but not necessarily acknowledged); - * false clears this flag - * @see #isCanceled() - */ - public void setCanceled(boolean value); - - /** - * Sets the task name to the given value. This method is used to restore the - * task label after a nested operation was executed. Normally there is no - * need for clients to call this method. - * - * @param name - * the name (or description) of the main task - * @see #beginTask(java.lang.String, int) - */ - public void setTaskName(String name); - - /** - * Notifies that a subtask of the main task is beginning. Subtasks are - * optional; the main task might not have subtasks. - * - * @param name - * the name (or description) of the subtask - */ - public void subTask(String name); - - /** - * Notifies that a given number of work unit of the main task has been - * completed. Note that this amount represents an installment, as opposed to - * a cumulative amount of work done to date. - * - * @param work - * a non-negative number of work units just completed - */ - public void worked(int work); - -} diff --git a/base/runtime/org.argeo.util/src/main/java/org/argeo/OperatingSystem.java b/base/runtime/org.argeo.util/src/main/java/org/argeo/OperatingSystem.java deleted file mode 100644 index 697c86c51..000000000 --- a/base/runtime/org.argeo.util/src/main/java/org/argeo/OperatingSystem.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo; - -/** The current operating system. */ -public class OperatingSystem { - public final static int NIX = 1; - public final static int WINDOWS = 2; - public final static int SOLARIS = 3; - - public final static int os; - static { - String osName = System.getProperty("os.name"); - if (osName.startsWith("Win")) - os = WINDOWS; - else if (osName.startsWith("Solaris")) - os = SOLARIS; - else - os = NIX; - } - -} diff --git a/base/runtime/org.argeo.util/src/main/java/org/argeo/StreamUtils.java b/base/runtime/org.argeo.util/src/main/java/org/argeo/StreamUtils.java deleted file mode 100644 index 39caaddda..000000000 --- a/base/runtime/org.argeo.util/src/main/java/org/argeo/StreamUtils.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.Reader; -import java.io.Writer; - -/** Utilities to be used when APache COmmons IO is not available. */ -public class StreamUtils { - private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; - - /* - * APACHE COMMONS IO (inspired) - */ - - /** @return the number of bytes */ - public static Long copy(InputStream in, OutputStream out) - throws IOException { - Long count = 0l; - byte[] buf = new byte[DEFAULT_BUFFER_SIZE]; - while (true) { - int length = in.read(buf); - if (length < 0) - break; - out.write(buf, 0, length); - count = count + length; - } - return count; - } - - /** @return the number of chars */ - public static Long copy(Reader in, Writer out) throws IOException { - Long count = 0l; - char[] buf = new char[DEFAULT_BUFFER_SIZE]; - while (true) { - int length = in.read(buf); - if (length < 0) - break; - out.write(buf, 0, length); - count = count + length; - } - return count; - } - - public static void closeQuietly(InputStream in) { - if (in != null) - try { - in.close(); - } catch (Exception e) { - // - } - } - - public static void closeQuietly(OutputStream out) { - if (out != null) - try { - out.close(); - } catch (Exception e) { - // - } - } - - public static void closeQuietly(Reader in) { - if (in != null) - try { - in.close(); - } catch (Exception e) { - // - } - } - - public static void closeQuietly(Writer out) { - if (out != null) - try { - out.close(); - } catch (Exception e) { - // - } - } - - /* - * APACHE COMMONS CODEC (forked) - */ - /** - * Used to build output as Hex - */ - private static final char[] DIGITS_LOWER = { '0', '1', '2', '3', '4', '5', - '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; - - /** - * Used to build output as Hex - */ - private static final char[] DIGITS_UPPER = { '0', '1', '2', '3', '4', '5', - '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - - /** - * Converts an array of bytes into a String representing the hexadecimal - * values of each byte in order. The returned String will be double the - * length of the passed array, as it takes two characters to represent any - * given byte. - * - * @param data - * a byte[] to convert to Hex characters - * @return A String containing hexadecimal characters - * @since 1.4 - */ - public static String encodeHexString(byte[] data) { - return new String(encodeHex(data)); - } - - /** - * Converts an array of bytes into an array of characters representing the - * hexadecimal values of each byte in order. The returned array will be - * double the length of the passed array, as it takes two characters to - * represent any given byte. - * - * @param data - * a byte[] to convert to Hex characters - * @return A char[] containing hexadecimal characters - */ - public static char[] encodeHex(byte[] data) { - return encodeHex(data, true); - } - - /** - * Converts an array of bytes into an array of characters representing the - * hexadecimal values of each byte in order. The returned array will be - * double the length of the passed array, as it takes two characters to - * represent any given byte. - * - * @param data - * a byte[] to convert to Hex characters - * @param toLowerCase - * true converts to lowercase, false to - * uppercase - * @return A char[] containing hexadecimal characters - * @since 1.4 - */ - public static char[] encodeHex(byte[] data, boolean toLowerCase) { - return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER); - } - - /** - * Converts an array of bytes into an array of characters representing the - * hexadecimal values of each byte in order. The returned array will be - * double the length of the passed array, as it takes two characters to - * represent any given byte. - * - * @param data - * a byte[] to convert to Hex characters - * @param toDigits - * the output alphabet - * @return A char[] containing hexadecimal characters - * @since 1.4 - */ - protected static char[] encodeHex(byte[] data, char[] toDigits) { - int l = data.length; - char[] out = new char[l << 1]; - // two characters form the hex value. - for (int i = 0, j = 0; i < l; i++) { - out[j++] = toDigits[(0xF0 & data[i]) >>> 4]; - out[j++] = toDigits[0x0F & data[i]]; - } - return out; - } - -} diff --git a/base/runtime/org.argeo.util/src/main/java/org/argeo/util/CsvParser.java b/base/runtime/org.argeo.util/src/main/java/org/argeo/util/CsvParser.java deleted file mode 100644 index 7680b3267..000000000 --- a/base/runtime/org.argeo.util/src/main/java/org/argeo/util/CsvParser.java +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.util; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import org.argeo.ArgeoException; -import org.argeo.StreamUtils; - -/** - * Parses a CSV file interpreting the first line as a header. The - * {@link #parse(InputStream)} method and the setters are synchronized so that - * the object cannot be modified when parsing. - */ -public abstract class CsvParser { - private char separator = ','; - private char quote = '\"'; - - private Boolean noHeader = false; - private Boolean strictLineAsLongAsHeader = true; - - /** - * Actually process a parsed line. If - * {@link #setStrictLineAsLongAsHeader(Boolean)} is true (default) the - * header and the tokens are guaranteed to have the same size. - * - * @param lineNumber - * the current line number, starts at 1 (the header, if header - * processing is enabled, the first line otherwise) - * @param header - * the read-only header or null if {@link #setNoHeader(Boolean)} - * is true (default is false) - * @param tokens - * the parsed tokens - */ - protected abstract void processLine(Integer lineNumber, - List header, List tokens); - - /** - * Parses the CSV file (stream is closed at the end) - */ - public synchronized void parse(InputStream in) { - parse(in, null); - } - - /** - * Parses the CSV file (stream is closed at the end) - */ - public synchronized void parse(InputStream in, String encoding) { - BufferedReader reader = null; - Integer lineCount = 0; - try { - if (encoding == null) - reader = new BufferedReader(new InputStreamReader(in)); - else - reader = new BufferedReader(new InputStreamReader(in, encoding)); - List header = null; - if (!noHeader) { - String headerStr = reader.readLine(); - if (headerStr == null)// empty file - return; - lineCount++; - header = new ArrayList(); - StringBuffer currStr = new StringBuffer(""); - Boolean wasInquote = false; - while (parseLine(headerStr, header, currStr, wasInquote)) { - headerStr = reader.readLine(); - if (headerStr == null) - break; - wasInquote = true; - } - header = Collections.unmodifiableList(header); - } - - String line = null; - lines: while ((line = reader.readLine()) != null) { - line = preProcessLine(line); - if (line == null) { - // skip line - continue lines; - } - lineCount++; - List tokens = new ArrayList(); - StringBuffer currStr = new StringBuffer(""); - Boolean wasInquote = false; - sublines: while (parseLine(line, tokens, currStr, wasInquote)) { - line = reader.readLine(); - if (line == null) - break sublines; - wasInquote = true; - } - if (!noHeader && strictLineAsLongAsHeader) { - int headerSize = header.size(); - int tokenSize = tokens.size(); - if (tokenSize == 1 && line.trim().equals("")) - continue lines;// empty line - if (headerSize != tokenSize) { - throw new ArgeoException("Token size " + tokenSize - + " is different from header size " - + headerSize + " at line " + lineCount - + ", line: " + line + ", header: " + header - + ", tokens: " + tokens); - } - } - processLine(lineCount, header, tokens); - } - } catch (ArgeoException e) { - throw e; - } catch (IOException e) { - throw new ArgeoException("Cannot parse CSV file (line: " - + lineCount + ")", e); - } finally { - StreamUtils.closeQuietly(reader); - } - } - - /** - * Called before each (logical) line is processed, giving a change to modify - * it (typically for cleaning dirty files). To be overridden, return the - * line unchanged by default. Skip the line if 'null' is returned. - */ - protected String preProcessLine(String line) { - return line; - } - - /** - * Parses a line character by character for performance purpose - * - * @return whether to continue parsing this line - */ - protected Boolean parseLine(String str, List tokens, - StringBuffer currStr, Boolean wasInquote) { - // List tokens = new ArrayList(); - - // System.out.println("#LINE: " + str); - - if (wasInquote) - currStr.append('\n'); - - char[] arr = str.toCharArray(); - boolean inQuote = wasInquote; - // StringBuffer currStr = new StringBuffer(""); - for (int i = 0; i < arr.length; i++) { - char c = arr[i]; - if (c == separator) { - if (!inQuote) { - tokens.add(currStr.toString()); - // System.out.println("# TOKEN: " + currStr); - currStr.delete(0, currStr.length()); - } else { - // we don't remove separator that are in a quoted substring - // System.out - // .println("IN QUOTE, got a separator: [" + c + "]"); - currStr.append(c); - } - } else if (c == quote) { - if (inQuote && (i + 1) < arr.length && arr[i + 1] == quote) { - // case of double quote - currStr.append(quote); - i++; - } else {// standard - inQuote = inQuote ? false : true; - } - } else { - currStr.append(c); - } - } - - if (!inQuote) { - tokens.add(currStr.toString()); - // System.out.println("# TOKEN: " + currStr); - } - // if (inQuote) - // throw new ArgeoException("Missing quote at the end of the line " - // + str + " (parsed: " + tokens + ")"); - if (inQuote) - return true; - else - return false; - // return tokens; - } - - public char getSeparator() { - return separator; - } - - public synchronized void setSeparator(char separator) { - this.separator = separator; - } - - public char getQuote() { - return quote; - } - - public synchronized void setQuote(char quote) { - this.quote = quote; - } - - public Boolean getNoHeader() { - return noHeader; - } - - public synchronized void setNoHeader(Boolean noHeader) { - this.noHeader = noHeader; - } - - public Boolean getStrictLineAsLongAsHeader() { - return strictLineAsLongAsHeader; - } - - public synchronized void setStrictLineAsLongAsHeader( - Boolean strictLineAsLongAsHeader) { - this.strictLineAsLongAsHeader = strictLineAsLongAsHeader; - } - -} diff --git a/base/runtime/org.argeo.util/src/main/java/org/argeo/util/CsvParserWithLinesAsMap.java b/base/runtime/org.argeo.util/src/main/java/org/argeo/util/CsvParserWithLinesAsMap.java deleted file mode 100644 index e7baabbf0..000000000 --- a/base/runtime/org.argeo.util/src/main/java/org/argeo/util/CsvParserWithLinesAsMap.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.util; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.argeo.ArgeoException; - -/** - * CSV parser allowing to process lines as maps whose keys are the header - * fields. - */ -public abstract class CsvParserWithLinesAsMap extends CsvParser { - - /** - * Actually processes a line. - * - * @param lineNumber - * the current line number, starts at 1 (the header, if header - * processing is enabled, the first lien otherwise) - * @param line - * the parsed tokens as a map whose keys are the header fields - */ - protected abstract void processLine(Integer lineNumber, - Map line); - - protected final void processLine(Integer lineNumber, List header, - List tokens) { - if (header == null) - throw new ArgeoException("Only CSV with header is supported"); - Map line = new HashMap(); - for (int i = 0; i < header.size(); i++) { - String key = header.get(i); - String value = null; - if (i < tokens.size()) - value = tokens.get(i); - line.put(key, value); - } - processLine(lineNumber, line); - } - -} diff --git a/base/runtime/org.argeo.util/src/main/java/org/argeo/util/CsvWriter.java b/base/runtime/org.argeo.util/src/main/java/org/argeo/util/CsvWriter.java deleted file mode 100644 index d90f47412..000000000 --- a/base/runtime/org.argeo.util/src/main/java/org/argeo/util/CsvWriter.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.util; - -import java.io.IOException; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.UnsupportedEncodingException; -import java.io.Writer; -import java.util.Iterator; -import java.util.List; - -import org.argeo.ArgeoException; - -/** Write in CSV format. */ -public class CsvWriter { - private final Writer out; - - private char separator = ','; - private char quote = '\"'; - - /** - * Creates a CSV writer. - * - * @param out - * the stream to write to. Caller is responsible for closing it. - */ - public CsvWriter(OutputStream out) { - this.out = new OutputStreamWriter(out); - } - - /** - * Creates a CSV writer. - * - * @param out - * the stream to write to. Caller is responsible for closing it. - */ - public CsvWriter(OutputStream out, String encoding) { - try { - this.out = new OutputStreamWriter(out, encoding); - } catch (UnsupportedEncodingException e) { - throw new ArgeoException("Cannot initialize CSV writer", e); - } - } - - /** - * Write a CSV line. Also used to write a header if needed (this is - * transparent for the CSV writer): simply call it first, before writing the - * lines. - */ - public void writeLine(List tokens) { - try { - Iterator it = tokens.iterator(); - while (it.hasNext()) { - writeToken(it.next().toString()); - if (it.hasNext()) - out.write(separator); - } - out.write('\n'); - out.flush(); - } catch (IOException e) { - throw new ArgeoException("Could not write " + tokens, e); - } - } - - /** - * Write a CSV line. Also used to write a header if needed (this is - * transparent for the CSV writer): simply call it first, before writing the - * lines. - */ - public void writeLine(Object[] tokens) { - try { - for (int i = 0; i < tokens.length; i++) { - if (tokens[i] == null) { - // TODO configure how to deal with null - writeToken(""); - } else { - writeToken(tokens[i].toString()); - } - if (i != (tokens.length - 1)) - out.write(separator); - } - out.write('\n'); - out.flush(); - } catch (IOException e) { - throw new ArgeoException("Could not write " + tokens, e); - } - } - - protected void writeToken(String token) throws IOException { - // +2 for possible quotes, another +2 assuming there would be an already - // quoted string where quotes needs to be duplicated - // another +2 for safety - // we don't want to increase buffer size while writing - StringBuffer buf = new StringBuffer(token.length() + 6); - char[] arr = token.toCharArray(); - boolean shouldQuote = false; - for (char c : arr) { - if (!shouldQuote) { - if (c == separator) - shouldQuote = true; - if (c == '\n') - shouldQuote = true; - } - - if (c == quote) { - shouldQuote = true; - // duplicate quote - buf.append(quote); - } - - // generic case - buf.append(c); - } - - if (shouldQuote == true) - out.write(quote); - out.write(buf.toString()); - if (shouldQuote == true) - out.write(quote); - } - - public void setSeparator(char separator) { - this.separator = separator; - } - - public void setQuote(char quote) { - this.quote = quote; - } - -} diff --git a/base/runtime/org.argeo.util/src/main/java/org/argeo/util/LocaleCallback.java b/base/runtime/org.argeo.util/src/main/java/org/argeo/util/LocaleCallback.java deleted file mode 100644 index 60bf4c40f..000000000 --- a/base/runtime/org.argeo.util/src/main/java/org/argeo/util/LocaleCallback.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.util; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Locale; - -import javax.security.auth.callback.Callback; - -/** Choose in a list of locales */ -public class LocaleCallback implements Callback { - private List availableLocales = new ArrayList(); - - private Integer selectedIndex = null; - private Integer defaultIndex = null; - private String prompt = "Language"; - - public LocaleCallback(Integer defaultIndex, List availableLocales) { - this.availableLocales = Collections - .unmodifiableList(new ArrayList(availableLocales)); - this.defaultIndex = defaultIndex; - this.selectedIndex = defaultIndex; - } - - /** - * Convenience constructor based on a comma separated list of iso codes (en, - * en_US, fr_CA, etc.). Default selection is default locale. - */ - public LocaleCallback(String locales) { - if (locales == null || locales.trim().equals("")) - return; - String[] codes = locales.split(","); - for (int i = 0; i < codes.length; i++) { - String code = codes[i]; - // variant not supported - int indexUnd = code.indexOf("_"); - Locale locale; - if (indexUnd > 0) { - String language = code.substring(0, indexUnd); - String country = code.substring(indexUnd + 1); - locale = new Locale(language, country); - } else { - locale = new Locale(code); - } - availableLocales.add(locale); - if (locale.equals(Locale.getDefault())) - defaultIndex = i; - } - - if (defaultIndex == null) - defaultIndex = 0; - - this.selectedIndex = defaultIndex; - } - - public String[] getSupportedLocalesLabels() { - String[] labels = new String[availableLocales.size()]; - for (int i = 0; i < availableLocales.size(); i++) { - Locale locale = availableLocales.get(i); - if (locale.getCountry().equals("")) - labels[i] = locale.getDisplayLanguage(locale) + " [" - + locale.getLanguage() + "]"; - else - labels[i] = locale.getDisplayLanguage(locale) + " (" - + locale.getDisplayCountry(locale) + ") [" - + locale.getLanguage() + "_" + locale.getCountry() - + "]"; - - } - return labels; - } - - public Locale getSelectedLocale() { - if (selectedIndex == null) - return null; - return availableLocales.get(selectedIndex); - } - - public void setSelectedIndex(Integer selectedIndex) { - this.selectedIndex = selectedIndex; - } - - public Integer getDefaultIndex() { - return defaultIndex; - } - - public String getPrompt() { - // TODO localize it? - return prompt; - } - - public void setPrompt(String prompt) { - this.prompt = prompt; - } - - public List getAvailableLocales() { - return availableLocales; - } - - public static void main(String[] args) { - for (String isoL : Locale.getISOLanguages()) { - Locale locale = new Locale(isoL); - System.out.println(isoL + "\t" + locale.getDisplayLanguage() + "\t" - + locale.getDisplayLanguage(locale)); - } - } - -} diff --git a/base/runtime/org.argeo.util/src/main/java/org/argeo/util/LocaleUtils.java b/base/runtime/org.argeo.util/src/main/java/org/argeo/util/LocaleUtils.java deleted file mode 100644 index bc04afa75..000000000 --- a/base/runtime/org.argeo.util/src/main/java/org/argeo/util/LocaleUtils.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.util; - -import java.util.Locale; - -import org.argeo.ArgeoException; - -/** Utilities around internationalization. */ -public class LocaleUtils { - /** - * The locale of the current thread and its children. Allows to deal with - * internationalisation as a cross cutting aspect. Never null. - */ - public final static InheritableThreadLocal threadLocale = new InheritableThreadLocal() { - @Override - protected Locale initialValue() { - return Locale.getDefault(); - } - - @Override - public void set(Locale value) { - if (value == null) - throw new ArgeoException("Thread local cannot be null."); - super.set(value); - } - - }; -} diff --git a/base/runtime/org.argeo.util/src/main/java/org/argeo/util/Throughput.java b/base/runtime/org.argeo.util/src/main/java/org/argeo/util/Throughput.java deleted file mode 100644 index d081189e2..000000000 --- a/base/runtime/org.argeo.util/src/main/java/org/argeo/util/Throughput.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.util; - -import java.text.NumberFormat; -import java.text.ParseException; -import java.util.Locale; - -import org.argeo.ArgeoException; - -public class Throughput { - private final static NumberFormat usNumberFormat = NumberFormat - .getInstance(Locale.US); - - public enum Unit { - s, m, h, d - } - - private final Double value; - private final Unit unit; - - public Throughput(Double value, Unit unit) { - this.value = value; - this.unit = unit; - } - - public Throughput(Long periodMs, Long count, Unit unit) { - if (unit.equals(Unit.s)) - value = ((double) count * 1000d) / periodMs; - else if (unit.equals(Unit.m)) - value = ((double) count * 60d * 1000d) / periodMs; - else if (unit.equals(Unit.h)) - value = ((double) count * 60d * 60d * 1000d) / periodMs; - else if (unit.equals(Unit.d)) - value = ((double) count * 24d * 60d * 60d * 1000d) / periodMs; - else - throw new ArgeoException("Unsupported unit " + unit); - this.unit = unit; - } - - public Throughput(Double value, String unitStr) { - this(value, Unit.valueOf(unitStr)); - } - - public Throughput(String def) { - int index = def.indexOf('/'); - if (def.length() < 3 || index <= 0 || index != def.length() - 2) - throw new ArgeoException(def + " no a proper throughput definition" - + " (should be /, e.g. 3.54/s or 1500/h"); - String valueStr = def.substring(0, index); - String unitStr = def.substring(index + 1); - try { - this.value = usNumberFormat.parse(valueStr).doubleValue(); - } catch (ParseException e) { - throw new ArgeoException("Cannot parse " + valueStr - + " as a number.", e); - } - this.unit = Unit.valueOf(unitStr); - } - - public Long asMsPeriod() { - if (unit.equals(Unit.s)) - return Math.round(1000d / value); - else if (unit.equals(Unit.m)) - return Math.round((60d * 1000d) / value); - else if (unit.equals(Unit.h)) - return Math.round((60d * 60d * 1000d) / value); - else if (unit.equals(Unit.d)) - return Math.round((24d * 60d * 60d * 1000d) / value); - else - throw new ArgeoException("Unsupported unit " + unit); - } - - @Override - public String toString() { - return usNumberFormat.format(value) + '/' + unit; - } - - public Double getValue() { - return value; - } - - public Unit getUnit() { - return unit; - } - -} diff --git a/base/runtime/org.argeo.util/src/main/java/org/argeo/util/ThroughputEditor.java b/base/runtime/org.argeo.util/src/main/java/org/argeo/util/ThroughputEditor.java deleted file mode 100644 index 4ebf26b81..000000000 --- a/base/runtime/org.argeo.util/src/main/java/org/argeo/util/ThroughputEditor.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.util; - -import java.beans.PropertyEditorSupport; - -public class ThroughputEditor extends PropertyEditorSupport { - - @Override - public String getAsText() { - return getValue().toString(); - } - - @Override - public void setAsText(String text) throws IllegalArgumentException { - setValue(new Throughput(text)); - } - -} diff --git a/base/runtime/org.argeo.util/src/main/java/org/argeo/util/security/DigestUtils.java b/base/runtime/org.argeo.util/src/main/java/org/argeo/util/security/DigestUtils.java deleted file mode 100644 index b6aae6fd4..000000000 --- a/base/runtime/org.argeo.util/src/main/java/org/argeo/util/security/DigestUtils.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.util.security; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - -import org.argeo.ArgeoException; -import org.argeo.StreamUtils; - -/** Utilities around cryptographic digests */ -public class DigestUtils { - private static Boolean debug = true; - // TODO: make it writable - private final static Integer byteBufferCapacity = 100 * 1024;// 100 KB - - public static String digest(String algorithm, byte[] bytes) { - try { - MessageDigest digest = MessageDigest.getInstance(algorithm); - digest.update(bytes); - byte[] checksum = digest.digest(); - String res = StreamUtils.encodeHexString(checksum); - return res; - } catch (Exception e) { - throw new ArgeoException("Cannot digest with algorithm " - + algorithm, e); - } - } - - public static String digest(String algorithm, InputStream in) { - try { - MessageDigest digest = MessageDigest.getInstance(algorithm); - // ReadableByteChannel channel = Channels.newChannel(in); - // ByteBuffer bb = ByteBuffer.allocateDirect(byteBufferCapacity); - // while (channel.read(bb) > 0) - // digest.update(bb); - byte[] buffer = new byte[byteBufferCapacity]; - int read = 0; - while ((read = in.read(buffer)) > 0) { - digest.update(buffer, 0, read); - } - - byte[] checksum = digest.digest(); - String res = StreamUtils.encodeHexString(checksum); - return res; - } catch (Exception e) { - throw new ArgeoException("Cannot digest with algorithm " - + algorithm, e); - } finally { - StreamUtils.closeQuietly(in); - } - } - - public static String digest(String algorithm, File file) { - FileInputStream fis = null; - FileChannel fc = null; - try { - fis = new FileInputStream(file); - fc = fis.getChannel(); - - // Get the file's size and then map it into memory - int sz = (int) fc.size(); - ByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, sz); - return digest(algorithm, bb); - } catch (IOException e) { - throw new ArgeoException("Cannot digest " + file - + " with algorithm " + algorithm, e); - } finally { - StreamUtils.closeQuietly(fis); - if (fc.isOpen()) - try { - fc.close(); - } catch (IOException e) { - // silent - } - } - } - - protected static String digest(String algorithm, ByteBuffer bb) { - long begin = System.currentTimeMillis(); - try { - MessageDigest digest = MessageDigest.getInstance(algorithm); - digest.update(bb); - byte[] checksum = digest.digest(); - String res = StreamUtils.encodeHexString(checksum); - long end = System.currentTimeMillis(); - if (debug) - System.out.println((end - begin) + " ms / " - + ((end - begin) / 1000) + " s"); - return res; - } catch (NoSuchAlgorithmException e) { - throw new ArgeoException("Cannot digest with algorithm " - + algorithm, e); - } - } - - public static void main(String[] args) { - File file; - if (args.length > 0) - file = new File(args[0]); - else { - System.err.println("Usage: []" - + " (see http://java.sun.com/j2se/1.5.0/" - + "docs/guide/security/CryptoSpec.html#AppA)"); - return; - } - - if (args.length > 1) { - String algorithm = args[1]; - System.out.println(digest(algorithm, file)); - } else { - String algorithm = "MD5"; - System.out.println(algorithm + ": " + digest(algorithm, file)); - algorithm = "SHA"; - System.out.println(algorithm + ": " + digest(algorithm, file)); - algorithm = "SHA-256"; - System.out.println(algorithm + ": " + digest(algorithm, file)); - algorithm = "SHA-512"; - System.out.println(algorithm + ": " + digest(algorithm, file)); - } - } - -} diff --git a/base/runtime/org.argeo.util/src/main/java/org/argeo/util/security/Keyring.java b/base/runtime/org.argeo.util/src/main/java/org/argeo/util/security/Keyring.java deleted file mode 100644 index 10dbabd49..000000000 --- a/base/runtime/org.argeo.util/src/main/java/org/argeo/util/security/Keyring.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.util.security; - -import java.io.InputStream; - -/** - * Access to private (typically encrypted) data. The keyring is responsible for - * retrieving the necessary credentials. Experimental. This API may - * change. - */ -public interface Keyring { - public void changePassword(char[] oldPassword, char[] newPassword); - - /** - * Returns the confidential information as chars. Must ask for it if it is - * not stored. - */ - public char[] getAsChars(String path); - - /** - * Returns the confidential information as a stream. Must ask for it if it - * is not stored. - */ - public InputStream getAsStream(String path); - - public void set(String path, char[] arr); - - public void set(String path, InputStream in); -} diff --git a/base/runtime/org.argeo.util/src/main/java/org/argeo/util/security/SimplePrincipal.java b/base/runtime/org.argeo.util/src/main/java/org/argeo/util/security/SimplePrincipal.java deleted file mode 100644 index c7a4daf12..000000000 --- a/base/runtime/org.argeo.util/src/main/java/org/argeo/util/security/SimplePrincipal.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.util.security; - -import java.security.Principal; - -import org.argeo.ArgeoException; - -/** Canonical implementation of a {@link Principal} */ -public class SimplePrincipal implements Principal { - private final String name; - - public SimplePrincipal(String name) { - if (name == null) - throw new ArgeoException("Principal name cannot be null"); - this.name = name; - } - - public String getName() { - return name; - } - - @Override - public int hashCode() { - return name.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj == null) - return false; - return name.equals(obj.toString()); - } - - @Override - protected Object clone() throws CloneNotSupportedException { - return new SimplePrincipal(name); - } - - @Override - public String toString() { - return name; - } - -} diff --git a/base/runtime/org.argeo.util/src/main/java/org/argeo/util/tabular/ArrayTabularRow.java b/base/runtime/org.argeo.util/src/main/java/org/argeo/util/tabular/ArrayTabularRow.java deleted file mode 100644 index b1672e94c..000000000 --- a/base/runtime/org.argeo.util/src/main/java/org/argeo/util/tabular/ArrayTabularRow.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.util.tabular; - -import java.util.List; - -/** Minimal tabular row wrapping an {@link Object} array */ -public class ArrayTabularRow implements TabularRow { - private final Object[] arr; - - public ArrayTabularRow(List objs) { - this.arr = objs.toArray(); - } - - public Object get(Integer col) { - return arr[col]; - } - - public int size() { - return arr.length; - } - - public Object[] toArray() { - return arr; - } - -} diff --git a/base/runtime/org.argeo.util/src/main/java/org/argeo/util/tabular/CsvTabularWriter.java b/base/runtime/org.argeo.util/src/main/java/org/argeo/util/tabular/CsvTabularWriter.java deleted file mode 100644 index 8f5c52dca..000000000 --- a/base/runtime/org.argeo.util/src/main/java/org/argeo/util/tabular/CsvTabularWriter.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.util.tabular; - -import java.io.OutputStream; - -import org.argeo.util.CsvWriter; - -/** Write tabular content in a stream as CSV. Wraps a {@link CsvWriter}. */ -public class CsvTabularWriter implements TabularWriter { - private CsvWriter csvWriter; - - public CsvTabularWriter(OutputStream out) { - this.csvWriter = new CsvWriter(out); - } - - public void appendRow(Object[] row) { - csvWriter.writeLine(row); - } - - public void close() { - } - -} diff --git a/base/runtime/org.argeo.util/src/main/java/org/argeo/util/tabular/TabularColumn.java b/base/runtime/org.argeo.util/src/main/java/org/argeo/util/tabular/TabularColumn.java deleted file mode 100644 index a5ee32f27..000000000 --- a/base/runtime/org.argeo.util/src/main/java/org/argeo/util/tabular/TabularColumn.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.util.tabular; - -/** The column in a tabular content */ -public class TabularColumn { - private String name; - /** - * JCR types, see - * http://www.day.com/maven/javax.jcr/javadocs/jcr-2.0/index.html - * ?javax/jcr/PropertyType.html - */ - private Integer type; - - /** column with default type */ - public TabularColumn(String name) { - super(); - this.name = name; - } - - public TabularColumn(String name, Integer type) { - super(); - this.name = name; - this.type = type; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Integer getType() { - return type; - } - - public void setType(Integer type) { - this.type = type; - } - -} diff --git a/base/runtime/org.argeo.util/src/main/java/org/argeo/util/tabular/TabularContent.java b/base/runtime/org.argeo.util/src/main/java/org/argeo/util/tabular/TabularContent.java deleted file mode 100644 index a2da86668..000000000 --- a/base/runtime/org.argeo.util/src/main/java/org/argeo/util/tabular/TabularContent.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.util.tabular; - -import java.util.List; - -/** - * Content organized as a table, possibly with headers. Only JCR types are - * supported even though there is not direct dependency on JCR. - */ -public interface TabularContent { - /** The headers of this table or null is none available. */ - public List getColumns(); - - public TabularRowIterator read(); -} diff --git a/base/runtime/org.argeo.util/src/main/java/org/argeo/util/tabular/TabularRow.java b/base/runtime/org.argeo.util/src/main/java/org/argeo/util/tabular/TabularRow.java deleted file mode 100644 index 05b8a40a9..000000000 --- a/base/runtime/org.argeo.util/src/main/java/org/argeo/util/tabular/TabularRow.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.util.tabular; - -/** A row of tabular data */ -public interface TabularRow { - /** The value at this column index */ - public Object get(Integer col); - - /** The raw objects (direct references) */ - public Object[] toArray(); - - /** Number of columns */ - public int size(); -} diff --git a/base/runtime/org.argeo.util/src/main/java/org/argeo/util/tabular/TabularRowIterator.java b/base/runtime/org.argeo.util/src/main/java/org/argeo/util/tabular/TabularRowIterator.java deleted file mode 100644 index 043463dd7..000000000 --- a/base/runtime/org.argeo.util/src/main/java/org/argeo/util/tabular/TabularRowIterator.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.util.tabular; - -import java.util.Iterator; - -/** Navigation of rows */ -public interface TabularRowIterator extends Iterator { - /** - * Current row number, has to be incremented by each call to next() ; starts at 0, will - * therefore be 1 for the first row returned. - */ - public Long getCurrentRowNumber(); -} diff --git a/base/runtime/org.argeo.util/src/main/java/org/argeo/util/tabular/TabularWriter.java b/base/runtime/org.argeo.util/src/main/java/org/argeo/util/tabular/TabularWriter.java deleted file mode 100644 index 20d6519fa..000000000 --- a/base/runtime/org.argeo.util/src/main/java/org/argeo/util/tabular/TabularWriter.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.util.tabular; - - -/** Write to a tabular content */ -public interface TabularWriter { - /** Append a new row of data */ - public void appendRow(Object[] row); - - /** Finish persisting data and release resources */ - public void close(); -} diff --git a/base/runtime/org.argeo.util/src/test/java/org/argeo/util/CsvParserEncodingTestCase.java b/base/runtime/org.argeo.util/src/test/java/org/argeo/util/CsvParserEncodingTestCase.java deleted file mode 100644 index 111a8738c..000000000 --- a/base/runtime/org.argeo.util/src/test/java/org/argeo/util/CsvParserEncodingTestCase.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.util; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.util.List; - -import junit.framework.TestCase; - -public class CsvParserEncodingTestCase extends TestCase { - - private String iso = "ISO-8859-1"; - private String utf8 = "UTF-8"; - - public void testParse() throws Exception { - - String xml = new String("áéíóúñ,éééé"); - byte[] utfBytes = xml.getBytes(utf8); - byte[] isoBytes = xml.getBytes(iso); - - InputStream inUtf = new ByteArrayInputStream(utfBytes); - InputStream inIso = new ByteArrayInputStream(isoBytes); - - CsvParser csvParser = new CsvParser() { - protected void processLine(Integer lineNumber, List header, - List tokens) { - assertEquals(header.size(), tokens.size()); - assertEquals(2, tokens.size()); - assertEquals("áéíóúñ", tokens.get(0)); - assertEquals("éééé", tokens.get(1)); - } - }; - - csvParser.parse(inUtf, utf8); - inUtf.close(); - csvParser.parse(inIso, iso); - inIso.close(); - } -} diff --git a/base/runtime/org.argeo.util/src/test/java/org/argeo/util/CsvParserParseFileTest.java b/base/runtime/org.argeo.util/src/test/java/org/argeo/util/CsvParserParseFileTest.java deleted file mode 100644 index a937ee7c7..000000000 --- a/base/runtime/org.argeo.util/src/test/java/org/argeo/util/CsvParserParseFileTest.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.util; - -import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; - -import junit.framework.TestCase; - -public class CsvParserParseFileTest extends TestCase { - public void testParse() throws Exception { - - final Map> lines = new HashMap>(); - InputStream in = getClass().getResourceAsStream( - "/org/argeo/util/ReferenceFile.csv"); - CsvParserWithLinesAsMap parser = new CsvParserWithLinesAsMap() { - protected void processLine(Integer lineNumber, - Map line) { - lines.put(lineNumber, line); - } - }; - - parser.parse(in); - in.close(); - - assertEquals(5, lines.size()); - } - -} diff --git a/base/runtime/org.argeo.util/src/test/java/org/argeo/util/CsvParserTestCase.java b/base/runtime/org.argeo.util/src/test/java/org/argeo/util/CsvParserTestCase.java deleted file mode 100644 index 02e8d1b59..000000000 --- a/base/runtime/org.argeo.util/src/test/java/org/argeo/util/CsvParserTestCase.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.util; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.util.List; - -import junit.framework.TestCase; - -public class CsvParserTestCase extends TestCase { - public void testParse() throws Exception { - String toParse = "Header1,\"Header\n2\",Header3,\"Header4\"\n" - + "Col1,\"Col\n2\",Col3,\"\"\"Col4\"\"\"\n" - + "Col1,\"Col\n2\",Col3,\"\"\"Col4\"\"\"\n" - + "Col1,\"Col\n2\",Col3,\"\"\"Col4\"\"\"\n"; - - InputStream in = new ByteArrayInputStream(toParse.getBytes()); - - CsvParser csvParser = new CsvParser() { - protected void processLine(Integer lineNumber, List header, - List tokens) { - assertEquals(header.size(), tokens.size()); - assertEquals(4, tokens.size()); - assertEquals("Col1", tokens.get(0)); - assertEquals("Col\n2", tokens.get(1)); - assertEquals("Col3", tokens.get(2)); - assertEquals("\"Col4\"", tokens.get(3)); - } - }; - - csvParser.parse(in); - in.close(); - } - -} diff --git a/base/runtime/org.argeo.util/src/test/java/org/argeo/util/CsvParserWithQuotedSeparatorTest.java b/base/runtime/org.argeo.util/src/test/java/org/argeo/util/CsvParserWithQuotedSeparatorTest.java deleted file mode 100644 index d4131a046..000000000 --- a/base/runtime/org.argeo.util/src/test/java/org/argeo/util/CsvParserWithQuotedSeparatorTest.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.util; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import junit.framework.TestCase; - -public class CsvParserWithQuotedSeparatorTest extends TestCase { - public void testSimpleParse() throws Exception { - String toParse = "Header1,\"Header2\",Header3,\"Header4\"\n" - + "\"Col1, Col2\",\"Col\n2\",Col3,\"\"\"Col4\"\"\"\n"; - - InputStream in = new ByteArrayInputStream(toParse.getBytes()); - - CsvParser csvParser = new CsvParser() { - protected void processLine(Integer lineNumber, List header, - List tokens) { - assertEquals(header.size(), tokens.size()); - assertEquals(4, tokens.size()); - assertEquals("Col1, Col2", tokens.get(0)); - } - }; - // System.out.println(toParse); - csvParser.parse(in); - in.close(); - - } - - public void testParseFile() throws Exception { - - final Map> lines = new HashMap>(); - InputStream in = getClass().getResourceAsStream( - "/org/argeo/util/ReferenceFile.csv"); - - CsvParserWithLinesAsMap parser = new CsvParserWithLinesAsMap() { - protected void processLine(Integer lineNumber, - Map line) { - // System.out.println("processing line #" + lineNumber); - lines.put(lineNumber, line); - } - }; - - parser.parse(in); - in.close(); - - Map line = lines.get(2); - assertEquals(",,,,", line.get("Coma testing")); - line = lines.get(3); - assertEquals(",, ,,", line.get("Coma testing")); - line = lines.get(4); - assertEquals("module1, module2", line.get("Coma testing")); - line = lines.get(5); - assertEquals("module1,module2", line.get("Coma testing")); - line = lines.get(6); - assertEquals(",module1,module2, \nmodule3, module4", - line.get("Coma testing")); - assertEquals(5, lines.size()); - - } -} diff --git a/base/runtime/org.argeo.util/src/test/java/org/argeo/util/CsvWriterTestCase.java b/base/runtime/org.argeo.util/src/test/java/org/argeo/util/CsvWriterTestCase.java deleted file mode 100644 index 26b356def..000000000 --- a/base/runtime/org.argeo.util/src/test/java/org/argeo/util/CsvWriterTestCase.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.util; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import junit.framework.TestCase; - -public class CsvWriterTestCase extends TestCase { - public void testWrite() throws Exception { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - final CsvWriter csvWriter = new CsvWriter(out); - - String[] header = { "Header1", "Header 2", "Header,3", "Header\n4", - "Header\"5\"" }; - String[] line1 = { "Value1", "Value 2", "Value,3", "Value\n4", - "Value\"5\"" }; - csvWriter.writeLine(Arrays.asList(header)); - csvWriter.writeLine(Arrays.asList(line1)); - - String reference = "Header1,Header 2,\"Header,3\",\"Header\n4\",\"Header\"\"5\"\"\"\n" - + "Value1,Value 2,\"Value,3\",\"Value\n4\",\"Value\"\"5\"\"\"\n"; - String written = new String(out.toByteArray()); - assertEquals(reference, written); - out.close(); - System.out.println(written); - - final List allTokens = new ArrayList(); - CsvParser csvParser = new CsvParser() { - protected void processLine(Integer lineNumber, List header, - List tokens) { - if (lineNumber == 2) - allTokens.addAll(header); - allTokens.addAll(tokens); - } - }; - ByteArrayInputStream in = new ByteArrayInputStream(written.getBytes()); - csvParser.parse(in); - in.close(); - List allTokensRef = new ArrayList(); - allTokensRef.addAll(Arrays.asList(header)); - allTokensRef.addAll(Arrays.asList(line1)); - - assertEquals(allTokensRef.size(), allTokens.size()); - for (int i = 0; i < allTokensRef.size(); i++) - assertEquals(allTokensRef.get(i), allTokens.get(i)); - } - -} diff --git a/base/runtime/org.argeo.util/src/test/java/org/argeo/util/ThroughputTest.java b/base/runtime/org.argeo.util/src/test/java/org/argeo/util/ThroughputTest.java deleted file mode 100644 index fc8007efd..000000000 --- a/base/runtime/org.argeo.util/src/test/java/org/argeo/util/ThroughputTest.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.util; - -import junit.framework.TestCase; - -public class ThroughputTest extends TestCase { - public void testParse() { - Throughput t; - t = new Throughput("3.54/s"); - assertEquals(3.54d, t.getValue()); - assertEquals(Throughput.Unit.s, t.getUnit()); - assertEquals(282l, (long) t.asMsPeriod()); - - t = new Throughput("35698.2569/h"); - assertEquals(Throughput.Unit.h, t.getUnit()); - assertEquals(101l, (long) t.asMsPeriod()); - } -} diff --git a/base/runtime/org.argeo.util/src/test/resources/org/argeo/util/ReferenceFile.csv b/base/runtime/org.argeo.util/src/test/resources/org/argeo/util/ReferenceFile.csv deleted file mode 100644 index 351453d10..000000000 --- a/base/runtime/org.argeo.util/src/test/resources/org/argeo/util/ReferenceFile.csv +++ /dev/null @@ -1,37 +0,0 @@ -"ID","A long Text","Name","Other","Number","Reference","Target","Date","Update","Language","ID Ref","Weird chars","line feeds","after line feed","Empty column","Status comment","Comments","Empty","Coma testing" -"AK251","Everything & with some line feed - more “some” quote","Marge S.",,78.6,"A1155222221111268515131",,12/12/12,03/12/08,,9821308500721,"%%%ùù","ao","Nothing special",,,"Some very usefull comment",,",,,," -"AG254","same","Roger “wallace” Big","15 – JI",78.5,"A1155222221111268515131","next milestone",12/12/12,03/12/08,"_fr (French - France)",9812309500953,"***µ”","a - - - - -o","after line feed",,"Do the job",,,",, ,," -"FG211","Very long text with some bullets. -1 first -2 second -3. some more very very very long. some more very very very long. some more very very very long. some more very very very long. some more very very very long. some more very very very long. some more very very very long. some more very very very long. some more very very very long. some more very very very long. some more very very very long. some more very very very long","Father & Son","15 – JI",15.4,"A1155222221111268515131","next milestone",12/12/12,03/12/08,"_fr (French - France)",9812309500952,"///","a - - - - - - -o","module1,module2",,"Be fast",,,"module1, module2" -"RRT152","Very long text with some bullets. -1 first -2 second -3. some more very very very long. some more very very very long. some more very very very long. some more very very very long. some more very very very long. some more very very very long. some more very very very long. some more very very very long. some more very very very long. some more very very very long. some more very very very long. some more very very very long","Another $$","15 – JI",12.3,"A1155222221111268515131","next milestone",12/12/12,03/12/08,"_fr (French - France)",9812309500950,"---","a - -o - - -","module1,module2",,,,,"module1,module2" -"YU121","Another use case : “blank line” - -After the blank.","nothing with brackets( )","15 – JI",15.2,"A1155222221111268515131",,12/12/12,03/12/08,"_fr (French - France)",9812309500925,",;:?./","ao"," - - - -After line feed again",,,,,",module1,module2, -module3, module4" diff --git a/base/runtime/org.argeo.util/src/test/resources/org/argeo/util/TestParse-ISO.csv b/base/runtime/org.argeo.util/src/test/resources/org/argeo/util/TestParse-ISO.csv deleted file mode 100644 index 0bec61111..000000000 --- a/base/runtime/org.argeo.util/src/test/resources/org/argeo/util/TestParse-ISO.csv +++ /dev/null @@ -1,8 +0,0 @@ -"Date d'imputation","N° de compte","Code journal","Pièce interne","Pièce externe","Libellé d'écriture","Débit","Crédit","Lettrage","Quantité","Code analytique","Date d'échéance","Date d'imputation origine","Code journal origine","Mode de règlement","Date début de période","Date fin de période" -26.01.2010,"101300","BQ","BQ01.10",,"Depot société en formation",,"3.000,00",,,," ",26.01.2010,"BQ"," "," "," " -26.01.2010,"101300","BQ","BQ01.10",,"Depot société en formation",,"7.000,00",,,," ",26.01.2010,"BQ"," "," "," " -26.01.2010,"411OPEN","BQ","BQ01.10",,"Vir Client ",,"2.508,00","A",,," ",26.01.2010,"BQ"," "," "," " -26.01.2010,"455100","BQ","BQ01.10",,"Bankomat Raiffeise","250,00",,,,," ",26.01.2010,"BQ"," "," "," " -26.01.2010,"512101","BQ","BQ01.10",,"Extrait bancaire 01.10","12.250,55",,,,," ",26.01.2010,"BQ"," "," "," " -26.01.2010,"627800","BQ","BQ01.10",,"Envoi de chequier","2,30",,,,," ",26.01.2010,"BQ"," "," "," " -26.01.2010,"627800","BQ","BQ01.10",,"Frais d'expedition","5,15",,,,," ",26.01.2010,"BQ"," "," "," " diff --git a/base/runtime/org.argeo.util/src/test/resources/org/argeo/util/TestParse-UTF-8.csv b/base/runtime/org.argeo.util/src/test/resources/org/argeo/util/TestParse-UTF-8.csv deleted file mode 100644 index 0bec61111..000000000 --- a/base/runtime/org.argeo.util/src/test/resources/org/argeo/util/TestParse-UTF-8.csv +++ /dev/null @@ -1,8 +0,0 @@ -"Date d'imputation","N° de compte","Code journal","Pièce interne","Pièce externe","Libellé d'écriture","Débit","Crédit","Lettrage","Quantité","Code analytique","Date d'échéance","Date d'imputation origine","Code journal origine","Mode de règlement","Date début de période","Date fin de période" -26.01.2010,"101300","BQ","BQ01.10",,"Depot société en formation",,"3.000,00",,,," ",26.01.2010,"BQ"," "," "," " -26.01.2010,"101300","BQ","BQ01.10",,"Depot société en formation",,"7.000,00",,,," ",26.01.2010,"BQ"," "," "," " -26.01.2010,"411OPEN","BQ","BQ01.10",,"Vir Client ",,"2.508,00","A",,," ",26.01.2010,"BQ"," "," "," " -26.01.2010,"455100","BQ","BQ01.10",,"Bankomat Raiffeise","250,00",,,,," ",26.01.2010,"BQ"," "," "," " -26.01.2010,"512101","BQ","BQ01.10",,"Extrait bancaire 01.10","12.250,55",,,,," ",26.01.2010,"BQ"," "," "," " -26.01.2010,"627800","BQ","BQ01.10",,"Envoi de chequier","2,30",,,,," ",26.01.2010,"BQ"," "," "," " -26.01.2010,"627800","BQ","BQ01.10",,"Frais d'expedition","5,15",,,,," ",26.01.2010,"BQ"," "," "," " diff --git a/base/runtime/pom.xml b/base/runtime/pom.xml index 8e2efbc20..c3ec59765 100644 --- a/base/runtime/pom.xml +++ b/base/runtime/pom.xml @@ -6,8 +6,8 @@ 2.1.12-SNAPSHOT .. - org.argeo.commons.base - runtime + org.argeo.commons + argeo-commons Commons Base Runtime pom diff --git a/demo/argeo_node_web.properties b/demo/argeo_node_web.properties index 65d63bcf8..ea1b6b127 100644 --- a/demo/argeo_node_web.properties +++ b/demo/argeo_node_web.properties @@ -90,6 +90,7 @@ eclipse.registry.MultiLanguage=true osgi.noShutdown=true eclipse.ignoreApp=true +#osgi.console.enable.builtin=true # Tomcat #argeo.server.port.http=7070 diff --git a/dep/org.argeo.dep.jackrabbit/pom.xml b/dep/org.argeo.dep.jackrabbit/pom.xml new file mode 100644 index 000000000..1ebb949c6 --- /dev/null +++ b/dep/org.argeo.dep.jackrabbit/pom.xml @@ -0,0 +1,110 @@ + + 4.0.0 + + org.argeo.commons + 2.1.12-SNAPSHOT + dep + .. + + org.argeo.dep.jackrabbit + pom + Commons Minimal Jackrabbit + + + + org.argeo.tp + org.apache.jackrabbit + + + + + org.argeo.tp + org.h2 + + + + + org.argeo.tp + javax.jcr + + + org.argeo.tp + org.apache.lucene + + + org.argeo.commons + org.argeo.dep.log4j + 2.1.12-SNAPSHOT + pom + + + + + org.argeo.tp + org.apache.commons.collections + + + org.argeo.tp + org.apache.commons.io + + + org.argeo.tp + org.apache.commons.httpclient + + + org.argeo.tp + org.apache.commons.fileupload + + + org.argeo.tp + org.apache.commons.compress + + + org.argeo.tp + org.apache.commons.pool + + + org.argeo.tp + org.apache.commons.dbcp + + + + + org.argeo.tp + edu.oswego.cs.dl.util.concurrent + + + + + org.argeo.tp + javax.servlet + + + + + org.argeo.tp + org.apache.tika + + + + org.argeo.tp + org.dom4j + + + org.argeo.tp + org.jdom + + + org.argeo.tp + org.objectweb.asm + + + org.argeo.tp + org.jaxen + + + org.argeo.tp + org.xmlpull + + + \ No newline at end of file diff --git a/dep/org.argeo.dep.log4j/pom.xml b/dep/org.argeo.dep.log4j/pom.xml new file mode 100644 index 000000000..15bf5d086 --- /dev/null +++ b/dep/org.argeo.dep.log4j/pom.xml @@ -0,0 +1,55 @@ + + 4.0.0 + + org.argeo.commons + 2.1.12-SNAPSHOT + dep + .. + + org.argeo.dep.log4j + pom + Commons Apache Log4j (SLF4J) Dependencies + + + org.argeo.tp + slf4j.org.apache.commons.logging + + + org.argeo.tp + org.apache.log4j + + + org.argeo.tp + slf4j.log4j + + + org.argeo.tp + slf4j.api + + + + \ No newline at end of file diff --git a/dep/org.argeo.eclipse.dep.rap/p2.inf b/dep/org.argeo.eclipse.dep.rap/p2.inf new file mode 100644 index 000000000..0423aa509 --- /dev/null +++ b/dep/org.argeo.eclipse.dep.rap/p2.inf @@ -0,0 +1,2 @@ +properties.1.name=org.eclipse.equinox.p2.type.category +properties.1.value=true \ No newline at end of file diff --git a/dep/org.argeo.eclipse.dep.rap/pom.xml b/dep/org.argeo.eclipse.dep.rap/pom.xml new file mode 100644 index 000000000..05675e210 --- /dev/null +++ b/dep/org.argeo.eclipse.dep.rap/pom.xml @@ -0,0 +1,238 @@ + + + 4.0.0 + + org.argeo.commons + dep + 2.1.12-SNAPSHOT + .. + + org.argeo.eclipse.dep.rap + Commons Eclipse RAP Dependencies + + + + org.argeo.maven.plugins + maven-argeo-osgi-plugin + + + + + + + + + + + org.argeo.tp.rap.addons + binaries + ${version.rap.addons} + pom + + + + org.argeo.tp.rap.addons + org.eclipse.osgi + + + + + + org.argeo.tp.rap.platform + binaries + ${version.rap} + pom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.argeo.tp.rap.platform + org.eclipse.rap.demo + + + org.argeo.tp.rap.platform + org.eclipse.rap.demo.databinding + + + org.argeo.tp.rap.platform + org.eclipse.rap.design.example + + + + + org.argeo.tp.rap.platform + org.eclipse.jdt.junit.runtime + + + org.argeo.tp.rap.platform + org.eclipse.rap.junit.runtime + + + org.argeo.tp.rap.platform + org.eclipse.rap.rwt.testfixture + + + + + + + + + + + + org.argeo.tp + org.apache.commons.io + + + org.argeo.tp + org.apache.commons.fileupload + + + + + org.argeo.tp + javax.servlet + + + + + org.argeo.tp.rap + org.eclipse.equinox.security + + + + + + + + + + + + check-osgi + + + + org.argeo.maven.plugins + maven-argeo-osgi-plugin + + + check-osgi + test + + equinox + + + true + + + + + + + + + rpmbuild-tp + + + + org.codehaus.mojo + rpm-maven-plugin + + + rpm-rap + package + + rpm + + + eclipse-rap + ${version.rap} + + + /usr/share/eclipse-rap + root + root + 644 + false + + + + + + + + + maven-antrun-plugin + + + install + + run + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dep/org.argeo.eclipse.dep.rcp/p2.inf b/dep/org.argeo.eclipse.dep.rcp/p2.inf new file mode 100644 index 000000000..0423aa509 --- /dev/null +++ b/dep/org.argeo.eclipse.dep.rcp/p2.inf @@ -0,0 +1,2 @@ +properties.1.name=org.eclipse.equinox.p2.type.category +properties.1.value=true \ No newline at end of file diff --git a/dep/org.argeo.eclipse.dep.rcp/pom.xml b/dep/org.argeo.eclipse.dep.rcp/pom.xml new file mode 100644 index 000000000..5035a4f42 --- /dev/null +++ b/dep/org.argeo.eclipse.dep.rcp/pom.xml @@ -0,0 +1,261 @@ + + + 4.0.0 + + org.argeo.commons + dep + 2.1.12-SNAPSHOT + .. + + org.argeo.eclipse.dep.rcp + Commons Eclipse RCP Dependencies + + + + + org.argeo.maven.plugins + maven-argeo-osgi-plugin + + + + + + org.argeo.tp + org.eclipse.osgi + + + + org.argeo.tp.rcp.platform + binaries + ${version.argeo-distribution} + pom + + + + org.argeo.tp.rcp.platform + org.eclipse.update.configurator + + + + org.argeo.tp.rcp.platform + org.eclipse.swt.win32.win32.x86_64 + + + org.argeo.tp.rcp.platform + org.eclipse.swt.carbon.macosx + + + org.argeo.tp.rcp.platform + org.eclipse.swt.cocoa.macosx.x86_64 + + + org.argeo.tp.rcp.platform + org.eclipse.swt.gtk.solaris.sparc + + + org.argeo.tp.rcp.platform + org.eclipse.swt.gtk.solaris.x86 + + + org.argeo.tp.rcp.platform + org.eclipse.swt.motif.solaris.sparc + + + org.argeo.tp.rcp.platform + org.eclipse.swt.gtk.linux.s390 + + + org.argeo.tp.rcp.platform + org.eclipse.swt.gtk.linux.s390x + + + org.argeo.tp.rcp.platform + org.eclipse.swt.gtk.linux.ppc64 + + + org.argeo.tp.rcp.platform + org.eclipse.swt.motif.linux.x86 + + + org.argeo.tp.rcp.platform + org.eclipse.swt.gtk.linux.ppc + + + org.argeo.tp.rcp.platform + org.eclipse.swt.photon.qnx.x86 + + + org.argeo.tp.rcp.platform + org.eclipse.swt.motif.aix.ppc + + + org.argeo.tp.rcp.platform + org.eclipse.swt.motif.aix.ppc64 + + + org.argeo.tp.rcp.platform + org.eclipse.swt.motif.hpux.ia64_32 + + + + + org.argeo.tp.rcp.platform + org.eclipse.equinox.launcher.win32.win32.x86_64 + + + org.argeo.tp.rcp.platform + org.eclipse.equinox.launcher.carbon.macosx + + + org.argeo.tp.rcp.platform + org.eclipse.equinox.launcher.cocoa.macosx.x86_64 + + + org.argeo.tp.rcp.platform + org.eclipse.equinox.launcher.gtk.solaris.sparc + + + org.argeo.tp.rcp.platform + org.eclipse.equinox.launcher.gtk.solaris.x86 + + + org.argeo.tp.rcp.platform + org.eclipse.equinox.launcher.motif.solaris.sparc + + + org.argeo.tp.rcp.platform + org.eclipse.equinox.launcher.gtk.linux.s390 + + + org.argeo.tp.rcp.platform + org.eclipse.equinox.launcher.gtk.linux.s390x + + + org.argeo.tp.rcp.platform + org.eclipse.equinox.launcher.gtk.linux.ppc64 + + + org.argeo.tp.rcp.platform + org.eclipse.equinox.launcher.motif.linux.x86 + + + org.argeo.tp.rcp.platform + org.eclipse.equinox.launcher.gtk.linux.ppc + + + org.argeo.tp.rcp.platform + org.eclipse.equinox.launcher.photon.qnx.x86 + + + org.argeo.tp.rcp.platform + org.eclipse.equinox.launcher.motif.aix.ppc + + + org.argeo.tp.rcp.platform + org.eclipse.equinox.launcher.motif.aix.ppc64 + + + org.argeo.tp.rcp.platform + org.eclipse.equinox.launcher.motif.hpux.ia64_32 + + + + + org.argeo.tp.rcp.platform + org.eclipse.ui.carbon + + + + + + + org.argeo.tp.rcp + org.eclipse.equinox.security + + + + + + org.argeo.tp.rcp + binaries + ${version.argeo-distribution} + pom + import + + + org.argeo.tp.rcp.platform + binaries + ${version.argeo-distribution} + pom + import + + + + + + check-osgi + + + + org.argeo.maven.plugins + maven-argeo-osgi-plugin + + + check-osgi + test + + equinox + + + true + + + + + + + + + \ No newline at end of file diff --git a/dep/org.argeo.security.dep.node.eclipse/p2.inf b/dep/org.argeo.security.dep.node.eclipse/p2.inf new file mode 100644 index 000000000..0423aa509 --- /dev/null +++ b/dep/org.argeo.security.dep.node.eclipse/p2.inf @@ -0,0 +1,2 @@ +properties.1.name=org.eclipse.equinox.p2.type.category +properties.1.value=true \ No newline at end of file diff --git a/dep/org.argeo.security.dep.node.eclipse/pom.xml b/dep/org.argeo.security.dep.node.eclipse/pom.xml new file mode 100644 index 000000000..0ca4b1f93 --- /dev/null +++ b/dep/org.argeo.security.dep.node.eclipse/pom.xml @@ -0,0 +1,137 @@ + + 4.0.0 + + org.argeo.commons + 2.1.12-SNAPSHOT + dep + .. + + org.argeo.security.dep.node.eclipse + Node Eclipse Perspectives + + + + org.argeo.maven.plugins + maven-argeo-osgi-plugin + + + generate-descriptors + + descriptors + + generate-resources + + + + + + + + + org.argeo.commons + org.argeo.jcr.ui.explorer + 2.1.12-SNAPSHOT + + + org.argeo.commons + org.argeo.osgi.ui.explorer + 2.1.12-SNAPSHOT + + + org.argeo.commons + org.argeo.security.ui.admin + 2.1.12-SNAPSHOT + + + + + org.argeo.commons + org.argeo.eclipse.ui + 2.1.12-SNAPSHOT + + + org.argeo.commons + org.argeo.eclipse.ui.jcr + 2.1.12-SNAPSHOT + + + org.argeo.commons + org.argeo.security.equinox + 2.1.12-SNAPSHOT + + + org.argeo.commons + org.argeo.security.ui + 2.1.12-SNAPSHOT + + + + + org.argeo.commons + org.argeo.security.dep.node + 2.1.12-SNAPSHOT + pom + + + + + rpmbuild + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-direct + package + + copy-dependencies + + + jar + true + ${project.build.directory}/argeo-node-eclipse + + + + + + org.codehaus.mojo + rpm-maven-plugin + + + rpm-node-eclipse + package + + rpm + + + argeo-node-eclipse + rpm-eclipse + + + /usr/share/osgi/eclipse + root + root + 644 + false + + + ${project.build.directory}/argeo-node-eclipse + + + + + + argeo-node + + + + + + + + + + diff --git a/dep/org.argeo.security.dep.node.rap/p2.inf b/dep/org.argeo.security.dep.node.rap/p2.inf new file mode 100644 index 000000000..0423aa509 --- /dev/null +++ b/dep/org.argeo.security.dep.node.rap/p2.inf @@ -0,0 +1,2 @@ +properties.1.name=org.eclipse.equinox.p2.type.category +properties.1.value=true \ No newline at end of file diff --git a/dep/org.argeo.security.dep.node.rap/pom.xml b/dep/org.argeo.security.dep.node.rap/pom.xml new file mode 100644 index 000000000..b3ea1f45c --- /dev/null +++ b/dep/org.argeo.security.dep.node.rap/pom.xml @@ -0,0 +1,198 @@ + + 4.0.0 + + org.argeo.commons + 2.1.12-SNAPSHOT + dep + .. + + org.argeo.security.dep.node.rap + Node Eclipse RAP + + + + org.apache.felix + maven-bundle-plugin + + + default + + + + + org.argeo.maven.plugins + maven-argeo-osgi-plugin + + + generate-descriptors + + descriptors + + generate-resources + + + + + + + + + org.argeo.commons + org.argeo.jcr.ui.explorer + 2.1.12-SNAPSHOT + + + org.argeo.commons + org.argeo.osgi.ui.explorer + 2.1.12-SNAPSHOT + + + org.argeo.commons + org.argeo.security.ui.admin + 2.1.12-SNAPSHOT + + + org.argeo.commons + org.argeo.security.mvc + 2.1.12-SNAPSHOT + + + + + org.argeo.commons + org.argeo.security.dep.node + 2.1.12-SNAPSHOT + pom + + + org.argeo.commons + org.argeo.security.dao.jackrabbit + + + org.argeo.commons + org.argeo.security.dao.os + + + org.argeo.commons + org.argeo.server.catalina.start + + + org.argeo.commons + org.argeo.server.webextender + + + org.argeo.tp + org.apache.jasper + + + org.argeo.tp + org.springframework.osgi.web.extender + + + + + org.argeo.commons + org.argeo.security.ui.rap + 2.1.12-SNAPSHOT + + + + + + + check-osgi + + + + org.argeo.maven.plugins + maven-argeo-osgi-plugin + + + check-osgi + test + + equinox + + + true + + + + + + + + + + org.argeo.commons + org.argeo.osgi.boot + 2.1.12-SNAPSHOT + test + + + + + rpmbuild + + + + org.codehaus.mojo + rpm-maven-plugin + + + rpm-node-rap + package + + rpm + + + argeo-node-rap + + + + + + + + + + + + + + + + /usr/share/osgi/rap + root + root + 644 + false + + + org.argeo.commons.base:org.argeo.eclipse.ui.rap + org.argeo.commons.server:org.argeo.server.rap.webapp + org.argeo.commons.security:org.argeo.security.ui.rap + + + + + + argeo-node + argeo-node-eclipse + eclipse-rap + + + + + + + + + + diff --git a/dep/org.argeo.security.dep.node.rap/src/assembly/dist.xml b/dep/org.argeo.security.dep.node.rap/src/assembly/dist.xml new file mode 100644 index 000000000..2cbbd389b --- /dev/null +++ b/dep/org.argeo.security.dep.node.rap/src/assembly/dist.xml @@ -0,0 +1,38 @@ + + + dist + argeo-node-server + + tar.gz + + + + false + ${artifact.artifactId}-${artifact.baseVersion}.${artifact.extension} + + lib + + *:jar + + + + \ No newline at end of file diff --git a/dep/org.argeo.security.dep.node.rcp/p2.inf b/dep/org.argeo.security.dep.node.rcp/p2.inf new file mode 100644 index 000000000..0423aa509 --- /dev/null +++ b/dep/org.argeo.security.dep.node.rcp/p2.inf @@ -0,0 +1,2 @@ +properties.1.name=org.eclipse.equinox.p2.type.category +properties.1.value=true \ No newline at end of file diff --git a/dep/org.argeo.security.dep.node.rcp/pom.xml b/dep/org.argeo.security.dep.node.rcp/pom.xml new file mode 100644 index 000000000..53a712510 --- /dev/null +++ b/dep/org.argeo.security.dep.node.rcp/pom.xml @@ -0,0 +1,129 @@ + + 4.0.0 + + org.argeo.commons + 2.1.12-SNAPSHOT + dep + .. + + org.argeo.security.dep.node.rcp + Node Eclipse RCP + + + + org.apache.felix + maven-bundle-plugin + + + default + + + + + org.argeo.maven.plugins + maven-argeo-osgi-plugin + + + generate-descriptors + + descriptors + + generate-resources + + + + + + + + org.argeo.commons + org.argeo.security.dep.node.eclipse + 2.1.12-SNAPSHOT + pom + + + org.argeo.commons + org.argeo.security.ui.rcp + 2.1.12-SNAPSHOT + + + + + check-osgi + + + + org.argeo.maven.plugins + maven-argeo-osgi-plugin + + + check-osgi + test + + equinox + + + true + + + + + + + + + + org.argeo.commons + org.argeo.osgi.boot + 2.1.12-SNAPSHOT + test + + + + + rpmbuild + + + + org.codehaus.mojo + rpm-maven-plugin + + + + + rpm-node-rcp + package + + rpm + + + argeo-node-rcp + + + /usr/share/osgi/rcp + root + root + 644 + false + + + org.argeo.commons.base:org.argeo.eclipse.ui.rcp + org.argeo.commons.security:org.argeo.security.ui.rcp + + + + + + argeo-node + argeo-node-eclipse + eclipse-platform + + + + + + + + + + diff --git a/dep/org.argeo.security.dep.node.rcp/src/assembly/linux.x86.xml b/dep/org.argeo.security.dep.node.rcp/src/assembly/linux.x86.xml new file mode 100644 index 000000000..0b321cdca --- /dev/null +++ b/dep/org.argeo.security.dep.node.rcp/src/assembly/linux.x86.xml @@ -0,0 +1,59 @@ + + + + + linux.x86 + argeo-node-ui + + tar.gz + + + + false + ${artifact.artifactId}-${artifact.baseVersion}.${artifact.extension} + + lib + + *:jar + + + org.eclipse.swt:org.eclipse.swt*:jar + + + + false + ${artifact.artifactId}-${artifact.baseVersion}.${artifact.extension} + + lib + + org.eclipse.swt:org.eclipse.swt.gtk.linux.x86:jar + + + + \ No newline at end of file diff --git a/dep/org.argeo.security.dep.node.rcp/src/assembly/linux.x86_64.xml b/dep/org.argeo.security.dep.node.rcp/src/assembly/linux.x86_64.xml new file mode 100644 index 000000000..12a0a3278 --- /dev/null +++ b/dep/org.argeo.security.dep.node.rcp/src/assembly/linux.x86_64.xml @@ -0,0 +1,59 @@ + + + + + linux.x86_64 + argeo-node-ui + + tar.gz + + + + false + ${artifact.artifactId}-${artifact.baseVersion}.${artifact.extension} + + lib + + *:jar + + + org.eclipse.swt:org.eclipse.swt*:jar + + + + false + ${artifact.artifactId}-${artifact.baseVersion}.${artifact.extension} + + lib + + org.eclipse.swt:org.eclipse.swt.gtk.linux.x86_64:jar + + + + \ No newline at end of file diff --git a/dep/org.argeo.security.dep.node.rcp/src/assembly/win32.x86.xml b/dep/org.argeo.security.dep.node.rcp/src/assembly/win32.x86.xml new file mode 100644 index 000000000..15cec0da6 --- /dev/null +++ b/dep/org.argeo.security.dep.node.rcp/src/assembly/win32.x86.xml @@ -0,0 +1,59 @@ + + + + + win32.x86 + argeo-node-ui + + zip + + + + false + ${artifact.artifactId}-${artifact.baseVersion}.${artifact.extension} + + lib + + *:jar + + + org.eclipse.swt:org.eclipse.swt*:jar + + + + false + ${artifact.artifactId}-${artifact.baseVersion}.${artifact.extension} + + lib + + org.eclipse.swt:org.eclipse.swt.win32.win32.x86:jar + + + + \ No newline at end of file diff --git a/dep/org.argeo.security.dep.node/p2.inf b/dep/org.argeo.security.dep.node/p2.inf new file mode 100644 index 000000000..0423aa509 --- /dev/null +++ b/dep/org.argeo.security.dep.node/p2.inf @@ -0,0 +1,2 @@ +properties.1.name=org.eclipse.equinox.p2.type.category +properties.1.value=true \ No newline at end of file diff --git a/dep/org.argeo.security.dep.node/pom.xml b/dep/org.argeo.security.dep.node/pom.xml new file mode 100644 index 000000000..797558a05 --- /dev/null +++ b/dep/org.argeo.security.dep.node/pom.xml @@ -0,0 +1,416 @@ + + + 4.0.0 + + org.argeo.commons + 2.1.12-SNAPSHOT + dep + .. + + org.argeo.security.dep.node + Node Backend + + + + org.apache.felix + maven-bundle-plugin + + + default + + + + + org.argeo.maven.plugins + maven-argeo-osgi-plugin + + + generate-descriptors + + descriptors + + generate-resources + + + + + + + + + org.argeo.commons + org.argeo.node.repo.jackrabbit + 2.1.12-SNAPSHOT + + + + + org.argeo.commons + org.argeo.osgi.boot + 2.1.12-SNAPSHOT + + + + + org.argeo.commons + org.argeo.dep.log4j + 2.1.12-SNAPSHOT + pom + + + + + org.argeo.commons + org.argeo.server.core + 2.1.12-SNAPSHOT + + + + + org.argeo.commons + org.argeo.security.core + 2.1.12-SNAPSHOT + + + + + org.argeo.tp + org.apache.xmlcommons + + + org.argeo.tp + org.apache.xalan + + + + + org.argeo.tp + javax.annotation + + + org.argeo.tp + javax.mail + + + + + org.argeo.tp + bcprov + + + org.argeo.tp + bcmail + + + + + org.argeo.tp + org.apache.commons.vfs + + + org.argeo.tp + org.apache.commons.exec + + + org.argeo.tp + org.apache.commons.cli + + + org.argeo.tp + org.apache.commons.dbcp + + + + + org.argeo.tp + jxl + + + org.argeo.tp + org.apache.pdfbox + + + + + org.argeo.tp + org.springframework.context.support + + + + + org.argeo.tp + org.springframework.osgi.extender + + + + + org.argeo.commons + org.argeo.server.jackrabbit + 2.1.12-SNAPSHOT + + + org.argeo.commons + org.argeo.security.jackrabbit + 2.1.12-SNAPSHOT + + + + + org.argeo.tp + org.quartz + + + + + org.argeo.commons + org.argeo.security.dao.ldap + 2.1.12-SNAPSHOT + + + org.argeo.commons + org.argeo.security.auth.ldap + 2.1.12-SNAPSHOT + + + org.argeo.commons + org.argeo.security.ldap + 2.1.12-SNAPSHOT + + + + + org.argeo.commons + org.argeo.security.dao.jackrabbit + 2.1.12-SNAPSHOT + + + + + org.argeo.commons + org.argeo.security.dao.os + 2.1.12-SNAPSHOT + + + + + org.argeo.tp + org.springframework.osgi.web.extender + + + org.argeo.tp + org.springframework.osgi.web + + + + + + + + + + + + + + org.argeo.commons + org.argeo.server.jcr.mvc + 2.1.12-SNAPSHOT + + + org.argeo.commons + org.argeo.jackrabbit.webapp + 2.1.12-SNAPSHOT + + + + + org.argeo.tp + org.h2 + + + org.argeo.tp + com.mysql.jdbc + + + org.argeo.tp + org.postgresql.jdbc3 + + + + + org.argeo.commons + org.argeo.server.dep.ads + 2.1.12-SNAPSHOT + pom + + + org.argeo.commons + org.argeo.server.ads.server + 2.1.12-SNAPSHOT + + + org.argeo.commons + org.argeo.server.ads + 2.1.12-SNAPSHOT + + + + + org.argeo.commons + org.argeo.support.junit + 2.1.12-SNAPSHOT + + + + + check-osgi + + + + org.argeo.maven.plugins + maven-argeo-osgi-plugin + + + check-osgi + test + + equinox + + + true + + + + + + + + + + org.argeo.commons + org.argeo.osgi.boot + 2.1.12-SNAPSHOT + test + + + + + rpmbuild + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-node + package + + copy-dependencies + + + jar + org.argeo.commons.base,org.argeo.commons.server,org.argeo.commons.security + org.argeo.osgi.boot + ${project.build.directory}/node + + + + + + org.codehaus.mojo + rpm-maven-plugin + + + rpm-node + package + + rpm + + + argeo-node + + + /usr/share/osgi + root + root + 644 + false + + + ${project.build.directory}/node + + + + + + argeo-node-tp + + + + + + + + + + rpmbuild-tp + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-tp + package + + copy-dependencies + + + jar + org.argeo.commons.base,org.argeo.commons.server,org.argeo.commons.security + org.eclipse.osgi + ${project.build.directory}/node-tp + + + + + + org.codehaus.mojo + rpm-maven-plugin + + + rpm-node-tp + package + + rpm + + + argeo-node-tp + rpm-tp + ${version.argeo-distribution} + + + /usr/share/osgi + root + root + 644 + false + + + ${project.build.directory}/node-tp + + + + + + + + + + + + + \ No newline at end of file diff --git a/dep/org.argeo.server.dep.ads/pom.xml b/dep/org.argeo.server.dep.ads/pom.xml new file mode 100644 index 000000000..d1341e000 --- /dev/null +++ b/dep/org.argeo.server.dep.ads/pom.xml @@ -0,0 +1,54 @@ + + 4.0.0 + + org.argeo.commons + 2.1.12-SNAPSHOT + dep + .. + + org.argeo.server.dep.ads + pom + Commons Apache Directory Server Dependencies + + + + org.argeo.commons + org.argeo.dep.log4j + 2.1.12-SNAPSHOT + pom + + + + + org.argeo.tp + org.apache.directory.server.core + + + org.argeo.tp + org.apache.directory.shared.asn.codec + + + org.argeo.tp + org.apache.mina.filter.ssl + + + org.argeo.tp + org.apache.directory.server.jndi + + + org.argeo.tp + jdbm + + + org.argeo.commons + org.argeo.ext.jdbm + 2.1.12-SNAPSHOT + + + + org.argeo.tp + org.apache.commons.lang + + + \ No newline at end of file diff --git a/dep/org.argeo.server.dep.jackrabbit.server/pom.xml b/dep/org.argeo.server.dep.jackrabbit.server/pom.xml new file mode 100644 index 000000000..d9561a296 --- /dev/null +++ b/dep/org.argeo.server.dep.jackrabbit.server/pom.xml @@ -0,0 +1,79 @@ + + 4.0.0 + + org.argeo.commons + 2.1.12-SNAPSHOT + dep + .. + + org.argeo.server.dep.jackrabbit.server + pom + Commons Jackrabbit Dependencies + + + org.argeo.commons + org.argeo.dep.jackrabbit + pom + 2.1.12-SNAPSHOT + + + + + org.argeo.tp + bcprov + + + org.argeo.tp + bcmail + + + + + + + + org.argeo.tp + org.apache.xmlbeans + + + org.argeo.tp + org.apache.xmlcommons + + + org.argeo.tp + org.apache.pdfbox + + + org.argeo.tp + org.apache.poi + + + org.argeo.tp + com.sun.syndication + + + org.argeo.tp + org.cyberneko.html + + + org.argeo.tp + de.l3s.boilerpipe + + + org.argeo.tp + javax.mail + + + org.argeo.tp + com.drewnoakes.metadata_extractor + + + org.argeo.tp + edu.ucar.unidata.netcdf + + + org.argeo.tp + org.ccil.cowan.tagsoup + + + \ No newline at end of file diff --git a/dep/pom.xml b/dep/pom.xml new file mode 100644 index 000000000..be0882915 --- /dev/null +++ b/dep/pom.xml @@ -0,0 +1,63 @@ + + + 4.0.0 + + org.argeo.commons + argeo-commons + 2.1.12-SNAPSHOT + .. + + dep + Commons Base Dependencies + pom + + org.argeo.dep.log4j + org.argeo.dep.jackrabbit + org.argeo.eclipse.dep.rap + org.argeo.eclipse.dep.rcp + org.argeo.server.dep.ads + org.argeo.server.dep.jackrabbit.server + org.argeo.security.dep.node + org.argeo.security.dep.node.eclipse + org.argeo.security.dep.node.rap + org.argeo.security.dep.node.rcp + + + + + org.apache.felix + maven-bundle-plugin + + + + + + org.argeo.maven.plugins + maven-argeo-osgi-plugin + + + generate-descriptors + + descriptors + + generate-resources + + + + + + + + + check-osgi + + + org.argeo.commons + org.argeo.osgi.boot + 2.1.12-SNAPSHOT + test + + + + + \ No newline at end of file diff --git a/dist/osgi-boot/pom.xml b/dist/osgi-boot/pom.xml new file mode 100644 index 000000000..7f5094ffe --- /dev/null +++ b/dist/osgi-boot/pom.xml @@ -0,0 +1,188 @@ + + 4.0.0 + + org.argeo.commons + 2.1.12-SNAPSHOT + dist + .. + + osgi-boot + pom + Commons OSGi Boot Distribution + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-dependencies + package + + copy-dependencies + + + jar + true + ${project.build.directory}/lib + + + + + + + + + org.argeo.commons + org.argeo.osgi.boot + 2.1.12-SNAPSHOT + + + + + rpmbuild + + + + org.codehaus.mojo + rpm-maven-plugin + + + rpm-osgi-boot + package + + rpm + + + osgi-boot + + + /etc/osgiboot + root + root + 644 + noreplace + false + + + src/main/rpm/etc/osgiboot + + *-settings.sh + + + + + + /etc/osgiboot + root + root + 644 + false + + + src/main/rpm/etc/osgiboot + + *-functions.sh + + + + + + /usr/sbin + root + root + 755 + + + src/main/rpm/usr/sbin + + + + + /usr/share/osgi/boot + root + root + 644 + false + + + ${project.build.directory}/lib + + org.argeo.osgi.boot.jar + + + + + + + osgi-boot-equinox + + + + + + + maven-antrun-plugin + + + install + + run + + + + + + + + + + + + + + + + + rpmbuild-tp + + + + org.codehaus.mojo + rpm-maven-plugin + + + rpm-osgi-boot-equinox + package + + rpm + + + osgi-boot-equinox + ${version.argeo-distribution} + + + /usr/share/osgi/boot + root + root + 644 + false + + + ${project.build.directory}/lib + + org.eclipse.osgi.jar + + + + + + + + + + + + + + diff --git a/dist/osgi-boot/src/main/rpm/etc/osgiboot/osgi-service-init-functions.sh b/dist/osgi-boot/src/main/rpm/etc/osgiboot/osgi-service-init-functions.sh new file mode 100644 index 000000000..35bf9703f --- /dev/null +++ b/dist/osgi-boot/src/main/rpm/etc/osgiboot/osgi-service-init-functions.sh @@ -0,0 +1,59 @@ +#!/bin/bash + +# Source function library. +. /etc/rc.d/init.d/functions + +RETVAL=0 + +osgi_service_start() { + APP=$1 + # create log an run directories writable by the application user + USER=$APP + GROUP=$APP + RUN_DIR=/var/run/$APP + LOG_DIR=/var/log/$APP + if [ ! -d $LOG_DIR ];then + mkdir -m 0750 $LOG_DIR + chown -R $USER.$GROUP $LOG_DIR + fi + if [ ! -d $RUN_DIR ];then + mkdir -m 0750 $RUN_DIR + chown -R $USER.$GROUP $RUN_DIR + fi + + # call Argeo Commons OSGi utilities as the application user + daemon --user $USER /usr/sbin/osgi-service $APP start + + RETVAL=$? + #action $"Start $APP" /bin/true + if [ $RETVAL -eq 0 ];then + PID=`cat $RUN_DIR/$APP.pid` + action $"Started $APP with pid $PID" /bin/true + else + action $"Could not start $APP" /bin/false + fi + return $RETVAL +} + +osgi_service_stop() { + APP=$1 + USER=$APP + # call Argeo Commons OSGi utilities as the application user + runuser -s /bin/bash $USER -c "/usr/sbin/osgi-service $APP stop" + RETVAL=$? + if [ $RETVAL -eq 0 ];then + action $"Stopped $APP" /bin/true + else + action $"Could not stop $APP" /bin/false + fi + return $RETVAL +} + +osgi_service_status() { + APP=$1 + USER=$APP + # call Argeo Commons OSGi utilities as the application user + runuser -s /bin/bash $USER -c "/usr/sbin/osgi-service $APP status" + RETVAL=$? + return $RETVAL +} diff --git a/dist/osgi-boot/src/main/rpm/etc/osgiboot/osgi-service-settings.sh b/dist/osgi-boot/src/main/rpm/etc/osgiboot/osgi-service-settings.sh new file mode 100644 index 000000000..f5504f811 --- /dev/null +++ b/dist/osgi-boot/src/main/rpm/etc/osgiboot/osgi-service-settings.sh @@ -0,0 +1 @@ +#JAVA_OPTS=-Xmx256m \ No newline at end of file diff --git a/dist/osgi-boot/src/main/rpm/usr/sbin/osgi-service b/dist/osgi-boot/src/main/rpm/usr/sbin/osgi-service new file mode 100644 index 000000000..5c37f9c82 --- /dev/null +++ b/dist/osgi-boot/src/main/rpm/usr/sbin/osgi-service @@ -0,0 +1,153 @@ +#!/bin/sh + +JVM=java +. /etc/osgiboot/osgi-service-settings.sh + +APP=$1 + +CONF_DIR=/etc/$APP +if [ -f $CONF_DIR/settings.sh ];then + . $CONF_DIR/settings.sh +fi + +LIB_DIR=/usr/share/$APP/lib + +# read/write +EXEC_DIR=/var/lib/$APP +DATA_DIR=$EXEC_DIR/data +CONF_RW=$EXEC_DIR/conf + +LOG_DIR=/var/log/$APP +LOG_FILE=$LOG_DIR/$APP.log + +RUN_DIR=/var/run/$APP +PID_FILE=$RUN_DIR/$APP.pid +SHUTDOWN_FILE=$RUN_DIR/$APP.shutdown + +OSGI_INSTALL_AREA=/usr/share/osgi/boot +OSGI_FRAMEWORK=$OSGI_INSTALL_AREA/org.eclipse.osgi.jar + +RETVAL=0 + +start() { + if [ -f $PID_FILE ];then + PID=`cat $PID_FILE` + kill -0 $PID &> /dev/null + PID_EXISTS=$? + if [ $PID_EXISTS -eq 0 ]; then + echo $APP already running with pid $PID + RETVAL=1 + return $RETVAL + else + echo Old $APP process with pid $PID is dead, removing $PID_FILE + rm -f $PID_FILE + fi + fi + + cp --preserve $CONF_DIR/config.ini $CONF_RW/config.ini + touch $SHUTDOWN_FILE + cd $EXEC_DIR + $JVM \ + -Dargeo.osgi.shutdownFile="$SHUTDOWN_FILE" \ + -Dlog4j.configuration="file:$CONF_DIR/log4j.properties" \ + $JAVA_OPTS -jar $OSGI_FRAMEWORK \ + -clean \ + -configuration "$CONF_RW" \ + -data "$DATA_DIR" \ + >> $LOG_FILE 2>&1 & + # (above) stderr redirected to stdout, then stdout to log file + # see http://tldp.org/LDP/abs/html/io-redirection.html + PID=$! + echo $PID > $PID_FILE + #echo Started $APP with pid $PID + return $RETVAL +} + +stop() { + if [ -f $PID_FILE ];then + PID=`cat $PID_FILE` + kill -0 $PID &> /dev/null + PID_EXISTS=$? + if [ $PID_EXISTS -ne 0 ]; then + echo Dead $APP process with pid $PID, removing $PID_FILE + rm -f $PID_FILE + RETVAL=1 + return $RETVAL + fi + else + echo $APP is not running + RETVAL=1 + return $RETVAL + fi + + # notifies application by removing the shutdown file + rm -f $SHUTDOWN_FILE + + # wait 5 min for application to shutdown, then kill it + TIMEOUT=$((5*60)) + BEGIN=$(date +%s) + while kill -0 $PID &> /dev/null + do + sleep 1 + NOW=$(date +%s) + DURATION=$(($NOW-$BEGIN)) + if [ $DURATION -gt $TIMEOUT ]; then + kill -9 $PID + echo Forcibly killed $APP with pid $PID + RETVAL=1 + fi + done + + # remove pid file + rm -f $PID_FILE + return $RETVAL + +# timeout is only available in EL6 +# timeout 5m sh << EOF +#while kill -0 $PID &> /dev/null; do sleep 1; done +#EOF +# TIMEOUT_EXIT=$? +# if [ $TIMEOUT_EXIT -eq 124 ];then +# kill -9 $PID +# RETVAL=1 +# echo Killed $APP with pid $PID +# else +# echo Stopped $APP with pid $PID +# fi +# rm -f $PID_FILE +# return $RETVAL +} + +status() { + if [ -f $PID_FILE ];then + PID=`cat $PID_FILE` + else + echo $APP is not running + return $RETVAL + fi + kill -0 $PID &> /dev/null + PID_EXISTS=$? + if [ $PID_EXISTS -eq 0 ]; then + echo $APP is running with pid $PID ... + else + echo No $APP process with pid $PID, removing $PID_FILE + rm -f $PID_FILE + fi + return $RETVAL +} + +# main +case "$2" in + start) + start + ;; + stop) + stop + ;; + status) + status + ;; + *) + echo $"Usage: $0 {start|stop|status}" + exit 1 +esac \ No newline at end of file diff --git a/dist/pom.xml b/dist/pom.xml new file mode 100644 index 000000000..5286dbb9d --- /dev/null +++ b/dist/pom.xml @@ -0,0 +1,16 @@ + + + 4.0.0 + + org.argeo.commons + argeo-commons + 2.1.12-SNAPSHOT + .. + + dist + Commons Distributions + pom + + osgi-boot + + \ No newline at end of file diff --git a/org.argeo.eclipse.ui.jcr/.classpath b/org.argeo.eclipse.ui.jcr/.classpath new file mode 100644 index 000000000..cf1efe7e4 --- /dev/null +++ b/org.argeo.eclipse.ui.jcr/.classpath @@ -0,0 +1,8 @@ + + + >> + + + + + diff --git a/org.argeo.eclipse.ui.jcr/.project b/org.argeo.eclipse.ui.jcr/.project new file mode 100644 index 000000000..d15268372 --- /dev/null +++ b/org.argeo.eclipse.ui.jcr/.project @@ -0,0 +1,28 @@ + + + org.argeo.eclipse.ui.jcr + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/org.argeo.eclipse.ui.jcr/.settings/org.eclipse.jdt.core.prefs b/org.argeo.eclipse.ui.jcr/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..57d3f0066 --- /dev/null +++ b/org.argeo.eclipse.ui.jcr/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +#Sat Jan 22 14:25:47 CET 2011 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.5 diff --git a/org.argeo.eclipse.ui.jcr/.settings/org.eclipse.pde.core.prefs b/org.argeo.eclipse.ui.jcr/.settings/org.eclipse.pde.core.prefs new file mode 100644 index 000000000..81635e90f --- /dev/null +++ b/org.argeo.eclipse.ui.jcr/.settings/org.eclipse.pde.core.prefs @@ -0,0 +1,4 @@ +#Sat Jan 22 14:25:47 CET 2011 +eclipse.preferences.version=1 +pluginProject.extensions=false +resolve.requirebundle=false diff --git a/org.argeo.eclipse.ui.jcr/build.properties b/org.argeo.eclipse.ui.jcr/build.properties new file mode 100644 index 000000000..0f2736b3a --- /dev/null +++ b/org.argeo.eclipse.ui.jcr/build.properties @@ -0,0 +1,6 @@ +source.. = src/main/java/,\ + src/main/resources +output.. = target/classes/ +bin.includes = META-INF/,\ + .,\ + icons/ diff --git a/org.argeo.eclipse.ui.jcr/icons/binary.png b/org.argeo.eclipse.ui.jcr/icons/binary.png new file mode 100644 index 000000000..fdf4f82be Binary files /dev/null and b/org.argeo.eclipse.ui.jcr/icons/binary.png differ diff --git a/org.argeo.eclipse.ui.jcr/icons/file.gif b/org.argeo.eclipse.ui.jcr/icons/file.gif new file mode 100644 index 000000000..ef3028807 Binary files /dev/null and b/org.argeo.eclipse.ui.jcr/icons/file.gif differ diff --git a/org.argeo.eclipse.ui.jcr/icons/folder.gif b/org.argeo.eclipse.ui.jcr/icons/folder.gif new file mode 100644 index 000000000..42e027c93 Binary files /dev/null and b/org.argeo.eclipse.ui.jcr/icons/folder.gif differ diff --git a/org.argeo.eclipse.ui.jcr/icons/home.gif b/org.argeo.eclipse.ui.jcr/icons/home.gif new file mode 100644 index 000000000..fd0c66950 Binary files /dev/null and b/org.argeo.eclipse.ui.jcr/icons/home.gif differ diff --git a/org.argeo.eclipse.ui.jcr/icons/node.gif b/org.argeo.eclipse.ui.jcr/icons/node.gif new file mode 100644 index 000000000..364c0e70b Binary files /dev/null and b/org.argeo.eclipse.ui.jcr/icons/node.gif differ diff --git a/org.argeo.eclipse.ui.jcr/icons/remote_connected.gif b/org.argeo.eclipse.ui.jcr/icons/remote_connected.gif new file mode 100644 index 000000000..1492b4efa Binary files /dev/null and b/org.argeo.eclipse.ui.jcr/icons/remote_connected.gif differ diff --git a/org.argeo.eclipse.ui.jcr/icons/remote_disconnected.gif b/org.argeo.eclipse.ui.jcr/icons/remote_disconnected.gif new file mode 100644 index 000000000..6c54da9ad Binary files /dev/null and b/org.argeo.eclipse.ui.jcr/icons/remote_disconnected.gif differ diff --git a/org.argeo.eclipse.ui.jcr/icons/repositories.gif b/org.argeo.eclipse.ui.jcr/icons/repositories.gif new file mode 100644 index 000000000..c13bea1ca Binary files /dev/null and b/org.argeo.eclipse.ui.jcr/icons/repositories.gif differ diff --git a/org.argeo.eclipse.ui.jcr/icons/repository_connected.gif b/org.argeo.eclipse.ui.jcr/icons/repository_connected.gif new file mode 100644 index 000000000..a15fa5538 Binary files /dev/null and b/org.argeo.eclipse.ui.jcr/icons/repository_connected.gif differ diff --git a/org.argeo.eclipse.ui.jcr/icons/repository_disconnected.gif b/org.argeo.eclipse.ui.jcr/icons/repository_disconnected.gif new file mode 100644 index 000000000..4576dc563 Binary files /dev/null and b/org.argeo.eclipse.ui.jcr/icons/repository_disconnected.gif differ diff --git a/org.argeo.eclipse.ui.jcr/icons/sort.gif b/org.argeo.eclipse.ui.jcr/icons/sort.gif new file mode 100644 index 000000000..23c5d0b11 Binary files /dev/null and b/org.argeo.eclipse.ui.jcr/icons/sort.gif differ diff --git a/org.argeo.eclipse.ui.jcr/icons/workspace_connected.png b/org.argeo.eclipse.ui.jcr/icons/workspace_connected.png new file mode 100644 index 000000000..0430baaf5 Binary files /dev/null and b/org.argeo.eclipse.ui.jcr/icons/workspace_connected.png differ diff --git a/org.argeo.eclipse.ui.jcr/icons/workspace_disconnected.png b/org.argeo.eclipse.ui.jcr/icons/workspace_disconnected.png new file mode 100644 index 000000000..fddcb8c4e Binary files /dev/null and b/org.argeo.eclipse.ui.jcr/icons/workspace_disconnected.png differ diff --git a/org.argeo.eclipse.ui.jcr/pom.xml b/org.argeo.eclipse.ui.jcr/pom.xml new file mode 100644 index 000000000..b46700283 --- /dev/null +++ b/org.argeo.eclipse.ui.jcr/pom.xml @@ -0,0 +1,89 @@ + + 4.0.0 + + org.argeo.commons + 2.1.12-SNAPSHOT + argeo-commons + .. + + org.argeo.eclipse.ui.jcr + Commons Eclipse UI JCR + jar + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-source-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + org.apache.felix + maven-bundle-plugin + + + + lazy + org.eclipse.ui;resolution:=optional,org.eclipse.rap.ui;resolution:=optional,org.eclipse.core.runtime + + org.eclipse.swt, + org.argeo.eclipse.ui.specific, + * + + + + + + + + + org.argeo.commons + org.argeo.eclipse.ui + 2.1.12-SNAPSHOT + + + + + org.argeo.tp + javax.jcr + + + org.argeo.commons + org.argeo.server.jcr + 2.1.12-SNAPSHOT + + + + + org.argeo.commons + org.argeo.eclipse.dep.rcp + 2.1.12-SNAPSHOT + provided + + + org.argeo.commons + org.argeo.eclipse.ui.rcp + 2.1.12-SNAPSHOT + provided + + + + + org.argeo.commons + org.argeo.util + 2.1.12-SNAPSHOT + + + + + org.argeo.tp + slf4j.org.apache.commons.logging + + + \ No newline at end of file diff --git a/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/AbstractNodeContentProvider.java b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/AbstractNodeContentProvider.java new file mode 100644 index 000000000..ef2b8a845 --- /dev/null +++ b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/AbstractNodeContentProvider.java @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.jcr; + +import java.util.ArrayList; +import java.util.List; + +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; +import org.argeo.eclipse.ui.AbstractTreeContentProvider; + +/** Canonic implementation of tree content provider manipulating JCR nodes. */ +public abstract class AbstractNodeContentProvider extends + AbstractTreeContentProvider { + private final static Log log = LogFactory + .getLog(AbstractNodeContentProvider.class); + + private Session session; + + public AbstractNodeContentProvider(Session session) { + this.session = session; + } + + /** + * Whether this path is a base path (and thus has no parent). By default it + * returns true if path is '/' (root node) + */ + protected Boolean isBasePath(String path) { + // root node + return path.equals("/"); + } + + @Override + public Object[] getChildren(Object element) { + Object[] children; + if (element instanceof Node) { + try { + Node node = (Node) element; + children = getChildren(node); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot get children of " + element, e); + } + } else if (element instanceof WrappedNode) { + WrappedNode wrappedNode = (WrappedNode) element; + try { + children = getChildren(wrappedNode.getNode()); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot get children of " + + wrappedNode, e); + } + } else if (element instanceof NodesWrapper) { + NodesWrapper node = (NodesWrapper) element; + children = node.getChildren(); + } else { + children = super.getChildren(element); + } + + children = sort(element, children); + return children; + } + + /** Do not sort by default. To be overidden to provide custom sort. */ + protected Object[] sort(Object parent, Object[] children) { + return children; + } + + /** + * To be overridden in order to filter out some nodes. Does nothing by + * default. The provided list is a temporary one and can thus be modified + * directly . (e.g. via an iterator) + */ + protected List filterChildren(List children) + throws RepositoryException { + return children; + } + + protected Object[] getChildren(Node node) throws RepositoryException { + List nodes = new ArrayList(); + for (NodeIterator nit = node.getNodes(); nit.hasNext();) + nodes.add(nit.nextNode()); + nodes = filterChildren(nodes); + return nodes.toArray(); + } + + @Override + public Object getParent(Object element) { + if (element instanceof Node) { + Node node = (Node) element; + try { + String path = node.getPath(); + if (isBasePath(path)) + return null; + else + return node.getParent(); + } catch (RepositoryException e) { + log.warn("Cannot get parent of " + element + ": " + e); + return null; + } + } else if (element instanceof WrappedNode) { + WrappedNode wrappedNode = (WrappedNode) element; + return wrappedNode.getParent(); + } else if (element instanceof NodesWrapper) { + NodesWrapper nodesWrapper = (NodesWrapper) element; + return this.getParent(nodesWrapper.getNode()); + } + return super.getParent(element); + } + + @Override + public boolean hasChildren(Object element) { + try { + if (element instanceof Node) { + Node node = (Node) element; + return node.hasNodes(); + } else if (element instanceof WrappedNode) { + WrappedNode wrappedNode = (WrappedNode) element; + return wrappedNode.getNode().hasNodes(); + } else if (element instanceof NodesWrapper) { + NodesWrapper nodesWrapper = (NodesWrapper) element; + return nodesWrapper.hasChildren(); + } + + } catch (RepositoryException e) { + throw new ArgeoException("Cannot check whether " + element + + " has children", e); + } + return super.hasChildren(element); + } + + public Session getSession() { + return session; + } +} diff --git a/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/AsyncUiEventListener.java b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/AsyncUiEventListener.java new file mode 100644 index 000000000..100ceb444 --- /dev/null +++ b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/AsyncUiEventListener.java @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.jcr; + +import java.util.ArrayList; +import java.util.List; + +import javax.jcr.RepositoryException; +import javax.jcr.observation.Event; +import javax.jcr.observation.EventIterator; +import javax.jcr.observation.EventListener; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; +import org.eclipse.swt.widgets.Display; + +/** {@link EventListener} which simplifies running actions within the UI thread. */ +public abstract class AsyncUiEventListener implements EventListener { +// private final static Log logSuper = LogFactory +// .getLog(AsyncUiEventListener.class); + private final Log logThis = LogFactory.getLog(getClass()); + + private final Display display; + + public AsyncUiEventListener(Display display) { + super(); + this.display = display; + } + + /** Called asynchronously in the UI thread. */ + protected abstract void onEventInUiThread(List events) + throws RepositoryException; + + /** + * Whether these events should be processed in the UI or skipped with no UI + * job created. + */ + protected Boolean willProcessInUiThread(List events) + throws RepositoryException { + return true; + } + + protected Log getLog() { + return logThis; + } + + public final void onEvent(final EventIterator eventIterator) { + final List events = new ArrayList(); + while (eventIterator.hasNext()) + events.add(eventIterator.nextEvent()); + + if (logThis.isTraceEnabled()) + logThis.trace("Received " + events.size() + " events"); + + try { + if (!willProcessInUiThread(events)) + return; + } catch (RepositoryException e) { + throw new ArgeoException("Cannot test skip events " + events, e); + } + +// Job job = new Job("JCR Events") { +// protected IStatus run(IProgressMonitor monitor) { +// if (display.isDisposed()) { +// logSuper.warn("Display is disposed cannot update UI"); +// return Status.CANCEL_STATUS; +// } + + display.asyncExec(new Runnable() { + public void run() { + try { + onEventInUiThread(events); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot process events " + + events, e); + } + } + }); + +// return Status.OK_STATUS; +// } +// }; +// job.schedule(); + } +} diff --git a/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/DefaultNodeLabelProvider.java b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/DefaultNodeLabelProvider.java new file mode 100644 index 000000000..76fac1256 --- /dev/null +++ b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/DefaultNodeLabelProvider.java @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.jcr; + +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.RepositoryException; +import javax.jcr.nodetype.NodeType; + +import org.argeo.ArgeoException; +import org.argeo.jcr.ArgeoTypes; +import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.swt.graphics.Image; + +/** Provides reasonable overridable defaults for know JCR types. */ +public class DefaultNodeLabelProvider extends ColumnLabelProvider { + // Images + /** + * @deprecated Use {@link JcrImages#NODE} instead + */ + public final static Image NODE = JcrImages.NODE; + /** + * @deprecated Use {@link JcrImages#FOLDER} instead + */ + public final static Image FOLDER = JcrImages.FOLDER; + /** + * @deprecated Use {@link JcrImages#FILE} instead + */ + public final static Image FILE = JcrImages.FILE; + /** + * @deprecated Use {@link JcrImages#BINARY} instead + */ + public final static Image BINARY = JcrImages.BINARY; + /** + * @deprecated Use {@link JcrImages#HOME} instead + */ + public final static Image HOME = JcrImages.HOME; + + public String getText(Object element) { + try { + if (element instanceof Node) { + return getText((Node) element); + } else if (element instanceof WrappedNode) { + return getText(((WrappedNode) element).getNode()); + } else if (element instanceof NodesWrapper) { + return getText(((NodesWrapper) element).getNode()); + } + return super.getText(element); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot get text for of " + element, e); + } + } + + protected String getText(Node node) throws RepositoryException { + if (node.isNodeType(NodeType.MIX_TITLE) + && node.hasProperty(Property.JCR_TITLE)) + return node.getProperty(Property.JCR_TITLE).getString(); + else + return node.getName(); + } + + @Override + public Image getImage(Object element) { + try { + if (element instanceof Node) { + return getImage((Node) element); + } else if (element instanceof WrappedNode) { + return getImage(((WrappedNode) element).getNode()); + } else if (element instanceof NodesWrapper) { + return getImage(((NodesWrapper) element).getNode()); + } + } catch (RepositoryException e) { + throw new ArgeoException("Cannot retrieve image for " + element, e); + } + return super.getImage(element); + } + + protected Image getImage(Node node) throws RepositoryException { + // optimized order + if (node.getPrimaryNodeType().isNodeType(NodeType.NT_FILE)) + return JcrImages.FILE; + else if (node.getPrimaryNodeType().isNodeType(NodeType.NT_FOLDER)) + return JcrImages.FOLDER; + else if (node.getPrimaryNodeType().isNodeType(NodeType.NT_RESOURCE)) + return JcrImages.BINARY; + else if (node.isNodeType(ArgeoTypes.ARGEO_USER_HOME)) + return JcrImages.HOME; + else + return JcrImages.NODE; + } + + @Override + public String getToolTipText(Object element) { + try { + if (element instanceof Node) { + return getToolTipText((Node) element); + } else if (element instanceof WrappedNode) { + return getToolTipText(((WrappedNode) element).getNode()); + } else if (element instanceof NodesWrapper) { + return getToolTipText(((NodesWrapper) element).getNode()); + } + } catch (RepositoryException e) { + throw new ArgeoException("Cannot get tooltip for " + element, e); + } + return super.getToolTipText(element); + } + + protected String getToolTipText(Node node) throws RepositoryException { + return null; + } + +} diff --git a/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/JcrImages.java b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/JcrImages.java new file mode 100644 index 000000000..255ea7a25 --- /dev/null +++ b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/JcrImages.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.jcr; + +import org.eclipse.swt.graphics.Image; + +/** Shared icons. */ +public class JcrImages { + public final static Image NODE = JcrUiPlugin.getImageDescriptor( + "icons/node.gif").createImage(); + public final static Image FOLDER = JcrUiPlugin.getImageDescriptor( + "icons/folder.gif").createImage(); + public final static Image FILE = JcrUiPlugin.getImageDescriptor( + "icons/file.gif").createImage(); + public final static Image BINARY = JcrUiPlugin.getImageDescriptor( + "icons/binary.png").createImage(); + public final static Image HOME = JcrUiPlugin.getImageDescriptor( + "icons/home.gif").createImage(); + public final static Image SORT = JcrUiPlugin.getImageDescriptor( + "icons/sort.gif").createImage(); + + public final static Image REPOSITORIES = JcrUiPlugin.getImageDescriptor( + "icons/repositories.gif").createImage(); + public final static Image REPOSITORY_DISCONNECTED = JcrUiPlugin + .getImageDescriptor("icons/repository_disconnected.gif") + .createImage(); + public final static Image REPOSITORY_CONNECTED = JcrUiPlugin + .getImageDescriptor("icons/repository_connected.gif").createImage(); + public final static Image REMOTE_DISCONNECTED = JcrUiPlugin + .getImageDescriptor("icons/remote_disconnected.gif").createImage(); + public final static Image REMOTE_CONNECTED = JcrUiPlugin + .getImageDescriptor("icons/remote_connected.gif").createImage(); + public final static Image WORKSPACE_DISCONNECTED = JcrUiPlugin + .getImageDescriptor("icons/workspace_disconnected.png") + .createImage(); + public final static Image WORKSPACE_CONNECTED = JcrUiPlugin + .getImageDescriptor("icons/workspace_connected.png").createImage(); + +} diff --git a/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/JcrPreferenceStore.java b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/JcrPreferenceStore.java new file mode 100644 index 000000000..c9777cefd --- /dev/null +++ b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/JcrPreferenceStore.java @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.jcr; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Properties; + +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.PropertyIterator; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.version.VersionManager; + +import org.apache.commons.io.IOUtils; +import org.argeo.ArgeoException; +import org.argeo.jcr.ArgeoNames; +import org.argeo.jcr.ArgeoTypes; +import org.argeo.jcr.JcrUtils; +import org.argeo.jcr.UserJcrUtils; +import org.eclipse.jface.preference.PreferenceStore; +import org.eclipse.ui.preferences.ScopedPreferenceStore; +import org.osgi.framework.BundleContext; + +/** + * Persist preferences as key/value pairs under ~/argeo:preferences.
+ * TODO: better integrate JCR and Eclipse:
+ * - typing
+ * - use eclipse preferences
+ * - better integrate with {@link ScopedPreferenceStore} provided by RAP + */ +public class JcrPreferenceStore extends PreferenceStore implements ArgeoNames { + private Session session; + private BundleContext bundleContext; + + /** Retrieves the preference node */ + protected Node getPreferenceNode() { + try { + if (session.hasPendingChanges()) + session.save(); + Node userHome = UserJcrUtils.getUserHome(session); + if (userHome == null) + throw new ArgeoException("No user home for " + + session.getUserID()); + Node preferences; + if (!userHome.hasNode(ARGEO_PREFERENCES)) { + preferences = userHome.addNode(ARGEO_PREFERENCES); + preferences.addMixin(ArgeoTypes.ARGEO_PREFERENCE_NODE); + session.save(); + } else + preferences = userHome.getNode(ARGEO_PREFERENCES); + + String pluginPreferencesName = bundleContext.getBundle() + .getSymbolicName(); + Node pluginPreferences; + if (!preferences.hasNode(pluginPreferencesName)) { + VersionManager vm = session.getWorkspace().getVersionManager(); + vm.checkout(preferences.getPath()); + pluginPreferences = preferences.addNode(pluginPreferencesName); + pluginPreferences.addMixin(ArgeoTypes.ARGEO_PREFERENCE_NODE); + session.save(); + vm.checkin(preferences.getPath()); + } else + pluginPreferences = preferences.getNode(pluginPreferencesName); + return pluginPreferences; + } catch (RepositoryException e) { + e.printStackTrace(); + JcrUtils.discardQuietly(session); + throw new ArgeoException("Cannot retrieve preferences", e); + } + + } + + @Override + public void load() throws IOException { + ByteArrayOutputStream out = null; + ByteArrayInputStream in = null; + try { + Properties props = new Properties(); + PropertyIterator it = getPreferenceNode().getProperties(); + while (it.hasNext()) { + Property p = it.nextProperty(); + if (!p.isMultiple() && !p.getDefinition().isProtected()) { + props.setProperty(p.getName(), p.getValue().getString()); + } + } + out = new ByteArrayOutputStream(); + props.store(out, ""); + in = new ByteArrayInputStream(out.toByteArray()); + load(in); + } catch (Exception e) { + e.printStackTrace(); + throw new ArgeoException("Cannot load preferences", e); + } finally { + IOUtils.closeQuietly(in); + IOUtils.closeQuietly(out); + } + } + + @Override + public void save() throws IOException { + ByteArrayOutputStream out = null; + ByteArrayInputStream in = null; + Node pluginPreferences = null; + try { + out = new ByteArrayOutputStream(); + save(out, ""); + in = new ByteArrayInputStream(out.toByteArray()); + Properties props = new Properties(); + props.load(in); + pluginPreferences = getPreferenceNode(); + VersionManager vm = pluginPreferences.getSession().getWorkspace() + .getVersionManager(); + vm.checkout(pluginPreferences.getPath()); + for (Object key : props.keySet()) { + String name = key.toString(); + String value = props.getProperty(name); + pluginPreferences.setProperty(name, value); + } + JcrUtils.updateLastModified(pluginPreferences); + pluginPreferences.getSession().save(); + vm.checkin(pluginPreferences.getPath()); + } catch (Exception e) { + JcrUtils.discardUnderlyingSessionQuietly(pluginPreferences); + throw new ArgeoException("Cannot save preferences", e); + } finally { + IOUtils.closeQuietly(in); + IOUtils.closeQuietly(out); + } + } + + public void init() { + try { + load(); + } catch (IOException e) { + throw new ArgeoException("Cannot initialize preference store", e); + } + } + + public void setSession(Session session) { + this.session = session; + } + + public void setBundleContext(BundleContext bundleContext) { + this.bundleContext = bundleContext; + } + +} diff --git a/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/JcrUiPlugin.java b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/JcrUiPlugin.java new file mode 100644 index 000000000..adfa1a4f4 --- /dev/null +++ b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/JcrUiPlugin.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.jcr; + +import java.util.ResourceBundle; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +public class JcrUiPlugin extends AbstractUIPlugin { + private final static Log log = LogFactory.getLog(JcrUiPlugin.class); + + public final static String ID = "org.argeo.eclipse.ui.jcr"; + + private ResourceBundle messages; + + private static JcrUiPlugin plugin; + + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + messages = ResourceBundle.getBundle("org.argeo.eclipse.ui.jcr"); + } + + public static JcrUiPlugin getDefault() { + return plugin; + } + + public static ImageDescriptor getImageDescriptor(String path) { + return imageDescriptorFromPlugin(ID, path); + } + + /** Returns the internationalized label for the given key */ + public static String getMessage(String key) { + try { + return getDefault().messages.getString(key); + } catch (NullPointerException npe) { + log.warn(key + " not found."); + return key; + } + } + + /** + * Gives access to the internationalization message bundle. Returns null in + * case the ClientUiPlugin is not started (for JUnit tests, by instance) + */ + public static ResourceBundle getMessagesBundle() { + if (getDefault() != null) + // To avoid NPE + return getDefault().messages; + else + return null; + } +} diff --git a/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/JcrUiUtils.java b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/JcrUiUtils.java new file mode 100644 index 000000000..8ee13aab0 --- /dev/null +++ b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/JcrUiUtils.java @@ -0,0 +1,146 @@ +package org.argeo.eclipse.ui.jcr; + +import java.util.Calendar; + +import javax.jcr.Node; +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; + +import org.argeo.ArgeoException; +import org.argeo.eclipse.ui.jcr.lists.NodeViewerComparator; +import org.argeo.eclipse.ui.jcr.lists.RowViewerComparator; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.widgets.Table; + +/** Utility methods to simplify UI development using eclipse and JCR. */ +public class JcrUiUtils { + + /** + * Centralizes management of updating property value. Among other to avoid + * infinite loop when the new value is the same as the ones that is already + * stored in JCR. + * + * @return true if the value as changed + */ + public static boolean setJcrProperty(Node node, String propName, + int propertyType, Object value) { + try { + // int propertyType = getPic().getProperty(propName).getType(); + switch (propertyType) { + case PropertyType.STRING: + if ("".equals((String) value) + && (!node.hasProperty(propName) || node + .hasProperty(propName) + && "".equals(node.getProperty(propName) + .getString()))) + // workaround the fact that the Text widget value cannot be + // set to null + return false; + else if (node.hasProperty(propName) + && node.getProperty(propName).getString() + .equals((String) value)) + // nothing changed yet + return false; + else { + node.setProperty(propName, (String) value); + return true; + } + case PropertyType.BOOLEAN: + if (node.hasProperty(propName) + && node.getProperty(propName).getBoolean() == (Boolean) value) + // nothing changed yet + return false; + else { + node.setProperty(propName, (Boolean) value); + return true; + } + case PropertyType.DATE: + if (node.hasProperty(propName) + && node.getProperty(propName).getDate() + .equals((Calendar) value)) + // nothing changed yet + return false; + else { + node.setProperty(propName, (Calendar) value); + return true; + } + case PropertyType.LONG: + Long lgValue = (Long) value; + + if (lgValue == null) + lgValue = 0L; + + if (node.hasProperty(propName) + && node.getProperty(propName).getLong() == lgValue) + // nothing changed yet + return false; + else { + node.setProperty(propName, lgValue); + return true; + } + + default: + throw new ArgeoException("Unimplemented property save"); + } + } catch (RepositoryException re) { + throw new ArgeoException("Unexpected error while setting property", + re); + } + } + + /** + * Creates a new selection adapter in order to provide sorting abitily on a + * swt table that display a row list + **/ + public static SelectionAdapter getRowSelectionAdapter(final int index, + final int propertyType, final String selectorName, + final String propertyName, final RowViewerComparator comparator, + final TableViewer viewer) { + SelectionAdapter selectionAdapter = new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + Table table = viewer.getTable(); + comparator.setColumn(propertyType, selectorName, propertyName); + int dir = table.getSortDirection(); + if (table.getSortColumn() == table.getColumn(index)) { + dir = dir == SWT.UP ? SWT.DOWN : SWT.UP; + } else { + dir = SWT.DOWN; + } + table.setSortDirection(dir); + table.setSortColumn(table.getColumn(index)); + viewer.refresh(); + } + }; + return selectionAdapter; + } + + /** + * Creates a new selection adapter in order to provide sorting abitily on a + * swt table that display a row list + **/ + public static SelectionAdapter getNodeSelectionAdapter(final int index, + final int propertyType, final String propertyName, + final NodeViewerComparator comparator, final TableViewer viewer) { + SelectionAdapter selectionAdapter = new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + Table table = viewer.getTable(); + comparator.setColumn(propertyType, propertyName); + int dir = table.getSortDirection(); + if (table.getSortColumn() == table.getColumn(index)) { + dir = dir == SWT.UP ? SWT.DOWN : SWT.UP; + } else { + dir = SWT.DOWN; + } + table.setSortDirection(dir); + table.setSortColumn(table.getColumn(index)); + viewer.refresh(); + } + }; + return selectionAdapter; + } +} diff --git a/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/NodeElementComparer.java b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/NodeElementComparer.java new file mode 100644 index 000000000..f284b9c13 --- /dev/null +++ b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/NodeElementComparer.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.jcr; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; + +import org.argeo.ArgeoException; +import org.eclipse.jface.viewers.IElementComparer; + +/** Element comparer for JCR node, to be used in JFace viewers. */ +public class NodeElementComparer implements IElementComparer { + + public boolean equals(Object a, Object b) { + try { + if ((a instanceof Node) && (b instanceof Node)) { + Node nodeA = (Node) a; + Node nodeB = (Node) b; + return nodeA.getIdentifier().equals(nodeB.getIdentifier()); + } else { + return a.equals(b); + } + } catch (RepositoryException e) { + throw new ArgeoException("Cannot compare nodes", e); + } + } + + public int hashCode(Object element) { + try { + if (element instanceof Node) + return ((Node) element).getIdentifier().hashCode(); + return element.hashCode(); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot get hash code", e); + } + } + +} diff --git a/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/NodesWrapper.java b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/NodesWrapper.java new file mode 100644 index 000000000..dcd3b42f6 --- /dev/null +++ b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/NodesWrapper.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.jcr; + +import java.util.ArrayList; +import java.util.List; + +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.RepositoryException; + +import org.argeo.ArgeoException; + +/** + * Element of tree which is based on a node, but whose children are not + * necessarily this node children. + */ +public class NodesWrapper { + private final Node node; + + public NodesWrapper(Node node) { + super(); + this.node = node; + } + + protected NodeIterator getNodeIterator() throws RepositoryException { + return node.getNodes(); + } + + protected List getWrappedNodes() throws RepositoryException { + List nodes = new ArrayList(); + for (NodeIterator nit = getNodeIterator(); nit.hasNext();) + nodes.add(new WrappedNode(this, nit.nextNode())); + return nodes; + } + + public Object[] getChildren() { + try { + return getWrappedNodes().toArray(); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot get wrapped children", e); + } + } + + /** + * @return true by default because we don't want to compute the wrapped + * nodes twice + */ + public Boolean hasChildren() { + return true; + } + + public Node getNode() { + return node; + } + + @Override + public int hashCode() { + return node.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof NodesWrapper) + return node.equals(((NodesWrapper) obj).getNode()); + else + return false; + } + + public String toString() { + return "nodes wrapper based on " + node; + } +} diff --git a/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/SimpleNodeContentProvider.java b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/SimpleNodeContentProvider.java new file mode 100644 index 000000000..0dad19cfe --- /dev/null +++ b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/SimpleNodeContentProvider.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.jcr; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.argeo.ArgeoException; +import org.argeo.jcr.JcrUtils; + +/** Simple JCR node content provider taking a list of String as base path. */ +public class SimpleNodeContentProvider extends AbstractNodeContentProvider { + private final List basePaths; + private Boolean mkdirs = false; + + public SimpleNodeContentProvider(Session session, String... basePaths) { + this(session, Arrays.asList(basePaths)); + } + + public SimpleNodeContentProvider(Session session, List basePaths) { + super(session); + this.basePaths = basePaths; + } + + @Override + protected Boolean isBasePath(String path) { + if (basePaths.contains(path)) + return true; + return super.isBasePath(path); + } + + public Object[] getElements(Object inputElement) { + try { + List baseNodes = new ArrayList(); + for (String basePath : basePaths) + if (mkdirs && !getSession().itemExists(basePath)) + baseNodes.add(JcrUtils.mkdirs(getSession(), basePath)); + else + baseNodes.add(getSession().getNode(basePath)); + return baseNodes.toArray(); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot get base nodes for " + basePaths, + e); + } + } + + public List getBasePaths() { + return basePaths; + } + + public void setMkdirs(Boolean mkdirs) { + this.mkdirs = mkdirs; + } + +} diff --git a/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/WrappedNode.java b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/WrappedNode.java new file mode 100644 index 000000000..c0e197336 --- /dev/null +++ b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/WrappedNode.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.jcr; + +import javax.jcr.Node; + +/** Wraps a node (created from a {@link NodesWrapper}) */ +public class WrappedNode { + private final NodesWrapper parent; + private final Node node; + + public WrappedNode(NodesWrapper parent, Node node) { + super(); + this.parent = parent; + this.node = node; + } + + public NodesWrapper getParent() { + return parent; + } + + public Node getNode() { + return node; + } + + public String toString() { + return "wrapped " + node; + } + + @Override + public int hashCode() { + return node.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof WrappedNode) + return node.equals(((WrappedNode) obj).getNode()); + else + return false; + } + +} diff --git a/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/commands/AddFileFolder.java b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/commands/AddFileFolder.java new file mode 100644 index 000000000..5fc7db031 --- /dev/null +++ b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/commands/AddFileFolder.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.jcr.commands; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.nodetype.NodeType; + +import org.argeo.eclipse.ui.ErrorFeedback; +import org.argeo.eclipse.ui.dialogs.SingleValue; +import org.argeo.eclipse.ui.jcr.JcrUiPlugin; +import org.argeo.eclipse.ui.jcr.views.AbstractJcrBrowser; +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.handlers.HandlerUtil; + +/** Adds a node of type nt:folder */ +public class AddFileFolder extends AbstractHandler { + + public Object execute(ExecutionEvent event) throws ExecutionException { + ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event) + .getActivePage().getSelection(); + AbstractJcrBrowser view = (AbstractJcrBrowser) HandlerUtil + .getActiveWorkbenchWindow(event).getActivePage() + .findView(HandlerUtil.getActivePartId(event)); + if (selection != null && !selection.isEmpty() + && selection instanceof IStructuredSelection) { + Object obj = ((IStructuredSelection) selection).getFirstElement(); + + if (obj instanceof Node) { + String folderName = SingleValue.ask("Folder name", + "Enter folder name"); + if (folderName != null) { + Node parentNode = (Node) obj; + try { + Node newNode = parentNode.addNode(folderName, + NodeType.NT_FOLDER); + view.nodeAdded(parentNode, newNode); + parentNode.getSession().save(); + } catch (RepositoryException e) { + ErrorFeedback.show("Cannot create folder " + folderName + + " under " + parentNode, e); + } + } + } else { + ErrorFeedback.show(JcrUiPlugin + .getMessage("errorUnvalidNtFolderNodeType")); + } + } + return null; + } + +} diff --git a/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/commands/DeleteNodes.java b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/commands/DeleteNodes.java new file mode 100644 index 000000000..168674806 --- /dev/null +++ b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/commands/DeleteNodes.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.jcr.commands; + +import java.util.Iterator; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; + +import org.argeo.ArgeoException; +import org.argeo.eclipse.ui.ErrorFeedback; +import org.argeo.eclipse.ui.jcr.views.AbstractJcrBrowser; +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.handlers.HandlerUtil; + +/** + * Deletes the selected nodes and refresh the corresponding AbstractJcrView. + * Note that no model specific check is done to see if the node can be removed + * or not. Extend or override to implement specific behaviour. + */ +public class DeleteNodes extends AbstractHandler { + public final static String ID = "org.argeo.eclipse.ui.jcr.deleteNodes"; + public final static String DEFAULT_LABEL = "Delete selected nodes"; + + public Object execute(ExecutionEvent event) throws ExecutionException { + ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event) + .getActivePage().getSelection(); + AbstractJcrBrowser view = (AbstractJcrBrowser) HandlerUtil + .getActiveWorkbenchWindow(event).getActivePage() + .findView(HandlerUtil.getActivePartId(event)); + + if (selection != null && selection instanceof IStructuredSelection) { + Iterator it = ((IStructuredSelection) selection).iterator(); + Object obj = null; + Node ancestor = null; + try { + while (it.hasNext()) { + obj = it.next(); + if (obj instanceof Node) { + Node node = (Node) obj; + Node parentNode = node.getParent(); + node.remove(); + node.getSession().save(); + ancestor = getOlder(ancestor, parentNode); + } + } + if (ancestor != null) + view.nodeRemoved(ancestor); + } catch (Exception e) { + ErrorFeedback.show("Cannot delete node " + obj, e); + } + } + return null; + } + + protected Node getOlder(Node A, Node B) { + try { + + if (A == null) + return B == null ? null : B; + // Todo enhanced this method + else + return A.getDepth() <= B.getDepth() ? A : B; + } catch (RepositoryException re) { + throw new ArgeoException("Cannot find ancestor", re); + } + } +} diff --git a/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/commands/OpenGenericJcrQueryEditor.java b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/commands/OpenGenericJcrQueryEditor.java new file mode 100644 index 000000000..ce42266cc --- /dev/null +++ b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/commands/OpenGenericJcrQueryEditor.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.jcr.commands; + +import org.argeo.eclipse.ui.jcr.editors.JcrQueryEditorInput; +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.handlers.HandlerUtil; + +/** Open a JCR query editor. */ +public class OpenGenericJcrQueryEditor extends AbstractHandler { + private String editorId; + + public Object execute(ExecutionEvent event) throws ExecutionException { + try { + JcrQueryEditorInput editorInput = new JcrQueryEditorInput("", null); + IWorkbenchPage activePage = HandlerUtil.getActiveWorkbenchWindow( + event).getActivePage(); + activePage.openEditor(editorInput, editorId); + } catch (Exception e) { + throw new ExecutionException("Cannot open editor", e); + } + return null; + } + + public void setEditorId(String editorId) { + this.editorId = editorId; + } + +} diff --git a/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/commands/Refresh.java b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/commands/Refresh.java new file mode 100644 index 000000000..f62be37eb --- /dev/null +++ b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/commands/Refresh.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.jcr.commands; + +import java.util.Iterator; + +import org.argeo.eclipse.ui.jcr.views.AbstractJcrBrowser; +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.handlers.HandlerUtil; + +/** + * Call the refresh method of the active AbstractJcrBrowser instance. + * + * Warning: this method only refreshes the viewer, if the model is "stale", e.g. + * if some changes in the underlying data have not yet been propagated to the + * model, the view will not display up-to-date information. + */ +@Deprecated +public class Refresh extends AbstractHandler { + + public Object execute(ExecutionEvent event) throws ExecutionException { + ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event) + .getActivePage().getSelection(); + AbstractJcrBrowser view = (AbstractJcrBrowser) HandlerUtil + .getActiveWorkbenchWindow(event).getActivePage() + .findView(HandlerUtil.getActivePartId(event)); + if (selection != null && selection instanceof IStructuredSelection) { + Iterator it = ((IStructuredSelection) selection).iterator(); + while (it.hasNext()) { + Object obj = it.next(); + view.refresh(obj); + } + } + return null; + } +} diff --git a/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/editors/AbstractJcrQueryEditor.java b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/editors/AbstractJcrQueryEditor.java new file mode 100644 index 000000000..5e7d69644 --- /dev/null +++ b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/editors/AbstractJcrQueryEditor.java @@ -0,0 +1,354 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.jcr.editors; + +import java.util.ArrayList; +import java.util.List; + +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.query.QueryResult; +import javax.jcr.query.Row; +import javax.jcr.query.RowIterator; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; +import org.argeo.eclipse.ui.GenericTableComparator; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TableViewerColumn; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.SashForm; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorSite; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.part.EditorPart; + +/** Executes any JCR query. */ +public abstract class AbstractJcrQueryEditor extends EditorPart { + private final static Log log = LogFactory + .getLog(AbstractJcrQueryEditor.class); + + protected String initialQuery; + protected String initialQueryType; + + /* DEPENDENCY INJECTION */ + private Session session; + + // Widgets + private TableViewer viewer; + private List tableViewerColumns = new ArrayList(); + private GenericTableComparator comparator; + + /** Override to layout a form enabling the end user to build his query */ + protected abstract void createQueryForm(Composite parent); + + @Override + public void init(IEditorSite site, IEditorInput input) + throws PartInitException { + JcrQueryEditorInput editorInput = (JcrQueryEditorInput) input; + initialQuery = editorInput.getQuery(); + initialQueryType = editorInput.getQueryType(); + setSite(site); + setInput(editorInput); + } + + @Override + public final void createPartControl(final Composite parent) { + parent.setLayout(new FillLayout()); + + SashForm sashForm = new SashForm(parent, SWT.VERTICAL); + sashForm.setSashWidth(4); + sashForm.setLayout(new FillLayout()); + + Composite top = new Composite(sashForm, SWT.NONE); + GridLayout gl = new GridLayout(1, false); + top.setLayout(gl); + + createQueryForm(top); + + Composite bottom = new Composite(sashForm, SWT.NONE); + bottom.setLayout(new GridLayout(1, false)); + sashForm.setWeights(getWeights()); + + viewer = new TableViewer(bottom); + viewer.getTable().setLayoutData( + new GridData(SWT.FILL, SWT.FILL, true, true)); + viewer.getTable().setHeaderVisible(true); + viewer.setContentProvider(getQueryResultContentProvider()); + viewer.setInput(getEditorSite()); + + if (getComparator() != null) { + comparator = getComparator(); + viewer.setComparator(comparator); + } + if (getTableDoubleClickListener() != null) + viewer.addDoubleClickListener(getTableDoubleClickListener()); + + } + + protected void executeQuery(String statement) { + try { + if (log.isDebugEnabled()) + log.debug("Query : " + statement); + + QueryResult qr = session.getWorkspace().getQueryManager() + .createQuery(statement, initialQueryType).execute(); + + // remove previous columns + for (TableViewerColumn tvc : tableViewerColumns) + tvc.getColumn().dispose(); + + int i = 0; + for (final String columnName : qr.getColumnNames()) { + TableViewerColumn tvc = new TableViewerColumn(viewer, SWT.NONE); + configureColumn(columnName, tvc, i); + tvc.setLabelProvider(getLabelProvider(columnName)); + tableViewerColumns.add(tvc); + i++; + } + + // Must create a local list: QueryResults can only be read once. + try { + List rows = new ArrayList(); + RowIterator rit = qr.getRows(); + while (rit.hasNext()) { + rows.add(rit.nextRow()); + } + viewer.setInput(rows); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot read query result", e); + } + + } catch (RepositoryException e) { + ErrorDialog.openError(null, "Error", "Cannot execute JCR query: " + + statement, new Status(IStatus.ERROR, + "org.argeo.eclipse.ui.jcr", e.getMessage())); + } + } + + /** + * To be overidden to adapt size of form and result frames. + * + * @return + */ + protected int[] getWeights() { + return new int[] { 30, 70 }; + } + + /** + * To be overidden to implement a doubleclick Listener on one of the rows of + * the table. + * + * @return + */ + protected IDoubleClickListener getTableDoubleClickListener() { + return null; + } + + /** + * To be overiden in order to implement a specific + * QueryResultContentProvider + */ + protected IStructuredContentProvider getQueryResultContentProvider() { + return new QueryResultContentProvider(); + } + + /** + * Enable specific implementation for columns + */ + protected List getTableViewerColumns() { + return tableViewerColumns; + } + + /** + * Enable specific implementation for columns + */ + protected TableViewer getTableViewer() { + return viewer; + } + + /** + * To be overridden in order to configure column label providers . + */ + protected ColumnLabelProvider getLabelProvider(final String columnName) { + return new ColumnLabelProvider() { + public String getText(Object element) { + Row row = (Row) element; + try { + return row.getValue(columnName).getString(); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot display row " + row, e); + } + } + + public Image getImage(Object element) { + return null; + } + }; + } + + /** + * To be overridden in order to configure the columns. + * + * @deprecated use {@link + * org.argeo.eclipse.ui.jcr.editors.AbstractJcrQueryEditor. + * configureColumn(String jcrColumnName, TableViewerColumn + * column, int columnIndex)} instead + */ + protected void configureColumn(String jcrColumnName, + TableViewerColumn column) { + column.getColumn().setWidth(50); + column.getColumn().setText(jcrColumnName); + } + + /** To be overridden in order to configure the columns. */ + protected void configureColumn(String jcrColumnName, + TableViewerColumn column, int columnIndex) { + column.getColumn().setWidth(50); + column.getColumn().setText(jcrColumnName); + } + + private class QueryResultContentProvider implements + IStructuredContentProvider { + + public void dispose() { + } + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + + public Object[] getElements(Object inputElement) { + + if (inputElement instanceof List) + return ((List) inputElement).toArray(); + + // Never reached might be deleted in future release + if (!(inputElement instanceof QueryResult)) + return new String[] {}; + + try { + QueryResult queryResult = (QueryResult) inputElement; + List rows = new ArrayList(); + RowIterator rit = queryResult.getRows(); + while (rit.hasNext()) { + rows.add(rit.nextRow()); + } + + // List elems = new ArrayList(); + // NodeIterator nit = queryResult.getNodes(); + // while (nit.hasNext()) { + // elems.add(nit.nextNode()); + // } + return rows.toArray(); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot read query result", e); + } + } + + } + + /** + * Might be used by children classes to sort columns. + * + * @param column + * @param index + * @return + */ + protected SelectionAdapter getSelectionAdapter(final TableColumn column, + final int index) { + + // A comparator must be define + if (comparator == null) + return null; + + SelectionAdapter selectionAdapter = new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + + try { + + comparator.setColumn(index); + int dir = viewer.getTable().getSortDirection(); + if (viewer.getTable().getSortColumn() == column) { + dir = dir == SWT.UP ? SWT.DOWN : SWT.UP; + } else { + + dir = SWT.DOWN; + } + viewer.getTable().setSortDirection(dir); + viewer.getTable().setSortColumn(column); + viewer.refresh(); + } catch (Exception exc) { + exc.printStackTrace(); + } + } + }; + return selectionAdapter; + } + + /** + * To be overridden to enable sorting. + */ + protected GenericTableComparator getComparator() { + return null; + } + + @Override + public boolean isDirty() { + return false; + } + + @Override + public void doSave(IProgressMonitor monitor) { + // TODO save the query in JCR? + } + + @Override + public void doSaveAs() { + } + + @Override + public boolean isSaveAsAllowed() { + return false; + } + + /** Returns the injected current session */ + protected Session getSession() { + return session; + } + + /* DEPENDENCY INJECTION */ + public void setSession(Session session) { + this.session = session; + } +} diff --git a/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/editors/JcrQueryEditorInput.java b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/editors/JcrQueryEditorInput.java new file mode 100644 index 000000000..eedccc85b --- /dev/null +++ b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/editors/JcrQueryEditorInput.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.jcr.editors; + +import javax.jcr.query.Query; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IPersistableElement; + +public class JcrQueryEditorInput implements IEditorInput { + private final String query; + private final String queryType; + + public JcrQueryEditorInput(String query, String queryType) { + this.query = query; + if (queryType == null) + this.queryType = Query.JCR_SQL2; + else + this.queryType = queryType; + } + + public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) { + return null; + } + + public boolean exists() { + return true; + } + + public ImageDescriptor getImageDescriptor() { + return null; + } + + public String getName() { + return query; + } + + public IPersistableElement getPersistable() { + return null; + } + + public String getToolTipText() { + return query; + } + + public String getQuery() { + return query; + } + + public String getQueryType() { + return queryType; + } + +} diff --git a/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/editors/NodeEditorInput.java b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/editors/NodeEditorInput.java new file mode 100644 index 000000000..a55884f2e --- /dev/null +++ b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/editors/NodeEditorInput.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.jcr.editors; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IPersistableElement; + +/** + * A canonical editor input based on a path to a node. In a multirepository + * environment, path can be enriched with Repository Alias and workspace + */ + +public class NodeEditorInput implements IEditorInput { + private final String path; + + public NodeEditorInput(String path) { + this.path = path; + } + + public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) { + return null; + } + + public boolean exists() { + return true; + } + + public ImageDescriptor getImageDescriptor() { + return null; + } + + public String getName() { + return path; + } + + public IPersistableElement getPersistable() { + return null; + } + + public String getToolTipText() { + return path; + } + + public String getPath() { + return path; + } +} diff --git a/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/lists/ColumnDefinition.java b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/lists/ColumnDefinition.java new file mode 100644 index 000000000..9e338276a --- /dev/null +++ b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/lists/ColumnDefinition.java @@ -0,0 +1,88 @@ +package org.argeo.eclipse.ui.jcr.lists; + +/** + * Utility object to manage column in various tables and extracts displaying + * data from JCR + */ +public class ColumnDefinition { + private final static int DEFAULT_COLUMN_SIZE = 120; + + private String selectorName; + private String propertyName; + private String headerLabel; + private int propertyType; + private int columnSize = DEFAULT_COLUMN_SIZE; + + /** + * new column using default width + * + * @param selectorName + * @param propertyName + * @param propertyType + * @param headerLabel + */ + public ColumnDefinition(String selectorName, String propertyName, + int propertyType, String headerLabel) { + this.selectorName = selectorName; + this.propertyName = propertyName; + this.propertyType = propertyType; + this.headerLabel = headerLabel; + } + + /** + * + * @param selectorName + * @param propertyName + * @param propertyType + * @param headerLabel + * @param columnSize + */ + public ColumnDefinition(String selectorName, String propertyName, + int propertyType, String headerLabel, int columnSize) { + this.selectorName = selectorName; + this.propertyName = propertyName; + this.propertyType = propertyType; + this.headerLabel = headerLabel; + this.columnSize = columnSize; + } + + public String getSelectorName() { + return selectorName; + } + + public void setSelectorName(String selectorName) { + this.selectorName = selectorName; + } + + public String getPropertyName() { + return propertyName; + } + + public void setPropertyName(String propertyName) { + this.propertyName = propertyName; + } + + public String getHeaderLabel() { + return headerLabel; + } + + public void setHeaderLabel(String headerLabel) { + this.headerLabel = headerLabel; + } + + public int getPropertyType() { + return propertyType; + } + + public void setPropertyType(int propertyType) { + this.propertyType = propertyType; + } + + public int getColumnSize() { + return columnSize; + } + + public void setColumnSize(int columnSize) { + this.columnSize = columnSize; + } +} diff --git a/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/lists/IListProvider.java b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/lists/IListProvider.java new file mode 100644 index 000000000..622e2e259 --- /dev/null +++ b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/lists/IListProvider.java @@ -0,0 +1,20 @@ +package org.argeo.eclipse.ui.jcr.lists; + +import java.util.List; + +/** + * Views and editors can implement this interface so that one of the row list + * that is displayed in the part (For instance in a Table or a Tree Viewer) can + * be rebuilt externally. typically to generate csv or calc extract. + */ +public interface IListProvider { + /** + * Returns an array of current and relevant elements + */ + public Object[] getElements(String extractId); + + /** + * Returns the column definition for passed ID + */ + public List getColumnDefinition(String extractId); +} diff --git a/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/lists/NodeViewerComparator.java b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/lists/NodeViewerComparator.java new file mode 100644 index 000000000..11f12e6f5 --- /dev/null +++ b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/lists/NodeViewerComparator.java @@ -0,0 +1,192 @@ +package org.argeo.eclipse.ui.jcr.lists; + +import java.math.BigDecimal; +import java.util.Calendar; + +import javax.jcr.Node; +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; +import javax.jcr.Value; +import javax.jcr.ValueFormatException; + +import org.argeo.ArgeoException; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerComparator; + +/** + * Base comparator to enable ordering on Table or Tree viewer that display Jcr + * Nodes. + * + * Note that the following snippet must be added before setting the comparator + * to the corresponding control: + * // IMPORTANT: initialize comparator before setting it + * ColumnDefinition firstCol = colDefs.get(0); + * comparator.setColumn(firstCol.getPropertyType(), + * firstCol.getPropertyName()); + * viewer.setComparator(comparator); + */ +public class NodeViewerComparator extends ViewerComparator { + + protected String propertyName; + + protected int propertyType; + public static final int ASCENDING = 0, DESCENDING = 1; + protected int direction = DESCENDING; + + public NodeViewerComparator() { + } + + /** + * e1 and e2 must both be Jcr nodes. + * + * @param viewer + * @param e1 + * @param e2 + * @return + */ + @Override + public int compare(Viewer viewer, Object e1, Object e2) { + int rc = 0; + long lc = 0; + + try { + + Node n1 = (Node) e1; + Node n2 = (Node) e2; + + Value v1 = null; + Value v2 = null; + if (n1.hasProperty(propertyName)) + v1 = n1.getProperty(propertyName).getValue(); + if (n2.hasProperty(propertyName)) + v2 = n2.getProperty(propertyName).getValue(); + + if (v2 == null && v1 == null) + return 0; + else if (v2 == null) + return -1; + else if (v1 == null) + return 1; + + switch (propertyType) { + case PropertyType.STRING: + rc = v1.getString().compareTo(v2.getString()); + break; + case PropertyType.BOOLEAN: + boolean b1 = v1.getBoolean(); + boolean b2 = v2.getBoolean(); + if (b1 == b2) + rc = 0; + else + // we assume true is greater than false + rc = b1 ? 1 : -1; + break; + case PropertyType.DATE: + Calendar c1 = v1.getDate(); + Calendar c2 = v2.getDate(); + if (c1 == null || c2 == null) + // log.trace("undefined date"); + ; + lc = c1.getTimeInMillis() - c2.getTimeInMillis(); + if (lc < Integer.MIN_VALUE) + // rc = Integer.MIN_VALUE; + rc = -1; + else if (lc > Integer.MAX_VALUE) + // rc = Integer.MAX_VALUE; + rc = 1; + else + rc = (int) lc; + break; + case PropertyType.LONG: + long l1; + long l2; + // FIXME sometimes an empty string is set instead of a long + try { + l1 = v1.getLong(); + } catch (ValueFormatException ve) { + l1 = 0; + } + try { + l2 = v2.getLong(); + } catch (ValueFormatException ve) { + l2 = 0; + } + + lc = l1 - l2; + if (lc < Integer.MIN_VALUE) + rc = -1; + else if (lc > Integer.MAX_VALUE) + rc = 1; + else + rc = (int) lc; + break; + case PropertyType.DECIMAL: + BigDecimal bd1 = v1.getDecimal(); + BigDecimal bd2 = v2.getDecimal(); + rc = bd1.compareTo(bd2); + break; + case PropertyType.DOUBLE: + Double d1 = v1.getDouble(); + Double d2 = v2.getDouble(); + rc = d1.compareTo(d2); + break; + default: + throw new ArgeoException( + "Unimplemented comparaison for PropertyType " + + propertyType); + } + // If descending order, flip the direction + if (direction == DESCENDING) { + rc = -rc; + } + + } catch (RepositoryException re) { + throw new ArgeoException("Unexpected error " + + "while comparing nodes", re); + } + return rc; + } + + /** + * @param propertyType + * Corresponding JCR type + * @param propertyName + * name of the property to use. + */ + public void setColumn(int propertyType, String propertyName) { + if (this.propertyName != null && this.propertyName.equals(propertyName)) { + // Same column as last sort; toggle the direction + direction = 1 - direction; + } else { + // New column; do an ascending sort + this.propertyType = propertyType; + this.propertyName = propertyName; + direction = ASCENDING; + } + } + + // Getters and setters + protected String getPropertyName() { + return propertyName; + } + + protected void setPropertyName(String propertyName) { + this.propertyName = propertyName; + } + + protected int getPropertyType() { + return propertyType; + } + + protected void setPropertyType(int propertyType) { + this.propertyType = propertyType; + } + + protected int getDirection() { + return direction; + } + + protected void setDirection(int direction) { + this.direction = direction; + } +} \ No newline at end of file diff --git a/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/lists/RowViewerComparator.java b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/lists/RowViewerComparator.java new file mode 100644 index 000000000..509f72324 --- /dev/null +++ b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/lists/RowViewerComparator.java @@ -0,0 +1,62 @@ +package org.argeo.eclipse.ui.jcr.lists; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.query.Row; + +import org.argeo.ArgeoException; +import org.eclipse.jface.viewers.Viewer; + +/** + * Base comparator to enable ordering on Table or Tree viewer that display Jcr + * rows + */ +public class RowViewerComparator extends NodeViewerComparator { + + protected String selectorName; + + public RowViewerComparator() { + } + + /** + * e1 and e2 must both be Jcr rows. + * + * @param viewer + * @param e1 + * @param e2 + * @return + */ + @Override + public int compare(Viewer viewer, Object e1, Object e2) { + try { + Node n1 = ((Row) e1).getNode(selectorName); + Node n2 = ((Row) e2).getNode(selectorName); + return super.compare(viewer, n1, n2); + } catch (RepositoryException re) { + throw new ArgeoException("Unexpected error " + + "while comparing nodes", re); + } + } + + /** + * @param propertyType + * Corresponding JCR type + * @param propertyName + * name of the property to use. + */ + public void setColumn(int propertyType, String selectorName, + String propertyName) { + if (this.selectorName != null && getPropertyName() != null + && this.selectorName.equals(selectorName) + && this.getPropertyName().equals(propertyName)) { + // Same column as last sort; toggle the direction + setDirection(1 - getDirection()); + } else { + // New column; do a descending sort + setPropertyType(propertyType); + setPropertyName(propertyName); + this.selectorName = selectorName; + setDirection(NodeViewerComparator.ASCENDING); + } + } +} \ No newline at end of file diff --git a/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/lists/SimpleJcrNodeLabelProvider.java b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/lists/SimpleJcrNodeLabelProvider.java new file mode 100644 index 000000000..88585c343 --- /dev/null +++ b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/lists/SimpleJcrNodeLabelProvider.java @@ -0,0 +1,122 @@ +package org.argeo.eclipse.ui.jcr.lists; + +import java.text.DateFormat; +import java.text.DecimalFormat; +import java.text.NumberFormat; +import java.text.SimpleDateFormat; + +import javax.jcr.Node; +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; +import javax.jcr.Value; + +import org.argeo.ArgeoException; +import org.eclipse.jface.viewers.ColumnLabelProvider; + +/** + * Base implementation of a label provider for widgets that display JCR Rows. + */ +public class SimpleJcrNodeLabelProvider extends ColumnLabelProvider { + private static final long serialVersionUID = -5215787695436221993L; + + private final static String DEFAULT_DATE_FORMAT = "EEE, dd MMM yyyy"; + private final static String DEFAULT_NUMBER_FORMAT = "#,##0.0"; + + private DateFormat dateFormat; + private NumberFormat numberFormat; + + final private String propertyName; + + /** + * Default Label provider for a given property of a node. Using default + * pattern for date and number formating + */ + public SimpleJcrNodeLabelProvider(String propertyName) { + this.propertyName = propertyName; + dateFormat = new SimpleDateFormat(DEFAULT_DATE_FORMAT); + numberFormat = DecimalFormat.getInstance(); + ((DecimalFormat) numberFormat).applyPattern(DEFAULT_NUMBER_FORMAT); + } + + /** + * Label provider for a given property of a node optionally precising date + * and/or number format patterns + */ + public SimpleJcrNodeLabelProvider(String propertyName, + String dateFormatPattern, String numberFormatPattern) { + this.propertyName = propertyName; + dateFormat = new SimpleDateFormat( + dateFormatPattern == null ? DEFAULT_DATE_FORMAT + : dateFormatPattern); + numberFormat = DecimalFormat.getInstance(); + ((DecimalFormat) numberFormat) + .applyPattern(numberFormatPattern == null ? DEFAULT_NUMBER_FORMAT + : numberFormatPattern); + } + + @Override + public String getText(Object element) { + try { + Node currNode = (Node) element; + + if (currNode.hasProperty(propertyName)) { + if (currNode.getProperty(propertyName).isMultiple()) { + StringBuilder builder = new StringBuilder(); + for (Value value : currNode.getProperty(propertyName) + .getValues()) { + String currStr = getSingleValueAsString(value); + if (notEmptyString(currStr)) + builder.append(currStr).append("; "); + } + if (builder.length() > 0) + builder.deleteCharAt(builder.length() - 2); + + return builder.toString(); + } else + return getSingleValueAsString(currNode.getProperty( + propertyName).getValue()); + } else + return ""; + } catch (RepositoryException re) { + throw new ArgeoException("Unable to get text from row", re); + } + } + + private String getSingleValueAsString(Value value) + throws RepositoryException { + switch (value.getType()) { + case PropertyType.STRING: + return value.getString(); + case PropertyType.BOOLEAN: + return "" + value.getBoolean(); + case PropertyType.DATE: + return dateFormat.format(value.getDate().getTime()); + case PropertyType.LONG: + return "" + value.getLong(); + case PropertyType.DECIMAL: + return numberFormat.format(value.getDecimal()); + case PropertyType.DOUBLE: + return numberFormat.format(value.getDouble()); + case PropertyType.NAME: + return value.getString(); + default: + throw new ArgeoException("Unimplemented label provider " + + "for property type " + value.getType() + + " while getting property " + propertyName + " - value: " + + value.getString()); + + } + } + + private boolean notEmptyString(String string) { + return string != null && !"".equals(string.trim()); + } + + public void setDateFormat(String dateFormatPattern) { + dateFormat = new SimpleDateFormat(dateFormatPattern); + } + + public void setNumberFormat(String numberFormatPattern) { + ((DecimalFormat) numberFormat).applyPattern(numberFormatPattern); + } +} \ No newline at end of file diff --git a/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/lists/SimpleJcrRowLabelProvider.java b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/lists/SimpleJcrRowLabelProvider.java new file mode 100644 index 000000000..bb55f187d --- /dev/null +++ b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/lists/SimpleJcrRowLabelProvider.java @@ -0,0 +1,47 @@ +package org.argeo.eclipse.ui.jcr.lists; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.query.Row; + +import org.argeo.ArgeoException; + +/** + * Base implementation of a label provider for widgets that display JCR Rows. + */ +public class SimpleJcrRowLabelProvider extends SimpleJcrNodeLabelProvider { + private static final long serialVersionUID = -3414654948197181740L; + + final private String selectorName; + + /** + * Default Label provider for a given property of a row. Using default + * pattern for date and number formating + */ + public SimpleJcrRowLabelProvider(String selectorName, String propertyName) { + super(propertyName); + this.selectorName = selectorName; + } + + /** + * Label provider for a given property of a node optionally precising date + * and/or number format patterns + */ + public SimpleJcrRowLabelProvider(String selectorName, String propertyName, + String dateFormatPattern, String numberFormatPattern) { + super(propertyName, dateFormatPattern, numberFormatPattern); + this.selectorName = selectorName; + } + + @Override + public String getText(Object element) { + try { + Row currRow = (Row) element; + Node currNode = currRow.getNode(selectorName); + return super.getText(currNode); + } catch (RepositoryException re) { + throw new ArgeoException("Unable to get Node " + selectorName + + " from row " + element, re); + } + } +} \ No newline at end of file diff --git a/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/utils/JcrFileProvider.java b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/utils/JcrFileProvider.java new file mode 100644 index 000000000..47cab6d6a --- /dev/null +++ b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/utils/JcrFileProvider.java @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.jcr.utils; + +import java.io.InputStream; + +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.RepositoryException; +import javax.jcr.nodetype.NodeType; + +import org.apache.commons.io.IOUtils; +import org.argeo.ArgeoException; +import org.argeo.eclipse.ui.specific.FileProvider; + +/** + * Implements a FileProvider for UI purposes. Note that it might not be very + * reliable as long as we have not fixed login & multi repository issues that + * will be addressed in the next version. + * + * NOTE: id used here is the real id of the JCR Node, not the JCR Path + * + * Relies on common approach for JCR file handling implementation. + * + */ + +public class JcrFileProvider implements FileProvider { + + // private Object[] rootNodes; + private Node refNode; + + /** + * Must be set in order for the provider to be able to get current session + * and thus have the ability to get the file node corresponding to a given + * file ID + * + * FIXME : this introduces some concurrences ISSUES. + * + * @param repositoryNode + */ + public void setReferenceNode(Node refNode) { + this.refNode = refNode; + } + + /** + * Must be set in order for the provider to be able to search the repository + * Provided object might be either JCR Nodes or UI RepositoryNode for the + * time being. + * + * @param repositoryNode + */ + // public void setRootNodes(Object[] rootNodes) { + // List tmpNodes = new ArrayList(); + // for (int i = 0; i < rootNodes.length; i++) { + // Object obj = rootNodes[i]; + // if (obj instanceof Node) { + // tmpNodes.add(obj); + // } else if (obj instanceof RepositoryRegister) { + // RepositoryRegister repositoryRegister = (RepositoryRegister) obj; + // Map repositories = repositoryRegister + // .getRepositories(); + // for (String name : repositories.keySet()) { + // // tmpNodes.add(new RepositoryNode(name, repositories + // // .get(name))); + // } + // + // } + // } + // this.rootNodes = tmpNodes.toArray(); + // } + + public byte[] getByteArrayFileFromId(String fileId) { + InputStream fis = null; + byte[] ba = null; + Node child = getFileNodeFromId(fileId); + try { + fis = (InputStream) child.getProperty(Property.JCR_DATA) + .getBinary().getStream(); + ba = IOUtils.toByteArray(fis); + + } catch (Exception e) { + throw new ArgeoException("Stream error while opening file", e); + } finally { + IOUtils.closeQuietly(fis); + } + return ba; + } + + public InputStream getInputStreamFromFileId(String fileId) { + try { + InputStream fis = null; + + Node child = getFileNodeFromId(fileId); + fis = (InputStream) child.getProperty(Property.JCR_DATA) + .getBinary().getStream(); + return fis; + } catch (RepositoryException re) { + throw new ArgeoException("Cannot get stream from file node for Id " + + fileId, re); + } + } + + /** + * Throws an exception if the node is not found in the current repository (a + * bit like a FileNotFoundException) + * + * @param fileId + * @return Returns the child node of the nt:file node. It is the child node + * that have the jcr:data property where actual file is stored. + * never null + */ + private Node getFileNodeFromId(String fileId) { + try { + Node result = refNode.getSession().getNodeByIdentifier(fileId); + + // rootNodes: for (int j = 0; j < rootNodes.length; j++) { + // // in case we have a classic JCR Node + // if (rootNodes[j] instanceof Node) { + // Node curNode = (Node) rootNodes[j]; + // if (result != null) + // break rootNodes; + // } // Case of a repository Node + // else if (rootNodes[j] instanceof RepositoryNode) { + // Object[] nodes = ((RepositoryNode) rootNodes[j]) + // .getChildren(); + // for (int i = 0; i < nodes.length; i++) { + // Node node = (Node) nodes[i]; + // result = node.getSession().getNodeByIdentifier(fileId); + // if (result != null) + // break rootNodes; + // } + // } + // } + + // Sanity checks + if (result == null) + throw new ArgeoException("File node not found for ID" + fileId); + + Node child = null; + + boolean isValid = true; + if (!result.isNodeType(NodeType.NT_FILE)) + // useless: mandatory child node + // || !result.hasNode(Property.JCR_CONTENT)) + isValid = false; + else { + child = result.getNode(Property.JCR_CONTENT); + if (!(child.isNodeType(NodeType.NT_RESOURCE) || child + .hasProperty(Property.JCR_DATA))) + isValid = false; + } + + if (!isValid) + throw new ArgeoException( + "ERROR: In the current implemented model, '" + + NodeType.NT_FILE + + "' file node must have a child node named jcr:content " + + "that has a BINARY Property named jcr:data " + + "where the actual data is stored"); + return child; + + } catch (RepositoryException re) { + throw new ArgeoException("Erreur while getting file node of ID " + + fileId, re); + } + } +} diff --git a/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/utils/JcrItemsComparator.java b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/utils/JcrItemsComparator.java new file mode 100644 index 000000000..2d36bf28a --- /dev/null +++ b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/utils/JcrItemsComparator.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.jcr.utils; + +import java.util.Comparator; + +import javax.jcr.Item; +import javax.jcr.RepositoryException; + +import org.argeo.ArgeoException; + +/** Compares two JCR items (node or properties) based on their names. */ +public class JcrItemsComparator implements Comparator { + public int compare(Item o1, Item o2) { + try { + // TODO: put folder before files + return o1.getName().compareTo(o2.getName()); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot compare " + o1 + " and " + o2, e); + } + } + +} diff --git a/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/utils/NodeViewerComparer.java b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/utils/NodeViewerComparer.java new file mode 100644 index 000000000..5a94ee76a --- /dev/null +++ b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/utils/NodeViewerComparer.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.jcr.utils; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; + +import org.argeo.ArgeoException; +import org.eclipse.jface.viewers.IElementComparer; + +/** Compare JCR nodes based on their JCR identifiers, for use in JFace viewers. */ +public class NodeViewerComparer implements IElementComparer { + + // force comparison on Node IDs only. + public boolean equals(Object elementA, Object elementB) { + if (!(elementA instanceof Node) || !(elementB instanceof Node)) { + return elementA == null ? elementB == null : elementA + .equals(elementB); + } else { + + boolean result = false; + try { + String idA = ((Node) elementA).getIdentifier(); + String idB = ((Node) elementB).getIdentifier(); + result = idA == null ? idB == null : idA.equals(idB); + } catch (RepositoryException re) { + throw new ArgeoException("cannot compare nodes", re); + } + + return result; + } + } + + public int hashCode(Object element) { + // TODO enhanced this method. + return element.getClass().toString().hashCode(); + } +} \ No newline at end of file diff --git a/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/utils/SingleSessionFileProvider.java b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/utils/SingleSessionFileProvider.java new file mode 100644 index 000000000..f0c378024 --- /dev/null +++ b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/utils/SingleSessionFileProvider.java @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.jcr.utils; + +import java.io.InputStream; + +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.nodetype.NodeType; + +import org.apache.commons.io.IOUtils; +import org.argeo.ArgeoException; +import org.argeo.eclipse.ui.specific.FileProvider; + +/** + * Implements a FileProvider for UI purposes. Unlike the + * JcrFileProvider , it relies on a single session and manages + * nodes with path only. + * + * Note that considered id is the JCR path + * + * Relies on common approach for JCR file handling implementation. + * + * @author bsinou + * + */ + +public class SingleSessionFileProvider implements FileProvider { + + private Session session; + + public SingleSessionFileProvider(Session session) { + this.session = session; + } + + public byte[] getByteArrayFileFromId(String fileId) { + InputStream fis = null; + byte[] ba = null; + Node child = getFileNodeFromId(fileId); + try { + fis = (InputStream) child.getProperty(Property.JCR_DATA) + .getBinary().getStream(); + ba = IOUtils.toByteArray(fis); + + } catch (Exception e) { + throw new ArgeoException("Stream error while opening file", e); + } finally { + IOUtils.closeQuietly(fis); + } + return ba; + } + + public InputStream getInputStreamFromFileId(String fileId) { + try { + InputStream fis = null; + + Node child = getFileNodeFromId(fileId); + fis = (InputStream) child.getProperty(Property.JCR_DATA) + .getBinary().getStream(); + return fis; + } catch (RepositoryException re) { + throw new ArgeoException("Cannot get stream from file node for Id " + + fileId, re); + } + } + + /** + * + * @param fileId + * @return Returns the child node of the nt:file node. It is the child node + * that have the jcr:data property where actual file is stored. + * never null + */ + private Node getFileNodeFromId(String fileId) { + try { + Node result = null; + result = session.getNode(fileId); + + // Sanity checks + if (result == null) + throw new ArgeoException("File node not found for ID" + fileId); + + // Ensure that the node have the correct type. + if (!result.isNodeType(NodeType.NT_FILE)) + throw new ArgeoException( + "Cannot open file children Node that are not of " + + NodeType.NT_RESOURCE + " type."); + + Node child = result.getNodes().nextNode(); + if (child == null || !child.isNodeType(NodeType.NT_RESOURCE)) + throw new ArgeoException( + "ERROR: IN the current implemented model, " + + NodeType.NT_FILE + + " file node must have one and only one child of the nt:ressource, where actual data is stored"); + return child; + } catch (RepositoryException re) { + throw new ArgeoException("Erreur while getting file node of ID " + + fileId, re); + } + } +} diff --git a/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/views/AbstractJcrBrowser.java b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/views/AbstractJcrBrowser.java new file mode 100644 index 000000000..133a65fd1 --- /dev/null +++ b/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/views/AbstractJcrBrowser.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.jcr.views; + +import javax.jcr.Node; + +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.part.ViewPart; + +public abstract class AbstractJcrBrowser extends ViewPart { + + @Override + public abstract void createPartControl(Composite parent); + + /** + * To be overridden to adapt size of form and result frames. + */ + abstract protected int[] getWeights(); + + /** + * To be overridden to provide an adapted size nodeViewer + */ + abstract protected TreeViewer createNodeViewer(Composite parent, + ITreeContentProvider nodeContentProvider); + + /** + * To be overridden to retrieve the current nodeViewer + */ + abstract protected TreeViewer getNodeViewer(); + + /* + * Enables the refresh of the tree. + */ + @Override + public void setFocus() { + getNodeViewer().getTree().setFocus(); + } + + public void refresh(Object obj) { + // getNodeViewer().update(obj, null); + getNodeViewer().refresh(obj); + // getNodeViewer().expandToLevel(obj, 1); + } + + public void nodeAdded(Node parentNode, Node newNode) { + getNodeViewer().refresh(parentNode); + getNodeViewer().expandToLevel(newNode, 0); + } + + public void nodeRemoved(Node parentNode) { + IStructuredSelection newSel = new StructuredSelection(parentNode); + getNodeViewer().setSelection(newSel, true); + // Force refresh + IStructuredSelection tmpSel = (IStructuredSelection) getNodeViewer() + .getSelection(); + getNodeViewer().refresh(tmpSel.getFirstElement()); + } +} diff --git a/org.argeo.eclipse.ui.jcr/src/main/resources/org/argeo/eclipse/ui/jcr/messages.properties b/org.argeo.eclipse.ui.jcr/src/main/resources/org/argeo/eclipse/ui/jcr/messages.properties new file mode 100644 index 000000000..a24aa3861 --- /dev/null +++ b/org.argeo.eclipse.ui.jcr/src/main/resources/org/argeo/eclipse/ui/jcr/messages.properties @@ -0,0 +1,7 @@ +## English labels for Agreo base JCR UI application + +## Generic labels + +## Errors +errorUnvalidNtFolderNodeType= Error: folder can only be created on a Jcr Node + diff --git a/org.argeo.eclipse.ui.rap/.classpath b/org.argeo.eclipse.ui.rap/.classpath new file mode 100644 index 000000000..8cf7f48a0 --- /dev/null +++ b/org.argeo.eclipse.ui.rap/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/org.argeo.eclipse.ui.rap/.project b/org.argeo.eclipse.ui.rap/.project new file mode 100644 index 000000000..df496c27d --- /dev/null +++ b/org.argeo.eclipse.ui.rap/.project @@ -0,0 +1,28 @@ + + + org.argeo.eclipse.ui.rap + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/org.argeo.eclipse.ui.rap/.settings/org.eclipse.jdt.core.prefs b/org.argeo.eclipse.ui.rap/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..ffba01eed --- /dev/null +++ b/org.argeo.eclipse.ui.rap/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +#Wed Mar 02 13:27:08 CET 2011 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/org.argeo.eclipse.ui.rap/build.properties b/org.argeo.eclipse.ui.rap/build.properties new file mode 100644 index 000000000..7cc98e7f8 --- /dev/null +++ b/org.argeo.eclipse.ui.rap/build.properties @@ -0,0 +1,4 @@ +source.. = src/main/java/ +output.. = target/classes/ +bin.includes = META-INF/,\ + .,\ \ No newline at end of file diff --git a/org.argeo.eclipse.ui.rap/pom.xml b/org.argeo.eclipse.ui.rap/pom.xml new file mode 100644 index 000000000..3f47275f0 --- /dev/null +++ b/org.argeo.eclipse.ui.rap/pom.xml @@ -0,0 +1,78 @@ + + 4.0.0 + + org.argeo.commons + 2.1.12-SNAPSHOT + argeo-commons + .. + + org.argeo.eclipse.ui.rap + Commons Eclipse UI RAP + jar + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-source-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + org.apache.felix + maven-bundle-plugin + + + + lazy + org.argeo.eclipse.ui.ArgeoUiPlugin + org.eclipse.rap.ui,org.eclipse.core.runtime + + + org.apache.commons.io, + org.argeo, + org.springframework.beans.factory, + org.springframework.core.io.support, + !org.eclipse.rwt.widgets, + !org.eclipse.core.runtime, + !org.eclipse.core.commands, + !org.eclipse.ui.plugin, + * + + + + + + + + + + + org.argeo.commons + org.argeo.util + 2.1.12-SNAPSHOT + + + + + org.argeo.commons + org.argeo.eclipse.dep.rap + 2.1.12-SNAPSHOT + + + + + org.argeo.tp + slf4j.org.apache.commons.logging + + + \ No newline at end of file diff --git a/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/DownloadServiceHandler.java b/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/DownloadServiceHandler.java new file mode 100644 index 000000000..b28229695 --- /dev/null +++ b/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/DownloadServiceHandler.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.specific; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.argeo.ArgeoException; +import org.eclipse.rap.rwt.service.ServiceHandler; + +@Deprecated +public class DownloadServiceHandler implements ServiceHandler { + + private FileProvider provider; + + public DownloadServiceHandler(FileProvider provider) { + this.provider = provider; + } + + public void service(HttpServletRequest request, HttpServletResponse response) + throws IOException, ServletException { + // Which file to download? + String fileName = request.getParameter("filename"); + String fileId = request.getParameter("fileid"); + + // Get the file content + byte[] download = provider.getByteArrayFileFromId(fileId); + + // Send the file in the response + response.setContentType("application/octet-stream"); + response.setContentLength(download.length); + String contentDisposition = "attachment; filename=\"" + fileName + "\""; + response.setHeader("Content-Disposition", contentDisposition); + + // Various header fields that can be set to solve some issues with some + // old browsers. + // Unused. + // String contentType = "application/force-download; name=\"" + fileName + // + "\""; + // response.setContentType(contentType); + // response.setHeader("Content-Transfer-Encoding", "binary"); + // response.setHeader("Pragma", "no-cache"); + // response.setHeader("Cache-Control", "no-cache, must-revalidate"); + // response.setHeader("Expires", "0"); + // response.setHeader("Connection", "Keep-Alive"); + // response.setHeader("Keep-Alive", "timeout=5, max=86"); + // response.setHeader("transfer-Encoding", "chunked"); + + try { + response.getOutputStream().write(download); + } catch (IOException ioe) { + throw new ArgeoException("Error while writing the file " + fileName + + " to the servlet response", ioe); + } + } +} diff --git a/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/EclipseUiSpecificUtils.java b/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/EclipseUiSpecificUtils.java new file mode 100644 index 000000000..c7ab28aaf --- /dev/null +++ b/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/EclipseUiSpecificUtils.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.specific; + +import org.eclipse.jface.viewers.AbstractTableViewer; +import org.eclipse.jface.viewers.ColumnViewerToolTipSupport; +import org.eclipse.jface.viewers.Viewer; + +/** Static utilities to bridge differences between RCP and RAP */ +public class EclipseUiSpecificUtils { + /** + * TootlTip support is supported only for {@link AbstractTableViewer} in RAP + * + * @see ColumnViewerToolTipSupport#enableFor(AbstractTableViewer) + */ + public static void enableToolTipSupport(Viewer viewer) { + if (viewer instanceof AbstractTableViewer) + ColumnViewerToolTipSupport.enableFor((AbstractTableViewer) viewer); + } + + private EclipseUiSpecificUtils() { + } + +} diff --git a/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/FileHandler.java b/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/FileHandler.java new file mode 100644 index 000000000..927747e62 --- /dev/null +++ b/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/FileHandler.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.specific; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; +import org.eclipse.rap.rwt.RWT; +import org.eclipse.rap.rwt.client.service.UrlLauncher; +import org.eclipse.rap.rwt.service.ServiceHandler; + +/** + * RAP SPECIFIC handler to enable the opening of a download dialog box triggered + * by whatever action in the UI + * + * Manages the registration of the effective DownloadServiceHandler at + * instantiation time. + * + * Manages the process of forwarding the request to the handler at runtime to + * open the dialog box encodedURL + */ +@Deprecated +public class FileHandler { + public final static String DOWNLOAD_SERVICE_NAME = "argeo.rap.download.service"; + private final static Log log = LogFactory.getLog(FileHandler.class); + + public FileHandler(FileProvider provider) { + ServiceHandler handler = new DownloadServiceHandler(provider); + try { + RWT.getServiceManager().registerServiceHandler( + DOWNLOAD_SERVICE_NAME, handler); + } catch (IllegalArgumentException iae) { + log.warn("Handler is already registered, clean this registering process"); + } + } + + public void openFile(String fileName, String fileId) { + try { + String downloadUrl = RWT.getServiceManager().getServiceHandlerUrl( + DOWNLOAD_SERVICE_NAME) + + createParamUrl(fileName, fileId); + if (log.isTraceEnabled()) + log.debug("URL : " + downloadUrl); + UrlLauncher launcher = RWT.getClient() + .getService(UrlLauncher.class); + launcher.openURL(downloadUrl); + } catch (Exception e) { + throw new ArgeoException("Unable to open file " + fileName, e); + } + // These lines are useless in the current use case but might be + // necessary with new browsers. Stored here for memo + // response.setContentType("application/force-download"); + // response.setHeader("Content-Disposition", contentDisposition); + // response.setHeader("Content-Transfer-Encoding", "binary"); + // response.setHeader("Pragma", "no-cache"); + // response.setHeader("Cache-Control", "no-cache, must-revalidate"); + } + + private String createParamUrl(String filename, String fileId) { + StringBuilder url = new StringBuilder(); + url.append("&filename="); + url.append(filename); + url.append("&fileid="); + url.append(fileId); + return url.toString(); + } +} \ No newline at end of file diff --git a/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/FileProvider.java b/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/FileProvider.java new file mode 100644 index 000000000..ae959fb6d --- /dev/null +++ b/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/FileProvider.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.specific; + +import java.io.InputStream; + +/** + * Used for file download : subclasses must implement model specific methods to + * get a byte array representing a file given is ID. + */ +@Deprecated +public interface FileProvider { + + public byte[] getByteArrayFileFromId(String fileId); + + public InputStream getInputStreamFromFileId(String fileId); + +} diff --git a/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/GenericUploadControl.java b/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/GenericUploadControl.java new file mode 100644 index 000000000..e3b319862 --- /dev/null +++ b/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/GenericUploadControl.java @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.specific; + +import java.io.InputStream; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; +//import org.eclipse.rap.rwt.widgets.Upload; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; + +public class GenericUploadControl extends Composite { + private final static Log log = LogFactory + .getLog(GenericUploadControl.class); + + //private Upload upload; + + public GenericUploadControl(Composite parent, int style, String browseLabel) { + super(parent, style); + createControl(this, browseLabel); + + } + + private void createControl(Composite parent, String browseLabel) { + parent.setLayout(new GridLayout(1, false)); + parent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + +// upload = new Upload(parent, SWT.BORDER); +// upload.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); +// upload.setBrowseButtonText(browseLabel); + // upload.addModifyListener(new UploadListener()); + parent.pack(); + } + + /** + * Wrap upload.getLastFileUploaded(). Gets the name of the last uploaded + * file. This method can be called even if the upload has not finished yet. + */ + public String getLastFileUploadedName() { + return ""; + } + + public boolean isControlEmpty() { + String path = ""; + if (log.isTraceEnabled()) + log.trace("UploadControl chosen path : " + path); + if (path == null || "".equals(path.trim())) + return true; + else + return false; + } + + public byte[] performUpload() { +// boolean success = upload.performUpload(); +// if (success) { +// if (upload.getUploadItem().getFileSize() == -1) +// throw new ArgeoException("File " +// + upload.getUploadItem().getFileName() +// + " has not been uploaded, its size is -1"); +// +// InputStream inStream = null; +// byte[] fileBA = null; +// try { +// inStream = upload.getUploadItem().getFileInputStream(); +// fileBA = IOUtils.toByteArray(inStream); +// } catch (Exception e) { +// throw new ArgeoException("Cannot read uploaded data", e); +// } finally { +// IOUtils.closeQuietly(inStream); +// } +// return fileBA; +// } + return null; + } + + public void addModifyListener(ModifyListener listener) { +// upload.addModifyListener(listener); + } + + // private class UploadManager extends UploadAdapter { + // private Upload upload; + // + // public UploadManager(Upload upload) { + // super(); + // this.upload = upload; + // } + // + // public void uploadFinished(UploadEvent uploadEvent) { + // handleUploadFinished(upload); + // } + // + // public void uploadInProgress(UploadEvent uploadEvent) { + // } + // + // public void uploadException(UploadEvent uploadEvent) { + // Exception exc = uploadEvent.getUploadException(); + // if (exc != null) { + // MessageDialog.openError(Display.getCurrent().getActiveShell(), + // "Error", exc.getMessage()); + // } + // } + // + // } + // + +} diff --git a/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/ImportToServerWizardPage.java b/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/ImportToServerWizardPage.java new file mode 100644 index 000000000..f66a279c6 --- /dev/null +++ b/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/ImportToServerWizardPage.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.specific; + +import java.io.InputStream; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; +import org.eclipse.jface.wizard.WizardPage; +//import org.eclipse.rap.rwt.widgets.Upload; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; + +public class ImportToServerWizardPage extends WizardPage { + private final static Log log = LogFactory + .getLog(ImportToServerWizardPage.class); + + public final static String FILE_ITEM_TYPE = "FILE"; + public final static String FOLDER_ITEM_TYPE = "FOLDER"; + + //private Upload uploadFile; + + public ImportToServerWizardPage() { + super("Import from file system"); + setDescription("Import files from the local file system to the server"); + } + + public void createControl(Composite parent) { + Composite composite = new Composite(parent, SWT.NONE); + composite.setLayout(new GridLayout(2, false)); + composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + new Label(composite, SWT.NONE).setText("Pick up a file"); +// uploadFile = new Upload(composite, SWT.BORDER); +// uploadFile.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); +// uploadFile.setBrowseButtonText("Open..."); + setControl(composite); + } + + public String getObjectPath() { + // NOTE Returns the full file name of the last uploaded file including + // the file path as selected by the user on his local machine. + // The full path including the directory and file drive are only + // returned, if the browser supports reading this properties. In Firefox + // 3, only the filename is returned. + return null; + } + + public String getObjectName() { + return null; + } + + public String getObjectType() { + return FILE_ITEM_TYPE; + } + + public void performFinish() { +// boolean success = uploadFile.performUpload(); +// if (!success) +// throw new ArgeoException("Cannot upload file named " +// + uploadFile.getPath()); + } + +// protected void handleUploadFinished(final Upload upload) { +// } + + public InputStream getFileInputStream() { + return null; + } + + public boolean getNeedsProgressMonitor() { + return false; + } + +} diff --git a/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/OpenFile.java b/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/OpenFile.java new file mode 100644 index 000000000..b55521b12 --- /dev/null +++ b/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/OpenFile.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.specific; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.rap.rwt.RWT; +import org.eclipse.rap.rwt.client.service.UrlLauncher; + +/** + * Rap specific command handler to open a file retrieved from the server. It + * forwards the request to the correct service after encoding file name and path + * in the request URI. + * + * The parameter "URI" is used to determine the correct file service, the path + * and the file name. An optional file name can be precised to present a + * different file name as the one used to retrieve it to the end user/ + * + * Various instances of this handler with different command ID might coexist in + * order to provide context specific download service. + * + * The instance specific service is called by its ID and must have been + * externally created + */ +public class OpenFile extends AbstractHandler { + private final static Log log = LogFactory.getLog(OpenFile.class); + + /* DEPENDENCY INJECTION */ + private String openFileServiceId; + + public final static String PARAM_FILE_NAME = OpenFileService.PARAM_FILE_NAME; + public final static String PARAM_FILE_URI = OpenFileService.PARAM_FILE_URI; // "param.fileURI"; + + public Object execute(ExecutionEvent event) throws ExecutionException { + String fileName = event.getParameter(PARAM_FILE_NAME); + String fileUri = event.getParameter(PARAM_FILE_URI); + + // sanity check + if (fileUri == null || "".equals(fileUri.trim()) + || openFileServiceId == null + || "".equals(openFileServiceId.trim())) + return null; + + StringBuilder url = new StringBuilder(); + url.append(RWT.getServiceManager().getServiceHandlerUrl( + openFileServiceId)); + + url.append("&").append(PARAM_FILE_NAME).append("="); + url.append(fileName); + url.append("&").append(PARAM_FILE_URI).append("="); + url.append(fileUri); + + String downloadUrl = url.toString(); + if (log.isTraceEnabled()) + log.debug("URL : " + downloadUrl); + + UrlLauncher launcher = RWT.getClient().getService(UrlLauncher.class); + launcher.openURL(downloadUrl); + + // These lines are useless in the current use case but might be + // necessary with new browsers. Stored here for memo + // response.setContentType("application/force-download"); + // response.setHeader("Content-Disposition", contentDisposition); + // response.setHeader("Content-Transfer-Encoding", "binary"); + // response.setHeader("Pragma", "no-cache"); + // response.setHeader("Cache-Control", "no-cache, must-revalidate"); + return null; + } + + /* DEPENDENCY INJECTION */ + public void setOpenFileServiceId(String openFileServiceId) { + this.openFileServiceId = openFileServiceId; + } +} \ No newline at end of file diff --git a/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/OpenFileService.java b/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/OpenFileService.java new file mode 100644 index 000000000..e48babf0b --- /dev/null +++ b/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/OpenFileService.java @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.specific; + +import java.io.File; +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.io.FileUtils; +import org.argeo.ArgeoException; +import org.eclipse.rap.rwt.service.ServiceHandler; + +/** + * Basic Default service handler that retrieves a file on the server file system + * using its absolute path and forwards it to the end user browser. Rap + * specific. + * + * Clients might extend to provide context specific services (to open files from + * a JCR repository for instance) + */ +public class OpenFileService implements ServiceHandler { + public final static String PARAM_FILE_NAME = "param.fileName"; + public final static String PARAM_FILE_URI = "param.fileURI"; + + public final static String SCHEME_HOST_SEPARATOR = "://"; + public final static String FILE_SCHEME = "file"; + + public OpenFileService() { + } + + public void service(HttpServletRequest request, HttpServletResponse response) + throws IOException, ServletException { + String fileName = request.getParameter(PARAM_FILE_NAME); + String uri = request.getParameter(PARAM_FILE_URI); + + // Set the Metadata + response.setContentType("application/octet-stream"); + response.setContentLength((int) getFileLength(uri)); + if (fileName == null || "".equals(fileName.trim())) + fileName = getFileName(uri); + String contentDisposition = "attachment; filename=\"" + fileName + "\""; + response.setHeader("Content-Disposition", contentDisposition); + + response.getOutputStream().write(getFileAsByteArray(uri)); + // FileUtils.readFileToByteArray(new File(path)) + } + + protected byte[] getFileAsByteArray(String uri) { + if (uri.startsWith(FILE_SCHEME)) { + try { + return FileUtils.readFileToByteArray(new File( + getFilePathFromUri(uri))); + } catch (IOException ioe) { + throw new ArgeoException("Error while getting the file at " + + uri, ioe); + } + } + return null; + } + + protected long getFileLength(String uri) { + if (uri.startsWith(FILE_SCHEME)) { + return new File(getFilePathFromUri(uri)).length(); + } + return -1l; + } + + protected String getFileName(String uri) { + if (uri.startsWith(FILE_SCHEME)) { + return new File(getFilePathFromUri(uri)).getName(); + } + return null; + } + + private String getFilePathFromUri(String uri) { + return uri.substring((FILE_SCHEME + SCHEME_HOST_SEPARATOR).length()); + } + +} \ No newline at end of file diff --git a/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/ThreadNLS.java b/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/ThreadNLS.java new file mode 100644 index 000000000..8b8837f2e --- /dev/null +++ b/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/ThreadNLS.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.specific; + +import org.eclipse.osgi.util.NLS; +import org.eclipse.rap.rwt.RWT; + +/** NLS attached to a given thread */ +public class ThreadNLS extends InheritableThreadLocal { + public final static String DEFAULT_BUNDLE_LOCATION = "/properties/plugin"; + + private final String bundleLocation; + + private Class type; + private Boolean utf8 = false; + + public ThreadNLS(String bundleLocation, Class type, Boolean utf8) { + this.bundleLocation = bundleLocation; + this.type = type; + this.utf8 = utf8; + } + + public ThreadNLS(Class type) { + this(DEFAULT_BUNDLE_LOCATION, type, false); + } + + @SuppressWarnings("unchecked") + @Override + protected T initialValue() { + if (utf8) + return (T) RWT.NLS.getUTF8Encoded(bundleLocation, type); + else + return (T) RWT.NLS.getISO8859_1Encoded(bundleLocation, type); + } +} diff --git a/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/UploadFileWizardPage.java b/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/UploadFileWizardPage.java new file mode 100644 index 000000000..17d4e22f3 --- /dev/null +++ b/org.argeo.eclipse.ui.rap/src/main/java/org/argeo/eclipse/ui/specific/UploadFileWizardPage.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.specific; + +import java.io.InputStream; + +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.rap.rwt.widgets.FileUpload; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; + +public class UploadFileWizardPage extends WizardPage { + // private final static Log log = LogFactory + // .getLog(UploadFileWizardPage.class); + private static final long serialVersionUID = 8251354244542973179L; + public final static String FILE_ITEM_TYPE = "FILE"; + public final static String FOLDER_ITEM_TYPE = "FOLDER"; + + private FileUpload fileUpload; + + public UploadFileWizardPage() { + super("Import from file system"); + setDescription("Import files from the local file system to the server"); + } + + public void createControl(Composite parent) { + Composite composite = new Composite(parent, SWT.NONE); + composite.setLayout(new GridLayout(2, false)); + composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + new Label(composite, SWT.NONE).setText("Pick up a file"); + fileUpload = new FileUpload(composite, SWT.BORDER); + fileUpload.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + fileUpload.setText("Browse"); + setControl(composite); + } + + public String getObjectPath() { + // NOTE Returns the full file name of the last uploaded file including + // the file path as selected by the user on his local machine. + // The full path including the directory and file drive are only + // returned, if the browser supports reading this properties. In Firefox + // 3, only the filename is returned. + return null; + } + + public String getObjectName() { + return fileUpload.getFileName(); + } + + public String getObjectType() { + return FILE_ITEM_TYPE; + } + + public void performFinish() { + // boolean success = uploadFile.performUpload(); + // if (!success) + // throw new ArgeoException("Cannot upload file named " + // + uploadFile.getPath()); + } + + // protected void handleUploadFinished(final Upload upload) { + // } + + public InputStream getFileInputStream() { + return null; + } + + public boolean getNeedsProgressMonitor() { + return false; + } + +} diff --git a/org.argeo.eclipse.ui.rcp/.classpath b/org.argeo.eclipse.ui.rcp/.classpath new file mode 100644 index 000000000..8cf7f48a0 --- /dev/null +++ b/org.argeo.eclipse.ui.rcp/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/org.argeo.eclipse.ui.rcp/.project b/org.argeo.eclipse.ui.rcp/.project new file mode 100644 index 000000000..ef2dc2dbb --- /dev/null +++ b/org.argeo.eclipse.ui.rcp/.project @@ -0,0 +1,28 @@ + + + org.argeo.eclipse.ui.rcp + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/org.argeo.eclipse.ui.rcp/.settings/org.eclipse.jdt.core.prefs b/org.argeo.eclipse.ui.rcp/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..b06d92e45 --- /dev/null +++ b/org.argeo.eclipse.ui.rcp/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +#Tue Mar 01 19:20:51 CET 2011 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/org.argeo.eclipse.ui.rcp/build.properties b/org.argeo.eclipse.ui.rcp/build.properties new file mode 100644 index 000000000..886a20027 --- /dev/null +++ b/org.argeo.eclipse.ui.rcp/build.properties @@ -0,0 +1,4 @@ +source.. = src/main/java/ +output.. = target/classes/ +bin.includes = META-INF/,\ + .,\ diff --git a/org.argeo.eclipse.ui.rcp/pom.xml b/org.argeo.eclipse.ui.rcp/pom.xml new file mode 100644 index 000000000..c86cb6a19 --- /dev/null +++ b/org.argeo.eclipse.ui.rcp/pom.xml @@ -0,0 +1,84 @@ + + 4.0.0 + + org.argeo.commons + 2.1.12-SNAPSHOT + argeo-commons + .. + + org.argeo.eclipse.ui.rcp + Commons Eclipse UI RCP + jar + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-source-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + org.apache.felix + maven-bundle-plugin + + + + lazy + org.argeo.eclipse.ui.ArgeoUiPlugin + org.eclipse.ui,org.eclipse.core.runtime + + org.springframework.beans.factory, + org.springframework.core.io.support, + org.apache.commons.io, + org.argeo, + !org.eclipse.core.runtime, + !org.eclipse.core.commands, + !org.eclipse.ui.plugin, + * + + + + + + + + + + org.argeo.commons + org.argeo.eclipse.ui + 2.1.12-SNAPSHOT + + + + + org.argeo.commons + org.argeo.eclipse.dep.rcp + 2.1.12-SNAPSHOT + + + + + org.argeo.commons + org.argeo.util + 2.1.12-SNAPSHOT + + + + + org.argeo.tp + org.apache.commons.io + + + + + org.argeo.tp + slf4j.org.apache.commons.logging + + + \ No newline at end of file diff --git a/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/DefaultNLS.java b/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/DefaultNLS.java new file mode 100644 index 000000000..71a0c898d --- /dev/null +++ b/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/DefaultNLS.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.specific; + +import org.eclipse.osgi.util.NLS; + +/** RCP specific {@link NLS} to be extended */ +public class DefaultNLS extends NLS { + public final static String DEFAULT_BUNDLE_LOCATION = "/properties/plugin"; + + public DefaultNLS() { + this(DEFAULT_BUNDLE_LOCATION); + } + + public DefaultNLS(String bundleName) { + NLS.initializeMessages(bundleName, getClass()); + } +} diff --git a/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/EclipseUiSpecificUtils.java b/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/EclipseUiSpecificUtils.java new file mode 100644 index 000000000..2642a35a1 --- /dev/null +++ b/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/EclipseUiSpecificUtils.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.specific; + +import org.eclipse.jface.viewers.ColumnViewer; +import org.eclipse.jface.viewers.ColumnViewerToolTipSupport; +import org.eclipse.jface.viewers.Viewer; + +/** Static utilities to bridge differences between RCP and RAP */ +public class EclipseUiSpecificUtils { + /** + * TootlTip support is supported for {@link ColumnViewer} in RCP + * + * @see ColumnViewerToolTipSupport#enableFor(Viewer) + */ + public static void enableToolTipSupport(Viewer viewer) { + if (viewer instanceof ColumnViewer) + ColumnViewerToolTipSupport.enableFor((ColumnViewer) viewer); + } + + private EclipseUiSpecificUtils() { + } + +} diff --git a/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/FileHandler.java b/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/FileHandler.java new file mode 100644 index 000000000..5da49736d --- /dev/null +++ b/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/FileHandler.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.specific; + +import java.awt.Desktop; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import org.apache.commons.io.IOUtils; +import org.argeo.ArgeoException; + +/** + * Abstraction that enable to implement runtime environment specific (typically + * RCP or RAP) methods while dealing with files in the UI. + * + */ +public class FileHandler { + + private FileProvider provider; + + public FileHandler(FileProvider provider) { + this.provider = provider; + } + + public void openFile(String fileName, String fileId) { + String tmpFileName = fileName; + String prefix = "", extension = ""; + if (fileName != null) { + int ind = fileName.lastIndexOf('.'); + if (ind > 0) { + prefix = fileName.substring(0, ind); + extension = fileName.substring(ind); + } + } + + InputStream is = null; + try { + is = provider.getInputStreamFromFileId(fileId); + File file = createTmpFile(prefix, extension, is); + tmpFileName = file.getName(); + Desktop desktop = null; + if (Desktop.isDesktopSupported()) { + desktop = Desktop.getDesktop(); + } + desktop.open(file); + } catch (IOException e) { + // Note : tmpFileName = fileName if the error has been thrown while + // creating the tmpFile. + throw new ArgeoException("Cannot open file " + tmpFileName, e); + } finally { + IOUtils.closeQuietly(is); + } + } + + private File createTmpFile(String prefix, String suffix, InputStream is) { + File tmpFile = null; + OutputStream os = null; + try { + tmpFile = File.createTempFile(prefix, suffix); + os = new FileOutputStream(tmpFile); + IOUtils.copy(is, os); + } catch (IOException e) { + throw new ArgeoException("Cannot open file " + prefix + "." + + suffix, e); + } finally { + IOUtils.closeQuietly(os); + } + return tmpFile; + } +} diff --git a/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/FileProvider.java b/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/FileProvider.java new file mode 100644 index 000000000..5c92260d7 --- /dev/null +++ b/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/FileProvider.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.specific; + +import java.io.InputStream; + +/** + * Used for file download : subclasses must implement model specific methods to + * get a byte array representing a file given is ID. + * + * @author bsinou + * + */ +public interface FileProvider { + + public byte[] getByteArrayFileFromId(String fileId); + + public InputStream getInputStreamFromFileId(String fileId); + +} diff --git a/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/GenericUploadControl.java b/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/GenericUploadControl.java new file mode 100644 index 000000000..80e1e539c --- /dev/null +++ b/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/GenericUploadControl.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.specific; + +import java.io.File; +import java.io.IOException; + +import org.apache.commons.io.FileUtils; +import org.argeo.ArgeoException; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Text; + +/** + * RCP specific composite that provides a control to upload a file. WARNING: for + * the time being we set a GridLayout(2, false) on th eparent control. + */ +public class GenericUploadControl extends Composite { + // private final static Log log = LogFactory + // .getLog(GenericUploadControl.class); + + private FileDialog dialog; + private Text filePath; + + public GenericUploadControl(Composite parent, int style, String browseLabel) { + super(parent, style); + createControl(this, browseLabel); + + } + + private void createControl(final Composite parent, String browseLabel) { + parent.setLayout(new GridLayout(2, false)); + + filePath = new Text(parent, SWT.BORDER | SWT.SINGLE); + GridData gd = new GridData(GridData.GRAB_HORIZONTAL + | GridData.FILL_HORIZONTAL); + filePath.setEditable(false); + filePath.setLayoutData(gd); + + // Execute button + Button execute = new Button(parent, SWT.PUSH); + GridData gridData = new GridData(); + gridData.horizontalAlignment = GridData.BEGINNING; + execute.setLayoutData(gridData); + execute.setText(browseLabel); + + // Button listener + Listener executeListener = new Listener() { + public void handleEvent(Event event) { + dialog = new FileDialog(parent.getShell()); + filePath.setText(dialog.open()); + } + }; + parent.layout(); + execute.addListener(SWT.Selection, executeListener); + } + + public boolean isControlEmpty() { + String path = filePath.getText(); + if (path == null || "".equals(path.trim())) + return true; + else + return false; + } + + public byte[] performUpload() { + String path = filePath.getText(); + if (path != null) { + try { + File file = new File(path); + byte[] fileBA = FileUtils.readFileToByteArray(file); + return fileBA; + } catch (IOException e) { + throw new ArgeoException("Unexpected error while " + + "reading file at path " + path, e); + } + } + return null; + } + + public void addModifyListener(ModifyListener listener) { + filePath.addModifyListener(listener); + } + + /** + * Always returns null in an RCP environment + */ + public String getLastFileUploadedName() { + return null; + } +} diff --git a/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/ImportToServerWizardPage.java b/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/ImportToServerWizardPage.java new file mode 100644 index 000000000..55065bfa0 --- /dev/null +++ b/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/ImportToServerWizardPage.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.specific; + +import java.io.InputStream; + +import org.eclipse.jface.preference.DirectoryFieldEditor; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.widgets.Composite; + +public class ImportToServerWizardPage extends WizardPage { + + public final static String FILE_ITEM_TYPE = "FILE"; + public final static String FOLDER_ITEM_TYPE = "FOLDER"; + + private DirectoryFieldEditor dfe; + + public ImportToServerWizardPage() { + super("Import from file system"); + setDescription("Import files from the local file system into the JCR repository"); + } + + public void createControl(Composite parent) { + dfe = new DirectoryFieldEditor("directory", "From", parent); + setControl(dfe.getTextControl(parent)); + } + + public String getObjectPath() { + return dfe.getStringValue(); + } + + public String getObjectType() { + return FOLDER_ITEM_TYPE; + } + + public boolean getNeedsProgressMonitor() { + return true; + } + + // Dummy methods : useless in RCP context but useful for RAP + /** WARNING : always return null in RCP context */ + public String getObjectName() { + return null; + } + + /** WARNING : do nothing in RCP context */ + public void performFinish() { + } + + /** WARNING : always return null in RCP context */ + public InputStream getFileInputStream() { + return null; + } +} \ No newline at end of file diff --git a/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/OpenFile.java b/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/OpenFile.java new file mode 100644 index 000000000..610020dd1 --- /dev/null +++ b/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/OpenFile.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.specific; + +import java.awt.Desktop; +import java.io.File; +import java.io.IOException; + +import org.argeo.ArgeoException; +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; + +/** + * RCP specific command handler to open a file. + * + * The parameter "URI" is used to determine the correct method to open it. + * + * Various instances of this handler with different command ID might coexist in + * order to provide context specific open file service. + * + */ +public class OpenFile extends AbstractHandler { + // private final static Log log = LogFactory.getLog(OpenFile.class); + + public final static String PARAM_FILE_NAME = "param.fileName"; + public final static String PARAM_FILE_URI = "param.fileURI"; + + private final static String FILE_SCHEME = "file"; + + public Object execute(ExecutionEvent event) throws ExecutionException { + @SuppressWarnings("unused") + @Deprecated + String fileName = event.getParameter(PARAM_FILE_NAME); + String fileUri = event.getParameter(PARAM_FILE_URI); + + // sanity check + if (fileUri == null || "".equals(fileUri.trim())) + return null; + + Desktop desktop = null; + if (Desktop.isDesktopSupported()) { + desktop = Desktop.getDesktop(); + } + + File file = getFileFromUri(fileUri); + if (file != null) + try { + desktop.open(file); + } catch (IOException e) { + throw new ArgeoException("Unable to open file with URI: " + + fileUri, e); + } + + return null; + } + + protected File getFileFromUri(String uri) { + if (uri.startsWith(FILE_SCHEME)) { + String path = uri.substring((FILE_SCHEME + "://").length()); + return new File(path); + } + return null; + } +} \ No newline at end of file diff --git a/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/ThreadNLS.java b/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/ThreadNLS.java new file mode 100644 index 000000000..c87f6e54f --- /dev/null +++ b/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/ThreadNLS.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.specific; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +import org.argeo.util.LocaleUtils; +import org.eclipse.osgi.util.NLS; + +/** NLS attached to a given thread */ +public class ThreadNLS extends InheritableThreadLocal { + public final static String DEFAULT_BUNDLE_LOCATION = "/properties/plugin"; + + private final String bundleLocation; + + private Class type; + private Boolean utf8 = false; + + public ThreadNLS(String bundleLocation, Class type, Boolean utf8) { + this.bundleLocation = bundleLocation; + this.type = type; + this.utf8 = utf8; + } + + public ThreadNLS(Class type) { + this(DEFAULT_BUNDLE_LOCATION, type, false); + } + + @Override + protected T initialValue() { + ResourceBundle bundle = ResourceBundle.getBundle(bundleLocation, + LocaleUtils.threadLocale.get(), type.getClassLoader()); + T result; + try { + NLS.initializeMessages(bundleLocation, type); + Constructor constructor = type.getConstructor(); + constructor.setAccessible(true); + result = constructor.newInstance(); + final Field[] fieldArray = type.getDeclaredFields(); + for (int i = 0; i < fieldArray.length; i++) { + int modifiers = fieldArray[i].getModifiers(); + if (String.class.isAssignableFrom(fieldArray[i].getType()) + && Modifier.isPublic(modifiers) + && !Modifier.isStatic(modifiers)) { + try { + String value = bundle + .getString(fieldArray[i].getName()); + byte[] bytes = value.getBytes(); + + String forcedValue; + if (utf8) + forcedValue = new String(bytes, "UTF8"); + else + forcedValue = value; + if (value != null) { + fieldArray[i].setAccessible(true); + fieldArray[i].set(result, forcedValue); + } + } catch (final MissingResourceException mre) { + fieldArray[i].setAccessible(true); + fieldArray[i].set(result, ""); + mre.printStackTrace(); + } + } + } + return result; + } catch (final Exception ex) { + throw new IllegalStateException(ex.getMessage()); + } + } + +} diff --git a/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/UploadFileWizardPage.java b/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/UploadFileWizardPage.java new file mode 100644 index 000000000..5bdaeceb5 --- /dev/null +++ b/org.argeo.eclipse.ui.rcp/src/main/java/org/argeo/eclipse/ui/specific/UploadFileWizardPage.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.specific; + +import java.io.InputStream; + +import org.eclipse.jface.preference.DirectoryFieldEditor; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.widgets.Composite; + +public class UploadFileWizardPage extends WizardPage { + + public final static String FILE_ITEM_TYPE = "FILE"; + public final static String FOLDER_ITEM_TYPE = "FOLDER"; + + private DirectoryFieldEditor dfe; + + public UploadFileWizardPage() { + super("Import from file system"); + setDescription("Import files from the local file system into the JCR repository"); + } + + public void createControl(Composite parent) { + dfe = new DirectoryFieldEditor("directory", "From", parent); + setControl(dfe.getTextControl(parent)); + } + + public String getObjectPath() { + return dfe.getStringValue(); + } + + public String getObjectType() { + return FOLDER_ITEM_TYPE; + } + + public boolean getNeedsProgressMonitor() { + return true; + } + + // Dummy methods : useless in RCP context but useful for RAP + /** WARNING : always return null in RCP context */ + public String getObjectName() { + return null; + } + + /** WARNING : do nothing in RCP context */ + public void performFinish() { + } + + /** WARNING : always return null in RCP context */ + public InputStream getFileInputStream() { + return null; + } +} \ No newline at end of file diff --git a/org.argeo.eclipse.ui/.classpath b/org.argeo.eclipse.ui/.classpath new file mode 100644 index 000000000..a50743442 --- /dev/null +++ b/org.argeo.eclipse.ui/.classpath @@ -0,0 +1,7 @@ + + + + > + + + diff --git a/org.argeo.eclipse.ui/.project b/org.argeo.eclipse.ui/.project new file mode 100644 index 000000000..53e9b324c --- /dev/null +++ b/org.argeo.eclipse.ui/.project @@ -0,0 +1,28 @@ + + + org.argeo.eclipse.ui + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/org.argeo.eclipse.ui/.settings/org.eclipse.jdt.core.prefs b/org.argeo.eclipse.ui/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..f441c9045 --- /dev/null +++ b/org.argeo.eclipse.ui/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +#Thu Jul 29 10:54:11 CEST 2010 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.5 diff --git a/org.argeo.eclipse.ui/.settings/org.eclipse.pde.core.prefs b/org.argeo.eclipse.ui/.settings/org.eclipse.pde.core.prefs new file mode 100644 index 000000000..8e36e3304 --- /dev/null +++ b/org.argeo.eclipse.ui/.settings/org.eclipse.pde.core.prefs @@ -0,0 +1,3 @@ +#Thu Jul 29 11:00:39 CEST 2010 +eclipse.preferences.version=1 +resolve.requirebundle=false diff --git a/org.argeo.eclipse.ui/build.properties b/org.argeo.eclipse.ui/build.properties new file mode 100644 index 000000000..5fc538bc8 --- /dev/null +++ b/org.argeo.eclipse.ui/build.properties @@ -0,0 +1,4 @@ +source.. = src/main/java/ +output.. = target/classes/ +bin.includes = META-INF/,\ + . diff --git a/org.argeo.eclipse.ui/pom.xml b/org.argeo.eclipse.ui/pom.xml new file mode 100644 index 000000000..899e271a8 --- /dev/null +++ b/org.argeo.eclipse.ui/pom.xml @@ -0,0 +1,88 @@ + + 4.0.0 + + org.argeo.commons + 2.1.12-SNAPSHOT + argeo-commons + .. + + org.argeo.eclipse.ui + Commons Eclipse UI + jar + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-source-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + org.apache.felix + maven-bundle-plugin + + + + ${project.artifactId};singleton:=true + lazy + org.argeo.eclipse.ui.ArgeoUiPlugin + org.eclipse.ui;resolution:=optional,org.eclipse.rap.ui;resolution:=optional,org.eclipse.core.runtime + + org.springframework.beans.factory, + org.springframework.core.io.support, + !org.eclipse.core.runtime, + !org.eclipse.core.commands, + !org.eclipse.ui.plugin, + * + + + + + + + + + + org.argeo.tp + javax.jcr + + + + + org.argeo.commons + org.argeo.eclipse.dep.rcp + 2.1.12-SNAPSHOT + provided + + + + + org.argeo.commons + org.argeo.util + 2.1.12-SNAPSHOT + + + + + org.argeo.tp + org.springframework.context + + + org.argeo.tp + org.springframework.osgi.extender + + + + + org.argeo.tp + slf4j.org.apache.commons.logging + + + + \ No newline at end of file diff --git a/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/spring/ApplicationContextTracker.java b/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/spring/ApplicationContextTracker.java new file mode 100644 index 000000000..070c70826 --- /dev/null +++ b/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/spring/ApplicationContextTracker.java @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.spring; + +import static java.text.MessageFormat.format; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.eclipse.core.runtime.Platform; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.BundleException; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.util.tracker.ServiceTracker; +import org.springframework.context.ApplicationContext; + +/** + * Tracks Spring application context published as services. + * + * @author Heiko Seeberger + * @author Mathieu Baudier + */ +class ApplicationContextTracker { + private final static Log log = LogFactory + .getLog(ApplicationContextTracker.class); + + private static final String FILTER = "(&(objectClass=org.springframework.context.ApplicationContext)" //$NON-NLS-1$ + + "(org.springframework.context.service.name={0}))"; //$NON-NLS-1$ + + public final static String APPLICATION_CONTEXT_TRACKER_TIMEOUT = "org.argeo.eclipse.spring.applicationContextTrackerTimeout"; + + private static Long defaultTimeout = Long.parseLong(System.getProperty( + APPLICATION_CONTEXT_TRACKER_TIMEOUT, "30000")); + + private ServiceTracker applicationContextServiceTracker; + + /** + * @param contributorBundle + * OSGi bundle for which the Spring application context is to be + * tracked. Must not be null! + * @param factoryBundleContext + * BundleContext object which can be used to track services + * @throws IllegalArgumentException + * if the given bundle is null. + */ + public ApplicationContextTracker(final Bundle contributorBundle, + final BundleContext factoryBundleContext) { + final String filter = format(FILTER, + contributorBundle.getSymbolicName()); + try { + applicationContextServiceTracker = new ServiceTracker( + factoryBundleContext, FrameworkUtil.createFilter(filter), + null); + // applicationContextServiceTracker.open(); + } catch (final InvalidSyntaxException e) { + e.printStackTrace(); + } + } + + public void open() { + if (applicationContextServiceTracker != null) { + applicationContextServiceTracker.open(); + } + } + + public void close() { + if (applicationContextServiceTracker != null) { + applicationContextServiceTracker.close(); + } + } + + public ApplicationContext getApplicationContext() { + ApplicationContext applicationContext = null; + if (applicationContextServiceTracker != null) { + try { + applicationContext = (ApplicationContext) applicationContextServiceTracker + .waitForService(defaultTimeout); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + return applicationContext; + } + + @Override + protected void finalize() throws Throwable { + close(); + super.finalize(); + } + + static ApplicationContext getApplicationContext(String bundleSymbolicName) { + Bundle contributorBundle = Platform.getBundle(bundleSymbolicName); + return getApplicationContext(contributorBundle); + } + + static ApplicationContext getApplicationContext( + final Bundle contributorBundle) { + if (log.isTraceEnabled()) + log.trace("Get application context for bundle " + contributorBundle); + + // Start if not yet started (also if in STARTING state, may be lazy) + if (contributorBundle.getState() != Bundle.ACTIVE) { + if (log.isTraceEnabled()) + log.trace("Starting bundle: " + + contributorBundle.getSymbolicName()); + // Thread startBundle = new Thread("Start bundle " + // + contributorBundle.getSymbolicName()) { + // public void run() { + try { + contributorBundle.start(); + } catch (BundleException e) { + log.error("Cannot start bundle " + contributorBundle, e); + } + // } + // }; + // startBundle.start(); + // try { + // startBundle.join(10 * 1000l); + // } catch (InterruptedException e) { + // // silent + // } + } + + final ApplicationContextTracker applicationContextTracker = new ApplicationContextTracker( + contributorBundle, contributorBundle.getBundleContext()); + ApplicationContext applicationContext = null; + try { + applicationContextTracker.open(); + applicationContext = applicationContextTracker + .getApplicationContext(); + } finally { + applicationContextTracker.close(); + } + return applicationContext; + } +} diff --git a/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/spring/SpringCommandHandler.java b/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/spring/SpringCommandHandler.java new file mode 100644 index 000000000..4c7a152df --- /dev/null +++ b/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/spring/SpringCommandHandler.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.spring; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.IHandler; +import org.eclipse.core.commands.IHandlerListener; +import org.springframework.context.ApplicationContext; + +/** Allows to declare Eclipse commands as Spring beans */ +public class SpringCommandHandler implements IHandler { + private final static Log log = LogFactory + .getLog(SpringCommandHandler.class); + + public void addHandlerListener(IHandlerListener handlerListener) { + } + + public void dispose() { + } + + public Object execute(ExecutionEvent event) throws ExecutionException { + String commandId = event.getCommand().getId(); + String bundleSymbolicName = commandId.substring(0, + commandId.lastIndexOf('.')); + try { + if (log.isTraceEnabled()) + log.trace("Execute " + event + " via spring command handler " + + this); + // TODO: make it more flexible and robust + ApplicationContext applicationContext = ApplicationContextTracker + .getApplicationContext(bundleSymbolicName); + if (applicationContext == null) + throw new ArgeoException("No application context found for " + + bundleSymbolicName); + + // retrieve the command via its id + String beanName = event.getCommand().getId(); + + if (!applicationContext.containsBean(beanName)) { + if (beanName.startsWith(bundleSymbolicName)) + beanName = beanName + .substring(bundleSymbolicName.length() + 1); + } + + if (!applicationContext.containsBean(beanName)) + throw new ExecutionException("No bean found with name " + + beanName + " in bundle " + bundleSymbolicName); + Object bean = applicationContext.getBean(beanName); + + if (!(bean instanceof IHandler)) + throw new ExecutionException("Bean with name " + beanName + + " and class " + bean.getClass() + + " does not implement the IHandler interface."); + + IHandler handler = (IHandler) bean; + return handler.execute(event); + } catch (Exception e) { + // TODO: use eclipse error management + // log.error(e); + throw new ExecutionException("Cannot execute Spring command " + + commandId + " in bundle " + bundleSymbolicName, e); + } + } + + public boolean isEnabled() { + return true; + } + + public boolean isHandled() { + return true; + } + + public void removeHandlerListener(IHandlerListener handlerListener) { + } + +} diff --git a/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/spring/SpringExtensionFactory.java b/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/spring/SpringExtensionFactory.java new file mode 100644 index 000000000..7a0486fd2 --- /dev/null +++ b/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/spring/SpringExtensionFactory.java @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.spring; + +import org.argeo.ArgeoException; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExecutableExtension; +import org.eclipse.core.runtime.IExecutableExtensionFactory; +import org.eclipse.core.runtime.IExtension; +import org.springframework.context.ApplicationContext; + +/** + * The Spring Extension Factory builds a bridge between the Eclipse Extension + * Registry and the Spring Framework (especially Spring Dynamic Modules). + * + * It allows you to define your extension as a spring bean within the spring + * application context of your bundle. If you would like to use this bean as an + * instance of an extension (an Eclipse RCP view, for example) you define the + * extension with this spring extension factory as the class to be created. + * + * To let the spring extension factory pick the right bean from your application + * context you need to set the bean id to the same value as the id of the view + * within the view definition, for example. This is important if your extension + * definition contains more than one element, where each element has its own id. + * + * If the extension definition elements themselves have no id attribute the + * spring extension factory uses the id of the extension itself to identify the + * bean. + * + * original code from: Blog entry + * + * @author Martin Lippert + * @author mbaudier + */ +public class SpringExtensionFactory implements IExecutableExtensionFactory, + IExecutableExtension { + + private Object bean; + + public Object create() throws CoreException { + if (bean == null) + throw new ArgeoException("No underlying bean for extension"); + return bean; + } + + public void setInitializationData(IConfigurationElement config, + String propertyName, Object data) throws CoreException { + String bundleSymbolicName = config.getContributor().getName(); + ApplicationContext applicationContext = ApplicationContextTracker + .getApplicationContext(bundleSymbolicName); + if (applicationContext == null) + throw new ArgeoException( + "Cannot find application context for bundle " + + bundleSymbolicName); + + String beanName = getBeanName(data, config); + if (beanName == null) + throw new ArgeoException("Cannot find bean name for extension " + + config); + + if (!applicationContext.containsBean(beanName)) { + if (beanName.startsWith(bundleSymbolicName)) + beanName = beanName.substring(bundleSymbolicName.length() + 1); + } + + if (!applicationContext.containsBean(beanName)) + throw new ArgeoException("No bean with name '" + beanName + "'"); + + this.bean = applicationContext.getBean(beanName); + if (this.bean instanceof IExecutableExtension) { + ((IExecutableExtension) this.bean).setInitializationData(config, + propertyName, data); + } + } + + private String getBeanName(Object data, IConfigurationElement config) { + + // try the specific bean id the extension defines + if (data != null && data.toString().length() > 0) { + return data.toString(); + } + + // try the id of the config element + if (config.getAttribute("id") != null) { + return config.getAttribute("id"); + } + + // try the id of the extension element itself + if (config.getParent() != null + && config.getParent() instanceof IExtension) { + IExtension extensionDefinition = (IExtension) config.getParent(); + return extensionDefinition.getSimpleIdentifier(); + } + + return null; + } + +} diff --git a/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/AbstractTreeContentProvider.java b/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/AbstractTreeContentProvider.java new file mode 100644 index 000000000..6b86676b4 --- /dev/null +++ b/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/AbstractTreeContentProvider.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui; + +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.Viewer; + +/** + * Tree content provider dealing with tree objects and providing reasonable + * defaults. + */ +public abstract class AbstractTreeContentProvider implements + ITreeContentProvider { + private static final long serialVersionUID = 8246126401957763868L; + + /** Does nothing */ + public void dispose() { + } + + /** Does nothing */ + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + + public Object[] getChildren(Object element) { + if (element instanceof TreeParent) { + return ((TreeParent) element).getChildren(); + } + return new Object[0]; + } + + public Object getParent(Object element) { + if (element instanceof TreeParent) { + return ((TreeParent) element).getParent(); + } + return null; + } + + public boolean hasChildren(Object element) { + if (element instanceof TreeParent) { + return ((TreeParent) element).hasChildren(); + } + return false; + } + +} diff --git a/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/ArgeoUiPlugin.java b/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/ArgeoUiPlugin.java new file mode 100644 index 000000000..6befdf7d4 --- /dev/null +++ b/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/ArgeoUiPlugin.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.eclipse.core.runtime.ILogListener; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class ArgeoUiPlugin extends AbstractUIPlugin implements ILogListener { + public static final String PLUGIN_ID = "org.argeo.eclipse.ui"; + private final static Log log = LogFactory.getLog(ArgeoUiPlugin.class); + // The shared instance + private static ArgeoUiPlugin plugin; + + public void start(BundleContext context) throws Exception { + super.start(context); + // weirdly, the start method is called twice... + if (plugin == null) { + plugin = this; + Platform.addLogListener(this); + log.debug("Eclipse logging now directed to standard logging"); + } + } + + public void stop(BundleContext context) throws Exception { + try { + // weirdly, the stop method is called twice... + if (plugin != null) { + Platform.removeLogListener(this); + log.debug("Eclipse logging not directed anymore to standard logging"); + plugin = null; + } + } finally { + super.stop(context); + } + } + + /** Returns the shared instance */ + public static ArgeoUiPlugin getDefault() { + return plugin; + } + + public void logging(IStatus status, String plugin) { + Log pluginLog = LogFactory.getLog(plugin); + Integer severity = status.getSeverity(); + if (severity == IStatus.ERROR) + pluginLog.error(status.getMessage(), status.getException()); + else if (severity == IStatus.WARNING) + pluginLog.warn(status.getMessage(), status.getException()); + else if (severity == IStatus.INFO) + pluginLog.info(status.getMessage(), status.getException()); + else if (severity == IStatus.CANCEL) + if (pluginLog.isDebugEnabled()) + pluginLog.debug(status.getMessage(), status.getException()); + + } + +} diff --git a/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/ColumnViewerComparator.java b/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/ColumnViewerComparator.java new file mode 100644 index 000000000..8db5d4fe8 --- /dev/null +++ b/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/ColumnViewerComparator.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui; + +import java.util.Comparator; + +import org.eclipse.jface.viewers.ColumnViewer; +import org.eclipse.jface.viewers.TableViewerColumn; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerComparator; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; + +/** Generic column viewer sorter */ +public class ColumnViewerComparator extends ViewerComparator { + private static final long serialVersionUID = -2266218906355859909L; + + public static final int ASC = 1; + + public static final int NONE = 0; + + public static final int DESC = -1; + + private int direction = 0; + + private TableViewerColumn column; + + private ColumnViewer viewer; + + public ColumnViewerComparator(TableViewerColumn column, + Comparator comparator) { + super(comparator); + this.column = column; + this.viewer = column.getViewer(); + this.column.getColumn().addSelectionListener(new SelectionAdapter() { + private static final long serialVersionUID = 7586796298965472189L; + + public void widgetSelected(SelectionEvent e) { + if (ColumnViewerComparator.this.viewer.getComparator() != null) { + if (ColumnViewerComparator.this.viewer.getComparator() == ColumnViewerComparator.this) { + int tdirection = ColumnViewerComparator.this.direction; + + if (tdirection == ASC) { + setSortDirection(DESC); + } else if (tdirection == DESC) { + setSortDirection(NONE); + } + } else { + setSortDirection(ASC); + } + } else { + setSortDirection(ASC); + } + } + }); + } + + private void setSortDirection(int direction) { + if (direction == NONE) { + column.getColumn().getParent().setSortColumn(null); + column.getColumn().getParent().setSortDirection(SWT.NONE); + viewer.setComparator(null); + } else { + column.getColumn().getParent().setSortColumn(column.getColumn()); + this.direction = direction; + + if (direction == ASC) { + column.getColumn().getParent().setSortDirection(SWT.DOWN); + } else { + column.getColumn().getParent().setSortDirection(SWT.UP); + } + + if (viewer.getComparator() == this) { + viewer.refresh(); + } else { + viewer.setComparator(this); + } + + } + } + + @SuppressWarnings("unchecked") + public int compare(Viewer viewer, Object e1, Object e2) { + return direction * getComparator().compare((T) e1, (T) e2); + } +} diff --git a/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/EclipseArgeoMonitor.java b/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/EclipseArgeoMonitor.java new file mode 100644 index 000000000..7c0b39884 --- /dev/null +++ b/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/EclipseArgeoMonitor.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui; + +import org.argeo.ArgeoMonitor; +import org.eclipse.core.runtime.IProgressMonitor; + +/** + * Wraps an Eclipse {@link IProgressMonitor} so that it can be passed to + * framework agnostic Argeo routines. + */ +public class EclipseArgeoMonitor implements ArgeoMonitor { + private final IProgressMonitor progressMonitor; + + public EclipseArgeoMonitor(IProgressMonitor progressMonitor) { + this.progressMonitor = progressMonitor; + } + + public void beginTask(String name, int totalWork) { + progressMonitor.beginTask(name, totalWork); + } + + public void done() { + progressMonitor.done(); + } + + public boolean isCanceled() { + return progressMonitor.isCanceled(); + } + + public void setCanceled(boolean value) { + progressMonitor.setCanceled(value); + } + + public void setTaskName(String name) { + progressMonitor.setTaskName(name); + } + + public void subTask(String name) { + progressMonitor.subTask(name); + } + + public void worked(int work) { + progressMonitor.worked(work); + } +} diff --git a/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/EclipseUiUtils.java b/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/EclipseUiUtils.java new file mode 100644 index 000000000..8e1c7e632 --- /dev/null +++ b/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/EclipseUiUtils.java @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui; + +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; + +/** Utilities to simplify UI development. */ +public class EclipseUiUtils { + /** + * Create a label and a text field for a grid layout, the text field grabing + * excess horizontal + * + * @param parent + * the parent composite + * @param label + * the lable to display + * @param modifyListener + * a {@link ModifyListener} to listen on events on the text, can + * be null + * @return the created text + * + */ + // FIXME why was this deprecated. + // * @ deprecated use { @ link #createGridLT(Composite, String)} instead + // @ Deprecated + public static Text createGridLT(Composite parent, String label, + ModifyListener modifyListener) { + Label lbl = new Label(parent, SWT.LEAD); + lbl.setText(label); + lbl.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false)); + Text txt = new Text(parent, SWT.LEAD | SWT.BORDER); + txt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + if (modifyListener != null) + txt.addModifyListener(modifyListener); + return txt; + } + + /** + * Create a label and a text field for a grid layout, the text field + * grabbing excess horizontal + */ + public static Text createGridLT(Composite parent, String label) { + return createGridLT(parent, label, null); + } + + /** + * Creates one label and a text field not editable with background color of + * the parent (like a label but with selectable text) + */ + public static Text createGridLL(Composite parent, String label, String text) { + Text txt = createGridLT(parent, label); + txt.setText(text); + txt.setEditable(false); + txt.setBackground(parent.getBackground()); + return txt; + } + + /** + * Create a label and a text field with password display for a grid layout, + * the text field grabbing excess horizontal + */ + public static Text createGridLP(Composite parent, String label, + ModifyListener modifyListener) { + Label lbl = new Label(parent, SWT.LEAD); + lbl.setText(label); + lbl.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false)); + Text txt = new Text(parent, SWT.LEAD | SWT.BORDER | SWT.PASSWORD); + txt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + if (txt != null) + txt.addModifyListener(modifyListener); + return txt; + } + + /** Shortcut to retrieve default italic font from display */ + public static Font getItalicFont(Composite parent) { + return JFaceResources.getFontRegistry().defaultFontDescriptor() + .setStyle(SWT.ITALIC).createFont(parent.getDisplay()); + } + + /** Shortcut to retrieve default bold font from display */ + public static Font getBoldFont(Composite parent) { + return JFaceResources.getFontRegistry().defaultFontDescriptor() + .setStyle(SWT.BOLD).createFont(parent.getDisplay()); + } + + /** Shortcut to retrieve default bold italic font from display */ + public static Font getBoldItalicFont(Composite parent) { + return JFaceResources.getFontRegistry().defaultFontDescriptor() + .setStyle(SWT.BOLD | SWT.ITALIC) + .createFont(parent.getDisplay()); + } +} \ No newline at end of file diff --git a/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/Error.java b/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/Error.java new file mode 100644 index 000000000..03b047001 --- /dev/null +++ b/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/Error.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui; + +import org.eclipse.swt.widgets.Shell; + +/** + * @deprecated deprecated because of poor naming, use {@link ErrorFeedback} + * instead + */ +@SuppressWarnings("serial") +@Deprecated +public class Error extends ErrorFeedback { + + public Error(Shell parentShell, String message, Throwable e) { + super(parentShell, message, e); + // TODO Auto-generated constructor stub + } + +} diff --git a/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/ErrorFeedback.java b/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/ErrorFeedback.java new file mode 100644 index 000000000..895e8b866 --- /dev/null +++ b/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/ErrorFeedback.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui; + +import java.io.PrintWriter; +import java.io.StringWriter; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.eclipse.jface.dialogs.IMessageProvider; +import org.eclipse.jface.dialogs.TitleAreaDialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.PlatformUI; + +/** Generic error dialog to be used in try/catch blocks */ +@SuppressWarnings("serial") +public class ErrorFeedback extends TitleAreaDialog { + private final static Log log = LogFactory.getLog(ErrorFeedback.class); + + private final String message; + private final Throwable exception; + + public static void show(String message, Throwable e) { + // rethrow ThreaDeath in order to make sure that RAP will properly clean + // up the UI thread + if (e instanceof ThreadDeath) + throw (ThreadDeath) e; + + new ErrorFeedback(getDisplay().getActiveShell(), message, e).open(); + } + + public static void show(String message) { + new ErrorFeedback(getDisplay().getActiveShell(), message, null).open(); + } + + /** Tries to find a display */ + private static Display getDisplay() { + try { + Display display = PlatformUI.getWorkbench().getDisplay(); + if (display != null) + return display; + else + return Display.getDefault(); + } catch (Exception e) { + return Display.getCurrent(); + } + } + + public ErrorFeedback(Shell parentShell, String message, Throwable e) { + super(parentShell); + this.message = message; + this.exception = e; + log.error(message, e); + } + + protected Point getInitialSize() { + if (exception != null) + return new Point(800, 600); + else + return new Point(400, 300); + } + + @Override + protected Control createDialogArea(Composite parent) { + Composite dialogarea = (Composite) super.createDialogArea(parent); + dialogarea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + Composite composite = new Composite(dialogarea, SWT.NONE); + composite.setLayout(new GridLayout(2, false)); + composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + + setMessage(message != null ? message + + (exception != null ? ": " + exception.getMessage() : "") + : exception != null ? exception.getMessage() : "Unkown Error", + IMessageProvider.ERROR); + + if (exception != null) { + Text stack = new Text(composite, SWT.MULTI | SWT.LEAD | SWT.BORDER + | SWT.V_SCROLL | SWT.H_SCROLL); + stack.setEditable(false); + stack.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + StringWriter sw = new StringWriter(); + exception.printStackTrace(new PrintWriter(sw)); + stack.setText(sw.toString()); + } + + parent.pack(); + return composite; + } + + protected void configureShell(Shell shell) { + super.configureShell(shell); + shell.setText("Error"); + } +} \ No newline at end of file diff --git a/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/GenericTableComparator.java b/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/GenericTableComparator.java new file mode 100644 index 000000000..a4179cbee --- /dev/null +++ b/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/GenericTableComparator.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui; + +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerComparator; + +public abstract class GenericTableComparator extends ViewerComparator { + private static final long serialVersionUID = -1175894935075325810L; + protected int propertyIndex; + public static final int ASCENDING = 0, DESCENDING = 1; + protected int direction = DESCENDING; + + /** + * Creates an instance of a sorter for TableViewer. + * + * @param defaultColumn + * the default sorter column + */ + + public GenericTableComparator(int defaultColumnIndex, int direction) { + propertyIndex = defaultColumnIndex; + this.direction = direction; + } + + public void setColumn(int column) { + if (column == this.propertyIndex) { + // Same column as last sort; toggle the direction + direction = 1 - direction; + } else { + // New column; do a descending sort + this.propertyIndex = column; + direction = DESCENDING; + } + } + + /** + * Must be Overriden in each view. + */ + public abstract int compare(Viewer viewer, Object e1, Object e2); +} diff --git a/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/TreeParent.java b/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/TreeParent.java new file mode 100644 index 000000000..2dfd2e60c --- /dev/null +++ b/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/TreeParent.java @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui; + +import java.util.ArrayList; +import java.util.List; + +/** Parent / children semantic to be used for simple UI Tree structure */ +public class TreeParent { + private String name; + private TreeParent parent; + + private List children; + + /** + * Unique id within the context of a tree display. If set, equals() and + * hashCode() methods will be based on it + */ + private String path = null; + + /** False until at least one child has been added, then true until cleared */ + private boolean loaded = false; + + public TreeParent(String name) { + this.name = name; + children = new ArrayList(); + } + + public synchronized void addChild(Object child) { + loaded = true; + children.add(child); + if (child instanceof TreeParent) + ((TreeParent) child).setParent(this); + } + + /** + * Remove this child. The child is disposed. + */ + public synchronized void removeChild(Object child) { + children.remove(child); + if (child instanceof TreeParent) { + ((TreeParent) child).dispose(); + } + } + + public synchronized void clearChildren() { + for (Object obj : children) { + if (obj instanceof TreeParent) + ((TreeParent) obj).dispose(); + } + loaded = false; + children.clear(); + } + + /** + * If overridden, super.dispose() must be called, typically + * after custom cleaning. + */ + public synchronized void dispose() { + clearChildren(); + parent = null; + children = null; + } + + public synchronized Object[] getChildren() { + return children.toArray(new Object[children.size()]); + } + + @SuppressWarnings("unchecked") + public synchronized List getChildrenOfType(Class clss) { + List lst = new ArrayList(); + for (Object obj : children) { + if (clss.isAssignableFrom(obj.getClass())) + lst.add((T) obj); + } + return lst; + } + + public synchronized boolean hasChildren() { + return children.size() > 0; + } + + public Object getChildByName(String name) { + for (Object child : children) { + if (child.toString().equals(name)) + return child; + } + return null; + } + + public synchronized Boolean isLoaded() { + return loaded; + } + + public String getName() { + return name; + } + + public void setParent(TreeParent parent) { + this.parent = parent; + if (parent != null && parent.path != null) + this.path = parent.path + '/' + name; + else + this.path = '/' + name; + } + + public TreeParent getParent() { + return parent; + } + + public String toString() { + return getName(); + } + + public int compareTo(TreeParent o) { + return name.compareTo(o.name); + } + + @Override + public int hashCode() { + if (path != null) + return path.hashCode(); + else + return name.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (path != null && obj instanceof TreeParent) + return path.equals(((TreeParent) obj).path); + else + return name.equals(obj.toString()); + } + +} diff --git a/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/dialogs/Error.java b/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/dialogs/Error.java new file mode 100644 index 000000000..918bfd244 --- /dev/null +++ b/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/dialogs/Error.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.dialogs; + +import org.eclipse.swt.widgets.Shell; + +/** + * Generic error dialog to be used in try/catch blocks + * + * @deprecated use {@link org.argeo.eclipse.ui.ErrorFeedback} instead. + */ +public class Error extends org.argeo.eclipse.ui.ErrorFeedback { + private static final long serialVersionUID = -93864960090248736L; + + public Error(Shell parentShell, String message, Throwable e) { + super(parentShell, message, e); + } +} diff --git a/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/dialogs/SingleValue.java b/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/dialogs/SingleValue.java new file mode 100644 index 000000000..b58f44694 --- /dev/null +++ b/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/dialogs/SingleValue.java @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.dialogs; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IMessageProvider; +import org.eclipse.jface.dialogs.TitleAreaDialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +/** Dialog retrieve a single value. */ +public class SingleValue extends TitleAreaDialog { + private static final long serialVersionUID = 2843538207460082349L; + + private Text valueT; + private String value; + private final String title, message, label; + private final Boolean multiline; + + public static String ask(String label, String message) { + SingleValue svd = new SingleValue(label, message); + if (svd.open() == Dialog.OK) + return svd.getString(); + else + return null; + } + + public static Long askLong(String label, String message) { + SingleValue svd = new SingleValue(label, message); + if (svd.open() == Dialog.OK) + return svd.getLong(); + else + return null; + } + + public static Double askDouble(String label, String message) { + SingleValue svd = new SingleValue(label, message); + if (svd.open() == Dialog.OK) + return svd.getDouble(); + else + return null; + } + + public SingleValue(String label, String message) { + this(Display.getDefault().getActiveShell(), label, message, label, + false); + } + + public SingleValue(Shell parentShell, String title, String message, + String label, Boolean multiline) { + super(parentShell); + this.title = title; + this.message = message; + this.label = label; + this.multiline = multiline; + } + + protected Point getInitialSize() { + return new Point(300, 250); + } + + protected Control createDialogArea(Composite parent) { + Composite dialogarea = (Composite) super.createDialogArea(parent); + dialogarea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + Composite composite = new Composite(dialogarea, SWT.NONE); + composite.setLayout(new GridLayout(2, false)); + composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + valueT = createLT(composite, label); + + setMessage(message, IMessageProvider.NONE); + + parent.pack(); + return composite; + } + + @Override + protected void okPressed() { + value = valueT.getText(); + super.okPressed(); + } + + /** Creates label and text. */ + protected Text createLT(Composite parent, String label) { + new Label(parent, SWT.NONE).setText(label); + Text text = new Text(parent, SWT.SINGLE | SWT.LEAD | SWT.BORDER + | (multiline ? SWT.MULTI : SWT.NONE)); + text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + return text; + } + + protected void configureShell(Shell shell) { + super.configureShell(shell); + shell.setText(title); + } + + public String getString() { + return value; + } + + public Long getLong() { + return Long.valueOf(getString()); + } + + public Double getDouble() { + return Double.valueOf(getString()); + } +} diff --git a/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/utils/CommandUtils.java b/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/utils/CommandUtils.java new file mode 100644 index 000000000..22a139f13 --- /dev/null +++ b/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/utils/CommandUtils.java @@ -0,0 +1,238 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.utils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +import org.argeo.ArgeoException; +import org.argeo.eclipse.ui.ArgeoUiPlugin; +import org.eclipse.core.commands.Command; +import org.eclipse.core.commands.IParameter; +import org.eclipse.core.commands.Parameterization; +import org.eclipse.core.commands.ParameterizedCommand; +import org.eclipse.jface.action.IContributionItem; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.swt.SWT; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.commands.ICommandService; +import org.eclipse.ui.handlers.IHandlerService; +import org.eclipse.ui.menus.CommandContributionItem; +import org.eclipse.ui.menus.CommandContributionItemParameter; +import org.eclipse.ui.services.IServiceLocator; + +/** + * Centralises useful and generic methods when dealing with commands in an + * Eclipse Workbench context + */ +public class CommandUtils { + + /** + * Commodities the refresh of a single command with no parameter in a + * Menu.aboutToShow method to simplify further development + * + * Note: that this method should be called with a false show command flag to + * remove a contribution that have been previously contributed + * + * @param menuManager + * @param locator + * @param cmdId + * @param label + * @param icon + * @param showCommand + */ + public static void refreshCommand(IMenuManager menuManager, + IServiceLocator locator, String cmdId, String label, + ImageDescriptor icon, boolean showCommand) { + refreshParameterizedCommand(menuManager, locator, cmdId, label, icon, + showCommand, null); + } + + /** + * Commodities the refresh the contribution of a command with a map of + * parameters in a context menu + * + * The command ID is used has contribution item ID + * + * @param menuManager + * @param locator + * @param cmdId + * @param label + * @param iconPath + * @param showCommand + */ + public static void refreshParameterizedCommand(IMenuManager menuManager, + IServiceLocator locator, String cmdId, String label, + ImageDescriptor icon, boolean showCommand, + Map params) { + refreshParameterizedCommand(menuManager, locator, cmdId, cmdId, label, + icon, showCommand, params); + } + + /** + * Commodities the refresh the contribution of a command with a map of + * parameters in a context menu + * + * @param menuManager + * @param locator + * @param contributionId + * @param commandId + * @param label + * @param icon + * @param showCommand + * @param params + */ + public static void refreshParameterizedCommand(IMenuManager menuManager, + IServiceLocator locator, String contributionId, String commandId, + String label, ImageDescriptor icon, boolean showCommand, + Map params) { + IContributionItem ici = menuManager.find(contributionId); + if (ici != null) + menuManager.remove(ici); + if (showCommand) { + CommandContributionItemParameter contributionItemParameter = new CommandContributionItemParameter( + locator, null, commandId, SWT.PUSH); + + // Set Params + contributionItemParameter.label = label; + contributionItemParameter.icon = icon; + + if (params != null) + contributionItemParameter.parameters = params; + + CommandContributionItem cci = new CommandContributionItem( + contributionItemParameter); + cci.setId(contributionId); + menuManager.add(cci); + } + } + + /** Helper to call a command without parameter easily */ + public static void callCommand(String commandID) { + callCommand(commandID, null); + } + + /** Helper to call a command with a single parameter easily */ + public static void callCommand(String commandID, String parameterID, + String parameterValue) { + Map params = new HashMap(); + params.put(parameterID, parameterValue); + callCommand(commandID, params); + } + + /** + * Helper to call a command with a map of parameters easily + * + * @param paramMap + * a map that links various command IDs with corresponding String + * values. + */ + public static void callCommand(String commandID, + Map paramMap) { + try { + IWorkbench iw = ArgeoUiPlugin.getDefault().getWorkbench(); + IHandlerService handlerService = (IHandlerService) iw + .getService(IHandlerService.class); + ICommandService cmdService = (ICommandService) iw + .getActiveWorkbenchWindow().getService( + ICommandService.class); + Command cmd = cmdService.getCommand(commandID); + + ArrayList parameters = null; + ParameterizedCommand pc; + + if (paramMap != null) { + // Set parameters of the command to launch : + parameters = new ArrayList(); + Parameterization parameterization; + + for (String id : paramMap.keySet()) { + parameterization = new Parameterization( + cmd.getParameter(id), paramMap.get(id)); + parameters.add(parameterization); + } + pc = new ParameterizedCommand(cmd, + parameters.toArray(new Parameterization[parameters + .size()])); + } else + pc = new ParameterizedCommand(cmd, null); + + // execute the command + handlerService.executeCommand(pc, null); + } catch (Exception e) { + throw new ArgeoException("Unexpected error while" + + " calling the command " + commandID, e); + } + } + + // legacy methods. Should be removed soon + + /** + * Shortcut to call a command with a single parameter. + * + * WARNING: none of the parameter can be null + * + * @deprecated rather use callCommand(commandID,parameterID, + parameterValue) + */ + public static void CallCommandWithOneParameter(String commandId, + String paramId, String paramValue) { + try { + IWorkbench iw = ArgeoUiPlugin.getDefault().getWorkbench(); + IHandlerService handlerService = (IHandlerService) iw + .getService(IHandlerService.class); + + // Gets a command that must have been previously registered + IWorkbenchWindow window = iw.getActiveWorkbenchWindow(); + ICommandService cmdService = (ICommandService) window + .getService(ICommandService.class); + Command cmd = cmdService.getCommand(commandId); + + // Manages the single parameter + ArrayList parameters = new ArrayList(); + IParameter iparam = cmd.getParameter(paramId); + Parameterization params = new Parameterization(iparam, paramValue); + parameters.add(params); + + // Create and execute the command + ParameterizedCommand pc = new ParameterizedCommand(cmd, + parameters.toArray(new Parameterization[parameters.size()])); + handlerService = (IHandlerService) window + .getService(IHandlerService.class); + handlerService.executeCommand(pc, null); + } catch (Exception e) { + throw new ArgeoException( + "Error calling command of id:" + commandId, e); + } + } + + /** + * Commodities the refresh of a single command with a map of parameters in a + * Menu.aboutToShow method to simplify further development Rather use + * {@link refreshParameterizedCommand()} + */ + @Deprecated + public static void refreshParametrizedCommand(IMenuManager menuManager, + IServiceLocator locator, String cmdId, String label, + ImageDescriptor icon, boolean showCommand, + Map params) { + refreshParameterizedCommand(menuManager, locator, cmdId, label, icon, + showCommand, params); + } +} \ No newline at end of file diff --git a/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/utils/ViewerUtils.java b/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/utils/ViewerUtils.java new file mode 100644 index 000000000..42e9fab99 --- /dev/null +++ b/org.argeo.eclipse.ui/src/main/java/org/argeo/eclipse/ui/utils/ViewerUtils.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.eclipse.ui.utils; + +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TableViewerColumn; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.TreeViewerColumn; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.TreeColumn; + +/** + * Centralizes useful methods to manage Jface Table, Tree and TreeColumn + * viewers. + */ +public class ViewerUtils { + + /** + * Creates a basic column for the given table. For the time being, we do not + * support moveable columns. + */ + public static TableColumn createColumn(Table parent, String name, + int style, int width) { + TableColumn result = new TableColumn(parent, style); + result.setText(name); + result.setWidth(width); + result.setResizable(true); + return result; + } + + /** + * Creates a TableViewerColumn for the given viewer. For the time being, we + * do not support moveable columns. + */ + public static TableViewerColumn createTableViewerColumn(TableViewer parent, + String name, int style, int width) { + TableViewerColumn tvc = new TableViewerColumn(parent, style); + final TableColumn column = tvc.getColumn(); + column.setText(name); + column.setWidth(width); + column.setResizable(true); + return tvc; + } + + /** + * Creates a TreeViewerColumn for the given viewer. For the time being, we + * do not support moveable columns. + */ + public static TreeViewerColumn createTreeViewerColumn(TreeViewer parent, + String name, int style, int width) { + TreeViewerColumn tvc = new TreeViewerColumn(parent, style); + final TreeColumn column = tvc.getColumn(); + column.setText(name); + column.setWidth(width); + column.setResizable(true); + return tvc; + } +} diff --git a/org.argeo.ext.jdbm/.project b/org.argeo.ext.jdbm/.project new file mode 100644 index 000000000..b1d7029b9 --- /dev/null +++ b/org.argeo.ext.jdbm/.project @@ -0,0 +1,22 @@ + + + org.argeo.ext.jdbm + + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + + diff --git a/org.argeo.ext.jdbm/build.properties b/org.argeo.ext.jdbm/build.properties new file mode 100644 index 000000000..5f22cdd44 --- /dev/null +++ b/org.argeo.ext.jdbm/build.properties @@ -0,0 +1 @@ +bin.includes = META-INF/ diff --git a/org.argeo.ext.jdbm/pom.xml b/org.argeo.ext.jdbm/pom.xml new file mode 100644 index 000000000..4c1c02f33 --- /dev/null +++ b/org.argeo.ext.jdbm/pom.xml @@ -0,0 +1,32 @@ + + 4.0.0 + + org.argeo.commons + 2.1.12-SNAPSHOT + argeo-commons + .. + + org.argeo.ext.jdbm + Commons Server JDBM Extension + Add Apache Directory Server support to JDBM + + + + org.apache.felix + maven-bundle-plugin + + + jdbm + + org.apache.directory.server.core.partition.impl.btree.jdbm;resolution:=optional, + org.apache.directory.server.core.schema;resolution:=optional, + org.apache.directory.server.core.partition.impl;resolution:=optional, + org.apache.directory.server.core.partition.impl.btree;resolution:=optional, + org.apache.directory.shared.ldap.message;resolution:=optional, + + + + + + + \ No newline at end of file diff --git a/org.argeo.jackrabbit.webapp/.project b/org.argeo.jackrabbit.webapp/.project new file mode 100644 index 000000000..37eed0584 --- /dev/null +++ b/org.argeo.jackrabbit.webapp/.project @@ -0,0 +1,22 @@ + + + org.argeo.jackrabbit.webapp + + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + + diff --git a/org.argeo.jackrabbit.webapp/.settings/org.eclipse.pde.core.prefs b/org.argeo.jackrabbit.webapp/.settings/org.eclipse.pde.core.prefs new file mode 100644 index 000000000..ee0c8b2c0 --- /dev/null +++ b/org.argeo.jackrabbit.webapp/.settings/org.eclipse.pde.core.prefs @@ -0,0 +1,4 @@ +#Tue Feb 22 17:15:24 CET 2011 +eclipse.preferences.version=1 +pluginProject.extensions=false +resolve.requirebundle=false diff --git a/org.argeo.jackrabbit.webapp/WEB-INF/applicationContext.xml b/org.argeo.jackrabbit.webapp/WEB-INF/applicationContext.xml new file mode 100644 index 000000000..723e6c70f --- /dev/null +++ b/org.argeo.jackrabbit.webapp/WEB-INF/applicationContext.xml @@ -0,0 +1,34 @@ + + + + + + + + + + osgibundle:jackrabbit-webapp.properties + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.jackrabbit.webapp/WEB-INF/osgi.xml b/org.argeo.jackrabbit.webapp/WEB-INF/osgi.xml new file mode 100644 index 000000000..b4a3c48df --- /dev/null +++ b/org.argeo.jackrabbit.webapp/WEB-INF/osgi.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.jackrabbit.webapp/WEB-INF/remoting-servlet.xml b/org.argeo.jackrabbit.webapp/WEB-INF/remoting-servlet.xml new file mode 100644 index 000000000..f5cd4d609 --- /dev/null +++ b/org.argeo.jackrabbit.webapp/WEB-INF/remoting-servlet.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.jackrabbit.webapp/WEB-INF/security-filters.xml b/org.argeo.jackrabbit.webapp/WEB-INF/security-filters.xml new file mode 100644 index 000000000..52238a7de --- /dev/null +++ b/org.argeo.jackrabbit.webapp/WEB-INF/security-filters.xml @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PATTERN_TYPE_APACHE_ANT + /**=ROLE_USER,ROLE_ADMIN + + + + + + + PATTERN_TYPE_APACHE_ANT + /**=IS_AUTHENTICATED_ANONYMOUSLY + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${argeo.server.realmName} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.jackrabbit.webapp/WEB-INF/web.xml b/org.argeo.jackrabbit.webapp/WEB-INF/web.xml new file mode 100644 index 000000000..a1876b306 --- /dev/null +++ b/org.argeo.jackrabbit.webapp/WEB-INF/web.xml @@ -0,0 +1,111 @@ + + + + Argeo Jackrabbit Webapp + + + + 5 + + + + + contextConfigLocation + /WEB-INF/applicationContext.xml + + + + Spring Context + org.springframework.web.context.ContextLoaderListener + + + contextClass + org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext + + + + + remoting + org.argeo.jackrabbit.remote.ExtendedDispatcherServlet + + contextClass + org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext + + + dispatchOptionsRequest + true + + 1 + + + + remoting + /jcr/* + + + + remoting + /pub/* + + + + + webdav + org.argeo.jackrabbit.remote.ExtendedDispatcherServlet + + contextClass + org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext + + + dispatchOptionsRequest + true + + 1 + + + + webdav + /files/* + + + + webdav + /public/* + + + + + filterChain.davex + org.springframework.web.filter.DelegatingFilterProxy + + + filterChain.davex + /jcr/* + + + + filterChain.private + org.springframework.web.filter.DelegatingFilterProxy + + + filterChain.private + /files/* + + + + filterChain.public + org.springframework.web.filter.DelegatingFilterProxy + + + filterChain.public + /pub/* + + + filterChain.public + /public/* + + + diff --git a/org.argeo.jackrabbit.webapp/WEB-INF/webdav-config.xml b/org.argeo.jackrabbit.webapp/WEB-INF/webdav-config.xml new file mode 100644 index 000000000..da4e18b11 --- /dev/null +++ b/org.argeo.jackrabbit.webapp/WEB-INF/webdav-config.xml @@ -0,0 +1,197 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + nt:file + nt:resource + + + + + + + + + + + + + rep + jcr + + + + + + + diff --git a/org.argeo.jackrabbit.webapp/WEB-INF/webdav-servlet.xml b/org.argeo.jackrabbit.webapp/WEB-INF/webdav-servlet.xml new file mode 100644 index 000000000..561d20c03 --- /dev/null +++ b/org.argeo.jackrabbit.webapp/WEB-INF/webdav-servlet.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.jackrabbit.webapp/build.properties b/org.argeo.jackrabbit.webapp/build.properties new file mode 100644 index 000000000..5f22cdd44 --- /dev/null +++ b/org.argeo.jackrabbit.webapp/build.properties @@ -0,0 +1 @@ +bin.includes = META-INF/ diff --git a/org.argeo.jackrabbit.webapp/jackrabbit-webapp.properties b/org.argeo.jackrabbit.webapp/jackrabbit-webapp.properties new file mode 100644 index 000000000..47f47b93b --- /dev/null +++ b/org.argeo.jackrabbit.webapp/jackrabbit-webapp.properties @@ -0,0 +1,3 @@ +argeo.security.systemKey=argeo +argeo.server.realmName=Argeo +argeo.jcr.webapp.rememberMeValidity=3600 \ No newline at end of file diff --git a/org.argeo.jackrabbit.webapp/pom.xml b/org.argeo.jackrabbit.webapp/pom.xml new file mode 100644 index 000000000..38db5a180 --- /dev/null +++ b/org.argeo.jackrabbit.webapp/pom.xml @@ -0,0 +1,61 @@ + + 4.0.0 + + org.argeo.commons + 2.1.12-SNAPSHOT + argeo-commons + .. + + org.argeo.jackrabbit.webapp + Commons Server Jackrabbit Webapp + JCR remoting, WebDav + + + + org.apache.felix + maven-bundle-plugin + + + data + + + *, + javax.jcr, + javax.servlet, + javax.servlet.http, + javax.servlet.resources, + org.aopalliance.aop, + org.argeo.jackrabbit.remote, + org.argeo.jcr, + org.argeo.jcr.mvc, + org.springframework.aop, + org.springframework.aop.framework, + org.springframework.aop.scope, + org.springframework.beans.factory.config, + org.springframework.osgi.web.context.support, + org.springframework.security, + org.springframework.security.providers.anonymous, + org.springframework.security.ui, + org.springframework.security.ui.webapp, + org.springframework.security.ui.preauth.x509, + org.springframework.security.userdetails, + org.springframework.web.context, + org.springframework.web.filter, + org.springframework.web.servlet, + org.springframework.web.servlet.handler, + org.springframework.web.servlet.view, + org.springframework.security.util, + org.springframework.security.context, + org.springframework.security.ui.basicauth, + org.springframework.security.intercept.web, + org.springframework.security.vote, + org.springframework.security.ui.logout, + org.apache.jackrabbit.server, + + + + + + + \ No newline at end of file diff --git a/org.argeo.jcr.ui.explorer/.classpath b/org.argeo.jcr.ui.explorer/.classpath new file mode 100644 index 000000000..527d8abab --- /dev/null +++ b/org.argeo.jcr.ui.explorer/.classpath @@ -0,0 +1,8 @@ + + + + + >> + + + diff --git a/org.argeo.jcr.ui.explorer/.project b/org.argeo.jcr.ui.explorer/.project new file mode 100644 index 000000000..162cd6b8b --- /dev/null +++ b/org.argeo.jcr.ui.explorer/.project @@ -0,0 +1,28 @@ + + + org.argeo.jcr.ui.explorer + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/org.argeo.jcr.ui.explorer/.settings/org.eclipse.jdt.core.prefs b/org.argeo.jcr.ui.explorer/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..992c5d722 --- /dev/null +++ b/org.argeo.jcr.ui.explorer/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +#Thu Feb 24 08:49:06 CET 2011 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.5 diff --git a/org.argeo.jcr.ui.explorer/META-INF/spring/commands.xml b/org.argeo.jcr.ui.explorer/META-INF/spring/commands.xml new file mode 100644 index 000000000..ef9f3f1d4 --- /dev/null +++ b/org.argeo.jcr.ui.explorer/META-INF/spring/commands.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.argeo.jcr.ui.explorer/META-INF/spring/editors.xml b/org.argeo.jcr.ui.explorer/META-INF/spring/editors.xml new file mode 100644 index 000000000..fc86ceef7 --- /dev/null +++ b/org.argeo.jcr.ui.explorer/META-INF/spring/editors.xml @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/org.argeo.jcr.ui.explorer/META-INF/spring/jcr.xml b/org.argeo.jcr.ui.explorer/META-INF/spring/jcr.xml new file mode 100644 index 000000000..e074154ed --- /dev/null +++ b/org.argeo.jcr.ui.explorer/META-INF/spring/jcr.xml @@ -0,0 +1,10 @@ + + + + + + diff --git a/org.argeo.jcr.ui.explorer/META-INF/spring/osgi.xml b/org.argeo.jcr.ui.explorer/META-INF/spring/osgi.xml new file mode 100644 index 000000000..255462be4 --- /dev/null +++ b/org.argeo.jcr.ui.explorer/META-INF/spring/osgi.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.jcr.ui.explorer/META-INF/spring/views.xml b/org.argeo.jcr.ui.explorer/META-INF/spring/views.xml new file mode 100644 index 000000000..14f1943d7 --- /dev/null +++ b/org.argeo.jcr.ui.explorer/META-INF/spring/views.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/org.argeo.jcr.ui.explorer/build.properties b/org.argeo.jcr.ui.explorer/build.properties new file mode 100644 index 000000000..9b0c715ca --- /dev/null +++ b/org.argeo.jcr.ui.explorer/build.properties @@ -0,0 +1,7 @@ +source.. = src/main/java/,\ + src/main/resources +output.. = target/classes/ +bin.includes = META-INF/,\ + .,\ + plugin.xml,\ + plugin.properties diff --git a/org.argeo.jcr.ui.explorer/icons/add.gif b/org.argeo.jcr.ui.explorer/icons/add.gif new file mode 100644 index 000000000..252d7ebcb Binary files /dev/null and b/org.argeo.jcr.ui.explorer/icons/add.gif differ diff --git a/org.argeo.jcr.ui.explorer/icons/addFolder.gif b/org.argeo.jcr.ui.explorer/icons/addFolder.gif new file mode 100755 index 000000000..d3f43d977 Binary files /dev/null and b/org.argeo.jcr.ui.explorer/icons/addFolder.gif differ diff --git a/org.argeo.jcr.ui.explorer/icons/addPrivileges.png b/org.argeo.jcr.ui.explorer/icons/addPrivileges.png new file mode 100644 index 000000000..a6b251fc8 Binary files /dev/null and b/org.argeo.jcr.ui.explorer/icons/addPrivileges.png differ diff --git a/org.argeo.jcr.ui.explorer/icons/addRepo.gif b/org.argeo.jcr.ui.explorer/icons/addRepo.gif new file mode 100755 index 000000000..26d81c065 Binary files /dev/null and b/org.argeo.jcr.ui.explorer/icons/addRepo.gif differ diff --git a/org.argeo.jcr.ui.explorer/icons/addWorkspace.png b/org.argeo.jcr.ui.explorer/icons/addWorkspace.png new file mode 100644 index 000000000..bbee7755f Binary files /dev/null and b/org.argeo.jcr.ui.explorer/icons/addWorkspace.png differ diff --git a/org.argeo.jcr.ui.explorer/icons/browser.gif b/org.argeo.jcr.ui.explorer/icons/browser.gif new file mode 100644 index 000000000..6c7320c69 Binary files /dev/null and b/org.argeo.jcr.ui.explorer/icons/browser.gif differ diff --git a/org.argeo.jcr.ui.explorer/icons/dumpNode.gif b/org.argeo.jcr.ui.explorer/icons/dumpNode.gif new file mode 100644 index 000000000..14eb1be09 Binary files /dev/null and b/org.argeo.jcr.ui.explorer/icons/dumpNode.gif differ diff --git a/org.argeo.jcr.ui.explorer/icons/getSize.gif b/org.argeo.jcr.ui.explorer/icons/getSize.gif new file mode 100755 index 000000000..b05bf3e3d Binary files /dev/null and b/org.argeo.jcr.ui.explorer/icons/getSize.gif differ diff --git a/org.argeo.jcr.ui.explorer/icons/import_fs.png b/org.argeo.jcr.ui.explorer/icons/import_fs.png new file mode 100644 index 000000000..d7c890c81 Binary files /dev/null and b/org.argeo.jcr.ui.explorer/icons/import_fs.png differ diff --git a/org.argeo.jcr.ui.explorer/icons/nodes.gif b/org.argeo.jcr.ui.explorer/icons/nodes.gif new file mode 100644 index 000000000..bba3dbc69 Binary files /dev/null and b/org.argeo.jcr.ui.explorer/icons/nodes.gif differ diff --git a/org.argeo.jcr.ui.explorer/icons/query.png b/org.argeo.jcr.ui.explorer/icons/query.png new file mode 100644 index 000000000..54c089de1 Binary files /dev/null and b/org.argeo.jcr.ui.explorer/icons/query.png differ diff --git a/org.argeo.jcr.ui.explorer/icons/refresh.png b/org.argeo.jcr.ui.explorer/icons/refresh.png new file mode 100644 index 000000000..a3884fb48 Binary files /dev/null and b/org.argeo.jcr.ui.explorer/icons/refresh.png differ diff --git a/org.argeo.jcr.ui.explorer/icons/remove.gif b/org.argeo.jcr.ui.explorer/icons/remove.gif new file mode 100644 index 000000000..0ae6decd0 Binary files /dev/null and b/org.argeo.jcr.ui.explorer/icons/remove.gif differ diff --git a/org.argeo.jcr.ui.explorer/icons/repositories.gif b/org.argeo.jcr.ui.explorer/icons/repositories.gif new file mode 100644 index 000000000..c13bea1ca Binary files /dev/null and b/org.argeo.jcr.ui.explorer/icons/repositories.gif differ diff --git a/org.argeo.jcr.ui.explorer/icons/sort.gif b/org.argeo.jcr.ui.explorer/icons/sort.gif new file mode 100644 index 000000000..23c5d0b11 Binary files /dev/null and b/org.argeo.jcr.ui.explorer/icons/sort.gif differ diff --git a/org.argeo.jcr.ui.explorer/plugin.properties b/org.argeo.jcr.ui.explorer/plugin.properties new file mode 100644 index 000000000..6dff863e6 --- /dev/null +++ b/org.argeo.jcr.ui.explorer/plugin.properties @@ -0,0 +1,2 @@ +## commands label +addNewFolderCmdLbl=Add folder \ No newline at end of file diff --git a/org.argeo.jcr.ui.explorer/plugin.xml b/org.argeo.jcr.ui.explorer/plugin.xml new file mode 100644 index 000000000..67b87515f --- /dev/null +++ b/org.argeo.jcr.ui.explorer/plugin.xml @@ -0,0 +1,360 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.jcr.ui.explorer/pom.xml b/org.argeo.jcr.ui.explorer/pom.xml new file mode 100644 index 000000000..d84d699a6 --- /dev/null +++ b/org.argeo.jcr.ui.explorer/pom.xml @@ -0,0 +1,63 @@ + + 4.0.0 + + org.argeo.commons + 2.1.12-SNAPSHOT + argeo-commons + .. + + org.argeo.jcr.ui.explorer + Commons JCR Explorer + + + + org.apache.felix + maven-bundle-plugin + + + ${project.artifactId};singleton:=true + lazy + plugin + org.argeo.jcr.ui.explorer.JcrExplorerPlugin + org.eclipse.ui;resolution:=optional, + org.eclipse.core.runtime;resolution:=optional, + org.eclipse.rap.ui;resolution:=optional, + org.eclipse.rap.ui.workbench;resolution:=optional + + *, + org.argeo.eclipse.spring, + + org.argeo.jcr.ui.explorer.* + + + + + + + + org.argeo.commons + org.argeo.util + 2.1.12-SNAPSHOT + + + org.argeo.commons + org.argeo.eclipse.ui.jcr + 2.1.12-SNAPSHOT + + + + + org.argeo.commons + org.argeo.eclipse.dep.rcp + 2.1.12-SNAPSHOT + provided + + + org.argeo.commons + org.argeo.eclipse.ui.rcp + 2.1.12-SNAPSHOT + provided + + + diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerConstants.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerConstants.java new file mode 100644 index 000000000..a9cb25841 --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerConstants.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer; + +/** Constants used across the application. */ +public interface JcrExplorerConstants { + /* + * MISCEALLENEOUS + */ + public final static String DATE_TIME_FORMAT = "dd/MM/yyyy, HH:mm"; + + public final static String PARAM_PATH = "org.argeo.jcr.ui.explorer.nodePath"; + +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerPerspective.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerPerspective.java new file mode 100644 index 000000000..2626415fc --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerPerspective.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer; + +import org.eclipse.ui.IFolderLayout; +import org.eclipse.ui.IPageLayout; +import org.eclipse.ui.IPerspectiveFactory; + +/** Base perspective for JcrExplorer browser */ +public class JcrExplorerPerspective implements IPerspectiveFactory { + public static String BROWSER_VIEW_ID = JcrExplorerPlugin.ID + + ".browserView"; + + public void createInitialLayout(IPageLayout layout) { + layout.setEditorAreaVisible(true); + + IFolderLayout upperLeft = layout.createFolder(JcrExplorerPlugin.ID + + ".upperLeft", IPageLayout.LEFT, 0.4f, layout.getEditorArea()); + upperLeft.addView(BROWSER_VIEW_ID); + +// String editorArea = layout.getEditorArea(); +// String logViewId = "org.argeo.security.ui.logView"; +// IFolderLayout bottom = layout.createFolder("bottom", +// IPageLayout.BOTTOM, 0.50f, editorArea); +// bottom.addView(logViewId); + } + +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerPlugin.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerPlugin.java new file mode 100644 index 000000000..3bf9e7f7d --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerPlugin.java @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer; + +import java.util.ResourceBundle; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class JcrExplorerPlugin extends AbstractUIPlugin { + private final static Log log = LogFactory.getLog(JcrExplorerPlugin.class); + private ResourceBundle messages; + + // The plug-in ID + public static final String ID = "org.argeo.jcr.ui.explorer"; //$NON-NLS-1$ + + // The shared instance + private static JcrExplorerPlugin plugin; + + /** + * The constructor + */ + public JcrExplorerPlugin() { + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext + * ) + */ + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + messages = ResourceBundle + .getBundle("org.argeo.jcr.ui.explorer.messages"); + + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext + * ) + */ + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static JcrExplorerPlugin getDefault() { + return plugin; + } + + public static ImageDescriptor getImageDescriptor(String path) { + return imageDescriptorFromPlugin(ID, path); + } + + /** Returns the internationalized label for the given key */ + public static String getMessage(String key) { + try { + return getDefault().messages.getString(key); + } catch (NullPointerException npe) { + log.warn(key + " not found."); + return key; + } + } + + /** + * Gives access to the internationalization message bundle. Returns null in + * case the ClientUiPlugin is not started (for JUnit tests, by instance) + */ + public static ResourceBundle getMessagesBundle() { + if (getDefault() != null) + // To avoid NPE + return getDefault().messages; + else + return null; + } + +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerView.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerView.java new file mode 100644 index 000000000..01a957a96 --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerView.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer; + +import org.argeo.jcr.ui.explorer.views.GenericJcrBrowser; + +public class JcrExplorerView extends GenericJcrBrowser { + +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/browser/NodeContentProvider.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/browser/NodeContentProvider.java new file mode 100644 index 000000000..fb6bd1a15 --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/browser/NodeContentProvider.java @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.browser; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.RepositoryFactory; +import javax.jcr.Session; +import javax.jcr.nodetype.NodeType; + +import org.argeo.eclipse.ui.TreeParent; +import org.argeo.jcr.ArgeoJcrConstants; +import org.argeo.jcr.RepositoryRegister; +import org.argeo.jcr.UserJcrUtils; +import org.argeo.jcr.ui.explorer.model.RepositoriesElem; +import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem; +import org.argeo.util.security.Keyring; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.Viewer; + +/** + * Implementation of the {@code ITreeContentProvider} to display multiple + * repository environment in a tree like structure + * + */ +public class NodeContentProvider implements ITreeContentProvider { + final private RepositoryRegister repositoryRegister; + final private RepositoryFactory repositoryFactory; + /** + * A session of the logged in user on the default workspace of the node + * repository. + */ + final private Session userSession; + final private Keyring keyring; + private boolean sortChildren; + + // reference for cleaning + private SingleJcrNodeElem homeNode = null; + private RepositoriesElem repositoriesNode = null; + + // Utils + private TreeBrowserComparator itemComparator = new TreeBrowserComparator(); + + public NodeContentProvider(Session userSession, Keyring keyring, + RepositoryRegister repositoryRegister, + RepositoryFactory repositoryFactory, Boolean sortChildren) { + this.userSession = userSession; + this.keyring = keyring; + this.repositoryRegister = repositoryRegister; + this.repositoryFactory = repositoryFactory; + this.sortChildren = sortChildren; + } + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + if (newInput == null)// dispose + return; + + if (userSession != null) { + Node userHome = UserJcrUtils.getUserHome(userSession); + if (userHome != null) { + // TODO : find a way to dynamically get alias for the node + if (homeNode != null) + homeNode.dispose(); + homeNode = new SingleJcrNodeElem(null, userHome, + userSession.getUserID(), ArgeoJcrConstants.ALIAS_NODE); + } + } + if (repositoryRegister != null) { + if (repositoriesNode != null) + repositoriesNode.dispose(); + repositoriesNode = new RepositoriesElem("Repositories", + repositoryRegister, repositoryFactory, null, userSession, + keyring); + } + } + + /** + * Sends back the first level of the Tree. Independent from inputElement + * that can be null + */ + public Object[] getElements(Object inputElement) { + List objs = new ArrayList(); + if (homeNode != null) + objs.add(homeNode); + if (repositoriesNode != null) + objs.add(repositoriesNode); + return objs.toArray(); + } + + public Object[] getChildren(Object parentElement) { + if (parentElement instanceof TreeParent) { + if (sortChildren) { + // TreeParent[] arr = (TreeParent[]) ((TreeParent) + // parentElement) + // .getChildren(); + Object[] tmpArr = ((TreeParent) parentElement).getChildren(); + TreeParent[] arr = new TreeParent[tmpArr.length]; + for (int i = 0; i < tmpArr.length; i++) + arr[i] = (TreeParent) tmpArr[i]; + + Arrays.sort(arr, itemComparator); + return arr; + } else + return ((TreeParent) parentElement).getChildren(); + + } else { + return new Object[0]; + } + } + + /** + * Sets whether the content provider should order the children nodes or not. + * It is user duty to call a full refresh of the tree after changing this + * parameter. + */ + public void setSortChildren(boolean sortChildren) { + this.sortChildren = sortChildren; + } + + public Object getParent(Object element) { + if (element instanceof TreeParent) { + return ((TreeParent) element).getParent(); + } else + return null; + } + + public boolean hasChildren(Object element) { + if (element instanceof RepositoriesElem) { + RepositoryRegister rr = ((RepositoriesElem) element) + .getRepositoryRegister(); + return rr.getRepositories().size() > 0; + } else if (element instanceof TreeParent) { + TreeParent tp = (TreeParent) element; + return tp.hasChildren(); + } + return false; + } + + public void dispose() { + if (homeNode != null) + homeNode.dispose(); + if (repositoriesNode != null) { + // logs out open sessions + // see https://bugzilla.argeo.org/show_bug.cgi?id=23 + repositoriesNode.dispose(); + } + } + + /** + * Specific comparator for this view. See spec in BUG : + * https://www.argeo.org/bugzilla/show_bug.cgi?id=139 + */ + private class TreeBrowserComparator implements Comparator { + + public int category(TreeParent element) { + if (element instanceof SingleJcrNodeElem) { + Node node = ((SingleJcrNodeElem) element).getNode(); + try { + if (node.isNodeType(NodeType.NT_FOLDER)) + return 5; + } catch (RepositoryException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + return 10; + } + + public int compare(TreeParent o1, TreeParent o2) { + int cat1 = category(o1); + int cat2 = category(o2); + + if (cat1 != cat2) { + return cat1 - cat2; + } + return o1.getName().compareTo(o2.getName()); + } + } +} \ No newline at end of file diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/browser/NodeLabelProvider.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/browser/NodeLabelProvider.java new file mode 100644 index 000000000..d6d593ce8 --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/browser/NodeLabelProvider.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.browser; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.nodetype.NodeType; + +import org.argeo.ArgeoException; +import org.argeo.eclipse.ui.jcr.DefaultNodeLabelProvider; +import org.argeo.eclipse.ui.jcr.JcrImages; +import org.argeo.jcr.ui.explorer.model.RemoteRepositoryElem; +import org.argeo.jcr.ui.explorer.model.RepositoriesElem; +import org.argeo.jcr.ui.explorer.model.RepositoryElem; +import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem; +import org.argeo.jcr.ui.explorer.model.WorkspaceElem; +import org.eclipse.swt.graphics.Image; + +public class NodeLabelProvider extends DefaultNodeLabelProvider { + // Images + + public String getText(Object element) { + try { + if (element instanceof SingleJcrNodeElem) { + SingleJcrNodeElem sjn = (SingleJcrNodeElem) element; + return getText(sjn.getNode()); + } else + return super.getText(element); + } catch (RepositoryException e) { + throw new ArgeoException( + "Unexpected JCR error while getting node name."); + } + } + + protected String getText(Node node) throws RepositoryException { + String label = node.getName(); + StringBuffer mixins = new StringBuffer(""); + for (NodeType type : node.getMixinNodeTypes()) + mixins.append(' ').append(type.getName()); + + return label + " [" + node.getPrimaryNodeType().getName() + mixins + + "]"; + } + + @Override + public Image getImage(Object element) { + if (element instanceof RemoteRepositoryElem) { + if (((RemoteRepositoryElem) element).isConnected()) + return JcrImages.REMOTE_CONNECTED; + else + return JcrImages.REMOTE_DISCONNECTED; + } else if (element instanceof RepositoryElem) { + if (((RepositoryElem) element).isConnected()) + return JcrImages.REPOSITORY_CONNECTED; + else + return JcrImages.REPOSITORY_DISCONNECTED; + } else if (element instanceof WorkspaceElem) { + if (((WorkspaceElem) element).isConnected()) + return JcrImages.WORKSPACE_CONNECTED; + else + return JcrImages.WORKSPACE_DISCONNECTED; + } else if (element instanceof RepositoriesElem) { + return JcrImages.REPOSITORIES; + } else if (element instanceof SingleJcrNodeElem) + try { + return super.getImage(((SingleJcrNodeElem) element).getNode()); + } catch (RepositoryException e) { + return null; + } + return super.getImage(element); + } + +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/browser/PropertiesContentProvider.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/browser/PropertiesContentProvider.java new file mode 100644 index 000000000..d39f3195e --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/browser/PropertiesContentProvider.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.browser; + +import java.util.Set; +import java.util.TreeSet; + +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.PropertyIterator; +import javax.jcr.RepositoryException; + +import org.argeo.ArgeoException; +import org.argeo.eclipse.ui.jcr.utils.JcrItemsComparator; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.Viewer; + +public class PropertiesContentProvider implements IStructuredContentProvider { + private JcrItemsComparator itemComparator = new JcrItemsComparator(); + + public void dispose() { + } + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + + public Object[] getElements(Object inputElement) { + try { + if (inputElement instanceof Node) { + Set props = new TreeSet(itemComparator); + PropertyIterator pit = ((Node) inputElement).getProperties(); + while (pit.hasNext()) + props.add(pit.nextProperty()); + return props.toArray(); + } + return new Object[] {}; + } catch (RepositoryException e) { + throw new ArgeoException("Cannot get element for " + inputElement, + e); + } + } + +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/AddFolderNode.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/AddFolderNode.java new file mode 100644 index 000000000..0389aeec0 --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/AddFolderNode.java @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.commands; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.nodetype.NodeType; + +import org.argeo.eclipse.ui.ErrorFeedback; +import org.argeo.eclipse.ui.TreeParent; +import org.argeo.eclipse.ui.dialogs.SingleValue; +import org.argeo.eclipse.ui.jcr.JcrUiPlugin; +import org.argeo.jcr.ui.explorer.JcrExplorerPlugin; +import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem; +import org.argeo.jcr.ui.explorer.model.WorkspaceElem; +import org.argeo.jcr.ui.explorer.views.GenericJcrBrowser; +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.handlers.HandlerUtil; + +/** + * Adds a node of type nt:folder, only on {@link SingleJcrNodeElem} and + * {@link WorkspaceElem} TreeObject types. + * + * + * This handler assumes that a selection provider is available and picks only + * first selected item. It is UI's job to enable the command only when the + * selection contains one and only one element. Thus no parameter is passed + * through the command. + * + * This handler is still 'hard linked' to a GenericJcrBrowser view to enable + * correct tree refresh when a node is added. This must be corrected in future + * versions. + */ +public class AddFolderNode extends AbstractHandler { + + public final static String ID = JcrExplorerPlugin.ID + ".addFolderNode"; + + // public final static String DEFAULT_LABEL = JcrExplorerPlugin + // .getMessage("addFolderNodeCmdLbl"); + // public final static String DEFAULT_ICON_REL_PATH = "icons/addRepo.gif"; + + public Object execute(ExecutionEvent event) throws ExecutionException { + + ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event) + .getActivePage().getSelection(); + + GenericJcrBrowser view = (GenericJcrBrowser) HandlerUtil + .getActiveWorkbenchWindow(event).getActivePage() + .findView(HandlerUtil.getActivePartId(event)); + + if (selection != null && !selection.isEmpty() + && selection instanceof IStructuredSelection) { + Object obj = ((IStructuredSelection) selection).getFirstElement(); + TreeParent treeParentNode = null; + Node jcrParentNode = null; + + if (obj instanceof SingleJcrNodeElem) { + treeParentNode = (TreeParent) obj; + jcrParentNode = ((SingleJcrNodeElem) treeParentNode).getNode(); + } else if (obj instanceof WorkspaceElem) { + treeParentNode = (TreeParent) obj; + jcrParentNode = ((WorkspaceElem) treeParentNode).getRootNode(); + } else + return null; + + String folderName = SingleValue.ask("Folder name", + "Enter folder name"); + if (folderName != null) { + try { + jcrParentNode.addNode(folderName, NodeType.NT_FOLDER); + jcrParentNode.getSession().save(); + view.nodeAdded(treeParentNode); + } catch (RepositoryException e) { + ErrorFeedback.show("Cannot create folder " + folderName + + " under " + treeParentNode, e); + } + } + } else { + ErrorFeedback.show(JcrUiPlugin + .getMessage("errorUnvalidNtFolderNodeType")); + } + return null; + } +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/AddPrivileges.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/AddPrivileges.java new file mode 100644 index 000000000..829290ebe --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/AddPrivileges.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.commands; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; + +import org.argeo.ArgeoException; +import org.argeo.eclipse.ui.ErrorFeedback; +import org.argeo.eclipse.ui.TreeParent; +import org.argeo.jcr.ui.explorer.JcrExplorerPlugin; +import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem; +import org.argeo.jcr.ui.explorer.model.WorkspaceElem; +import org.argeo.jcr.ui.explorer.wizards.ChangeRightsWizard; +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.ui.handlers.HandlerUtil; + +/** + * Open a dialog to change rights on the selected node. + */ + +public class AddPrivileges extends AbstractHandler { + public final static String ID = JcrExplorerPlugin.ID + ".addPrivileges"; + + public Object execute(ExecutionEvent event) throws ExecutionException { + + ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event) + .getActivePage().getSelection(); + if (selection != null && !selection.isEmpty() + && selection instanceof IStructuredSelection) { + Object obj = ((IStructuredSelection) selection).getFirstElement(); + TreeParent treeParentNode = null; + Node jcrParentNode = null; + + if (obj instanceof SingleJcrNodeElem) { + treeParentNode = (TreeParent) obj; + jcrParentNode = ((SingleJcrNodeElem) treeParentNode).getNode(); + } else if (obj instanceof WorkspaceElem) { + treeParentNode = (TreeParent) obj; + jcrParentNode = ((WorkspaceElem) treeParentNode).getRootNode(); + } else + return null; + + try { + ChangeRightsWizard wizard = new ChangeRightsWizard( + jcrParentNode.getSession(), jcrParentNode.getPath()); + WizardDialog dialog = new WizardDialog( + HandlerUtil.getActiveShell(event), wizard); + dialog.open(); + return null; + } catch (RepositoryException re) { + throw new ArgeoException( + "Unexpected error while creating the new workspace.", + re); + } + } else { + ErrorFeedback.show("Cannot add privileges"); + } + return null; + } +} \ No newline at end of file diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/AddRemoteRepository.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/AddRemoteRepository.java new file mode 100644 index 000000000..e41edfca8 --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/AddRemoteRepository.java @@ -0,0 +1,230 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.commands; + +import java.net.URI; +import java.util.Hashtable; + +import javax.jcr.Node; +import javax.jcr.Repository; +import javax.jcr.RepositoryFactory; +import javax.jcr.Session; +import javax.jcr.SimpleCredentials; + +import org.argeo.ArgeoException; +import org.argeo.eclipse.ui.ErrorFeedback; +import org.argeo.eclipse.ui.utils.CommandUtils; +import org.argeo.jcr.ArgeoJcrConstants; +import org.argeo.jcr.ArgeoNames; +import org.argeo.jcr.ArgeoTypes; +import org.argeo.jcr.JcrUtils; +import org.argeo.jcr.UserJcrUtils; +import org.argeo.jcr.ui.explorer.JcrExplorerConstants; +import org.argeo.util.security.Keyring; +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IMessageProvider; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.dialogs.TitleAreaDialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +/** + * Connect to a remote repository and, if successful publish it as an OSGi + * service. + */ +public class AddRemoteRepository extends AbstractHandler implements + JcrExplorerConstants, ArgeoNames { + + private RepositoryFactory repositoryFactory; + private Repository nodeRepository; + private Keyring keyring; + + public Object execute(ExecutionEvent event) throws ExecutionException { + RemoteRepositoryLoginDialog dlg = new RemoteRepositoryLoginDialog( + Display.getDefault().getActiveShell()); + if (dlg.open() == Dialog.OK) { + CommandUtils.callCommand(Refresh.ID); + } + return null; + } + + public void setRepositoryFactory(RepositoryFactory repositoryFactory) { + this.repositoryFactory = repositoryFactory; + } + + public void setKeyring(Keyring keyring) { + this.keyring = keyring; + } + + public void setNodeRepository(Repository nodeRepository) { + this.nodeRepository = nodeRepository; + } + + class RemoteRepositoryLoginDialog extends TitleAreaDialog { + private Text name; + private Text uri; + private Text username; + private Text password; + private Button saveInKeyring; + + public RemoteRepositoryLoginDialog(Shell parentShell) { + super(parentShell); + } + + protected Point getInitialSize() { + return new Point(600, 400); + } + + protected Control createDialogArea(Composite parent) { + Composite dialogarea = (Composite) super.createDialogArea(parent); + dialogarea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, + true)); + Composite composite = new Composite(dialogarea, SWT.NONE); + composite.setLayout(new GridLayout(2, false)); + composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, + false)); + setMessage("Login to remote repository", IMessageProvider.NONE); + name = createLT(composite, "Name", "remoteRepository"); + uri = createLT(composite, "URI", + "http://localhost:7070/data/jcr/node"); + username = createLT(composite, "User", ""); + password = createLP(composite, "Password"); + + saveInKeyring = createLC(composite, "Remember password", false); + parent.pack(); + return composite; + } + + @Override + protected void createButtonsForButtonBar(Composite parent) { + super.createButtonsForButtonBar(parent); + Button test = createButton(parent, 2, "Test", false); + test.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent arg0) { + testConnection(); + } + }); + } + + void testConnection() { + Session session = null; + try { + URI checkedUri = new URI(uri.getText()); + String checkedUriStr = checkedUri.toString(); + + Hashtable params = new Hashtable(); + params.put(ArgeoJcrConstants.JCR_REPOSITORY_URI, checkedUriStr); + Repository repository = repositoryFactory.getRepository(params); + if (username.getText().trim().equals("")) {// anonymous + session = repository.login(); + } else { + // FIXME use getTextChars() when upgrading to 3.7 + // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=297412 + char[] pwd = password.getText().toCharArray(); + SimpleCredentials sc = new SimpleCredentials( + username.getText(), pwd); + session = repository.login(sc); + MessageDialog.openInformation(getParentShell(), "Success", + "Connection to '" + uri.getText() + "' successful"); + } + } catch (Exception e) { + ErrorFeedback.show( + "Connection test failed for " + uri.getText(), e); + } finally { + JcrUtils.logoutQuietly(session); + } + } + + @Override + protected void okPressed() { + Session nodeSession = null; + try { + nodeSession = nodeRepository.login(); + Node home = UserJcrUtils.getUserHome(nodeSession); + + Node remote = home.hasNode(ARGEO_REMOTE) ? home + .getNode(ARGEO_REMOTE) : home.addNode(ARGEO_REMOTE); + if (remote.hasNode(name.getText())) + throw new ArgeoException( + "There is already a remote repository named " + + name.getText()); + Node remoteRepository = remote.addNode(name.getText(), + ArgeoTypes.ARGEO_REMOTE_REPOSITORY); + remoteRepository.setProperty(ARGEO_URI, uri.getText()); + remoteRepository.setProperty(ARGEO_USER_ID, username.getText()); + nodeSession.save(); + if (saveInKeyring.getSelection()) { + String pwdPath = remoteRepository.getPath() + '/' + + ARGEO_PASSWORD; + keyring.set(pwdPath, password.getText().toCharArray()); + } + nodeSession.save(); + MessageDialog.openInformation( + getParentShell(), + "Repository Added", + "Remote repository '" + username.getText() + "@" + + uri.getText() + "' added"); + + super.okPressed(); + } catch (Exception e) { + ErrorFeedback.show("Cannot add remote repository", e); + } finally { + JcrUtils.logoutQuietly(nodeSession); + } + } + + /** Creates label and text. */ + protected Text createLT(Composite parent, String label, String initial) { + new Label(parent, SWT.NONE).setText(label); + Text text = new Text(parent, SWT.SINGLE | SWT.LEAD | SWT.BORDER); + text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + text.setText(initial); + return text; + } + + /** Creates label and check. */ + protected Button createLC(Composite parent, String label, + Boolean initial) { + new Label(parent, SWT.NONE).setText(label); + Button check = new Button(parent, SWT.CHECK); + check.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + check.setSelection(initial); + return check; + } + + protected Text createLP(Composite parent, String label) { + new Label(parent, SWT.NONE).setText(label); + Text text = new Text(parent, SWT.SINGLE | SWT.LEAD | SWT.BORDER + | SWT.PASSWORD); + text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + return text; + } + } +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/CreateWorkspace.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/CreateWorkspace.java new file mode 100644 index 000000000..e579630ce --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/CreateWorkspace.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.commands; + +import java.util.Arrays; + +import org.argeo.eclipse.ui.ErrorFeedback; +import org.argeo.eclipse.ui.dialogs.SingleValue; +import org.argeo.jcr.ui.explorer.JcrExplorerPlugin; +import org.argeo.jcr.ui.explorer.model.RepositoryElem; +import org.argeo.jcr.ui.explorer.views.GenericJcrBrowser; +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.handlers.HandlerUtil; + +/** Creates a new JCR workspace */ +public class CreateWorkspace extends AbstractHandler { + + public final static String ID = JcrExplorerPlugin.ID + ".addFolderNode"; + + public Object execute(ExecutionEvent event) throws ExecutionException { + + ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event) + .getActivePage().getSelection(); + + GenericJcrBrowser view = (GenericJcrBrowser) HandlerUtil + .getActiveWorkbenchWindow(event).getActivePage() + .findView(HandlerUtil.getActivePartId(event)); + + if (selection != null && !selection.isEmpty() + && selection instanceof IStructuredSelection) { + Object obj = ((IStructuredSelection) selection).getFirstElement(); + if (!(obj instanceof RepositoryElem)) + return null; + + RepositoryElem repositoryNode = (RepositoryElem) obj; + String workspaceName = SingleValue.ask("Workspace name", + "Enter workspace name"); + if (workspaceName != null) { + if (Arrays.asList(repositoryNode.getAccessibleWorkspaceNames()) + .contains(workspaceName)) { + ErrorFeedback.show("Workspace " + workspaceName + + " already exists."); + } else { + repositoryNode.createWorkspace(workspaceName); + view.nodeAdded(repositoryNode); + } + } + } else { + ErrorFeedback.show("Cannot create workspace"); + } + return null; + } +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/DeleteNodes.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/DeleteNodes.java new file mode 100644 index 000000000..26d4cdd43 --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/DeleteNodes.java @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.commands; + +import java.util.Iterator; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; + +import org.argeo.ArgeoException; +import org.argeo.eclipse.ui.ErrorFeedback; +import org.argeo.eclipse.ui.TreeParent; +import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem; +import org.argeo.jcr.ui.explorer.model.WorkspaceElem; +import org.argeo.jcr.ui.explorer.views.GenericJcrBrowser; +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.handlers.HandlerUtil; + +/** + * Deletes the selected nodes: both in the JCR repository and in the UI view. + * Warning no check is done, except implementation dependent native checks, + * handle with care. + * + * This handler is still 'hard linked' to a GenericJcrBrowser view to enable + * correct tree refresh when a node is added. This must be corrected in future + * versions. + */ +public class DeleteNodes extends AbstractHandler { + public Object execute(ExecutionEvent event) throws ExecutionException { + ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event) + .getActivePage().getSelection(); + if (selection == null || !(selection instanceof IStructuredSelection)) + return null; + + GenericJcrBrowser view = (GenericJcrBrowser) HandlerUtil + .getActiveWorkbenchWindow(event).getActivePage() + .findView(HandlerUtil.getActivePartId(event)); + + // confirmation + StringBuffer buf = new StringBuffer(""); + Iterator lst = ((IStructuredSelection) selection).iterator(); + while (lst.hasNext()) { + SingleJcrNodeElem sjn = ((SingleJcrNodeElem) lst.next()); + buf.append(sjn.getName()).append(' '); + } + Boolean ok = MessageDialog.openConfirm( + HandlerUtil.getActiveShell(event), "Confirm deletion", + "Do you want to delete " + buf + "?"); + + // operation + if (ok) { + Iterator it = ((IStructuredSelection) selection).iterator(); + Object obj = null; + SingleJcrNodeElem ancestor = null; + WorkspaceElem rootAncestor = null; + try { + while (it.hasNext()) { + obj = it.next(); + if (obj instanceof SingleJcrNodeElem) { + // Cache objects + SingleJcrNodeElem sjn = (SingleJcrNodeElem) obj; + TreeParent tp = (TreeParent) sjn.getParent(); + Node node = sjn.getNode(); + + // Jcr Remove + node.remove(); + node.getSession().save(); + // UI remove + tp.removeChild(sjn); + + // Check if the parent is the root node + if (tp instanceof WorkspaceElem) + rootAncestor = (WorkspaceElem) tp; + else + ancestor = getOlder(ancestor, (SingleJcrNodeElem) tp); + } + } + if (rootAncestor != null) + view.nodeRemoved(rootAncestor); + else if (ancestor != null) + view.nodeRemoved(ancestor); + } catch (Exception e) { + ErrorFeedback.show("Cannot delete selected node ", e); + } + } + return null; + } + + private SingleJcrNodeElem getOlder(SingleJcrNodeElem A, SingleJcrNodeElem B) { + try { + if (A == null) + return B == null ? null : B; + // Todo enhanced this method + else + return A.getNode().getDepth() <= B.getNode().getDepth() ? A : B; + } catch (RepositoryException re) { + throw new ArgeoException("Cannot find ancestor", re); + } + } +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/DumpNode.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/DumpNode.java new file mode 100644 index 000000000..c8a235d73 --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/DumpNode.java @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.commands; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; + +import org.argeo.ArgeoException; +import org.argeo.eclipse.ui.specific.OpenFile; +import org.argeo.eclipse.ui.utils.CommandUtils; +import org.argeo.jcr.JcrUtils; +import org.argeo.jcr.ui.explorer.JcrExplorerPlugin; +import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem; +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.handlers.HandlerUtil; + +/** + * If the method + * HandlerUtil.getActiveWorkbenchWindow(event).getActivePage().getSelection() + * exits and has a SingleJcrNodeElem as first element, it canonically calls the + * JCR Session.exportSystemView() method on the underlying node with both + * skipBinary & noRecurse boolean flags set to false. + * + * Resulting stream is saved in a tmp file and opened via the "open file" + * single-sourced command. + */ +public class DumpNode extends AbstractHandler { + public final static String ID = JcrExplorerPlugin.ID + ".dumpNode"; + + private final static DateFormat df = new SimpleDateFormat( + "yyyy-MM-dd_HH-mm"); + + public Object execute(ExecutionEvent event) throws ExecutionException { + ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event) + .getActivePage().getSelection(); + if (selection == null || !(selection instanceof IStructuredSelection)) + return null; + + Iterator lst = ((IStructuredSelection) selection).iterator(); + if (lst.hasNext()) { + Object element = lst.next(); + if (element instanceof SingleJcrNodeElem) { + SingleJcrNodeElem sjn = (SingleJcrNodeElem) element; + Node node = sjn.getNode(); + + // TODO add a dialog to configure the export and ask for + // confirmation + // Boolean ok = MessageDialog.openConfirm( + // HandlerUtil.getActiveShell(event), "Confirm deletion", + // "Do you want to delete " + buf + "?"); + + File tmpFile; + FileOutputStream fos; + try { + tmpFile = File.createTempFile("JcrExport", ".xml"); + tmpFile.deleteOnExit(); + fos = new FileOutputStream(tmpFile); + String dateVal = df.format(new GregorianCalendar() + .getTime()); + node.getSession().exportSystemView(node.getPath(), fos, + true, false); + openGeneratedFile(tmpFile.getAbsolutePath(), + "Dump-" + JcrUtils.replaceInvalidChars(node.getName())+ "-" + dateVal + ".xml"); + } catch (RepositoryException e) { + throw new ArgeoException( + "Unable to perform SystemExport on " + node, e); + } catch (IOException e) { + throw new ArgeoException("Unable to SystemExport " + node, + e); + } + } + } + return null; + } + + private synchronized void openGeneratedFile(String path, String fileName) { + Map params = new HashMap(); + params.put(OpenFile.PARAM_FILE_NAME, fileName); + params.put(OpenFile.PARAM_FILE_URI, "file://" + path); + CommandUtils.callCommand("org.argeo.security.ui.specific.openFile", + params); + } +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/EditNode.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/EditNode.java new file mode 100644 index 000000000..e98973e47 --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/EditNode.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.commands; + +import java.util.HashMap; +import java.util.Map; + +import javax.jcr.Property; +import javax.jcr.nodetype.NodeType; + +import org.argeo.eclipse.ui.ErrorFeedback; +import org.argeo.eclipse.ui.jcr.editors.NodeEditorInput; +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.handlers.HandlerUtil; + +/** Generic command to open a path in an editor. */ +public class EditNode extends AbstractHandler { + public final static String EDITOR_PARAM = "editor"; + + private String defaultEditorId; + + private Map nodeTypeToEditor = new HashMap(); + + public Object execute(ExecutionEvent event) throws ExecutionException { + String path = event.getParameter(Property.JCR_PATH); + + String type = event.getParameter(NodeType.NT_NODE_TYPE); + if (type == null) + type = NodeType.NT_UNSTRUCTURED; + + String editorId = event.getParameter(NodeType.NT_NODE_TYPE); + if (editorId == null) + editorId = nodeTypeToEditor.containsKey(type) ? nodeTypeToEditor + .get(type) : defaultEditorId; + + NodeEditorInput nei = new NodeEditorInput(path); + + try { + HandlerUtil.getActiveWorkbenchWindow(event).getActivePage() + .openEditor(nei, editorId); + } catch (PartInitException e) { + ErrorFeedback.show("Cannot open " + editorId + " with " + path + + " of type " + type, e); + } + // TODO Auto-generated method stub + return null; + } + + public void setDefaultEditorId(String defaultEditorId) { + this.defaultEditorId = defaultEditorId; + } + +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/GetNodeSize.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/GetNodeSize.java new file mode 100644 index 000000000..cfcac1354 --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/GetNodeSize.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.commands; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javax.jcr.Node; + +import org.argeo.eclipse.ui.ErrorFeedback; +import org.argeo.jcr.JcrUtils; +import org.argeo.jcr.ui.explorer.JcrExplorerPlugin; +import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem; +import org.argeo.jcr.ui.explorer.model.WorkspaceElem; +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.handlers.HandlerUtil; + +/** Opens the generic node editor. */ +public class GetNodeSize extends AbstractHandler { + // private final static Log log = LogFactory.getLog(GetNodeSize.class); + + public final static String ID = JcrExplorerPlugin.ID + ".getNodeSize"; + + // public final static String DEFAULT_ICON_REL_PATH = "icons/getSize.gif"; + // public final static String DEFAULT_LABEL = JcrExplorerPlugin + // .getMessage("getNodeSizeCmdLbl"); + + public Object execute(ExecutionEvent event) throws ExecutionException { + // JcrUtils.getRepositoryByAlias(repositoryRegister, + // ArgeoJcrConstants.ALIAS_NODE); + + ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event) + .getActivePage().getSelection(); + + if (selection != null && !selection.isEmpty() + && selection instanceof IStructuredSelection) { + + // IStructuredSelection iss = (IStructuredSelection) selection; + // if (iss.size() > 1) + // ErrorFeedback.show(JcrExplorerPlugin + // .getMessage("warningInvalidMultipleSelection"), null); + + long size = 0; + + Iterator it = ((IStructuredSelection) selection).iterator(); + + // as the size method is recursive, we keep track of nodes for which + // we already have computed size so that we don't count them twice. + // In a first approximation, we assume that the structure selection + // keep the nodes ordered. + // TODO : enhance that. + List importedPathes = new ArrayList(); + try { + nodesIt: while (it.hasNext()) { + Object obj = it.next(); + String curPath; + Node node; + if (obj instanceof SingleJcrNodeElem) { + node = ((SingleJcrNodeElem) obj).getNode(); + curPath = node.getSession().getWorkspace().getName(); + curPath += "/" + node.getPath(); + } else if (obj instanceof WorkspaceElem) { + node = ((WorkspaceElem) obj).getRootNode(); + curPath = node.getSession().getWorkspace().getName(); + } else + // unvalid object type + continue nodesIt; + + Iterator itPath = importedPathes.iterator(); + while (itPath.hasNext()) { + String refPath = itPath.next(); + if (curPath.startsWith(refPath)) + // Already done : skip node + continue nodesIt; + } + size += JcrUtils.getNodeApproxSize(node); + importedPathes.add(curPath); + } + } catch (Exception e) { + ErrorFeedback.show("Cannot Get size of selected node ", e); + } + + String[] labels = { "OK" }; + Shell shell = HandlerUtil.getActiveWorkbenchWindow(event) + .getShell(); + MessageDialog md = new MessageDialog(shell, "Node size", null, + "Node size is: " + size / 1024 + " KB", + MessageDialog.INFORMATION, labels, 0); + md.open(); + } + return null; + } +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/ImportFileSystem.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/ImportFileSystem.java new file mode 100644 index 000000000..5c4bf7e6b --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/ImportFileSystem.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.commands; + +import javax.jcr.Node; + +import org.argeo.eclipse.ui.ErrorFeedback; +import org.argeo.eclipse.ui.TreeParent; +import org.argeo.jcr.ui.explorer.JcrExplorerPlugin; +import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem; +import org.argeo.jcr.ui.explorer.model.WorkspaceElem; +import org.argeo.jcr.ui.explorer.views.GenericJcrBrowser; +import org.argeo.jcr.ui.explorer.wizards.ImportFileSystemWizard; +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.ui.handlers.HandlerUtil; + +/** Import a local file system directory tree. */ +public class ImportFileSystem extends AbstractHandler { + public Object execute(ExecutionEvent event) throws ExecutionException { + ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event) + .getActivePage().getSelection(); + GenericJcrBrowser view = (GenericJcrBrowser) HandlerUtil + .getActiveWorkbenchWindow(event).getActivePage() + .findView(HandlerUtil.getActivePartId(event)); + if (selection != null && !selection.isEmpty() + && selection instanceof IStructuredSelection) { + Object obj = ((IStructuredSelection) selection).getFirstElement(); + try { + Node folder = null; + if (obj instanceof SingleJcrNodeElem) { + folder = ((SingleJcrNodeElem) obj).getNode(); + } else if (obj instanceof WorkspaceElem) { + folder = ((WorkspaceElem) obj).getRootNode(); + } else { + ErrorFeedback.show(JcrExplorerPlugin + .getMessage("warningInvalidNodeToImport")); + } + if (folder != null) { + ImportFileSystemWizard wizard = new ImportFileSystemWizard( + folder); + WizardDialog dialog = new WizardDialog( + HandlerUtil.getActiveShell(event), wizard); + dialog.open(); + view.nodeAdded((TreeParent) obj); + } + } catch (Exception e) { + ErrorFeedback.show("Cannot import files to " + obj, e); + } + } + return null; + } +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/OpenGenericNodeEditor.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/OpenGenericNodeEditor.java new file mode 100644 index 000000000..6799d1706 --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/OpenGenericNodeEditor.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.commands; + +import org.argeo.ArgeoException; +import org.argeo.eclipse.ui.jcr.editors.NodeEditorInput; +import org.argeo.jcr.ui.explorer.JcrExplorerConstants; +import org.argeo.jcr.ui.explorer.JcrExplorerPlugin; +import org.argeo.jcr.ui.explorer.editors.GenericNodeEditor; +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.ui.handlers.HandlerUtil; + +/** Opens the generic node editor. */ +public class OpenGenericNodeEditor extends AbstractHandler { + public final static String ID = JcrExplorerPlugin.ID + ".openGenericNodeEditor"; + + public Object execute(ExecutionEvent event) throws ExecutionException { + String path = event.getParameter(JcrExplorerConstants.PARAM_PATH); + try { + NodeEditorInput nei = new NodeEditorInput(path); + HandlerUtil.getActiveWorkbenchWindow(event).getActivePage() + .openEditor(nei, GenericNodeEditor.ID); + } catch (Exception e) { + throw new ArgeoException("Cannot open editor", e); + } + return null; + } + +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/Refresh.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/Refresh.java new file mode 100644 index 000000000..21ce25658 --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/Refresh.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.commands; + +import java.util.Iterator; + +import org.argeo.eclipse.ui.TreeParent; +import org.argeo.eclipse.ui.jcr.views.AbstractJcrBrowser; +import org.argeo.jcr.ui.explorer.JcrExplorerPlugin; +import org.argeo.jcr.ui.explorer.utils.JcrUiUtils; +import org.argeo.jcr.ui.explorer.views.GenericJcrBrowser; +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; + +/** + * Force the selected objects of the active view to be refreshed doing the + * following: + *
    + *
  1. The model objects are recomputed
  2. + *
  3. the view is refreshed
  4. + *
+ */ +public class Refresh extends AbstractHandler { + + public final static String ID = JcrExplorerPlugin.ID + ".refresh"; + + public Object execute(ExecutionEvent event) throws ExecutionException { + + AbstractJcrBrowser view = (AbstractJcrBrowser) JcrExplorerPlugin + .getDefault().getWorkbench().getActiveWorkbenchWindow() + .getActivePage().getActivePart();// + + ISelection selection = JcrExplorerPlugin.getDefault().getWorkbench() + .getActiveWorkbenchWindow().getActivePage().getSelection(); + + if (selection != null && selection instanceof IStructuredSelection + && !selection.isEmpty()) { + Iterator it = ((IStructuredSelection) selection).iterator(); + while (it.hasNext()) { + Object obj = it.next(); + if (obj instanceof TreeParent) { + TreeParent tp = (TreeParent) obj; + JcrUiUtils.forceRefreshIfNeeded(tp); + view.refresh(obj); + } + } + } else if (view instanceof GenericJcrBrowser) + ((GenericJcrBrowser) view).refresh(null); // force full refresh + + return null; + } +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/RemoveRemoteRepository.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/RemoveRemoteRepository.java new file mode 100644 index 000000000..ec23dd08c --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/RemoveRemoteRepository.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.commands; + +import org.argeo.jcr.ui.explorer.model.RemoteRepositoryElem; +import org.argeo.jcr.ui.explorer.views.GenericJcrBrowser; +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.handlers.HandlerUtil; + +/** Remove a registered remote repository */ +public class RemoveRemoteRepository extends AbstractHandler { + + public Object execute(ExecutionEvent event) throws ExecutionException { + + ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event) + .getActivePage().getSelection(); + + GenericJcrBrowser view = (GenericJcrBrowser) HandlerUtil + .getActiveWorkbenchWindow(event).getActivePage() + .findView(HandlerUtil.getActivePartId(event)); + + if (selection != null && !selection.isEmpty() + && selection instanceof IStructuredSelection) { + Object obj = ((IStructuredSelection) selection).getFirstElement(); + + if (obj instanceof RemoteRepositoryElem) { + ((RemoteRepositoryElem) obj).remove(); + view.refresh(null); + } + } + return null; + } + +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/SortChildNodes.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/SortChildNodes.java new file mode 100644 index 000000000..2961529d8 --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/SortChildNodes.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.commands; + +import org.argeo.jcr.ui.explorer.JcrExplorerPlugin; +import org.argeo.jcr.ui.explorer.views.GenericJcrBrowser; +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.Command; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.State; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.commands.ICommandService; +import org.eclipse.ui.handlers.HandlerUtil; + +/** + * Change isSorted state of the JcrExplorer Browser + */ +public class SortChildNodes extends AbstractHandler { + public final static String ID = JcrExplorerPlugin.ID + ".sortChildNodes"; + + public Object execute(ExecutionEvent event) throws ExecutionException { + GenericJcrBrowser view = (GenericJcrBrowser) HandlerUtil + .getActiveWorkbenchWindow(event).getActivePage() + .findView(GenericJcrBrowser.ID); + + ICommandService service = (ICommandService) PlatformUI.getWorkbench() + .getService(ICommandService.class); + Command command = service.getCommand(ID); + State state = command.getState(ID + ".toggleState"); + + boolean wasSorted = (Boolean) state.getValue(); + view.setSortChildNodes(!wasSorted); + state.setValue(!wasSorted); + return null; + } +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/dialogs/ChooseNameDialog.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/dialogs/ChooseNameDialog.java new file mode 100644 index 000000000..d4a5cc757 --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/dialogs/ChooseNameDialog.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.dialogs; + +import org.eclipse.jface.dialogs.IMessageProvider; +import org.eclipse.jface.dialogs.TitleAreaDialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +/** Dialog to change the current user password */ +public class ChooseNameDialog extends TitleAreaDialog { + private Text nameT; + + public ChooseNameDialog(Shell parentShell) { + super(parentShell); + setTitle("Choose name"); + } + + protected Point getInitialSize() { + return new Point(300, 250); + } + + protected Control createDialogArea(Composite parent) { + Composite dialogarea = (Composite) super.createDialogArea(parent); + dialogarea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + Composite composite = new Composite(dialogarea, SWT.NONE); + composite.setLayout(new GridLayout(2, false)); + composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + nameT = createLT(composite, "Name"); + + setMessage("Choose name", IMessageProvider.INFORMATION); + parent.pack(); + return composite; + } + + /** Creates label and text. */ + protected Text createLT(Composite parent, String label) { + new Label(parent, SWT.NONE).setText(label); + Text text = new Text(parent, SWT.SINGLE | SWT.LEAD | SWT.BORDER); + text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + return text; + } + + public String getName() { + return nameT.getText(); + } +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/ChildNodesPage.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/ChildNodesPage.java new file mode 100644 index 000000000..682254a48 --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/ChildNodesPage.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.editors; + +import javax.jcr.Node; + +import org.argeo.ArgeoException; +import org.argeo.jcr.ui.explorer.JcrExplorerPlugin; +import org.argeo.jcr.ui.explorer.browser.NodeLabelProvider; +import org.argeo.jcr.ui.explorer.providers.SingleNodeAsTreeContentProvider; +import org.argeo.jcr.ui.explorer.utils.GenericNodeDoubleClickListener; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.forms.IManagedForm; +import org.eclipse.ui.forms.editor.FormEditor; +import org.eclipse.ui.forms.editor.FormPage; +import org.eclipse.ui.forms.widgets.ScrolledForm; + +/** + * List all childs of the current node and brings some browsing capabilities + * accross the repository + */ +public class ChildNodesPage extends FormPage { + // private final static Log log = LogFactory.getLog(ChildNodesPage.class); + + // business objects + private Node currentNode; + + // this page UI components + private SingleNodeAsTreeContentProvider nodeContentProvider; + private TreeViewer nodesViewer; + + public ChildNodesPage(FormEditor editor, String title, Node currentNode) { + super(editor, "ChildNodesPage", title); + this.currentNode = currentNode; + } + + protected void createFormContent(IManagedForm managedForm) { + try { + ScrolledForm form = managedForm.getForm(); + form.setText(JcrExplorerPlugin.getMessage("childNodesPageTitle")); + Composite body = form.getBody(); + GridLayout twt = new GridLayout(1, false); + twt.marginWidth = twt.marginHeight = 5; + body.setLayout(twt); + if (!currentNode.hasNodes()) { + managedForm.getToolkit().createLabel(body, + JcrExplorerPlugin.getMessage("warningNoChildNode")); + } else { + + nodeContentProvider = new SingleNodeAsTreeContentProvider(); + nodesViewer = createNodeViewer(body, nodeContentProvider); + nodesViewer.setInput(currentNode); + } + } catch (Exception e) { + throw new ArgeoException( + "Unexpected error while creating child node page", e); + } + } + + protected TreeViewer createNodeViewer(Composite parent, + final ITreeContentProvider nodeContentProvider) { + + final TreeViewer tmpNodeViewer = new TreeViewer(parent, SWT.MULTI); + + tmpNodeViewer.getTree().setLayoutData( + new GridData(SWT.FILL, SWT.FILL, true, true)); + + tmpNodeViewer.setContentProvider(nodeContentProvider); + tmpNodeViewer.setLabelProvider(new NodeLabelProvider()); + tmpNodeViewer + .addDoubleClickListener(new GenericNodeDoubleClickListener( + tmpNodeViewer)); + return tmpNodeViewer; + } +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/EmptyNodePage.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/EmptyNodePage.java new file mode 100644 index 000000000..322c7ebd2 --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/EmptyNodePage.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.editors; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Label; +import org.eclipse.ui.forms.IManagedForm; +import org.eclipse.ui.forms.editor.FormEditor; +import org.eclipse.ui.forms.editor.FormPage; +import org.eclipse.ui.forms.widgets.ScrolledForm; + +/** + * This page is only used at editor's creation time when current node has not + * yet been set + */ +public class EmptyNodePage extends FormPage { + // private final static Log log = LogFactory.getLog(EmptyNodePage.class); + + public EmptyNodePage(FormEditor editor, String title) { + super(editor, "Empty Page", title); + } + + protected void createFormContent(IManagedForm managedForm) { + try { + ScrolledForm form = managedForm.getForm(); + GridLayout twt = new GridLayout(1, false); + twt.marginWidth = twt.marginHeight = 0; + form.getBody().setLayout(twt); + Label lbl = new Label(form.getBody(), SWT.NONE); + lbl.setText("Empty page"); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericJcrQueryEditor.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericJcrQueryEditor.java new file mode 100644 index 000000000..3b98ed137 --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericJcrQueryEditor.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.editors; + +import org.argeo.eclipse.ui.jcr.editors.AbstractJcrQueryEditor; +import org.argeo.jcr.ui.explorer.JcrExplorerPlugin; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Text; + +/** Enables end user to type and execute any JCR query. */ +public class GenericJcrQueryEditor extends AbstractJcrQueryEditor { + public final static String ID = JcrExplorerPlugin.ID + ".genericJcrQueryEditor"; + + private Text queryField; + + @Override + public void createQueryForm(Composite parent) { + parent.setLayout(new GridLayout(1, false)); + + queryField = new Text(parent, SWT.BORDER | SWT.MULTI | SWT.WRAP); + queryField.setText(initialQuery); + queryField.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + + Button execute = new Button(parent, SWT.PUSH); + execute.setText("Execute"); + + Listener executeListener = new Listener() { + public void handleEvent(Event event) { + executeQuery(queryField.getText()); + } + }; + + execute.addListener(SWT.Selection, executeListener); + // queryField.addListener(SWT.DefaultSelection, executeListener); + } + + @Override + public void setFocus() { + queryField.setFocus(); + } +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericNodeEditor.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericNodeEditor.java new file mode 100644 index 000000000..57f3aa236 --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericNodeEditor.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.editors; + +import javax.jcr.Node; + +import org.argeo.ArgeoException; +import org.argeo.jcr.JcrUtils; +import org.argeo.jcr.ui.explorer.JcrExplorerPlugin; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorSite; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.forms.editor.FormEditor; + +/** + * Container for the node editor page. At creation time, it takes a JCR Node + * that cannot be changed afterwards. + */ +public class GenericNodeEditor extends FormEditor { + + // private final static Log log = + // LogFactory.getLog(GenericNodeEditor.class); + public final static String ID = JcrExplorerPlugin.ID + ".genericNodeEditor"; + + private Node currentNode; + + private GenericPropertyPage genericPropertyPage; + private ChildNodesPage childNodesPage; + private NodeRightsManagementPage nodeRightsManagementPage; + private NodeVersionHistoryPage nodeVersionHistoryPage; + + public void init(IEditorSite site, IEditorInput input) + throws PartInitException { + super.init(site, input); + GenericNodeEditorInput nei = (GenericNodeEditorInput) getEditorInput(); + currentNode = nei.getCurrentNode(); + this.setPartName(JcrUtils.lastPathElement(nei.getPath())); + } + + @Override + protected void addPages() { + try { + // genericNodePage = new GenericNodePage(this, + // JcrExplorerPlugin.getMessage("genericNodePageTitle"), + // currentNode); + // addPage(genericNodePage); + + genericPropertyPage = new GenericPropertyPage(this, + JcrExplorerPlugin.getMessage("genericNodePageTitle"), + currentNode); + addPage(genericPropertyPage); + + childNodesPage = new ChildNodesPage(this, + JcrExplorerPlugin.getMessage("childNodesPageTitle"), + currentNode); + addPage(childNodesPage); + + nodeRightsManagementPage = new NodeRightsManagementPage(this, + JcrExplorerPlugin + .getMessage("nodeRightsManagementPageTitle"), + currentNode); + addPage(nodeRightsManagementPage); + + nodeVersionHistoryPage = new NodeVersionHistoryPage( + this, + JcrExplorerPlugin.getMessage("nodeVersionHistoryPageTitle"), + currentNode); + addPage(nodeVersionHistoryPage); + } catch (PartInitException e) { + throw new ArgeoException("Not able to add an empty page ", e); + } + } + + @Override + public void doSaveAs() { + // unused compulsory method + } + + @Override + public void doSave(IProgressMonitor monitor) { + try { + // Automatically commit all pages of the editor + commitPages(true); + firePropertyChange(PROP_DIRTY); + } catch (Exception e) { + throw new ArgeoException("Error while saving node", e); + } + + } + + @Override + public boolean isSaveAsAllowed() { + return true; + } + + Node getCurrentNode() { + return currentNode; + } +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericNodeEditorInput.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericNodeEditorInput.java new file mode 100644 index 000000000..45e337e5d --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericNodeEditorInput.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.editors; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; + +import org.argeo.ArgeoException; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IPersistableElement; + +/** + * An editor input based the JCR node object. + * */ + +public class GenericNodeEditorInput implements IEditorInput { + private final Node currentNode; + + // cache key properties at creation time to avoid Exception at recoring time + // when the session has been closed + private String path; + private String uid; + private String name; + + public GenericNodeEditorInput(Node currentNode) { + this.currentNode = currentNode; + try { + name = currentNode.getName(); + uid = currentNode.getIdentifier(); + path = currentNode.getPath(); + } catch (RepositoryException re) { + throw new ArgeoException( + "unexpected error while getting node key values at creation time", + re); + } + } + + public Node getCurrentNode() { + return currentNode; + } + + public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) { + return null; + } + + public boolean exists() { + return true; + } + + public ImageDescriptor getImageDescriptor() { + return null; + } + + public String getName() { + return name; + } + + public String getUid() { + return uid; + } + + public String getToolTipText() { + return path; + } + + public String getPath() { + return path; + } + + public IPersistableElement getPersistable() { + return null; + } + + /** + * equals method based on UID that is unique within a workspace and path of + * the node, thus 2 shared node that have same UID as defined in the spec + * but 2 different pathes will open two distinct editors. + * + * TODO enhance this method to support multirepository and multiworkspace + * environments + */ + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + + GenericNodeEditorInput other = (GenericNodeEditorInput) obj; + if (!getUid().equals(other.getUid())) + return false; + if (!getPath().equals(other.getPath())) + return false; + return true; + } +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericNodePage.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericNodePage.java new file mode 100644 index 000000000..fd4dafe76 --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericNodePage.java @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.editors; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.ListIterator; + +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.PropertyIterator; +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; + +import org.argeo.ArgeoException; +import org.argeo.jcr.JcrUtils; +import org.argeo.jcr.ui.explorer.JcrExplorerConstants; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.forms.AbstractFormPart; +import org.eclipse.ui.forms.IManagedForm; +import org.eclipse.ui.forms.editor.FormEditor; +import org.eclipse.ui.forms.editor.FormPage; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.ScrolledForm; + +/** + * Main node editor page. Lists all properties of the current node and enable + * access and editing for some of them. + */ + +public class GenericNodePage extends FormPage implements JcrExplorerConstants { + // private final static Log log = LogFactory.getLog(GenericNodePage.class); + + // local constants + private final static String JCR_PROPERTY_NAME = "jcr:name"; + + // Utils + protected DateFormat timeFormatter = new SimpleDateFormat(DATE_TIME_FORMAT); + + // Main business Objects + private Node currentNode; + + // This page widgets + private FormToolkit tk; + private List modifyableProperties = new ArrayList(); + + public GenericNodePage(FormEditor editor, String title, Node currentNode) { + super(editor, "id", title); + this.currentNode = currentNode; + } + + protected void createFormContent(IManagedForm managedForm) { + tk = managedForm.getToolkit(); + ScrolledForm form = managedForm.getForm(); + GridLayout twt = new GridLayout(3, false); + twt.marginWidth = twt.marginHeight = 5; + + form.getBody().setLayout(twt); + createPropertiesPart(form.getBody()); + } + + private void createPropertiesPart(Composite parent) { + try { + + PropertyIterator pi = currentNode.getProperties(); + + // Initializes form part + AbstractFormPart part = new AbstractFormPart() { + public void commit(boolean onSave) { + try { + if (onSave) { + ListIterator it = modifyableProperties + .listIterator(); + while (it.hasNext()) { + // we only support Text controls for the time + // being + Text curControl = (Text) it.next(); + String value = curControl.getText(); + currentNode.setProperty((String) curControl + .getData(JCR_PROPERTY_NAME), value); + } + + // We only commit when onSave = true, + // thus it is still possible to save after a tab + // change. + super.commit(onSave); + } + } catch (RepositoryException re) { + throw new ArgeoException( + "Unexpected error while saving properties", re); + } + } + }; + + while (pi.hasNext()) { + Property prop = pi.nextProperty(); + addPropertyLine(parent, part, prop); + } + + getManagedForm().addPart(part); + } catch (RepositoryException re) { + throw new ArgeoException( + "Error during creation of network details section", re); + } + + } + + private void addPropertyLine(Composite parent, AbstractFormPart part, + Property prop) { + try { + tk.createLabel(parent, prop.getName()); + tk.createLabel(parent, + "[" + JcrUtils.getPropertyDefinitionAsString(prop) + "]"); + + if (prop.getDefinition().isProtected()) { + tk.createLabel(parent, formatReadOnlyPropertyValue(prop)); + } else + addModifyableValueWidget(parent, part, prop); + } catch (RepositoryException re) { + throw new ArgeoException("Cannot get property " + prop, re); + } + } + + private String formatReadOnlyPropertyValue(Property prop) { + try { + String strValue; + + if (prop.getType() == PropertyType.BINARY) + strValue = ""; + else if (prop.isMultiple()) + strValue = Arrays.asList(prop.getValues()).toString(); + else if (prop.getType() == PropertyType.DATE) + strValue = timeFormatter.format(prop.getValue().getDate() + .getTime()); + else + strValue = prop.getValue().getString(); + + return strValue; + } catch (RepositoryException re) { + throw new ArgeoException( + "Unexpected error while formatting read only property value", + re); + } + } + + private Control addModifyableValueWidget(Composite parent, + AbstractFormPart part, Property prop) { + GridData gd; + try { + if (prop.getType() == PropertyType.STRING) { + Text txt = tk.createText(parent, prop.getString()); + gd = new GridData(GridData.FILL_HORIZONTAL); + txt.setLayoutData(gd); + txt.addModifyListener(new ModifiedFieldListener(part)); + txt.setData(JCR_PROPERTY_NAME, prop.getName()); + modifyableProperties.add(txt); + } else { + // unsupported property type for editing, we create a read only + // label. + return tk + .createLabel(parent, formatReadOnlyPropertyValue(prop)); + } + return null; + } catch (RepositoryException re) { + throw new ArgeoException( + "Unexpected error while formatting read only property value", + re); + } + + } + + // + // LISTENERS + // + + private class ModifiedFieldListener implements ModifyListener { + + private AbstractFormPart formPart; + + public ModifiedFieldListener(AbstractFormPart generalPart) { + this.formPart = generalPart; + } + + public void modifyText(ModifyEvent e) { + formPart.markDirty(); + } + } + +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericPropertyPage.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericPropertyPage.java new file mode 100644 index 000000000..3aec4538c --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericPropertyPage.java @@ -0,0 +1,306 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.editors; + +import java.util.ArrayList; +import java.util.List; + +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.PropertyIterator; +import javax.jcr.RepositoryException; +import javax.jcr.Value; + +import org.argeo.ArgeoException; +import org.argeo.jcr.ui.explorer.JcrExplorerConstants; +import org.argeo.jcr.ui.explorer.JcrExplorerPlugin; +import org.argeo.jcr.ui.explorer.providers.PropertyLabelProvider; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeColumn; +import org.eclipse.ui.forms.IManagedForm; +import org.eclipse.ui.forms.editor.FormEditor; +import org.eclipse.ui.forms.editor.FormPage; +import org.eclipse.ui.forms.widgets.ScrolledForm; + +/** + * Generic editor property page. Lists all properties of current node as a + * complex tree. TODO: enable editing + */ + +public class GenericPropertyPage extends FormPage implements + JcrExplorerConstants { + // private final static Log log = + // LogFactory.getLog(GenericPropertyPage.class); + + // Main business Objects + private Node currentNode; + + public GenericPropertyPage(FormEditor editor, String title, Node currentNode) { + super(editor, "id", title); + this.currentNode = currentNode; + } + + protected void createFormContent(IManagedForm managedForm) { + ScrolledForm form = managedForm.getForm(); + form.setText(JcrExplorerPlugin.getMessage("genericNodePageTitle")); + FillLayout layout = new FillLayout(); + layout.marginHeight = 5; + layout.marginWidth = 5; + form.getBody().setLayout(layout); + + createComplexTree(form.getBody()); + + // TODO remove following + // createPropertiesPart(form.getBody()); + } + + private TreeViewer createComplexTree(Composite parent) { + int style = SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION; + Tree tree = new Tree(parent, style); + createColumn(tree, "Property", SWT.LEFT, 200); + createColumn(tree, "Value(s)", SWT.LEFT, 300); + createColumn(tree, "Attributes", SWT.LEFT, 65); + tree.setLinesVisible(true); + tree.setHeaderVisible(true); + + TreeViewer result = new TreeViewer(tree); + result.setContentProvider(new TreeContentProvider()); + result.setLabelProvider(new PropertyLabelProvider()); + result.setInput(currentNode); + result.expandAll(); + return result; + } + + private static TreeColumn createColumn(Tree parent, String name, int style, + int width) { + TreeColumn result = new TreeColumn(parent, style); + result.setText(name); + result.setWidth(width); + result.setMoveable(true); + result.setResizable(true); + return result; + } + + // + // private void createPropertiesPart(Composite parent) { + // try { + // + // PropertyIterator pi = currentNode.getProperties(); + // + // // Initializes form part + // AbstractFormPart part = new AbstractFormPart() { + // public void commit(boolean onSave) { + // try { + // if (onSave) { + // ListIterator it = modifyableProperties + // .listIterator(); + // while (it.hasNext()) { + // // we only support Text controls for the time + // // being + // Text curControl = (Text) it.next(); + // String value = curControl.getText(); + // currentNode.setProperty((String) curControl + // .getData(JCR_PROPERTY_NAME), value); + // } + // + // // We only commit when onSave = true, + // // thus it is still possible to save after a tab + // // change. + // super.commit(onSave); + // } + // } catch (RepositoryException re) { + // throw new ArgeoException( + // "Unexpected error while saving properties", re); + // } + // } + // }; + // + // while (pi.hasNext()) { + // Property prop = pi.nextProperty(); + // addPropertyLine(parent, part, prop); + // } + // + // getManagedForm().addPart(part); + // } catch (RepositoryException re) { + // throw new ArgeoException( + // "Error during creation of network details section", re); + // } + // + // } + // + // private void addPropertyLine(Composite parent, AbstractFormPart part, + // Property prop) { + // try { + // tk.createLabel(parent, prop.getName()); + // tk.createLabel(parent, + // "[" + JcrUtils.getPropertyDefinitionAsString(prop) + "]"); + // + // if (prop.getDefinition().isProtected()) { + // tk.createLabel(parent, formatReadOnlyPropertyValue(prop)); + // } else + // addModifyableValueWidget(parent, part, prop); + // } catch (RepositoryException re) { + // throw new ArgeoException("Cannot get property " + prop, re); + // } + // } + // + // private String formatReadOnlyPropertyValue(Property prop) { + // try { + // String strValue; + // + // if (prop.getType() == PropertyType.BINARY) + // strValue = ""; + // else if (prop.isMultiple()) + // strValue = Arrays.asList(prop.getValues()).toString(); + // else if (prop.getType() == PropertyType.DATE) + // strValue = timeFormatter.format(prop.getValue().getDate() + // .getTime()); + // else + // strValue = prop.getValue().getString(); + // + // return strValue; + // } catch (RepositoryException re) { + // throw new ArgeoException( + // "Unexpected error while formatting read only property value", + // re); + // } + // } + // + // private Control addModifyableValueWidget(Composite parent, + // AbstractFormPart part, Property prop) { + // GridData gd; + // try { + // if (prop.getType() == PropertyType.STRING) { + // Text txt = tk.createText(parent, prop.getString()); + // gd = new GridData(GridData.FILL_HORIZONTAL); + // txt.setLayoutData(gd); + // txt.addModifyListener(new ModifiedFieldListener(part)); + // txt.setData(JCR_PROPERTY_NAME, prop.getName()); + // modifyableProperties.add(txt); + // } else { + // // unsupported property type for editing, we create a read only + // // label. + // return tk + // .createLabel(parent, formatReadOnlyPropertyValue(prop)); + // } + // return null; + // } catch (RepositoryException re) { + // throw new ArgeoException( + // "Unexpected error while formatting read only property value", + // re); + // } + // + // } + + // Multiple Value Model + // protected class MultipleValueItem { + // private int index; + // private Value value; + // + // public MultipleValueItem(int index, Value value) { + // this.index = index; + // this.value = value; + // } + // + // public int getIndex() { + // return index; + // } + // + // public Object getValue() { + // return value; + // } + // } + + private class TreeContentProvider implements ITreeContentProvider { + public Object[] getElements(Object parent) { + Object[] props = null; + try { + + if (parent instanceof Node) { + Node node = (Node) parent; + PropertyIterator pi; + pi = node.getProperties(); + List propList = new ArrayList(); + while (pi.hasNext()) { + propList.add(pi.nextProperty()); + } + props = propList.toArray(); + } + } catch (RepositoryException e) { + throw new ArgeoException( + "Unexpected exception while listing node properties", e); + } + return props; + } + + public Object getParent(Object child) { + return null; + } + + public Object[] getChildren(Object parent) { + Object[] result = null; + if (parent instanceof Property) { + Property prop = (Property) parent; + try { + + if (prop.isMultiple()) { + Value[] values = prop.getValues(); + // List list = new + // ArrayList(); + // for (int i = 0; i < values.length; i++) { + // MultipleValueItem mvi = new MultipleValueItem(i, + // values[i]); + // list.add(mvi); + // } + + return values; + } + } catch (RepositoryException e) { + throw new ArgeoException( + "Unexpected error getting multiple values property.", + e); + } + } + return result; + } + + public boolean hasChildren(Object parent) { + try { + if (parent instanceof Property + && ((Property) parent).isMultiple()) { + return true; + } + } catch (RepositoryException e) { + throw new ArgeoException( + "Unexpected exception while checking if property is multiple", + e); + } + return false; + } + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + + public void dispose() { + } + } +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/NodeRightsManagementPage.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/NodeRightsManagementPage.java new file mode 100644 index 000000000..cc5efb5f9 --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/NodeRightsManagementPage.java @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.editors; + +import javax.jcr.Node; +import javax.jcr.security.AccessControlManager; +import javax.jcr.security.Privilege; + +import org.argeo.ArgeoException; +import org.argeo.jcr.ui.explorer.JcrExplorerPlugin; +import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TableViewerColumn; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.ui.forms.IManagedForm; +import org.eclipse.ui.forms.editor.FormEditor; +import org.eclipse.ui.forms.editor.FormPage; +import org.eclipse.ui.forms.widgets.ScrolledForm; + +/** + * This comments will be nicely fill by mbaudier in. + */ +public class NodeRightsManagementPage extends FormPage { + // private final static Log log = + // LogFactory.getLog(NodeRightsManagementPage.class); + + private Node currentNode; + + private TableViewer viewer; + + public NodeRightsManagementPage(FormEditor editor, String title, + Node currentNode) { + super(editor, "NodeRightsManagementPage", title); + this.currentNode = currentNode; + } + + protected void createFormContent(IManagedForm managedForm) { + ScrolledForm form = managedForm.getForm(); + form.setText(JcrExplorerPlugin + .getMessage("nodeRightsManagementPageTitle")); + FillLayout layout = new FillLayout(); + layout.marginHeight = 5; + layout.marginWidth = 5; + form.getBody().setLayout(layout); + createRightsPart(form.getBody()); + } + + /** Creates the rights part */ + protected void createRightsPart(Composite parent) { + Table table = new Table(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); + table.setLinesVisible(true); + table.setHeaderVisible(true); + viewer = new TableViewer(table); + + // check column + TableViewerColumn column = createTableViewerColumn(viewer, "checked", + 20); + column.setLabelProvider(new ColumnLabelProvider() { + public String getText(Object element) { + return null; + } + + public Image getImage(Object element) { + return null; + } + }); + // column.setEditingSupport(new RoleEditingSupport(rolesViewer, part)); + + // role column + column = createTableViewerColumn(viewer, "Role", 200); + column.setLabelProvider(new ColumnLabelProvider() { + public String getText(Object element) { + Privilege p = (Privilege) element; + return p.getName(); + } + + public Image getImage(Object element) { + return null; + } + }); + viewer.setContentProvider(new RightsContentProvider()); + viewer.setInput(getEditorSite()); + } + + protected TableViewerColumn createTableViewerColumn(TableViewer viewer, + String title, int bound) { + final TableViewerColumn viewerColumn = new TableViewerColumn(viewer, + SWT.NONE); + final TableColumn column = viewerColumn.getColumn(); + column.setText(title); + column.setWidth(bound); + column.setResizable(true); + column.setMoveable(true); + return viewerColumn; + } + + private class RightsContentProvider implements IStructuredContentProvider { + + public void dispose() { + } + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + + public Object[] getElements(Object inputElement) { + try { + AccessControlManager accessControlManager = currentNode + .getSession().getAccessControlManager(); + Privilege[] privileges = accessControlManager + .getPrivileges(currentNode.getPath()); + return privileges; + } catch (Exception e) { + throw new ArgeoException("Cannot retrieve rights", e); + } + } + + } +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/NodeVersionHistoryPage.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/NodeVersionHistoryPage.java new file mode 100644 index 000000000..59fff5e59 --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/NodeVersionHistoryPage.java @@ -0,0 +1,319 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.editors; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; +import java.util.Map; + +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; +import javax.jcr.Value; +import javax.jcr.nodetype.NodeType; +import javax.jcr.version.Version; +import javax.jcr.version.VersionHistory; +import javax.jcr.version.VersionIterator; +import javax.jcr.version.VersionManager; + +import org.argeo.ArgeoException; +import org.argeo.jcr.JcrUtils; +import org.argeo.jcr.PropertyDiff; +import org.argeo.jcr.VersionDiff; +import org.argeo.jcr.ui.explorer.JcrExplorerConstants; +import org.argeo.jcr.ui.explorer.JcrExplorerPlugin; +import org.argeo.jcr.ui.explorer.providers.FullVersioningTreeContentProvider; +import org.argeo.jcr.ui.explorer.providers.VersionLabelProvider; +import org.argeo.jcr.ui.explorer.utils.GenericNodeDoubleClickListener; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.forms.AbstractFormPart; +import org.eclipse.ui.forms.IManagedForm; +import org.eclipse.ui.forms.editor.FormEditor; +import org.eclipse.ui.forms.editor.FormPage; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.ScrolledForm; +import org.eclipse.ui.forms.widgets.Section; +import org.eclipse.ui.forms.widgets.TableWrapData; +import org.eclipse.ui.forms.widgets.TableWrapLayout; + +/** + * Offers two main sections : one to display a text area with a summary of all + * variations between a version and its predecessor and one tree view that + * enable browsing + * */ +public class NodeVersionHistoryPage extends FormPage implements + JcrExplorerConstants { + // private final static Log log = LogFactory + // .getLog(NodeVersionHistoryPage.class); + + // Utils + protected DateFormat timeFormatter = new SimpleDateFormat(DATE_TIME_FORMAT); + + // business objects + private Node currentNode; + + // this page UI components + private FullVersioningTreeContentProvider nodeContentProvider; + private TreeViewer nodesViewer; + private FormToolkit tk; + + public NodeVersionHistoryPage(FormEditor editor, String title, + Node currentNode) { + super(editor, "NodeVersionHistoryPage", title); + this.currentNode = currentNode; + } + + protected void createFormContent(IManagedForm managedForm) { + ScrolledForm form = managedForm.getForm(); + form.setText(JcrExplorerPlugin + .getMessage("nodeVersionHistoryPageTitle")); + tk = managedForm.getToolkit(); + GridLayout twt = new GridLayout(1, false); + twt.marginWidth = twt.marginHeight = 5; + Composite body = form.getBody(); + body.setLayout(twt); + + try { + if (!currentNode.isNodeType(NodeType.MIX_VERSIONABLE)) { + tk.createLabel(body, JcrExplorerPlugin + .getMessage("warningUnversionableNode")); + } else { + createHistorySection(form.getBody()); + createTreeSection(form.getBody()); + } + } catch (RepositoryException e) { + throw new ArgeoException( + "Unexpected error while checking if node is versionable", e); + } + } + + protected void createTreeSection(Composite parent) { + // Section Layout & MetaData + Section section = tk.createSection(parent, Section.TWISTIE); + section.setLayoutData(new GridData(GridData.FILL_BOTH)); + section.setText(JcrExplorerPlugin.getMessage("versionTreeSectionTitle")); + + // Section Body + Composite body = tk.createComposite(section, SWT.FILL); + // WARNING : 2 following lines are compulsory or body won't be + // displayed. + body.setLayout(new GridLayout()); + section.setClient(body); + + body.setLayoutData(new GridData(GridData.FILL_BOTH)); + section.setExpanded(true); + + nodeContentProvider = new FullVersioningTreeContentProvider(); + nodesViewer = createNodeViewer(body, nodeContentProvider); + nodesViewer.setInput(currentNode); + } + + protected TreeViewer createNodeViewer(Composite parent, + final ITreeContentProvider nodeContentProvider) { + + final TreeViewer tmpNodeViewer = new TreeViewer(parent, SWT.MULTI); + + tmpNodeViewer.getTree().setLayoutData( + new GridData(SWT.FILL, SWT.FILL, true, true)); + + tmpNodeViewer.setContentProvider(nodeContentProvider); + tmpNodeViewer.setLabelProvider(new VersionLabelProvider()); + tmpNodeViewer + .addDoubleClickListener(new GenericNodeDoubleClickListener( + tmpNodeViewer)); + return tmpNodeViewer; + } + + protected void createHistorySection(Composite parent) { + + // Section Layout + Section section = tk.createSection(parent, Section.TWISTIE); + section.setLayoutData(new GridData(TableWrapData.FILL_GRAB)); + TableWrapLayout twt = new TableWrapLayout(); + section.setLayout(twt); + + // Set title of the section + section.setText(JcrExplorerPlugin + .getMessage("versionHistorySectionTitle")); + + final Text styledText = tk.createText(section, "", SWT.FULL_SELECTION + | SWT.BORDER | SWT.MULTI | SWT.WRAP | SWT.V_SCROLL); + styledText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + section.setClient(styledText); + refreshHistory(styledText); + styledText.setEditable(false); + section.setExpanded(false); + + AbstractFormPart part = new AbstractFormPart() { + public void commit(boolean onSave) { + } + + public void refresh() { + super.refresh(); + refreshHistory(styledText); + } + }; + getManagedForm().addPart(part); + } + + protected void refreshHistory(Text styledText) { + try { + List lst = listHistoryDiff(); + StringBuffer main = new StringBuffer(""); + + for (int i = lst.size() - 1; i >= 0; i--) { + if (i == 0) + main.append("Creation ("); + else + main.append("Update " + i + " ("); + + if (lst.get(i).getUserId() != null) + main.append("UserId : " + lst.get(i).getUserId()); + + if (lst.get(i).getUserId() != null + && lst.get(i).getUpdateTime() != null) + main.append(", "); + + if (lst.get(i).getUpdateTime() != null) + main.append("Date : " + + timeFormatter.format(lst.get(i).getUpdateTime() + .getTime()) + ")\n"); + + StringBuffer buf = new StringBuffer(""); + Map diffs = lst.get(i).getDiffs(); + for (String prop : diffs.keySet()) { + PropertyDiff pd = diffs.get(prop); + // String propName = pd.getRelPath(); + Value refValue = pd.getReferenceValue(); + Value newValue = pd.getNewValue(); + String refValueStr = ""; + String newValueStr = ""; + + if (refValue != null) { + if (refValue.getType() == PropertyType.DATE) { + refValueStr = timeFormatter.format(refValue + .getDate().getTime()); + } else + refValueStr = refValue.getString(); + } + if (newValue != null) { + if (newValue.getType() == PropertyType.DATE) { + newValueStr = timeFormatter.format(newValue + .getDate().getTime()); + } else + newValueStr = newValue.getString(); + } + + if (pd.getType() == PropertyDiff.MODIFIED) { + buf.append(prop).append(": "); + buf.append(refValueStr); + buf.append(" > "); + buf.append(newValueStr); + buf.append("\n"); + } else if (pd.getType() == PropertyDiff.ADDED + && !"".equals(newValueStr)) { + // we don't list property that have been added with an + // empty string as value + buf.append(prop).append(": "); + buf.append(" + "); + buf.append(newValueStr); + buf.append("\n"); + } else if (pd.getType() == PropertyDiff.REMOVED) { + buf.append(prop).append(": "); + buf.append(" - "); + buf.append(refValueStr); + buf.append("\n"); + } + } + buf.append("\n"); + main.append(buf); + } + styledText.setText(main.toString()); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot generate history for node", e); + } + + } + + public List listHistoryDiff() { + try { + List res = new ArrayList(); + VersionManager versionManager = currentNode.getSession() + .getWorkspace().getVersionManager(); + VersionHistory versionHistory = versionManager + .getVersionHistory(currentNode.getPath()); + + VersionIterator vit = versionHistory.getAllLinearVersions(); + while (vit.hasNext()) { + Version version = vit.nextVersion(); + Node node = version.getFrozenNode(); + Version predecessor = null; + try { + predecessor = version.getLinearPredecessor(); + } catch (Exception e) { + // no predecessor seems to throw an exception even if it + // shouldn't... + } + if (predecessor == null) {// original + } else { + Map diffs = JcrUtils.diffProperties( + predecessor.getFrozenNode(), node); + if (!diffs.isEmpty()) { + String lastUserName = null; + Calendar lastUpdate = null; + try { + if (currentNode + .isNodeType(NodeType.MIX_LAST_MODIFIED)) { + lastUserName = node.getProperty( + Property.JCR_LAST_MODIFIED_BY) + .getString(); + lastUpdate = node.getProperty( + Property.JCR_LAST_MODIFIED).getDate(); + } else + lastUpdate = version.getProperty( + Property.JCR_CREATED).getDate(); + + } catch (Exception e) { + // Silent that info is optional + } + VersionDiff vd = new VersionDiff(lastUserName, + lastUpdate, diffs); + res.add(vd); + } + } + } + return res; + } catch (RepositoryException e) { + throw new ArgeoException("Cannot generate history for node "); + } + + } + + @Override + public void setActive(boolean active) { + super.setActive(active); + } +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/StringNodeEditorInput.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/StringNodeEditorInput.java new file mode 100644 index 000000000..654b2aeea --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/StringNodeEditorInput.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.editors; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IPersistableElement; + +/** + * An editor input based on three strings define a node : + *
    + *
  • complete path to the node
  • + *
  • the workspace name
  • + *
  • the repository alias
  • + *
+ * In a single workspace and/or repository environment, name and alias can be + * null. + * + * Note : unused for the time being. + */ + +public class StringNodeEditorInput implements IEditorInput { + private final String path; + private final String repositoryAlias; + private final String workspaceName; + + /** + * In order to implement a generic explorer that supports remote and multi + * workspaces repositories, node path can be detailed by these strings. + * + * @param repositoryAlias + * : can be null + * @param workspaceName + * : can be null + * @param path + */ + public StringNodeEditorInput(String repositoryAlias, String workspaceName, + String path) { + this.path = path; + this.repositoryAlias = repositoryAlias; + this.workspaceName = workspaceName; + } + + public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) { + return null; + } + + public boolean exists() { + return true; + } + + public ImageDescriptor getImageDescriptor() { + return null; + } + + public String getName() { + return path; + } + + public String getRepositoryAlias() { + return repositoryAlias; + } + + public String getWorkspaceName() { + return workspaceName; + } + + public IPersistableElement getPersistable() { + return null; + } + + public String getToolTipText() { + return path; + } + + public String getPath() { + return path; + } + + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + + StringNodeEditorInput other = (StringNodeEditorInput) obj; + + if (!path.equals(other.getPath())) + return false; + + String own = other.getWorkspaceName(); + if ((workspaceName == null && own != null) + || (workspaceName != null && (own == null || !workspaceName + .equals(own)))) + return false; + + String ora = other.getRepositoryAlias(); + if ((repositoryAlias == null && ora != null) + || (repositoryAlias != null && (ora == null || !repositoryAlias + .equals(ora)))) + return false; + + return true; + } +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/MaintainedRepositoryElem.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/MaintainedRepositoryElem.java new file mode 100644 index 000000000..abb97a9e8 --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/MaintainedRepositoryElem.java @@ -0,0 +1,24 @@ +package org.argeo.jcr.ui.explorer.model; + +import javax.jcr.Repository; + +import org.argeo.ArgeoException; +import org.argeo.eclipse.ui.TreeParent; +import org.argeo.jcr.MaintainedRepository; + +/** Wraps a {@link MaintainedRepository} */ +public class MaintainedRepositoryElem extends RepositoryElem { + + public MaintainedRepositoryElem(String alias, Repository repository, + TreeParent parent) { + super(alias, repository, parent); + if (!(repository instanceof MaintainedRepository)) { + throw new ArgeoException("Repository " + alias + + " is not amiantained repository"); + } + } + + protected MaintainedRepository getMaintainedRepository() { + return (MaintainedRepository) getRepository(); + } +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/RemoteRepositoryElem.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/RemoteRepositoryElem.java new file mode 100644 index 000000000..0be69781c --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/RemoteRepositoryElem.java @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.model; + +import java.util.Arrays; + +import javax.jcr.Node; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.RepositoryFactory; +import javax.jcr.Session; +import javax.jcr.SimpleCredentials; + +import org.argeo.ArgeoException; +import org.argeo.eclipse.ui.TreeParent; +import org.argeo.jcr.ArgeoJcrUtils; +import org.argeo.jcr.ArgeoNames; +import org.argeo.util.security.Keyring; + +/** Root of a remote repository */ +public class RemoteRepositoryElem extends RepositoryElem { + private final Keyring keyring; + /** + * A session of the logged in user on the default workspace of the node + * repository. + */ + private final Session userSession; + private final String remoteNodePath; + + private final RepositoryFactory repositoryFactory; + private final String uri; + + public RemoteRepositoryElem(String alias, + RepositoryFactory repositoryFactory, String uri, TreeParent parent, + Session userSession, Keyring keyring, String remoteNodePath) { + super(alias, null, parent); + this.repositoryFactory = repositoryFactory; + this.uri = uri; + this.keyring = keyring; + this.userSession = userSession; + this.remoteNodePath = remoteNodePath; + } + + @Override + protected Session repositoryLogin(String workspaceName) + throws RepositoryException { + Node remoteRepository = userSession.getNode(remoteNodePath); + String userID = remoteRepository.getProperty(ArgeoNames.ARGEO_USER_ID) + .getString(); + String pwdPath = remoteRepository.getPath() + '/' + + ArgeoNames.ARGEO_PASSWORD; + char[] password = keyring.getAsChars(pwdPath); + + try { + SimpleCredentials credentials = new SimpleCredentials(userID, + password); + return getRepository().login(credentials, workspaceName); + } finally { + Arrays.fill(password, 0, password.length, ' '); + } + } + + @Override + public Repository getRepository() { + if (repository == null) + repository = ArgeoJcrUtils.getRepositoryByUri(repositoryFactory, + uri); + return super.getRepository(); + } + + public void remove() { + try { + Node remoteNode = userSession.getNode(remoteNodePath); + remoteNode.remove(); + remoteNode.getSession().save(); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot remove " + remoteNodePath, e); + } + } + +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/RepositoriesElem.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/RepositoriesElem.java new file mode 100644 index 000000000..b123727bc --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/RepositoriesElem.java @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.model; + +import java.util.Map; + +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.RepositoryFactory; +import javax.jcr.Session; + +import org.argeo.ArgeoException; +import org.argeo.eclipse.ui.ErrorFeedback; +import org.argeo.eclipse.ui.TreeParent; +import org.argeo.jcr.ArgeoNames; +import org.argeo.jcr.MaintainedRepository; +import org.argeo.jcr.RepositoryRegister; +import org.argeo.jcr.UserJcrUtils; +import org.argeo.util.security.Keyring; + +/** + * UI Tree component. Implements the Argeo abstraction of a + * {@link RepositoryFactory} that enable a user to "mount" various repositories + * in a single Tree like View. It is usually meant to be at the root of the UI + * Tree and thus {@link getParent()} method will return null. + * + * The {@link RepositoryFactory} is injected at instantiation time and must be + * use get or register new {@link Repository} objects upon which a reference is + * kept here. + */ + +public class RepositoriesElem extends TreeParent implements ArgeoNames { + private final RepositoryRegister repositoryRegister; + private final RepositoryFactory repositoryFactory; + + /** + * A session of the logged in user on the default workspace of the node + * repository. + */ + private final Session userSession; + private final Keyring keyring; + + public RepositoriesElem(String name, RepositoryRegister repositoryRegister, + RepositoryFactory repositoryFactory, TreeParent parent, + Session userSession, Keyring keyring) { + super(name); + this.repositoryRegister = repositoryRegister; + this.repositoryFactory = repositoryFactory; + this.userSession = userSession; + this.keyring = keyring; + } + + /** + * Override normal behavior to initialize the various repositories only at + * request time + */ + @Override + public synchronized Object[] getChildren() { + if (isLoaded()) { + return super.getChildren(); + } else { + // initialize current object + Map refRepos = repositoryRegister + .getRepositories(); + for (String name : refRepos.keySet()) { + Repository repository = refRepos.get(name); + if (repository instanceof MaintainedRepository) + super.addChild(new MaintainedRepositoryElem(name, + repository, this)); + else + super.addChild(new RepositoryElem(name, repository, this)); + } + + // remote + if (keyring != null) { + try { + addRemoteRepositories(keyring); + } catch (RepositoryException e) { + throw new ArgeoException( + "Cannot browse remote repositories", e); + } + } + return super.getChildren(); + } + } + + protected void addRemoteRepositories(Keyring jcrKeyring) + throws RepositoryException { + Node userHome = UserJcrUtils.getUserHome(userSession); + if (userHome != null && userHome.hasNode(ARGEO_REMOTE)) { + NodeIterator it = userHome.getNode(ARGEO_REMOTE).getNodes(); + while (it.hasNext()) { + Node remoteNode = it.nextNode(); + String uri = remoteNode.getProperty(ARGEO_URI).getString(); + try { + RemoteRepositoryElem remoteRepositoryNode = new RemoteRepositoryElem( + remoteNode.getName(), repositoryFactory, uri, this, + userSession, jcrKeyring, remoteNode.getPath()); + super.addChild(remoteRepositoryNode); + } catch (Exception e) { + ErrorFeedback.show("Cannot add remote repository " + + remoteNode, e); + } + } + } + } + + public void registerNewRepository(String alias, Repository repository) { + // TODO: implement this + // Create a new RepositoryNode Object + // add it + // super.addChild(new RepositoriesNode(...)); + } + + /** Returns the {@link RepositoryRegister} wrapped by this object. */ + public RepositoryRegister getRepositoryRegister() { + return repositoryRegister; + } +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/RepositoryElem.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/RepositoryElem.java new file mode 100644 index 000000000..935bac12b --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/RepositoryElem.java @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.model; + +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.argeo.ArgeoException; +import org.argeo.eclipse.ui.TreeParent; + +/** + * UI Tree component. Wraps a JCR {@link Repository}. It also keeps a reference + * to its parent Tree Ui component; typically the unique {@link Repositories} + * object of the current view to enable bi-directionnal browsing in the tree. + */ + +public class RepositoryElem extends TreeParent { + private String alias; + protected Repository repository; + private Session defaultSession = null; + + /** Create a new repository with distinct name & alias */ + public RepositoryElem(String alias, Repository repository, TreeParent parent) { + super(alias); + this.repository = repository; + setParent(parent); + this.alias = alias; + } + + public void login() { + try { + defaultSession = repositoryLogin(null); + String[] wkpNames = defaultSession.getWorkspace() + .getAccessibleWorkspaceNames(); + for (String wkpName : wkpNames) { + if (wkpName.equals(defaultSession.getWorkspace().getName())) + addChild(new WorkspaceElem(this, wkpName, defaultSession)); + else + addChild(new WorkspaceElem(this, wkpName)); + } + } catch (RepositoryException e) { + throw new ArgeoException("Cannot connect to repository " + alias, e); + } + } + + /** + * Actual call to the + * {@link Repository#login(javax.jcr.Credentials, String)} method. To be + * overridden. + */ + protected Session repositoryLogin(String workspaceName) + throws RepositoryException { + return repository.login(workspaceName); + } + + public String[] getAccessibleWorkspaceNames() { + try { + return defaultSession.getWorkspace().getAccessibleWorkspaceNames(); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot retrieve workspace names", e); + } + } + + public void createWorkspace(String workspaceName) { + if (!isConnected()) + login(); + try { + defaultSession.getWorkspace().createWorkspace(workspaceName); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot create workspace", e); + } + } + + /** returns the {@link Repository} referenced by the current UI Node */ + public Repository getRepository() { + return repository; + } + + public String getAlias() { + return alias; + } + + public Boolean isConnected() { + if (defaultSession != null && defaultSession.isLive()) + return true; + else + return false; + } +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/SingleJcrNodeElem.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/SingleJcrNodeElem.java new file mode 100644 index 000000000..7b588f83b --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/SingleJcrNodeElem.java @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.model; + +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.RepositoryException; +import javax.jcr.Workspace; + +import org.argeo.ArgeoException; +import org.argeo.eclipse.ui.TreeParent; + +/** + * UI Tree component. Wraps a node of a JCR {@link Workspace}. It also keeps a + * reference to its parent node that can either be a {@link WorkspaceElem}, a + * {@link SingleJcrNodeElem} or null if the node is "mounted" as the root of the UI + * tree. + */ + +public class SingleJcrNodeElem extends TreeParent { + + private final Node node; + private String alias = null; + + // keeps a local reference to the node's name to avoid exception when the + // session is lost + // private final String name; + + /** Creates a new UiNode in the UI Tree */ + public SingleJcrNodeElem(TreeParent parent, Node node, String name) { + super(name); + setParent(parent); + this.node = node; + } + + /** + * Creates a new UiNode in the UI Tree, keeping a reference to the alias of + * the corresponding repository in the current UI environment. It is useful + * to be able to mount nodes as roots of the UI tree. + */ + public SingleJcrNodeElem(TreeParent parent, Node node, String name, String alias) { + super(name); + setParent(parent); + this.node = node; + this.alias = alias; + } + + /** returns the node wrapped by the current Ui object */ + public Node getNode() { + return node; + } + + protected String getRepositoryAlias() { + return alias; + } + + /** + * Override normal behavior to initialize children only when first requested + */ + @Override + public synchronized Object[] getChildren() { + if (isLoaded()) { + return super.getChildren(); + } else { + // initialize current object + try { + NodeIterator ni = node.getNodes(); + while (ni.hasNext()) { + Node curNode = ni.nextNode(); + addChild(new SingleJcrNodeElem(this, curNode, curNode.getName())); + } + return super.getChildren(); + } catch (RepositoryException re) { + throw new ArgeoException( + "Unexcpected error while initializing children SingleJcrNode", + re); + } + } + } + + @Override + public boolean hasChildren() { + try { + if (node.getSession().isLive()) + return node.hasNodes(); + else + return false; + } catch (RepositoryException re) { + throw new ArgeoException( + "Unexpected error while checking children node existence", + re); + } + } + +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/WorkspaceElem.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/WorkspaceElem.java new file mode 100644 index 000000000..bb9b69caf --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/WorkspaceElem.java @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.model; + +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.Workspace; + +import org.argeo.ArgeoException; +import org.argeo.eclipse.ui.TreeParent; +import org.argeo.jcr.JcrUtils; + +/** + * UI Tree component. Wraps the root node of a JCR {@link Workspace}. It also + * keeps a reference to its parent {@link RepositoryElem}, to be able to + * retrieve alias of the current used repository + */ +public class WorkspaceElem extends TreeParent { + private Session session = null; + + public WorkspaceElem(RepositoryElem parent, String name) { + this(parent, name, null); + } + + public WorkspaceElem(RepositoryElem parent, String name, Session session) { + super(name); + this.session = session; + setParent(parent); + } + + public Session getSession() { + return session; + } + + public Node getRootNode() { + try { + if (session != null) + return session.getRootNode(); + else + return null; + } catch (RepositoryException e) { + throw new ArgeoException("Cannot get root node of workspace " + + getName(), e); + } + } + + public void login() { + try { + session = ((RepositoryElem) getParent()).repositoryLogin(getName()); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot connect to repository " + + getName(), e); + } + } + + public Boolean isConnected() { + if (session != null && session.isLive()) + return true; + else + return false; + } + + @Override + public synchronized void dispose() { + logout(); + super.dispose(); + } + + /** Logouts the session, does not nothing if there is no live session. */ + public void logout() { + clearChildren(); + JcrUtils.logoutQuietly(session); + } + + @Override + public boolean hasChildren() { + try { + if (isConnected()) + return session.getRootNode().hasNodes(); + else + return false; + } catch (RepositoryException re) { + throw new ArgeoException( + "Unexpected error while checking children node existence", + re); + } + } + + /** Override normal behaviour to initialize display of the workspace */ + @Override + public synchronized Object[] getChildren() { + if (isLoaded()) { + return super.getChildren(); + } else { + // initialize current object + try { + Node rootNode; + if (session == null) + return null; + else + rootNode = session.getRootNode(); + NodeIterator ni = rootNode.getNodes(); + while (ni.hasNext()) { + Node node = ni.nextNode(); + addChild(new SingleJcrNodeElem(this, node, node.getName())); + } + return super.getChildren(); + } catch (RepositoryException e) { + throw new ArgeoException( + "Cannot initialize WorkspaceNode UI object." + + getName(), e); + } + } + } +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/providers/FullVersioningTreeContentProvider.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/providers/FullVersioningTreeContentProvider.java new file mode 100644 index 000000000..736a5aa2f --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/providers/FullVersioningTreeContentProvider.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.providers; + +import java.util.ArrayList; +import java.util.List; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.nodetype.NodeType; +import javax.jcr.version.Version; +import javax.jcr.version.VersionHistory; +import javax.jcr.version.VersionIterator; +import javax.jcr.version.VersionManager; + +import org.argeo.ArgeoException; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.Viewer; + +/** + * Implementation of the {@code ITreeContentProvider} in order to display some + * version informations of a JCR full versionable node in a tree like structure + * + */ +public class FullVersioningTreeContentProvider implements ITreeContentProvider { + // private Node rootNode; + // private ItemComparator itemComparator = new ItemComparator(); + + /** + * Sends back the first level of the Tree. input element must be a single + * node object + */ + public Object[] getElements(Object inputElement) { + try { + Node rootNode = (Node) inputElement; + String curPath = rootNode.getPath(); + VersionManager vm = rootNode.getSession().getWorkspace() + .getVersionManager(); + + VersionHistory vh = vm.getVersionHistory(curPath); + List result = new ArrayList(); + VersionIterator vi = vh.getAllLinearVersions(); + + while (vi.hasNext()) { + result.add(vi.nextVersion()); + } + return result.toArray(); + } catch (RepositoryException re) { + throw new ArgeoException( + "Unexpected error while getting version elements", re); + } + } + + public Object[] getChildren(Object parentElement) { + try { + if (parentElement instanceof Version) { + List tmp = new ArrayList(); + tmp.add(((Version) parentElement).getFrozenNode()); + return tmp.toArray(); + } + } catch (RepositoryException re) { + throw new ArgeoException("Unexpected error while getting child " + + "node for version element", re); + } + return null; + } + + public Object getParent(Object element) { + try { + // this will not work in a simpleVersionning environment, parent is + // not a node. + if (element instanceof Node + && ((Node) element).isNodeType(NodeType.NT_FROZEN_NODE)) { + Node node = (Node) element; + return node.getParent(); + } else + return null; + } catch (RepositoryException e) { + return null; + } + } + + public boolean hasChildren(Object element) { + try { + if (element instanceof Version) + return true; + else if (element instanceof Node) + return ((Node) element).hasNodes(); + else + return false; + } catch (RepositoryException e) { + throw new ArgeoException("Cannot check children of " + element, e); + } + } + + public void dispose() { + } + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/providers/PropertyLabelProvider.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/providers/PropertyLabelProvider.java new file mode 100644 index 000000000..decbe6338 --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/providers/PropertyLabelProvider.java @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.providers; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; + +import javax.jcr.Property; +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; +import javax.jcr.Value; + +import org.argeo.ArgeoException; +import org.argeo.jcr.JcrUtils; +import org.argeo.jcr.ui.explorer.JcrExplorerConstants; +import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.jface.viewers.ViewerCell; + +public class PropertyLabelProvider extends ColumnLabelProvider implements + JcrExplorerConstants { + + // To be able to change column order easily + public static final int COLUMN_PROPERTY = 0; + public static final int COLUMN_VALUE = 1; + public static final int COLUMN_ATTRIBUTES = 2; + + // Utils + protected DateFormat timeFormatter = new SimpleDateFormat(DATE_TIME_FORMAT); + + public void update(ViewerCell cell) { + Object element = cell.getElement(); + cell.setText(getColumnText(element, cell.getColumnIndex())); + // Image image = getImage(element); + // cell.setImage(image); + // cell.setBackground(getBackground(element)); + // cell.setForeground(getForeground(element)); + // cell.setFont(getFont(element)); + } + + public String getColumnText(Object element, int columnIndex) { + try { + if (element instanceof Property) { + Property prop = (Property) element; + if (prop.isMultiple()) { + switch (columnIndex) { + case COLUMN_PROPERTY: + return prop.getName(); + case COLUMN_VALUE: + // Corresponding values are listed on children + return ""; + case COLUMN_ATTRIBUTES: + return JcrUtils.getPropertyDefinitionAsString(prop); + } + } else { + switch (columnIndex) { + case COLUMN_PROPERTY: + return prop.getName(); + case COLUMN_VALUE: + return formatValueAsString(prop.getValue()); + case COLUMN_ATTRIBUTES: + return JcrUtils.getPropertyDefinitionAsString(prop); + } + } + } else if (element instanceof Value) { + Value val = (Value) element; + + switch (columnIndex) { + case COLUMN_PROPERTY: + // Nothing to show + return ""; + case COLUMN_VALUE: + return formatValueAsString(val); + case COLUMN_ATTRIBUTES: + // Corresponding attributes are listed on the parent + return ""; + } + } + + } catch (RepositoryException re) { + throw new ArgeoException( + "Unexepected error while getting property values", re); + } + return null; + } + + private String formatValueAsString(Value value) { + // TODO enhance this method + try { + String strValue; + + if (value.getType() == PropertyType.BINARY) + strValue = ""; + else if (value.getType() == PropertyType.DATE) + strValue = timeFormatter.format(value.getDate().getTime()); + else + strValue = value.getString(); + return strValue; + } catch (RepositoryException e) { + throw new ArgeoException("unexpected error while formatting value", + e); + } + } +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/providers/SingleNodeAsTreeContentProvider.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/providers/SingleNodeAsTreeContentProvider.java new file mode 100644 index 000000000..8c69b6b9c --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/providers/SingleNodeAsTreeContentProvider.java @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.providers; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.RepositoryException; + +import org.argeo.ArgeoException; +import org.argeo.eclipse.ui.jcr.utils.JcrItemsComparator; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.Viewer; + +/** + * Implementation of the {@code ITreeContentProvider} in order to display a + * single JCR node and its children in a tree like structure + * + */ +public class SingleNodeAsTreeContentProvider implements ITreeContentProvider { + // private Node rootNode; + private JcrItemsComparator itemComparator = new JcrItemsComparator(); + + /** + * Sends back the first level of the Tree. input element must be a single + * node object + */ + public Object[] getElements(Object inputElement) { + try { + Node rootNode = (Node) inputElement; + List result = new ArrayList(); + NodeIterator ni = rootNode.getNodes(); + while (ni.hasNext()) { + result.add(ni.nextNode()); + } + + return result.toArray(); + } catch (RepositoryException re) { + throw new ArgeoException( + "Unexpected error while getting child nodes for children editor page ", + re); + } + } + + public Object[] getChildren(Object parentElement) { + return childrenNodes((Node) parentElement); + } + + public Object getParent(Object element) { + try { + Node node = (Node) element; + if (!node.getPath().equals("/")) + return node.getParent(); + else + return null; + } catch (RepositoryException e) { + return null; + } + } + + public boolean hasChildren(Object element) { + try { + return ((Node) element).hasNodes(); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot check children of " + element, e); + } + } + + public void dispose() { + } + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + + protected Object[] childrenNodes(Node parentNode) { + try { + List children = new ArrayList(); + NodeIterator nit = parentNode.getNodes(); + while (nit.hasNext()) { + Node node = nit.nextNode(); + children.add(node); + } + Node[] arr = children.toArray(new Node[children.size()]); + Arrays.sort(arr, itemComparator); + return arr; + } catch (RepositoryException e) { + throw new ArgeoException("Cannot list children of " + parentNode, e); + } + } +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/providers/VersionLabelProvider.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/providers/VersionLabelProvider.java new file mode 100644 index 000000000..69b35ebb5 --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/providers/VersionLabelProvider.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.providers; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.version.Version; + +import org.argeo.ArgeoException; +import org.eclipse.jface.viewers.ColumnLabelProvider; + +/** + * simple wrapping of the ColumnLabelProvider class to provide text display in + * order to build a tree for version. The Get text method does not assume that + * Version extends Node class to respect JCR 2.0 specification + * + */ +public class VersionLabelProvider extends ColumnLabelProvider { + + public String getText(Object element) { + try { + if (element instanceof Version) { + Version version = (Version) element; + return version.getName(); + } else if (element instanceof Node) { + return ((Node) element).getName(); + } + } catch (RepositoryException re) { + throw new ArgeoException( + "Unexpected error while getting element name", re); + } + return super.getText(element); + } +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/utils/GenericNodeDoubleClickListener.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/utils/GenericNodeDoubleClickListener.java new file mode 100644 index 000000000..0f93450eb --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/utils/GenericNodeDoubleClickListener.java @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.utils; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.nodetype.NodeType; + +import org.argeo.ArgeoException; +import org.argeo.eclipse.ui.jcr.utils.JcrFileProvider; +import org.argeo.eclipse.ui.specific.FileHandler; +import org.argeo.jcr.ui.explorer.JcrExplorerPlugin; +import org.argeo.jcr.ui.explorer.editors.GenericNodeEditor; +import org.argeo.jcr.ui.explorer.editors.GenericNodeEditorInput; +import org.argeo.jcr.ui.explorer.model.RepositoryElem; +import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem; +import org.argeo.jcr.ui.explorer.model.WorkspaceElem; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.ui.PartInitException; + +/** + * Centralizes the management of double click on a NodeTreeViewer + */ +public class GenericNodeDoubleClickListener implements IDoubleClickListener { + + // private final static Log log = LogFactory + // .getLog(GenericNodeDoubleClickListener.class); + + private TreeViewer nodeViewer; + private JcrFileProvider jfp; + private FileHandler fileHandler; + + public GenericNodeDoubleClickListener(TreeViewer nodeViewer) { + this.nodeViewer = nodeViewer; + jfp = new JcrFileProvider(); + // Commented out. see https://www.argeo.org/bugzilla/show_bug.cgi?id=188 + fileHandler = null; + // fileHandler = new FileHandler(jfp); + } + + public void doubleClick(DoubleClickEvent event) { + if (event.getSelection() == null || event.getSelection().isEmpty()) + return; + Object obj = ((IStructuredSelection) event.getSelection()) + .getFirstElement(); + if (obj instanceof RepositoryElem) { + RepositoryElem rpNode = (RepositoryElem) obj; + if (!rpNode.isConnected()) { + rpNode.login(); + nodeViewer.refresh(obj); + } + // else do nothing + } else if (obj instanceof WorkspaceElem) { + WorkspaceElem wn = (WorkspaceElem) obj; + if (wn.isConnected()) + wn.logout(); + else + wn.login(); + nodeViewer.refresh(obj); + } else if (obj instanceof SingleJcrNodeElem) { + SingleJcrNodeElem sjn = (SingleJcrNodeElem) obj; + Node node = sjn.getNode(); + try { + if (node.isNodeType(NodeType.NT_FILE)) { + // double click on a file node triggers its opening + String name = node.getName(); + String id = node.getIdentifier(); + + // For the file provider to be able to browse the + // various + // repository. + // TODO : enhanced that. + // ITreeContentProvider itcp = (ITreeContentProvider) + // nodeViewer + // .getContentProvider(); + jfp.setReferenceNode(node); + if (fileHandler != null) + fileHandler.openFile(name, id); + } + GenericNodeEditorInput gnei = new GenericNodeEditorInput(node); + JcrExplorerPlugin.getDefault().getWorkbench() + .getActiveWorkbenchWindow().getActivePage() + .openEditor(gnei, GenericNodeEditor.ID); + } catch (RepositoryException re) { + throw new ArgeoException( + "Repository error while getting node info", re); + } catch (PartInitException pie) { + throw new ArgeoException( + "Unexepected exception while opening node editor", pie); + } + } + } +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/utils/JcrUiUtils.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/utils/JcrUiUtils.java new file mode 100644 index 000000000..ca32113ed --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/utils/JcrUiUtils.java @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.utils; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; + +import org.argeo.ArgeoException; +import org.argeo.eclipse.ui.TreeParent; +import org.argeo.jcr.ui.explorer.model.RepositoriesElem; +import org.argeo.jcr.ui.explorer.model.RepositoryElem; +import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem; +import org.argeo.jcr.ui.explorer.model.WorkspaceElem; + +/** Centralizes some useful methods to build UIs with JCR */ +public class JcrUiUtils { + + /** Insure that the UI component is not stale, refresh if needed */ + public static void forceRefreshIfNeeded(TreeParent element) { + Node curNode = null; + + boolean doRefresh = false; + + try { + if (element instanceof SingleJcrNodeElem) { + curNode = ((SingleJcrNodeElem) element).getNode(); + } else if (element instanceof WorkspaceElem) { + curNode = ((WorkspaceElem) element).getRootNode(); + } + + if (curNode != null + && element.getChildren().length != curNode.getNodes() + .getSize()) + doRefresh = true; + else if (element instanceof RepositoryElem) { + RepositoryElem rn = (RepositoryElem) element; + if (rn.isConnected()) { + String[] wkpNames = rn.getAccessibleWorkspaceNames(); + if (element.getChildren().length != wkpNames.length) + doRefresh = true; + } + } else if (element instanceof RepositoriesElem) { + doRefresh = true; + // Always force refresh for RepositoriesElem : the condition + // below does not take remote repository into account and it is + // not trivial to do so. + + // RepositoriesElem rn = (RepositoriesElem) element; + // if (element.getChildren().length != + // rn.getRepositoryRegister() + // .getRepositories().size()) + // doRefresh = true; + } + if (doRefresh) { + element.clearChildren(); + element.getChildren(); + } + } catch (RepositoryException re) { + throw new ArgeoException( + "Unexpected error while synchronising the UI with the JCR repository", + re); + } + } + + /** + * Insure that a model element is inline with the underlying data by + * cleaning the corresponding subtree and building it again. + */ + public static void forceRebuild(TreeParent element) { + // TODO implement this method if needed. + } + /** + * Workaround to get the alias of the repository that contains the given + * element. As we cannot browse the UI tree upward we recursively browse it + * downward until we find the given element + * */ + // public static String getRepositoryAliasFromITreeElement( + // NodeContentProvider ncp, Object element) { + // RepositoryNode repositoryNode = null; + // if (element instanceof RepositoryNode) + // return ((RepositoryNode) element).getName(); + // else if (element instanceof RepositoryRegister) + // throw new ArgeoException( + // "Cannot get alias for a repository register"); + // + // // Get root elements + // Object[] elements = ncp.getElements(null); + // + // try { + // for (int i = 0; i < elements.length; i++) { + // if (elements[i] instanceof Node) { + // Node curNode = (Node) elements[i]; + // if (curNode.isNodeType(ArgeoTypes.ARGEO_USER_HOME)) { + // // Do nothing, we'll find the node in the "normal" tree + // // and + // // get corresponding alias this way round + // } else + // throw new ArgeoException( + // "Normal nodes should not be at the root of NodeTreeViewer"); + // } else if (elements[i] instanceof RepositoryRegister) { + // RepositoryRegister repositoryRegister = (RepositoryRegister) elements[i]; + // Map repositories = repositoryRegister + // .getRepositories(); + // + // for (String name : repositories.keySet()) { + // boolean found = isElementInCurrentTreePart( + // ncp, + // new RepositoryNode(name, repositories.get(name)), + // (Node) element); + // if (found) + // return name; + // } + // } else + // throw new ArgeoException( + // "Unexpected object class at the root of NodeTreeViewer"); + // } + // } catch (RepositoryException re) { + // throw new ArgeoException( + // "Unexpected error while retrieving Alias name", re); + // } + // return null; + // } + // + // /** implements the recursivity */ + // private static boolean isElementInCurrentTreePart(NodeContentProvider + // ncp, + // Object parentElement, NodParente searchedElement) { + // boolean found = false; + // if (parentElement instanceof WorkspaceNode) { + // WorkspaceNode wn = (WorkspaceNode) parentElement; + // Object[] children = wn.getChildren(); + // int i = children.length - 1; + // while (!found && i >= 0) { + // found = isElementInCurrentTreePart(ncp, children[i], + // searchedElement); + // } + // return found; + // } else if (parentElement instanceof RepositoryNode) { + // RepositoryNode rn = (RepositoryNode) parentElement; + // Object[] children = rn.getChildren(); + // int i = children.length - 1; + // while (!found && i >= 0) { + // found = isElementInCurrentTreePart(ncp, children[i], + // searchedElement); + // } + // return found; + // } else { + // Node node = (Node) parentElement; + // if (node.equals(searchedElement)) + // return true; + // NodeIterator ni; + // try { + // ni = node.getNodes(); + // while (!found && ni.hasNext()) { + // found = isElementInCurrentTreePart(ncp, ni.nextNode(), + // searchedElement); + // } + // } catch (RepositoryException e) { + // throw new ArgeoException("unexpected erreur while recursively" + // + " recovering RepositoryNode for selected object", e); + // } + // + // return found; + // } + // } +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/utils/TreeObjectsComparator.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/utils/TreeObjectsComparator.java new file mode 100644 index 000000000..02450d6ed --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/utils/TreeObjectsComparator.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.utils; + +import java.util.Comparator; + +import org.argeo.eclipse.ui.TreeParent; + +public class TreeObjectsComparator implements Comparator { + public int compare(TreeParent o1, TreeParent o2) { + return o1.getName().compareTo(o2.getName()); + } +} \ No newline at end of file diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/views/GenericJcrBrowser.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/views/GenericJcrBrowser.java new file mode 100644 index 000000000..f401ae8fe --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/views/GenericJcrBrowser.java @@ -0,0 +1,357 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.views; + +import java.util.List; + +import javax.jcr.Property; +import javax.jcr.PropertyType; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.RepositoryFactory; +import javax.jcr.Session; +import javax.jcr.Value; +import javax.jcr.observation.Event; +import javax.jcr.observation.EventListener; +import javax.jcr.observation.ObservationManager; + +import org.argeo.ArgeoException; +import org.argeo.eclipse.ui.TreeParent; +import org.argeo.eclipse.ui.jcr.AsyncUiEventListener; +import org.argeo.eclipse.ui.jcr.utils.NodeViewerComparer; +import org.argeo.eclipse.ui.jcr.views.AbstractJcrBrowser; +import org.argeo.jcr.RepositoryRegister; +import org.argeo.jcr.ui.explorer.JcrExplorerPlugin; +import org.argeo.jcr.ui.explorer.browser.NodeContentProvider; +import org.argeo.jcr.ui.explorer.browser.NodeLabelProvider; +import org.argeo.jcr.ui.explorer.browser.PropertiesContentProvider; +import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem; +import org.argeo.jcr.ui.explorer.utils.GenericNodeDoubleClickListener; +import org.argeo.jcr.ui.explorer.utils.JcrUiUtils; +import org.argeo.util.security.Keyring; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TableViewerColumn; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.SashForm; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Menu; + +/** + * Basic View to display a sash form to browse a JCR compliant multirepository + * environment + */ +public class GenericJcrBrowser extends AbstractJcrBrowser { + public final static String ID = JcrExplorerPlugin.ID + ".browserView"; + private boolean sortChildNodes = true; + + /* DEPENDENCY INJECTION */ + private Keyring keyring; + private RepositoryRegister repositoryRegister; + private RepositoryFactory repositoryFactory; + private Repository nodeRepository; + /** + * A session of the logged in user on the default workspace of the node + * repository. + */ + private Session userSession; + + // This page widgets + private TreeViewer nodesViewer; + private NodeContentProvider nodeContentProvider; + private TableViewer propertiesViewer; + private EventListener resultsObserver; + + @Override + public void createPartControl(Composite parent) { + parent.setLayout(new FillLayout()); + SashForm sashForm = new SashForm(parent, SWT.VERTICAL); + sashForm.setSashWidth(4); + sashForm.setLayout(new FillLayout()); + + // Create the tree on top of the view + Composite top = new Composite(sashForm, SWT.NONE); + GridLayout gl = new GridLayout(1, false); + top.setLayout(gl); + + try { + this.userSession = this.nodeRepository.login(); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot open user session", e); + } + + nodeContentProvider = new NodeContentProvider(userSession, keyring, + repositoryRegister, repositoryFactory, sortChildNodes); + + // nodes viewer + nodesViewer = createNodeViewer(top, nodeContentProvider); + + // context menu : it is completely defined in the plugin.xml file. + MenuManager menuManager = new MenuManager(); + Menu menu = menuManager.createContextMenu(nodesViewer.getTree()); + + nodesViewer.getTree().setMenu(menu); + getSite().registerContextMenu(menuManager, nodesViewer); + getSite().setSelectionProvider(nodesViewer); + + nodesViewer.setInput(getViewSite()); + + // Create the property viewer on the bottom + Composite bottom = new Composite(sashForm, SWT.NONE); + bottom.setLayout(new GridLayout(1, false)); + propertiesViewer = createPropertiesViewer(bottom); + + sashForm.setWeights(getWeights()); + nodesViewer.setComparer(new NodeViewerComparer()); + } + + @Override + public void refresh(Object obj) { + // Enable full refresh from a command when no element of the tree is + // selected + if (obj == null) { + Object[] elements = nodeContentProvider.getElements(null); + for (Object el : elements) { + if (el instanceof TreeParent) + JcrUiUtils.forceRefreshIfNeeded((TreeParent) el); + getNodeViewer().refresh(el); + } + } + super.refresh(obj); + } + + /** + * To be overridden to adapt size of form and result frames. + */ + protected int[] getWeights() { + return new int[] { 70, 30 }; + } + + protected TreeViewer createNodeViewer(Composite parent, + final ITreeContentProvider nodeContentProvider) { + + final TreeViewer tmpNodeViewer = new TreeViewer(parent, SWT.MULTI); + + tmpNodeViewer.getTree().setLayoutData( + new GridData(SWT.FILL, SWT.FILL, true, true)); + + tmpNodeViewer.setContentProvider(nodeContentProvider); + tmpNodeViewer.setLabelProvider(new NodeLabelProvider()); + tmpNodeViewer + .addSelectionChangedListener(new ISelectionChangedListener() { + public void selectionChanged(SelectionChangedEvent event) { + if (!event.getSelection().isEmpty()) { + IStructuredSelection sel = (IStructuredSelection) event + .getSelection(); + Object firstItem = sel.getFirstElement(); + if (firstItem instanceof SingleJcrNodeElem) + propertiesViewer + .setInput(((SingleJcrNodeElem) firstItem) + .getNode()); + } else { + propertiesViewer.setInput(getViewSite()); + } + } + }); + + resultsObserver = new TreeObserver(tmpNodeViewer.getTree().getDisplay()); + if (keyring != null) + try { + ObservationManager observationManager = userSession + .getWorkspace().getObservationManager(); + observationManager.addEventListener(resultsObserver, + Event.PROPERTY_ADDED | Event.PROPERTY_CHANGED, "/", + true, null, null, false); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot register listeners", e); + } + + tmpNodeViewer + .addDoubleClickListener(new GenericNodeDoubleClickListener( + tmpNodeViewer)); + return tmpNodeViewer; + } + + protected TableViewer createPropertiesViewer(Composite parent) { + propertiesViewer = new TableViewer(parent); + propertiesViewer.getTable().setLayoutData( + new GridData(SWT.FILL, SWT.FILL, true, true)); + propertiesViewer.getTable().setHeaderVisible(true); + propertiesViewer.setContentProvider(new PropertiesContentProvider()); + TableViewerColumn col = new TableViewerColumn(propertiesViewer, + SWT.NONE); + col.getColumn().setText("Name"); + col.getColumn().setWidth(200); + col.setLabelProvider(new ColumnLabelProvider() { + public String getText(Object element) { + try { + return ((Property) element).getName(); + } catch (RepositoryException e) { + throw new ArgeoException( + "Unexpected exception in label provider", e); + } + } + }); + col = new TableViewerColumn(propertiesViewer, SWT.NONE); + col.getColumn().setText("Value"); + col.getColumn().setWidth(400); + col.setLabelProvider(new ColumnLabelProvider() { + public String getText(Object element) { + try { + Property property = (Property) element; + if (property.getType() == PropertyType.BINARY) + return ""; + else if (property.isMultiple()) { + StringBuffer buf = new StringBuffer("["); + Value[] values = property.getValues(); + for (int i = 0; i < values.length; i++) { + if (i != 0) + buf.append(", "); + buf.append(values[i].getString()); + } + buf.append(']'); + return buf.toString(); + } else + return property.getValue().getString(); + } catch (RepositoryException e) { + throw new ArgeoException( + "Unexpected exception in label provider", e); + } + } + }); + col = new TableViewerColumn(propertiesViewer, SWT.NONE); + col.getColumn().setText("Type"); + col.getColumn().setWidth(200); + col.setLabelProvider(new ColumnLabelProvider() { + public String getText(Object element) { + try { + return PropertyType.nameFromValue(((Property) element) + .getType()); + } catch (RepositoryException e) { + throw new ArgeoException( + "Unexpected exception in label provider", e); + } + } + }); + propertiesViewer.setInput(getViewSite()); + return propertiesViewer; + } + + @Override + public void dispose() { + super.dispose(); + } + + @Override + protected TreeViewer getNodeViewer() { + return nodesViewer; + } + + /** + * Resets the tree content provider + * + * @param sortChildNodes + * if true the content provider will use a comparer to sort nodes + * that might slow down the display + * */ + public void setSortChildNodes(boolean sortChildNodes) { + this.sortChildNodes = sortChildNodes; + ((NodeContentProvider) nodesViewer.getContentProvider()) + .setSortChildren(sortChildNodes); + nodesViewer.setInput(getViewSite()); + } + + /** Notifies the current view that a node has been added */ + public void nodeAdded(TreeParent parentNode) { + // insure that Ui objects have been correctly created: + JcrUiUtils.forceRefreshIfNeeded(parentNode); + getNodeViewer().refresh(parentNode); + getNodeViewer().expandToLevel(parentNode, 1); + } + + /** Notifies the current view that a node has been removed */ + public void nodeRemoved(TreeParent parentNode) { + IStructuredSelection newSel = new StructuredSelection(parentNode); + getNodeViewer().setSelection(newSel, true); + // Force refresh + IStructuredSelection tmpSel = (IStructuredSelection) getNodeViewer() + .getSelection(); + getNodeViewer().refresh(tmpSel.getFirstElement()); + } + + class TreeObserver extends AsyncUiEventListener { + + public TreeObserver(Display display) { + super(display); + } + + @Override + protected Boolean willProcessInUiThread(List events) + throws RepositoryException { + for (Event event : events) { + if (getLog().isTraceEnabled()) + getLog().debug("Received event " + event); + String path = event.getPath(); + int index = path.lastIndexOf('/'); + String propertyName = path.substring(index + 1); + if (getLog().isTraceEnabled()) + getLog().debug("Concerned property " + propertyName); + } + return false; + } + + protected void onEventInUiThread(List events) + throws RepositoryException { + if (getLog().isTraceEnabled()) + getLog().trace("Refresh result list"); + nodesViewer.refresh(); + } + + } + + public boolean getSortChildNodes() { + return sortChildNodes; + } + + /* DEPENDENCY INJECTION */ + public void setRepositoryRegister(RepositoryRegister repositoryRegister) { + this.repositoryRegister = repositoryRegister; + } + + public void setKeyring(Keyring keyring) { + this.keyring = keyring; + } + + public void setRepositoryFactory(RepositoryFactory repositoryFactory) { + this.repositoryFactory = repositoryFactory; + } + + public void setNodeRepository(Repository nodeRepository) { + this.nodeRepository = nodeRepository; + } + +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/wizards/ChangeRightsWizard.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/wizards/ChangeRightsWizard.java new file mode 100644 index 000000000..4381837e4 --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/wizards/ChangeRightsWizard.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.wizards; + +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.argeo.ArgeoException; +import org.argeo.jcr.JcrUtils; +import org.eclipse.jface.wizard.Wizard; + +/** + * Small wizard to manage authorizations on the root node of the current + * workspace + */ +public class ChangeRightsWizard extends Wizard { + + private Session currentSession; + private String path; + + // This page widget + private ChooseRightsPage page; + + public ChangeRightsWizard(Session currentSession, String path) { + super(); + this.currentSession = currentSession; + this.path = path; + } + + @Override + public void addPages() { + try { + page = new ChooseRightsPage(path); + addPage(page); + } catch (Exception e) { + throw new ArgeoException("Cannot add page to wizard ", e); + } + } + + @Override + public boolean performFinish() { + if (!canFinish()) + return false; + try { + JcrUtils.addPrivilege(currentSession, path, page.getGroupName(), + page.getAuthTypeStr()); + } catch (RepositoryException re) { + throw new ArgeoException( + "Unexpected error while setting privileges", re); + } + return true; + } +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/wizards/ChooseRightsPage.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/wizards/ChooseRightsPage.java new file mode 100644 index 000000000..69948ce83 --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/wizards/ChooseRightsPage.java @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.wizards; + +import javax.jcr.security.Privilege; + +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; + +public class ChooseRightsPage extends WizardPage implements ModifyListener { + + // This page widget + private Text groupNameTxt; + private Combo authorizationCmb; + + // USABLE SHORTCUTS + protected final static String[] validAuthType = { Privilege.JCR_READ, + Privilege.JCR_WRITE, Privilege.JCR_ALL }; + + public ChooseRightsPage(String path) { + super("Main"); + setTitle("Add privilege to " + path); + } + + public void createControl(Composite parent) { + // specify subject + Composite composite = new Composite(parent, SWT.NONE); + composite.setLayout(new GridLayout(2, false)); + Label lbl = new Label(composite, SWT.LEAD); + lbl.setText("Group or user name (no blank, no special chars)"); + lbl.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false)); + groupNameTxt = new Text(composite, SWT.LEAD | SWT.BORDER); + groupNameTxt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, + false)); + if (groupNameTxt != null) + groupNameTxt.addModifyListener(this); + + // Choose rigths + new Label(composite, SWT.NONE).setText("Choose corresponding rights"); + authorizationCmb = new Combo(composite, SWT.BORDER | SWT.V_SCROLL); + authorizationCmb.setItems(validAuthType); + GridData gd = new GridData(GridData.FILL_HORIZONTAL); + authorizationCmb.setLayoutData(gd); + + authorizationCmb.select(0); + + // Compulsory + setControl(composite); + } + + protected String getGroupName() { + return groupNameTxt.getText(); + } + + protected String getAuthTypeStr() { + return authorizationCmb.getItem(authorizationCmb.getSelectionIndex()); + } + + public void modifyText(ModifyEvent event) { + String message = checkComplete(); + if (message != null) + setMessage(message, WizardPage.ERROR); + else { + setMessage("Complete", WizardPage.INFORMATION); + setPageComplete(true); + } + } + + /** @return error message or null if complete */ + protected String checkComplete() { + String groupStr = groupNameTxt.getText(); + if (groupStr == null || "".equals(groupStr)) + return "Please enter the name of the corresponding group."; + // Remove regexp check for the time being. + // else if (!match(groupStr)) + // return + // "Please use only alphanumerical chars for the short technical name."; + return null; + } +} diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/wizards/ImportFileSystemWizard.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/wizards/ImportFileSystemWizard.java new file mode 100644 index 000000000..127c2cd54 --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/wizards/ImportFileSystemWizard.java @@ -0,0 +1,237 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.ui.explorer.wizards; + +import java.io.File; +import java.io.FileInputStream; + +import javax.jcr.Binary; +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.nodetype.NodeType; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; +import org.argeo.eclipse.ui.ErrorFeedback; +import org.argeo.eclipse.ui.specific.ImportToServerWizardPage; +import org.argeo.eclipse.ui.specific.UploadFileWizardPage; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.wizard.Wizard; + +public class ImportFileSystemWizard extends Wizard { + private final static Log log = LogFactory + .getLog(ImportFileSystemWizard.class); + + private UploadFileWizardPage importPage; + private final Node folder; + + public ImportFileSystemWizard(Node folder) { + this.folder = folder; + setWindowTitle("Import from file system"); + } + + @Override + public void addPages() { + importPage = new UploadFileWizardPage(); + addPage(importPage); + setNeedsProgressMonitor(importPage.getNeedsProgressMonitor()); + } + + /** + * Called when the user click on 'Finish' in the wizard. The real upload to + * the JCR repository is done here. + */ + @Override + public boolean performFinish() { + + // Initialization + final String objectType = importPage.getObjectType(); + final String objectPath = importPage.getObjectPath(); + + // We do not display a progress bar for one file only + if (ImportToServerWizardPage.FILE_ITEM_TYPE.equals(objectType)) { + // In Rap we must force the "real" upload of the file + importPage.performFinish(); + try { + Node fileNode = folder.addNode(importPage.getObjectName(), + NodeType.NT_FILE); + Node resNode = fileNode.addNode(Property.JCR_CONTENT, + NodeType.NT_RESOURCE); + Binary binary = null; + try { + binary = folder.getSession().getValueFactory() + .createBinary(importPage.getFileInputStream()); + resNode.setProperty(Property.JCR_DATA, binary); + } finally { + if (binary != null) + binary.dispose(); + IOUtils.closeQuietly(importPage.getFileInputStream()); + } + folder.getSession().save(); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + return true; + } else if (ImportToServerWizardPage.FOLDER_ITEM_TYPE.equals(objectType)) { + if (objectPath == null || !new File(objectPath).exists()) { + ErrorFeedback.show("Directory " + objectPath + + " does not exist"); + return false; + } + + Boolean failed = false; + final File dir = new File(objectPath).getAbsoluteFile(); + final Long sizeB = directorySize(dir, 0l); + final Stats stats = new Stats(); + Long begin = System.currentTimeMillis(); + try { + getContainer().run(true, true, new IRunnableWithProgress() { + public void run(IProgressMonitor monitor) { + try { + Integer sizeKB = (int) (sizeB / FileUtils.ONE_KB); + monitor.beginTask("", sizeKB); + importDirectory(folder, dir, monitor, stats); + monitor.done(); + } catch (Exception e) { + if (e instanceof RuntimeException) + throw (RuntimeException) e; + else + throw new ArgeoException("Cannot import " + + objectPath, e); + } + } + }); + } catch (Exception e) { + ErrorFeedback.show("Cannot import " + objectPath, e); + failed = true; + } + + Long duration = System.currentTimeMillis() - begin; + Long durationS = duration / 1000l; + String durationStr = (durationS / 60) + " min " + (durationS % 60) + + " s"; + StringBuffer message = new StringBuffer("Imported\n"); + message.append(stats.fileCount).append(" files\n"); + message.append(stats.dirCount).append(" directories\n"); + message.append(FileUtils.byteCountToDisplaySize(stats.sizeB)); + if (failed) + message.append(" of planned ").append( + FileUtils.byteCountToDisplaySize(sizeB)); + message.append("\n"); + message.append("in ").append(durationStr).append("\n"); + if (failed) + MessageDialog.openError(getShell(), "Import failed", + message.toString()); + else + MessageDialog.openInformation(getShell(), "Import successful", + message.toString()); + + return true; + } + return false; + + } + + /** Recursively computes the size of the directory in bytes. */ + protected Long directorySize(File dir, Long currentSize) { + Long size = currentSize; + File[] files = dir.listFiles(); + for (File file : files) { + if (file.isDirectory()) { + size = directorySize(file, size); + } else { + size = size + file.length(); + } + } + return size; + } + + /** + * Import recursively a directory and its content to the repository. + */ + protected void importDirectory(Node folder, File dir, + IProgressMonitor monitor, Stats stats) { + try { + File[] files = dir.listFiles(); + for (File file : files) { + if (file.isDirectory()) { + Node childFolder = folder.addNode(file.getName(), + NodeType.NT_FOLDER); + importDirectory(childFolder, file, monitor, stats); + folder.getSession().save(); + stats.dirCount++; + } else { + Long fileSize = file.length(); + + // we skip tempory files that are created by apps when a + // file is being edited. + // TODO : make this configurable. + if (file.getName().lastIndexOf('~') != file.getName() + .length() - 1) { + + monitor.subTask(file.getName() + " (" + + FileUtils.byteCountToDisplaySize(fileSize) + + ") " + file.getCanonicalPath()); + try { + Node fileNode = folder.addNode(file.getName(), + NodeType.NT_FILE); + Node resNode = fileNode.addNode( + Property.JCR_CONTENT, NodeType.NT_RESOURCE); + Binary binary = null; + try { + binary = folder + .getSession() + .getValueFactory() + .createBinary(new FileInputStream(file)); + resNode.setProperty(Property.JCR_DATA, binary); + } finally { + if (binary != null) + binary.dispose(); + } + folder.getSession().save(); + stats.fileCount++; + stats.sizeB = stats.sizeB + fileSize; + } catch (Exception e) { + log.warn("Import of " + + file + + " (" + + FileUtils + .byteCountToDisplaySize(fileSize) + + ") failed: " + e); + folder.getSession().refresh(false); + } + monitor.worked((int) (fileSize / FileUtils.ONE_KB)); + } + } + } + } catch (Exception e) { + throw new ArgeoException("Cannot import " + dir + " to " + folder, + e); + } + } + + static class Stats { + public Long fileCount = 0l; + public Long dirCount = 0l; + public Long sizeB = 0l; + } +} diff --git a/org.argeo.jcr.ui.explorer/src/main/resources/org/argeo/jcr/ui/explorer/messages.properties b/org.argeo.jcr.ui.explorer/src/main/resources/org/argeo/jcr/ui/explorer/messages.properties new file mode 100644 index 000000000..3023c523f --- /dev/null +++ b/org.argeo.jcr.ui.explorer/src/main/resources/org/argeo/jcr/ui/explorer/messages.properties @@ -0,0 +1,28 @@ +## English labels for Agreo JCR UI application + +## Generic labels + +## Errors & warnings +errorUnvalidNtFolderNodeType= Error: folder can only be created on a Jcr Node +warningInvalidNodeToImport=Can only import to a node +warningInvalidMultipleSelection=This functionality is implemented only on a single node for the time being. +warningUnversionableNode= Current node is not versionable. +warningNoChildNode= Current node has no child. + +## Commands +getNodeSizeCmdLbl= Get approx. size +addFolderNodeCmdLbl= Add Folder + +## GenericNodeEditor +nodeEditorLbl=Generic node editor +genericNodePageTitle=Properties +childNodesPageTitle=Children +nodeRightsManagementPageTitle=Rights +nodeVersionHistoryPageTitle=History + +# History +versionTreeSectionTitle=Version list +versionHistorySectionTitle=History + +## Dummy ones +testLbl=Internationalizations of messages seems to work properly. diff --git a/org.argeo.node.repo.jackrabbit/.project b/org.argeo.node.repo.jackrabbit/.project new file mode 100644 index 000000000..648ec17d9 --- /dev/null +++ b/org.argeo.node.repo.jackrabbit/.project @@ -0,0 +1,22 @@ + + + org.argeo.node.repo.jackrabbit + + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + + diff --git a/org.argeo.node.repo.jackrabbit/.settings/org.eclipse.pde.core.prefs b/org.argeo.node.repo.jackrabbit/.settings/org.eclipse.pde.core.prefs new file mode 100644 index 000000000..aae24717e --- /dev/null +++ b/org.argeo.node.repo.jackrabbit/.settings/org.eclipse.pde.core.prefs @@ -0,0 +1,4 @@ +#Wed Feb 23 10:53:42 CET 2011 +eclipse.preferences.version=1 +pluginProject.extensions=false +resolve.requirebundle=false diff --git a/org.argeo.node.repo.jackrabbit/META-INF/spring/noderepo-osgi.xml b/org.argeo.node.repo.jackrabbit/META-INF/spring/noderepo-osgi.xml new file mode 100644 index 000000000..957dda144 --- /dev/null +++ b/org.argeo.node.repo.jackrabbit/META-INF/spring/noderepo-osgi.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + javax.jcr.Repository + org.argeo.jcr.MaintainedRepository + + + + + + + + \ No newline at end of file diff --git a/org.argeo.node.repo.jackrabbit/META-INF/spring/noderepo.xml b/org.argeo.node.repo.jackrabbit/META-INF/spring/noderepo.xml new file mode 100644 index 000000000..6648c1550 --- /dev/null +++ b/org.argeo.node.repo.jackrabbit/META-INF/spring/noderepo.xml @@ -0,0 +1,26 @@ + + + + + + + osgibundle:noderepo.properties + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.node.repo.jackrabbit/build.properties b/org.argeo.node.repo.jackrabbit/build.properties new file mode 100644 index 000000000..a275ae638 --- /dev/null +++ b/org.argeo.node.repo.jackrabbit/build.properties @@ -0,0 +1,4 @@ +bin.includes = META-INF/,\ + noderepo.properties,\ + repository-h2.xml,\ + repository-postgresql.xml diff --git a/org.argeo.node.repo.jackrabbit/noderepo.properties b/org.argeo.node.repo.jackrabbit/noderepo.properties new file mode 100644 index 000000000..c91d51d08 --- /dev/null +++ b/org.argeo.node.repo.jackrabbit/noderepo.properties @@ -0,0 +1,16 @@ +# Workspace used by the node session +argeo.node.repo.defaultWorkspace=main +#argeo.node.repo.securityWorkspace=security +argeo.node.repo.forceCndImport=true + +# Repository base directory +argeo.node.repo.home=${osgi.instance.area}/node + +## H2 Embedded (DEFAULT) +argeo.node.repo.configuration=osgibundle:repository-h2.xml +argeo.node.repo.dburl=jdbc:h2:${osgi.instance.area}/node/h2/repository +argeo.node.repo.dbuser=sa +argeo.node.repo.dbpassword= + +# ADVANCED +argeo.node.repo.maxPoolSize=10 \ No newline at end of file diff --git a/org.argeo.node.repo.jackrabbit/pom.xml b/org.argeo.node.repo.jackrabbit/pom.xml new file mode 100644 index 000000000..d35367eee --- /dev/null +++ b/org.argeo.node.repo.jackrabbit/pom.xml @@ -0,0 +1,40 @@ + + 4.0.0 + + org.argeo.commons + 2.1.12-SNAPSHOT + argeo-commons + .. + + org.argeo.node.repo.jackrabbit + Commons Server Node Repository Jackrabbit + Default Node Repository Based on Jackrabbit + + + + org.apache.felix + maven-bundle-plugin + + + ${project.artifactId};singleton:=true + + META-INF/spring/*.xml;create-asynchronously:=false + + *, + com.mysql.jdbc;resolution:=optional, + org.h2;resolution:=optional, + org.postgresql;resolution:=optional, + javax.jcr, + org.apache.jackrabbit.core, + org.apache.jackrabbit.core.config, + org.argeo.jackrabbit, + org.argeo.jcr, + org.springframework.beans.factory.config, + + + + + + + \ No newline at end of file diff --git a/org.argeo.node.repo.jackrabbit/repository-h2.xml b/org.argeo.node.repo.jackrabbit/repository-h2.xml new file mode 100644 index 000000000..583bf4c1c --- /dev/null +++ b/org.argeo.node.repo.jackrabbit/repository-h2.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.node.repo.jackrabbit/repository-memory.xml b/org.argeo.node.repo.jackrabbit/repository-memory.xml new file mode 100644 index 000000000..b41cfad6d --- /dev/null +++ b/org.argeo.node.repo.jackrabbit/repository-memory.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.node.repo.jackrabbit/repository-mysql.xml b/org.argeo.node.repo.jackrabbit/repository-mysql.xml new file mode 100644 index 000000000..208cd1de1 --- /dev/null +++ b/org.argeo.node.repo.jackrabbit/repository-mysql.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.node.repo.jackrabbit/repository-postgresql.xml b/org.argeo.node.repo.jackrabbit/repository-postgresql.xml new file mode 100644 index 000000000..811f0c6bc --- /dev/null +++ b/org.argeo.node.repo.jackrabbit/repository-postgresql.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.osgi.boot/.classpath b/org.argeo.osgi.boot/.classpath new file mode 100644 index 000000000..2f7e966c4 --- /dev/null +++ b/org.argeo.osgi.boot/.classpath @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/org.argeo.osgi.boot/.project b/org.argeo.osgi.boot/.project new file mode 100644 index 000000000..e145e9691 --- /dev/null +++ b/org.argeo.osgi.boot/.project @@ -0,0 +1,23 @@ + + + org.argeo.osgi.boot + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.pde.PluginNature + + diff --git a/org.argeo.osgi.boot/.settings/org.eclipse.jdt.core.prefs b/org.argeo.osgi.boot/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..ba812fb90 --- /dev/null +++ b/org.argeo.osgi.boot/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,12 @@ +#Fri Jun 26 11:15:56 CEST 2009 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.4 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=warning +org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning +org.eclipse.jdt.core.compiler.source=1.3 diff --git a/org.argeo.osgi.boot/build.properties b/org.argeo.osgi.boot/build.properties new file mode 100644 index 000000000..f17a5821b --- /dev/null +++ b/org.argeo.osgi.boot/build.properties @@ -0,0 +1 @@ +additional.bundles = junit diff --git a/org.argeo.osgi.boot/pom.xml b/org.argeo.osgi.boot/pom.xml new file mode 100644 index 000000000..eae04e72f --- /dev/null +++ b/org.argeo.osgi.boot/pom.xml @@ -0,0 +1,53 @@ + + + 4.0.0 + + org.argeo.commons + 2.1.12-SNAPSHOT + argeo-commons + .. + + org.argeo.osgi.boot + jar + Commons OSGi Boot + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.4 + 1.4 + + + + org.apache.felix + maven-bundle-plugin + + + + org.argeo.osgi.boot.Activator + J2SE-1.4 + org.eclipse.*;resolution:=optional,* + + + + + + + + org.argeo.tp.rap.platform + org.eclipse.osgi + provided + + + + + org.argeo.tp + junit + test + + + + + \ No newline at end of file diff --git a/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/Activator.java b/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/Activator.java new file mode 100644 index 000000000..cd9f3583d --- /dev/null +++ b/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/Activator.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.osgi.boot; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + +/** + * An OSGi configurator. See http: + * //wiki.eclipse.org/Configurator + */ +public class Activator implements BundleActivator { + + public void start(final BundleContext bundleContext) throws Exception { + // admin thread + Thread adminThread = new AdminThread(bundleContext); + adminThread.start(); + + // bootstrap + OsgiBoot osgiBoot = new OsgiBoot(bundleContext); + osgiBoot.bootstrap(); + } + + public void stop(BundleContext context) throws Exception { + } +} diff --git a/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/AdminThread.java b/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/AdminThread.java new file mode 100644 index 000000000..6f01b89bb --- /dev/null +++ b/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/AdminThread.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.osgi.boot; + +import java.io.File; + +import org.osgi.framework.BundleContext; +import org.osgi.framework.launch.Framework; + +/** Monitors the runtime and can shut it down. */ +public class AdminThread extends Thread { + public final static String PROP_ARGEO_OSGI_SHUTDOWN_FILE = "argeo.osgi.shutdownFile"; + private File shutdownFile; + private final BundleContext bundleContext; + + public AdminThread(BundleContext bundleContext) { + super("OSGi Boot Admin"); + this.bundleContext = bundleContext; + if (System.getProperty(PROP_ARGEO_OSGI_SHUTDOWN_FILE) != null) { + shutdownFile = new File( + System.getProperty(PROP_ARGEO_OSGI_SHUTDOWN_FILE)); + if (!shutdownFile.exists()) { + shutdownFile = null; + OsgiBootUtils.warn("Shutdown file " + shutdownFile + + " not found, feature deactivated"); + } + } + } + + public void run() { + if (shutdownFile != null) { + // wait for file to be removed + while (shutdownFile.exists()) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + Framework framework = (Framework) bundleContext.getBundle(0); + try { + // shutdown framework + framework.stop(); + // wait 10 mins for shutdown + framework.waitForStop(10 * 60 * 1000); + // close VM + System.exit(0); + } catch (Exception e) { + e.printStackTrace(); + System.exit(1); + } + } + } +} diff --git a/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/DistributionBundle.java b/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/DistributionBundle.java new file mode 100644 index 000000000..e6c04281f --- /dev/null +++ b/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/DistributionBundle.java @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.osgi.boot; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; +import java.util.jar.JarEntry; +import java.util.jar.JarInputStream; +import java.util.jar.Manifest; + +import org.osgi.framework.Constants; + +/** + * A distribution bundle is a bundle within a maven-like distribution + * groupId:Bundle-SymbolicName:Bundle-Version which references others OSGi + * bundle. It is not required to be OSGi complete also it will generally be + * expected that it is. The root of the repository is computed based on the file + * name of the URL and of the content of the index. + */ +public class DistributionBundle { + private final static String INDEX_FILE_NAME = "modularDistribution.csv"; + + private final String url; + + private Manifest manifest; + private String symbolicName; + private String version; + + /** can be null */ + private String baseUrl; + /** can be null */ + private String relativeUrl; + + private List/* */artifacts; + + private String separator = ","; + + public DistributionBundle(String url) { + this.url = url; + } + + public DistributionBundle(String baseUrl, String relativeUrl) { + if (baseUrl == null || !baseUrl.endsWith("/")) + throw new OsgiBootException("Base url " + baseUrl + + " badly formatted"); + if (relativeUrl.startsWith("http") || relativeUrl.startsWith("file:")) + throw new OsgiBootException("Relative URL " + relativeUrl + + " badly formatted"); + this.url = baseUrl + relativeUrl; + this.baseUrl = baseUrl; + this.relativeUrl = relativeUrl; + } + + public void processUrl() { + JarInputStream jarIn = null; + try { + URL u = new URL(url); + jarIn = new JarInputStream(u.openStream()); + + // meta data + manifest = jarIn.getManifest(); + symbolicName = manifest.getMainAttributes().getValue( + Constants.BUNDLE_SYMBOLICNAME); + version = manifest.getMainAttributes().getValue( + Constants.BUNDLE_VERSION); + + JarEntry indexEntry; + while ((indexEntry = jarIn.getNextJarEntry()) != null) { + String entryName = indexEntry.getName(); + if (entryName.equals(INDEX_FILE_NAME)) { + break; + } + jarIn.closeEntry(); + } + + // list artifacts + if (indexEntry == null) + throw new OsgiBootException("No index " + INDEX_FILE_NAME + + " in " + url); + artifacts = listArtifacts(jarIn); + jarIn.closeEntry(); + + // find base URL + // won't work if distribution artifact is not listed + for (int i = 0; i < artifacts.size(); i++) { + OsgiArtifact osgiArtifact = (OsgiArtifact) artifacts.get(i); + if (osgiArtifact.getSymbolicName().equals(symbolicName) + && osgiArtifact.getVersion().equals(version)) { + String relativeUrl = osgiArtifact.getRelativeUrl(); + if (url.endsWith(relativeUrl)) { + baseUrl = url.substring(0, url.length() + - osgiArtifact.getRelativeUrl().length()); + break; + } + } + } + } catch (Exception e) { + throw new OsgiBootException("Cannot list URLs from " + url, e); + } finally { + if (jarIn != null) + try { + jarIn.close(); + } catch (IOException e) { + // silent + } + } + } + + protected List/* */listArtifacts(InputStream in) { + List osgiArtifacts = new ArrayList(); + BufferedReader reader = null; + try { + reader = new BufferedReader(new InputStreamReader(in)); + String line = null; + while ((line = reader.readLine()) != null) { + StringTokenizer st = new StringTokenizer(line, separator); + String moduleName = st.nextToken(); + String moduleVersion = st.nextToken(); + String relativeUrl = st.nextToken(); + osgiArtifacts.add(new OsgiArtifact(moduleName, moduleVersion, + relativeUrl)); + } + } catch (Exception e) { + throw new OsgiBootException("Cannot list artifacts", e); + } + return osgiArtifacts; + } + + /** Convenience method */ + public static DistributionBundle processUrl(String baseUrl, + String realtiveUrl) { + DistributionBundle distributionBundle = new DistributionBundle(baseUrl, + realtiveUrl); + distributionBundle.processUrl(); + return distributionBundle; + } + + /** + * List full URLs of the bunmdles, based on base URL, usable directly for + * download. + */ + public List/* */listUrls() { + if (baseUrl == null) + throw new OsgiBootException("Base URL is not set"); + + if (artifacts == null) + throw new OsgiBootException("Artifact list not initialized"); + + List/* */urls = new ArrayList(); + for (int i = 0; i < artifacts.size(); i++) { + OsgiArtifact osgiArtifact = (OsgiArtifact) artifacts.get(i); + urls.add(baseUrl + osgiArtifact.getRelativeUrl()); + } + return urls; + } + + public void setBaseUrl(String baseUrl) { + this.baseUrl = baseUrl; + } + + /** Separator used to parse the tabular file */ + public void setSeparator(String modulesUrlSeparator) { + this.separator = modulesUrlSeparator; + } + + public String getRelativeUrl() { + return relativeUrl; + } + + /** One of the listed artifact */ + protected static class OsgiArtifact { + private final String symbolicName; + private final String version; + private final String relativeUrl; + + public OsgiArtifact(String symbolicName, String version, + String relativeUrl) { + super(); + this.symbolicName = symbolicName; + this.version = version; + this.relativeUrl = relativeUrl; + } + + public String getSymbolicName() { + return symbolicName; + } + + public String getVersion() { + return version; + } + + public String getRelativeUrl() { + return relativeUrl; + } + + } +} diff --git a/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/Launcher.java b/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/Launcher.java new file mode 100644 index 000000000..6af1a7184 --- /dev/null +++ b/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/Launcher.java @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.osgi.boot; + +import java.io.FileInputStream; +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.List; +import java.util.Vector; + +import org.eclipse.core.runtime.adaptor.EclipseStarter; +import org.osgi.framework.BundleContext; + +/** Command line interface. */ +public class Launcher { + + public static void main(String[] args) { + // Try to load system properties + String systemPropertiesFilePath = OsgiBootUtils + .getProperty(OsgiBoot.PROP_ARGEO_OSGI_BOOT_SYSTEM_PROPERTIES_FILE); + if (systemPropertiesFilePath != null) { + FileInputStream in; + try { + in = new FileInputStream(systemPropertiesFilePath); + System.getProperties().load(in); + } catch (IOException e1) { + throw new RuntimeException( + "Cannot load system properties from " + + systemPropertiesFilePath, e1); + } + if (in != null) { + try { + in.close(); + } catch (Exception e) { + // silent + } + } + } + + // Start main class + startMainClass(); + + // Start Equinox + BundleContext bundleContext = null; + try { + bundleContext = EclipseStarter.startup(args, null); + } catch (Exception e) { + throw new RuntimeException("Cannot start Equinox.", e); + } + + // OSGi bootstrap + OsgiBoot osgiBoot = new OsgiBoot(bundleContext); + osgiBoot.bootstrap(); + } + + protected static void startMainClass() { + String className = OsgiBootUtils + .getProperty(OsgiBoot.PROP_ARGEO_OSGI_BOOT_APPCLASS); + if (className == null) + return; + + String line = System.getProperty(OsgiBoot.PROP_ARGEO_OSGI_BOOT_APPARGS, + ""); + + String[] uiArgs = readArgumentsFromLine(line); + + try { + // Launch main method using reflection + Class clss = Class.forName(className); + Class[] mainArgsClasses = new Class[] { uiArgs.getClass() }; + Object[] mainArgs = { uiArgs }; + Method mainMethod = clss.getMethod("main", mainArgsClasses); + mainMethod.invoke(null, mainArgs); + } catch (Exception e) { + throw new RuntimeException("Cannot start main class.", e); + } + + } + + /** + * Transform a line into an array of arguments, taking "" as single + * arguments. (nested \" are not supported) + */ + private static String[] readArgumentsFromLine(String lineOrig) { + String line = lineOrig.trim();// remove trailing spaces + List args = new Vector(); + StringBuffer curr = new StringBuffer(""); + boolean inQuote = false; + char[] arr = line.toCharArray(); + for (int i = 0; i < arr.length; i++) { + char c = arr[i]; + switch (c) { + case '\"': + inQuote = !inQuote; + break; + case ' ': + if (!inQuote) {// otherwise, no break: goes to default + if (curr.length() > 0) { + args.add(curr.toString()); + curr = new StringBuffer(""); + } + break; + } + default: + curr.append(c); + break; + } + } + + // Add last arg + if (curr.length() > 0) { + args.add(curr.toString()); + curr = null; + } + + String[] res = new String[args.size()]; + for (int i = 0; i < args.size(); i++) { + res[i] = args.get(i).toString(); + } + return res; + } + +} diff --git a/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/OsgiBoot.java b/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/OsgiBoot.java new file mode 100644 index 000000000..300ebb82d --- /dev/null +++ b/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/OsgiBoot.java @@ -0,0 +1,1036 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.osgi.boot; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.SortedMap; +import java.util.StringTokenizer; +import java.util.TreeMap; +import java.util.TreeSet; + +import org.argeo.osgi.boot.internal.springutil.AntPathMatcher; +import org.argeo.osgi.boot.internal.springutil.PathMatcher; +import org.argeo.osgi.boot.internal.springutil.SystemPropertyUtils; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.BundleException; +import org.osgi.framework.Constants; +import org.osgi.framework.ServiceReference; +import org.osgi.service.packageadmin.ExportedPackage; +import org.osgi.service.packageadmin.PackageAdmin; + +/** + * Basic provisioning of an OSGi runtime via file path patterns and system + * properties. Java 1.4 compatible.
+ * The approach is to generate list of URLs based on various methods, configured + * via system properties. + */ +public class OsgiBoot { + public final static String SYMBOLIC_NAME_OSGI_BOOT = "org.argeo.osgi.boot"; + public final static String SYMBOLIC_NAME_EQUINOX = "org.eclipse.osgi"; + + public final static String PROP_OSGI_STARTLEVEL = "osgi.startLevel"; + public final static String PROP_OSGI_BUNDLES_DEFAULTSTARTLEVEL = "osgi.bundles.defaultStartLevel"; + + public final static String PROP_ARGEO_OSGI_DATA_DIR = "argeo.osgi.data.dir"; + + public final static String PROP_ARGEO_OSGI_START = "argeo.osgi.start"; + public final static String PROP_ARGEO_OSGI_BUNDLES = "argeo.osgi.bundles"; + public final static String PROP_ARGEO_OSGI_LOCATIONS = "argeo.osgi.locations"; + public final static String PROP_ARGEO_OSGI_BASE_URL = "argeo.osgi.baseUrl"; + /** @deprecated */ + public final static String PROP_ARGEO_OSGI_MODULES_URL = "argeo.osgi.modulesUrl"; + public final static String PROP_ARGEO_OSGI_DISTRIBUTION_URL = "argeo.osgi.distributionUrl"; + + // booleans + public final static String PROP_ARGEO_OSGI_BOOT_DEBUG = "argeo.osgi.boot.debug"; + public final static String PROP_ARGEO_OSGI_BOOT_EXCLUDE_SVN = "argeo.osgi.boot.excludeSvn"; + public final static String PROP_ARGEO_OSGI_BOOT_INSTALL_IN_LEXICOGRAPHIC_ORDER = "argeo.osgi.boot.installInLexicographicOrder"; + + public final static String PROP_ARGEO_OSGI_BOOT_DEFAULT_TIMEOUT = "argeo.osgi.boot.defaultTimeout"; + public final static String PROP_ARGEO_OSGI_BOOT_MODULES_URL_SEPARATOR = "argeo.osgi.boot.modulesUrlSeparator"; + public final static String PROP_ARGEO_OSGI_BOOT_SYSTEM_PROPERTIES_FILE = "argeo.osgi.boot.systemPropertiesFile"; + public final static String PROP_ARGEO_OSGI_BOOT_APPCLASS = "argeo.osgi.boot.appclass"; + public final static String PROP_ARGEO_OSGI_BOOT_APPARGS = "argeo.osgi.boot.appargs"; + + public final static String DEFAULT_BASE_URL = "reference:file:"; + public final static String EXCLUDES_SVN_PATTERN = "**/.svn/**"; + + // OSGi system properties + public final static String INSTANCE_AREA_PROP = "osgi.instance.area"; + public final static String INSTANCE_AREA_DEFAULT_PROP = "osgi.instance.area.default"; + + private boolean debug = Boolean.valueOf( + System.getProperty(PROP_ARGEO_OSGI_BOOT_DEBUG, "false")) + .booleanValue(); + /** Exclude svn metadata implicitely(a bit costly) */ + private boolean excludeSvn = Boolean.valueOf( + System.getProperty(PROP_ARGEO_OSGI_BOOT_EXCLUDE_SVN, "false")) + .booleanValue(); + + /** + * The {@link #installUrls(List)} methods won't follow the list order but + * order the urls according to the alphabetical order of the file names + * (last part of the URL). The goal is to stay closer from Eclipse PDE way + * of installing target platform bundles. + */ + private boolean installInLexicographicOrder = Boolean + .valueOf( + System.getProperty( + PROP_ARGEO_OSGI_BOOT_INSTALL_IN_LEXICOGRAPHIC_ORDER, + "true")).booleanValue();; + + /** Default is 10s (set in constructor) */ + private long defaultTimeout; + + /** Default is ',' (set in constructor) */ + private String modulesUrlSeparator = ","; + + private final BundleContext bundleContext; + + /* + * INITIALIZATION + */ + /** Constructor */ + public OsgiBoot(BundleContext bundleContext) { + this.bundleContext = bundleContext; + defaultTimeout = Long.parseLong(OsgiBootUtils.getProperty( + PROP_ARGEO_OSGI_BOOT_DEFAULT_TIMEOUT, "10000")); + modulesUrlSeparator = OsgiBootUtils.getProperty( + PROP_ARGEO_OSGI_BOOT_MODULES_URL_SEPARATOR, ","); + initSystemProperties(); + } + + /** + * Set additional system properties, especially ${argeo.osgi.data.dir} as an + * OS file path (and not a file:// URL) + */ + protected void initSystemProperties() { + String osgiInstanceArea = System.getProperty(INSTANCE_AREA_PROP); + String osgiInstanceAreaDefault = System + .getProperty(INSTANCE_AREA_DEFAULT_PROP); + String tempDir = System.getProperty("java.io.tmpdir"); + + File dataDir = null; + if (osgiInstanceArea != null) { + // within OSGi with -data specified + osgiInstanceArea = removeFilePrefix(osgiInstanceArea); + dataDir = new File(osgiInstanceArea); + } else if (osgiInstanceAreaDefault != null) { + // within OSGi without -data specified + osgiInstanceAreaDefault = removeFilePrefix(osgiInstanceAreaDefault); + dataDir = new File(osgiInstanceAreaDefault); + } else {// outside OSGi + dataDir = new File(tempDir + File.separator + "argeoOsgiData"); + } + System.setProperty(PROP_ARGEO_OSGI_DATA_DIR, dataDir.getAbsolutePath()); + } + + /* + * HIGH-LEVEL METHODS + */ + /** Bootstraps the OSGi runtime */ + public void bootstrap() { + long begin = System.currentTimeMillis(); + System.out.println(); + OsgiBootUtils.info("OSGi bootstrap starting..."); + OsgiBootUtils.info("Writable data directory : " + + System.getProperty(PROP_ARGEO_OSGI_DATA_DIR) + + " (set as system property " + PROP_ARGEO_OSGI_DATA_DIR + ")"); + installUrls(getBundlesUrls()); + installUrls(getLocationsUrls()); + installUrls(getModulesUrls()); + installUrls(getDistributionUrls()); + checkUnresolved(); + startBundles(); + long duration = System.currentTimeMillis() - begin; + OsgiBootUtils.info("OSGi bootstrap completed in " + + Math.round(((double) duration) / 1000) + "s (" + duration + + "ms), " + bundleContext.getBundles().length + " bundles"); + + // display packages exported twice + if (debug) { + Map /* > */duplicatePackages = findPackagesExportedTwice(); + if (duplicatePackages.size() > 0) { + OsgiBootUtils.info("Packages exported twice:"); + Iterator it = duplicatePackages.keySet().iterator(); + while (it.hasNext()) { + String pkgName = it.next().toString(); + OsgiBootUtils.info(pkgName); + Set bdles = (Set) duplicatePackages.get(pkgName); + Iterator bdlesIt = bdles.iterator(); + while (bdlesIt.hasNext()) + OsgiBootUtils.info(" " + bdlesIt.next()); + } + } + } + + System.out.println(); + } + + /* + * INSTALLATION + */ + /** Install a single url. Convenience method. */ + public Bundle installUrl(String url) { + List urls = new ArrayList(); + urls.add(url); + installUrls(urls); + return (Bundle) getBundlesByLocation().get(url); + } + + /** Install the bundles at this URL list. */ + public void installUrls(List urls) { + Map installedBundles = getBundlesByLocation(); + + if (installInLexicographicOrder) { + SortedMap map = new TreeMap(); + // reorder + for (int i = 0; i < urls.size(); i++) { + String url = (String) urls.get(i); + int index = url.lastIndexOf('/'); + String fileName; + if (index >= 0) + fileName = url.substring(index + 1); + else + fileName = url; + map.put(fileName, url); + } + + // install + Iterator keys = map.keySet().iterator(); + while (keys.hasNext()) { + Object key = keys.next(); + String url = map.get(key).toString(); + installUrl(url, installedBundles); + } + } else { + for (int i = 0; i < urls.size(); i++) { + String url = (String) urls.get(i); + installUrl(url, installedBundles); + } + } + + } + + /** Actually install the provided URL */ + protected void installUrl(String url, Map installedBundles) { + try { + if (installedBundles.containsKey(url)) { + Bundle bundle = (Bundle) installedBundles.get(url); + // bundle.update(); + if (debug) + debug("Bundle " + bundle.getSymbolicName() + + " already installed from " + url); + } else { + Bundle bundle = bundleContext.installBundle(url); + if (debug) + debug("Installed bundle " + bundle.getSymbolicName() + + " from " + url); + } + } catch (BundleException e) { + String message = e.getMessage(); + if ((message.contains("Bundle \"" + SYMBOLIC_NAME_OSGI_BOOT + "\"") || message + .contains("Bundle \"" + SYMBOLIC_NAME_EQUINOX + "\"")) + && message.contains("has already been installed")) { + // silent, in order to avoid warnings: we know that both + // have already been installed... + } else { + OsgiBootUtils.warn("Could not install bundle from " + url + + ": " + message); + } + if (debug) + e.printStackTrace(); + } + } + + /* + * START + */ + public void startBundles() { + // default and active start levels from System properties + Integer defaultStartLevel = new Integer(Integer.parseInt(OsgiBootUtils + .getProperty(PROP_OSGI_BUNDLES_DEFAULTSTARTLEVEL, "4"))); + Integer activeStartLevel = new Integer(OsgiBootUtils.getProperty( + PROP_OSGI_STARTLEVEL, "6")); + + SortedMap/* > */startLevels = new TreeMap(); + computeStartLevels(startLevels, System.getProperties(), + defaultStartLevel); + + Iterator/* */levels = startLevels.keySet().iterator(); + while (levels.hasNext()) { + Integer level = (Integer) levels.next(); + boolean allStarted = startBundles((List) startLevels.get(level)); + if (!allStarted) + OsgiBootUtils + .warn("Not all bundles started for level " + level); + if (level.equals(activeStartLevel)) + break;// active start level reached + } + + } + + public static void computeStartLevels( + SortedMap/* > */startLevels, + Properties properties, Integer defaultStartLevel) { + + // default (and previously, only behaviour) + appendToStartLevels(startLevels, defaultStartLevel, + properties.getProperty(PROP_ARGEO_OSGI_START, "")); + + // list argeo.osgi.start.* system properties + Iterator/* */keys = properties.keySet().iterator(); + final String prefix = PROP_ARGEO_OSGI_START + "."; + while (keys.hasNext()) { + String key = (String) keys.next(); + if (key.startsWith(prefix)) { + Integer startLevel; + String suffix = key.substring(prefix.length()); + String[] tokens = suffix.split("\\."); + if (tokens.length > 0 && !tokens[0].trim().equals("")) + try { + // first token is start level + startLevel = new Integer(tokens[0]); + } catch (NumberFormatException e) { + startLevel = defaultStartLevel; + } + else + startLevel = defaultStartLevel; + + // append bundle names + String bundleNames = properties.getProperty(key); + appendToStartLevels(startLevels, startLevel, bundleNames); + } + } + } + + /** Append a comma-separated list of bundles to the start levels. */ + private static void appendToStartLevels( + SortedMap/* > */startLevels, + Integer startLevel, String str) { + if (str == null || str.trim().equals("")) + return; + + if (!startLevels.containsKey(startLevel)) + startLevels.put(startLevel, new ArrayList()); + String[] bundleNames = str.split(","); + for (int i = 0; i < bundleNames.length; i++) { + if (bundleNames[i] != null && !bundleNames[i].trim().equals("")) + ((List) startLevels.get(startLevel)).add(bundleNames[i]); + } + } + + /** + * Convenience method accepting a comma-separated list of bundle to start + * + * @deprecated + */ + public void startBundles(String bundlesToStartStr) { + if (bundlesToStartStr == null) + return; + + StringTokenizer st = new StringTokenizer(bundlesToStartStr, ","); + List bundlesToStart = new ArrayList(); + while (st.hasMoreTokens()) { + String name = st.nextToken().trim(); + bundlesToStart.add(name); + } + startBundles(bundlesToStart); + } + + /** + * Start the provided list of bundles + * + * @return whether all bundlesa are now in active state + */ + public boolean startBundles(List bundlesToStart) { + if (bundlesToStart.size() == 0) + return true; + + // used to monitor ACTIVE states + List/* */startedBundles = new ArrayList(); + // used to log the bundles not found + List/* */notFoundBundles = new ArrayList(bundlesToStart); + + Bundle[] bundles = bundleContext.getBundles(); + long startBegin = System.currentTimeMillis(); + for (int i = 0; i < bundles.length; i++) { + Bundle bundle = bundles[i]; + String symbolicName = bundle.getSymbolicName(); + if (bundlesToStart.contains(symbolicName)) + try { + try { + bundle.start(); + if (debug) + debug("Bundle " + symbolicName + " started"); + } catch (Exception e) { + OsgiBootUtils.warn("Start of bundle " + symbolicName + + " failed because of " + e + + ", maybe bundle is not yet resolved," + + " waiting and trying again."); + waitForBundleResolvedOrActive(startBegin, bundle); + bundle.start(); + startedBundles.add(bundle); + } + notFoundBundles.remove(symbolicName); + } catch (Exception e) { + OsgiBootUtils.warn("Bundle " + symbolicName + + " cannot be started: " + e.getMessage()); + if (debug) + e.printStackTrace(); + // was found even if start failed + notFoundBundles.remove(symbolicName); + } + } + + for (int i = 0; i < notFoundBundles.size(); i++) + OsgiBootUtils.warn("Bundle '" + notFoundBundles.get(i) + + "' not started because it was not found."); + + // monitors that all bundles are started + long beginMonitor = System.currentTimeMillis(); + boolean allStarted = !(startedBundles.size() > 0); + List/* */notStarted = new ArrayList(); + while (!allStarted + && (System.currentTimeMillis() - beginMonitor) < defaultTimeout) { + notStarted = new ArrayList(); + allStarted = true; + for (int i = 0; i < startedBundles.size(); i++) { + Bundle bundle = (Bundle) startedBundles.get(i); + // TODO check behaviour of lazs bundles + if (bundle.getState() != Bundle.ACTIVE) { + allStarted = false; + notStarted.add(bundle.getSymbolicName()); + } + } + try { + Thread.sleep(100); + } catch (InterruptedException e) { + // silent + } + } + long duration = System.currentTimeMillis() - beginMonitor; + + if (!allStarted) + for (int i = 0; i < notStarted.size(); i++) + OsgiBootUtils.warn("Bundle '" + notStarted.get(i) + + "' not ACTIVE after " + (duration / 1000) + "s"); + + return allStarted; + } + + /* + * DIAGNOSTICS + */ + /** Check unresolved bundles */ + protected void checkUnresolved() { + // Refresh + ServiceReference packageAdminRef = bundleContext + .getServiceReference(PackageAdmin.class.getName()); + PackageAdmin packageAdmin = (PackageAdmin) bundleContext + .getService(packageAdminRef); + packageAdmin.resolveBundles(null); + + Bundle[] bundles = bundleContext.getBundles(); + List /* Bundle */unresolvedBundles = new ArrayList(); + for (int i = 0; i < bundles.length; i++) { + int bundleState = bundles[i].getState(); + if (!(bundleState == Bundle.ACTIVE + || bundleState == Bundle.RESOLVED || bundleState == Bundle.STARTING)) + unresolvedBundles.add(bundles[i]); + } + + if (unresolvedBundles.size() != 0) { + OsgiBootUtils.warn("Unresolved bundles " + unresolvedBundles); + } + } + + /** List packages exported twice. */ + public Map findPackagesExportedTwice() { + ServiceReference paSr = bundleContext + .getServiceReference(PackageAdmin.class.getName()); + PackageAdmin packageAdmin = (PackageAdmin) bundleContext + .getService(paSr); + + // find packages exported twice + Bundle[] bundles = bundleContext.getBundles(); + Map /* > */exportedPackages = new TreeMap(); + for (int i = 0; i < bundles.length; i++) { + Bundle bundle = bundles[i]; + ExportedPackage[] pkgs = packageAdmin.getExportedPackages(bundle); + if (pkgs != null) + for (int j = 0; j < pkgs.length; j++) { + String pkgName = pkgs[j].getName(); + if (!exportedPackages.containsKey(pkgName)) { + exportedPackages.put(pkgName, new TreeSet()); + } + ((Set) exportedPackages.get(pkgName)).add(bundle + .getSymbolicName() + "_" + bundle.getVersion()); + } + } + Map /* > */duplicatePackages = new TreeMap(); + Iterator it = exportedPackages.keySet().iterator(); + while (it.hasNext()) { + String pkgName = it.next().toString(); + Set bdles = (Set) exportedPackages.get(pkgName); + if (bdles.size() > 1) + duplicatePackages.put(pkgName, bdles); + } + return duplicatePackages; + } + + /** Waits for a bundle to become active or resolved */ + protected void waitForBundleResolvedOrActive(long startBegin, Bundle bundle) + throws Exception { + int originalState = bundle.getState(); + if ((originalState == Bundle.RESOLVED) + || (originalState == Bundle.ACTIVE)) + return; + + String originalStateStr = OsgiBootUtils.stateAsString(originalState); + + int currentState = bundle.getState(); + while (!(currentState == Bundle.RESOLVED || currentState == Bundle.ACTIVE)) { + long now = System.currentTimeMillis(); + if ((now - startBegin) > defaultTimeout * 10) + throw new Exception("Bundle " + bundle.getSymbolicName() + + " was not RESOLVED or ACTIVE after " + + (now - startBegin) + "ms (originalState=" + + originalStateStr + ", currentState=" + + OsgiBootUtils.stateAsString(currentState) + ")"); + + try { + Thread.sleep(100l); + } catch (InterruptedException e) { + // silent + } + currentState = bundle.getState(); + } + } + + /* + * EXPLICIT LOCATIONS INSTALLATION + */ + /** Gets the list of resolved explicit URL locations. */ + public List getLocationsUrls() { + String baseUrl = OsgiBootUtils.getProperty(PROP_ARGEO_OSGI_BASE_URL, + DEFAULT_BASE_URL); + String bundleLocations = OsgiBootUtils + .getProperty(PROP_ARGEO_OSGI_LOCATIONS); + return getLocationsUrls(baseUrl, bundleLocations); + } + + /** + * Gets a list of URLs based on explicit locations, resolving placeholder + * ${...} containing system properties, e.g. ${user.home}. + */ + public List getLocationsUrls(String baseUrl, String bundleLocations) { + List urls = new ArrayList(); + + if (bundleLocations == null) + return urls; + bundleLocations = SystemPropertyUtils + .resolvePlaceholders(bundleLocations); + if (debug) + debug(PROP_ARGEO_OSGI_LOCATIONS + "=" + bundleLocations); + + StringTokenizer st = new StringTokenizer(bundleLocations, + File.pathSeparator); + while (st.hasMoreTokens()) { + urls.add(locationToUrl(baseUrl, st.nextToken().trim())); + } + return urls; + } + + /* + * BUNDLE PATTERNS INSTALLATION + */ + /** + * Computes a list of URLs based on Ant-like incluide/exclude patterns + * defined by ${argeo.osgi.bundles} with the following format:
+ * /base/directory;in=*.jar;in=**;ex=org.eclipse.osgi_*;jar
+ * WARNING: /base/directory;in=*.jar,\ at the end of a file, + * without a new line causes a '.' to be appended with unexpected side + * effects. + */ + public List getBundlesUrls() { + String bundlePatterns = OsgiBootUtils + .getProperty(PROP_ARGEO_OSGI_BUNDLES); + return getBundlesUrls(bundlePatterns); + } + + /** + * Compute alist of URLs to install based on the provided patterns, with + * default base url + */ + public List getBundlesUrls(String bundlePatterns) { + String baseUrl = OsgiBootUtils.getProperty(PROP_ARGEO_OSGI_BASE_URL, + DEFAULT_BASE_URL); + return getBundlesUrls(baseUrl, bundlePatterns); + } + + /** Implements the path matching logic */ + List getBundlesUrls(String baseUrl, String bundlePatterns) { + List urls = new ArrayList(); + if (bundlePatterns == null) + return urls; + + bundlePatterns = SystemPropertyUtils + .resolvePlaceholders(bundlePatterns); + if (debug) + debug(PROP_ARGEO_OSGI_BUNDLES + "=" + bundlePatterns + + " (excludeSvn=" + excludeSvn + ")"); + + StringTokenizer st = new StringTokenizer(bundlePatterns, ","); + List bundlesSets = new ArrayList(); + while (st.hasMoreTokens()) { + bundlesSets.add(new BundlesSet(st.nextToken())); + } + + // find included + List included = new ArrayList(); + PathMatcher matcher = new AntPathMatcher(); + for (int i = 0; i < bundlesSets.size(); i++) { + BundlesSet bundlesSet = (BundlesSet) bundlesSets.get(i); + for (int j = 0; j < bundlesSet.getIncludes().size(); j++) { + String pattern = (String) bundlesSet.getIncludes().get(j); + match(matcher, included, bundlesSet.getDir(), null, pattern); + } + } + + // find excluded + List excluded = new ArrayList(); + for (int i = 0; i < bundlesSets.size(); i++) { + BundlesSet bundlesSet = (BundlesSet) bundlesSets.get(i); + for (int j = 0; j < bundlesSet.getExcludes().size(); j++) { + String pattern = (String) bundlesSet.getExcludes().get(j); + match(matcher, excluded, bundlesSet.getDir(), null, pattern); + } + } + + // construct list + for (int i = 0; i < included.size(); i++) { + String fullPath = (String) included.get(i); + if (!excluded.contains(fullPath)) + urls.add(locationToUrl(baseUrl, fullPath)); + } + + return urls; + } + + /* + * DISTRIBUTION JAR INSTALLATION + */ + public List getDistributionUrls() { + List urls = new ArrayList(); + String distributionUrl = OsgiBootUtils + .getProperty(PROP_ARGEO_OSGI_DISTRIBUTION_URL); + if (distributionUrl == null) + return urls; + String baseUrl = OsgiBootUtils.getProperty(PROP_ARGEO_OSGI_BASE_URL); + + DistributionBundle distributionBundle; + if (baseUrl != null + && !(distributionUrl.startsWith("http") || distributionUrl + .startsWith("file"))) { + // relative url + distributionBundle = new DistributionBundle(baseUrl, + distributionUrl); + } else { + distributionBundle = new DistributionBundle(distributionUrl); + if (baseUrl != null) + distributionBundle.setBaseUrl(baseUrl); + + } + distributionBundle.processUrl(); + return distributionBundle.listUrls(); + } + + /* + * MODULES LIST INSTALLATION (${argeo.osgi.modulesUrl}) + */ + /** + * Downloads a list of URLs in CSV format from ${argeo.osgi.modulesUrl}:
+ * Bundle-SymbolicName,Bundle-Version,url)
+ * If ${argeo.osgi.baseUrl} is set, URLs will be considered relative paths + * and be concatenated with the base URL, typically the root of a Maven + * repository. + * + * @deprecated + */ + public List getModulesUrls() { + List urls = new ArrayList(); + String modulesUrlStr = OsgiBootUtils + .getProperty(PROP_ARGEO_OSGI_MODULES_URL); + if (modulesUrlStr == null) + return urls; + + String baseUrl = OsgiBootUtils.getProperty(PROP_ARGEO_OSGI_BASE_URL); + + Map installedBundles = getBundlesBySymbolicName(); + + BufferedReader reader = null; + try { + URL modulesUrl = new URL(modulesUrlStr); + reader = new BufferedReader(new InputStreamReader( + modulesUrl.openStream())); + String line = null; + while ((line = reader.readLine()) != null) { + StringTokenizer st = new StringTokenizer(line, + modulesUrlSeparator); + String moduleName = st.nextToken(); + String moduleVersion = st.nextToken(); + String url = st.nextToken(); + if (baseUrl != null) + url = baseUrl + url; + + if (installedBundles.containsKey(moduleName)) { + Bundle bundle = (Bundle) installedBundles.get(moduleName); + String bundleVersion = bundle.getHeaders() + .get(Constants.BUNDLE_VERSION).toString(); + int comp = OsgiBootUtils.compareVersions(bundleVersion, + moduleVersion); + if (comp > 0) { + OsgiBootUtils.warn("Installed version " + bundleVersion + + " of bundle " + moduleName + + " is newer than provided version " + + moduleVersion); + } else if (comp < 0) { + urls.add(url); + OsgiBootUtils.info("Updated bundle " + moduleName + + " with version " + moduleVersion + + " (old version was " + bundleVersion + ")"); + } else { + // do nothing + } + } else { + urls.add(url); + } + } + } catch (Exception e1) { + throw new RuntimeException("Cannot read url " + modulesUrlStr, e1); + } finally { + if (reader != null) + try { + reader.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return urls; + } + + /* + * HIGH LEVEL UTILITIES + */ + /** Actually performs the matching logic. */ + protected void match(PathMatcher matcher, List matched, String base, + String currentPath, String pattern) { + if (currentPath == null) { + // Init + File baseDir = new File(base.replace('/', File.separatorChar)); + File[] files = baseDir.listFiles(); + + if (files == null) { + if (debug) + OsgiBootUtils.warn("Base dir " + baseDir + + " has no children, exists=" + baseDir.exists() + + ", isDirectory=" + baseDir.isDirectory()); + return; + } + + for (int i = 0; i < files.length; i++) + match(matcher, matched, base, files[i].getName(), pattern); + } else { + String fullPath = base + '/' + currentPath; + if (matched.contains(fullPath)) + return;// don't try deeper if already matched + + boolean ok = matcher.match(pattern, currentPath); + // if (debug) + // debug(currentPath + " " + (ok ? "" : " not ") + // + " matched with " + pattern); + if (ok) { + matched.add(fullPath); + return; + } else { + String newFullPath = relativeToFullPath(base, currentPath); + File newFile = new File(newFullPath); + File[] files = newFile.listFiles(); + if (files != null) { + for (int i = 0; i < files.length; i++) { + String newCurrentPath = currentPath + '/' + + files[i].getName(); + if (files[i].isDirectory()) { + if (matcher.matchStart(pattern, newCurrentPath)) { + // recurse only if start matches + match(matcher, matched, base, newCurrentPath, + pattern); + } else { + if (debug) + debug(newCurrentPath + + " does not start match with " + + pattern); + + } + } else { + boolean nonDirectoryOk = matcher.match(pattern, + newCurrentPath); + if (debug) + debug(currentPath + " " + (ok ? "" : " not ") + + " matched with " + pattern); + if (nonDirectoryOk) + matched.add(relativeToFullPath(base, + newCurrentPath)); + } + } + } + } + } + } + + protected void matchFile() { + + } + + /* + * LOW LEVEL UTILITIES + */ + /** + * The bundles already installed. Key is location (String) , value is a + * {@link Bundle} + */ + public Map getBundlesByLocation() { + Map installedBundles = new HashMap(); + Bundle[] bundles = bundleContext.getBundles(); + for (int i = 0; i < bundles.length; i++) { + installedBundles.put(bundles[i].getLocation(), bundles[i]); + } + return installedBundles; + } + + /** + * The bundles already installed. Key is symbolic name (String) , value is a + * {@link Bundle} + */ + public Map getBundlesBySymbolicName() { + Map namedBundles = new HashMap(); + Bundle[] bundles = bundleContext.getBundles(); + for (int i = 0; i < bundles.length; i++) { + namedBundles.put(bundles[i].getSymbolicName(), bundles[i]); + } + return namedBundles; + } + + /** Creates an URL from a location */ + protected String locationToUrl(String baseUrl, String location) { + // int extInd = location.lastIndexOf('.'); + // String ext = null; + // if (extInd > 0) + // ext = location.substring(extInd); + // + // if (baseUrl.startsWith("reference:") && ".jar".equals(ext)) + // return "file:" + location; + // else + return baseUrl + location; + } + + /** Transforms a relative path in a full system path. */ + protected String relativeToFullPath(String basePath, String relativePath) { + return (basePath + '/' + relativePath).replace('/', File.separatorChar); + } + + private String removeFilePrefix(String url) { + if (url.startsWith("file:")) + return url.substring("file:".length()); + else if (url.startsWith("reference:file:")) + return url.substring("reference:file:".length()); + else + return url; + } + + /** + * Convenience method to avoid cluttering the code with + * OsgiBootUtils.debug() + */ + protected void debug(Object obj) { + OsgiBootUtils.debug(obj); + } + + /* + * BEAN METHODS + */ + + public boolean getDebug() { + return debug; + } + + public void setDebug(boolean debug) { + this.debug = debug; + } + + public BundleContext getBundleContext() { + return bundleContext; + } + + public void setInstallInLexicographicOrder( + boolean installInAlphabeticalOrder) { + this.installInLexicographicOrder = installInAlphabeticalOrder; + } + + public boolean isInstallInLexicographicOrder() { + return installInLexicographicOrder; + } + + public void setDefaultTimeout(long defaultTimeout) { + this.defaultTimeout = defaultTimeout; + } + + public void setModulesUrlSeparator(String modulesUrlSeparator) { + this.modulesUrlSeparator = modulesUrlSeparator; + } + + public boolean isExcludeSvn() { + return excludeSvn; + } + + public void setExcludeSvn(boolean excludeSvn) { + this.excludeSvn = excludeSvn; + } + + /* + * INTERNAL CLASSES + */ + + /** Intermediary structure used by path matching */ + protected class BundlesSet { + private String baseUrl = "reference:file";// not used yet + private final String dir; + private List includes = new ArrayList(); + private List excludes = new ArrayList(); + + public BundlesSet(String def) { + StringTokenizer st = new StringTokenizer(def, ";"); + + if (!st.hasMoreTokens()) + throw new RuntimeException("Base dir not defined."); + try { + String dirPath = st.nextToken(); + + if (dirPath.startsWith("file:")) + dirPath = dirPath.substring("file:".length()); + + dir = new File(dirPath.replace('/', File.separatorChar)) + .getCanonicalPath(); + if (debug) + debug("Base dir: " + dir); + } catch (IOException e) { + throw new RuntimeException("Cannot convert to absolute path", e); + } + + while (st.hasMoreTokens()) { + String tk = st.nextToken(); + StringTokenizer stEq = new StringTokenizer(tk, "="); + String type = stEq.nextToken(); + String pattern = stEq.nextToken(); + if ("in".equals(type) || "include".equals(type)) { + includes.add(pattern); + } else if ("ex".equals(type) || "exclude".equals(type)) { + excludes.add(pattern); + } else if ("baseUrl".equals(type)) { + baseUrl = pattern; + } else { + System.err.println("Unkown bundles pattern type " + type); + } + } + + if (excludeSvn && !excludes.contains(EXCLUDES_SVN_PATTERN)) { + excludes.add(EXCLUDES_SVN_PATTERN); + } + } + + public String getDir() { + return dir; + } + + public List getIncludes() { + return includes; + } + + public List getExcludes() { + return excludes; + } + + public String getBaseUrl() { + return baseUrl; + } + + } + + /* @deprecated Doesn't seem to be used anymore. */ + // public void installOrUpdateUrls(Map urls) { + // Map installedBundles = getBundles(); + // + // for (Iterator modules = urls.keySet().iterator(); modules.hasNext();) { + // String moduleName = (String) modules.next(); + // String urlStr = (String) urls.get(moduleName); + // if (installedBundles.containsKey(moduleName)) { + // Bundle bundle = (Bundle) installedBundles.get(moduleName); + // InputStream in; + // try { + // URL url = new URL(urlStr); + // in = url.openStream(); + // bundle.update(in); + // OsgiBootUtils.info("Updated bundle " + moduleName + // + " from " + urlStr); + // } catch (Exception e) { + // throw new RuntimeException("Cannot update " + moduleName + // + " from " + urlStr); + // } + // if (in != null) + // try { + // in.close(); + // } catch (IOException e) { + // e.printStackTrace(); + // } + // } else { + // try { + // Bundle bundle = bundleContext.installBundle(urlStr); + // if (debug) + // debug("Installed bundle " + bundle.getSymbolicName() + // + " from " + urlStr); + // } catch (BundleException e) { + // OsgiBootUtils.warn("Could not install bundle from " + // + urlStr + ": " + e.getMessage()); + // } + // } + // } + // + // } + +} diff --git a/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/OsgiBootException.java b/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/OsgiBootException.java new file mode 100644 index 000000000..9a75f1766 --- /dev/null +++ b/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/OsgiBootException.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.osgi.boot; + +/** OsgiBoot specific exceptions */ +public class OsgiBootException extends RuntimeException { + private static final long serialVersionUID = 2414011711711425353L; + + public OsgiBootException() { + } + + public OsgiBootException(String message) { + super(message); + } + + public OsgiBootException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/OsgiBootUtils.java b/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/OsgiBootUtils.java new file mode 100644 index 000000000..20891c7f9 --- /dev/null +++ b/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/OsgiBootUtils.java @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.osgi.boot; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.StringTokenizer; + +import org.osgi.framework.Bundle; + +/** Utilities, mostly related to logging. */ +public class OsgiBootUtils { + /** ISO8601 (as per log4j) and difference to UTC */ + private static DateFormat dateFormat = new SimpleDateFormat( + "yyyy-MM-dd HH:mm:ss,SSS Z"); + + public static void info(Object obj) { + System.out.println("# OSGiBOOT # " + dateFormat.format(new Date()) + + " # " + obj); + } + + public static void debug(Object obj) { + System.out.println("# OSGiBOOT DBG # " + dateFormat.format(new Date()) + + " # " + obj); + } + + public static void warn(Object obj) { + System.out.println("# OSGiBOOT WARN # " + dateFormat.format(new Date()) + + " # " + obj); + } + + /** + * Gets a property value + * + * @return null when defaultValue is "" + */ + public static String getProperty(String name, String defaultValue) { + final String value; + if (defaultValue != null) + value = System.getProperty(name, defaultValue); + else + value = System.getProperty(name); + + if (value == null || value.equals("")) + return null; + else + return value; + } + + public static String getProperty(String name) { + return getProperty(name, null); + } + + public static String stateAsString(int state) { + switch (state) { + case Bundle.UNINSTALLED: + return "UNINSTALLED"; + case Bundle.INSTALLED: + return "INSTALLED"; + case Bundle.RESOLVED: + return "RESOLVED"; + case Bundle.STARTING: + return "STARTING"; + case Bundle.ACTIVE: + return "ACTIVE"; + case Bundle.STOPPING: + return "STOPPING"; + default: + return Integer.toString(state); + } + } + + /** + * @return ==0: versions are identical, <0: tested version is newer, >0: + * currentVersion is newer. + */ + public static int compareVersions(String currentVersion, + String testedVersion) { + List cToks = new ArrayList(); + StringTokenizer cSt = new StringTokenizer(currentVersion, "."); + while (cSt.hasMoreTokens()) + cToks.add(cSt.nextToken()); + List tToks = new ArrayList(); + StringTokenizer tSt = new StringTokenizer(currentVersion, "."); + while (tSt.hasMoreTokens()) + tToks.add(tSt.nextToken()); + + int comp = 0; + comp: for (int i = 0; i < cToks.size(); i++) { + if (tToks.size() <= i) { + // equals until then, tested shorter + comp = 1; + break comp; + } + + String c = (String) cToks.get(i); + String t = (String) tToks.get(i); + + try { + int cInt = Integer.parseInt(c); + int tInt = Integer.parseInt(t); + if (cInt == tInt) + continue comp; + else { + comp = (cInt - tInt); + break comp; + } + } catch (NumberFormatException e) { + if (c.equals(t)) + continue comp; + else { + comp = c.compareTo(t); + break comp; + } + } + } + + if (comp == 0 && tToks.size() > cToks.size()) { + // equals until then, current shorter + comp = -1; + } + + return comp; + } + +} diff --git a/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/internal/springutil/AntPathMatcher.java b/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/internal/springutil/AntPathMatcher.java new file mode 100644 index 000000000..0b9ad1a23 --- /dev/null +++ b/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/internal/springutil/AntPathMatcher.java @@ -0,0 +1,411 @@ +/* + * Copyright 2002-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.argeo.osgi.boot.internal.springutil; + +/** + * PathMatcher implementation for Ant-style path patterns. + * Examples are provided below. + * + *

Part of this mapping code has been kindly borrowed from + * Apache Ant. + * + *

The mapping matches URLs using the following rules:
+ *

    + *
  • ? matches one character
  • + *
  • * matches zero or more characters
  • + *
  • ** matches zero or more 'directories' in a path
  • + *
+ * + *

Some examples:
+ *

    + *
  • com/t?st.jsp - matches com/test.jsp but also + * com/tast.jsp or com/txst.jsp
  • + *
  • com/*.jsp - matches all .jsp files in the + * com directory
  • + *
  • com/**/test.jsp - matches all test.jsp + * files underneath the com path
  • + *
  • org/springframework/**/*.jsp - matches all .jsp + * files underneath the org/springframework path
  • + *
  • org/**/servlet/bla.jsp - matches + * org/springframework/servlet/bla.jsp but also + * org/springframework/testing/servlet/bla.jsp and + * org/servlet/bla.jsp
  • + *
+ * + * @author Alef Arendsen + * @author Juergen Hoeller + * @author Rob Harrop + * @since 16.07.2003 + */ +public class AntPathMatcher implements PathMatcher { + + /** Default path separator: "/" */ + public static final String DEFAULT_PATH_SEPARATOR = "/"; + + private String pathSeparator = DEFAULT_PATH_SEPARATOR; + + + /** + * Set the path separator to use for pattern parsing. + * Default is "/", as in Ant. + */ + public void setPathSeparator(String pathSeparator) { + this.pathSeparator = (pathSeparator != null ? pathSeparator : DEFAULT_PATH_SEPARATOR); + } + + + public boolean isPattern(String path) { + return (path.indexOf('*') != -1 || path.indexOf('?') != -1); + } + + public boolean match(String pattern, String path) { + return doMatch(pattern, path, true); + } + + public boolean matchStart(String pattern, String path) { + return doMatch(pattern, path, false); + } + + + /** + * Actually match the given path against the given pattern. + * @param pattern the pattern to match against + * @param path the path String to test + * @param fullMatch whether a full pattern match is required + * (else a pattern match as far as the given base path goes is sufficient) + * @return true if the supplied path matched, + * false if it didn't + */ + protected boolean doMatch(String pattern, String path, boolean fullMatch) { + if (path.startsWith(this.pathSeparator) != pattern.startsWith(this.pathSeparator)) { + return false; + } + + String[] pattDirs = StringUtils.tokenizeToStringArray(pattern, this.pathSeparator); + String[] pathDirs = StringUtils.tokenizeToStringArray(path, this.pathSeparator); + + int pattIdxStart = 0; + int pattIdxEnd = pattDirs.length - 1; + int pathIdxStart = 0; + int pathIdxEnd = pathDirs.length - 1; + + // Match all elements up to the first ** + while (pattIdxStart <= pattIdxEnd && pathIdxStart <= pathIdxEnd) { + String patDir = pattDirs[pattIdxStart]; + if ("**".equals(patDir)) { + break; + } + if (!matchStrings(patDir, pathDirs[pathIdxStart])) { + return false; + } + pattIdxStart++; + pathIdxStart++; + } + + if (pathIdxStart > pathIdxEnd) { + // Path is exhausted, only match if rest of pattern is * or **'s + if (pattIdxStart > pattIdxEnd) { + return (pattern.endsWith(this.pathSeparator) ? + path.endsWith(this.pathSeparator) : !path.endsWith(this.pathSeparator)); + } + if (!fullMatch) { + return true; + } + if (pattIdxStart == pattIdxEnd && pattDirs[pattIdxStart].equals("*") && + path.endsWith(this.pathSeparator)) { + return true; + } + for (int i = pattIdxStart; i <= pattIdxEnd; i++) { + if (!pattDirs[i].equals("**")) { + return false; + } + } + return true; + } + else if (pattIdxStart > pattIdxEnd) { + // String not exhausted, but pattern is. Failure. + return false; + } + else if (!fullMatch && "**".equals(pattDirs[pattIdxStart])) { + // Path start definitely matches due to "**" part in pattern. + return true; + } + + // up to last '**' + while (pattIdxStart <= pattIdxEnd && pathIdxStart <= pathIdxEnd) { + String patDir = pattDirs[pattIdxEnd]; + if (patDir.equals("**")) { + break; + } + if (!matchStrings(patDir, pathDirs[pathIdxEnd])) { + return false; + } + pattIdxEnd--; + pathIdxEnd--; + } + if (pathIdxStart > pathIdxEnd) { + // String is exhausted + for (int i = pattIdxStart; i <= pattIdxEnd; i++) { + if (!pattDirs[i].equals("**")) { + return false; + } + } + return true; + } + + while (pattIdxStart != pattIdxEnd && pathIdxStart <= pathIdxEnd) { + int patIdxTmp = -1; + for (int i = pattIdxStart + 1; i <= pattIdxEnd; i++) { + if (pattDirs[i].equals("**")) { + patIdxTmp = i; + break; + } + } + if (patIdxTmp == pattIdxStart + 1) { + // '**/**' situation, so skip one + pattIdxStart++; + continue; + } + // Find the pattern between padIdxStart & padIdxTmp in str between + // strIdxStart & strIdxEnd + int patLength = (patIdxTmp - pattIdxStart - 1); + int strLength = (pathIdxEnd - pathIdxStart + 1); + int foundIdx = -1; + + strLoop: + for (int i = 0; i <= strLength - patLength; i++) { + for (int j = 0; j < patLength; j++) { + String subPat = (String) pattDirs[pattIdxStart + j + 1]; + String subStr = (String) pathDirs[pathIdxStart + i + j]; + if (!matchStrings(subPat, subStr)) { + continue strLoop; + } + } + foundIdx = pathIdxStart + i; + break; + } + + if (foundIdx == -1) { + return false; + } + + pattIdxStart = patIdxTmp; + pathIdxStart = foundIdx + patLength; + } + + for (int i = pattIdxStart; i <= pattIdxEnd; i++) { + if (!pattDirs[i].equals("**")) { + return false; + } + } + + return true; + } + + /** + * Tests whether or not a string matches against a pattern. + * The pattern may contain two special characters:
+ * '*' means zero or more characters
+ * '?' means one and only one character + * @param pattern pattern to match against. + * Must not be null. + * @param str string which must be matched against the pattern. + * Must not be null. + * @return true if the string matches against the + * pattern, or false otherwise. + */ + private boolean matchStrings(String pattern, String str) { + char[] patArr = pattern.toCharArray(); + char[] strArr = str.toCharArray(); + int patIdxStart = 0; + int patIdxEnd = patArr.length - 1; + int strIdxStart = 0; + int strIdxEnd = strArr.length - 1; + char ch; + + boolean containsStar = false; + for (int i = 0; i < patArr.length; i++) { + if (patArr[i] == '*') { + containsStar = true; + break; + } + } + + if (!containsStar) { + // No '*'s, so we make a shortcut + if (patIdxEnd != strIdxEnd) { + return false; // Pattern and string do not have the same size + } + for (int i = 0; i <= patIdxEnd; i++) { + ch = patArr[i]; + if (ch != '?') { + if (ch != strArr[i]) { + return false;// Character mismatch + } + } + } + return true; // String matches against pattern + } + + + if (patIdxEnd == 0) { + return true; // Pattern contains only '*', which matches anything + } + + // Process characters before first star + while ((ch = patArr[patIdxStart]) != '*' && strIdxStart <= strIdxEnd) { + if (ch != '?') { + if (ch != strArr[strIdxStart]) { + return false;// Character mismatch + } + } + patIdxStart++; + strIdxStart++; + } + if (strIdxStart > strIdxEnd) { + // All characters in the string are used. Check if only '*'s are + // left in the pattern. If so, we succeeded. Otherwise failure. + for (int i = patIdxStart; i <= patIdxEnd; i++) { + if (patArr[i] != '*') { + return false; + } + } + return true; + } + + // Process characters after last star + while ((ch = patArr[patIdxEnd]) != '*' && strIdxStart <= strIdxEnd) { + if (ch != '?') { + if (ch != strArr[strIdxEnd]) { + return false;// Character mismatch + } + } + patIdxEnd--; + strIdxEnd--; + } + if (strIdxStart > strIdxEnd) { + // All characters in the string are used. Check if only '*'s are + // left in the pattern. If so, we succeeded. Otherwise failure. + for (int i = patIdxStart; i <= patIdxEnd; i++) { + if (patArr[i] != '*') { + return false; + } + } + return true; + } + + // process pattern between stars. padIdxStart and patIdxEnd point + // always to a '*'. + while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd) { + int patIdxTmp = -1; + for (int i = patIdxStart + 1; i <= patIdxEnd; i++) { + if (patArr[i] == '*') { + patIdxTmp = i; + break; + } + } + if (patIdxTmp == patIdxStart + 1) { + // Two stars next to each other, skip the first one. + patIdxStart++; + continue; + } + // Find the pattern between padIdxStart & padIdxTmp in str between + // strIdxStart & strIdxEnd + int patLength = (patIdxTmp - patIdxStart - 1); + int strLength = (strIdxEnd - strIdxStart + 1); + int foundIdx = -1; + strLoop: + for (int i = 0; i <= strLength - patLength; i++) { + for (int j = 0; j < patLength; j++) { + ch = patArr[patIdxStart + j + 1]; + if (ch != '?') { + if (ch != strArr[strIdxStart + i + j]) { + continue strLoop; + } + } + } + + foundIdx = strIdxStart + i; + break; + } + + if (foundIdx == -1) { + return false; + } + + patIdxStart = patIdxTmp; + strIdxStart = foundIdx + patLength; + } + + // All characters in the string are used. Check if only '*'s are left + // in the pattern. If so, we succeeded. Otherwise failure. + for (int i = patIdxStart; i <= patIdxEnd; i++) { + if (patArr[i] != '*') { + return false; + } + } + + return true; + } + + /** + * Given a pattern and a full path, determine the pattern-mapped part. + *

For example: + *

    + *
  • '/docs/cvs/commit.html' and '/docs/cvs/commit.html -> ''
  • + *
  • '/docs/*' and '/docs/cvs/commit -> 'cvs/commit'
  • + *
  • '/docs/cvs/*.html' and '/docs/cvs/commit.html -> 'commit.html'
  • + *
  • '/docs/**' and '/docs/cvs/commit -> 'cvs/commit'
  • + *
  • '/docs/**\/*.html' and '/docs/cvs/commit.html -> 'cvs/commit.html'
  • + *
  • '/*.html' and '/docs/cvs/commit.html -> 'docs/cvs/commit.html'
  • + *
  • '*.html' and '/docs/cvs/commit.html -> '/docs/cvs/commit.html'
  • + *
  • '*' and '/docs/cvs/commit.html -> '/docs/cvs/commit.html'
  • + *
+ *

Assumes that {@link #match} returns true for 'pattern' + * and 'path', but does not enforce this. + */ + public String extractPathWithinPattern(String pattern, String path) { + String[] patternParts = StringUtils.tokenizeToStringArray(pattern, this.pathSeparator); + String[] pathParts = StringUtils.tokenizeToStringArray(path, this.pathSeparator); + + StringBuffer buffer = new StringBuffer(); + + // Add any path parts that have a wildcarded pattern part. + int puts = 0; + for (int i = 0; i < patternParts.length; i++) { + String patternPart = patternParts[i]; + if ((patternPart.indexOf('*') > -1 || patternPart.indexOf('?') > -1) && pathParts.length >= i + 1) { + if (puts > 0 || (i == 0 && !pattern.startsWith(this.pathSeparator))) { + buffer.append(this.pathSeparator); + } + buffer.append(pathParts[i]); + puts++; + } + } + + // Append any trailing path parts. + for (int i = patternParts.length; i < pathParts.length; i++) { + if (puts > 0 || i > 0) { + buffer.append(this.pathSeparator); + } + buffer.append(pathParts[i]); + } + + return buffer.toString(); + } + +} diff --git a/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/internal/springutil/CollectionUtils.java b/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/internal/springutil/CollectionUtils.java new file mode 100644 index 000000000..ad0154293 --- /dev/null +++ b/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/internal/springutil/CollectionUtils.java @@ -0,0 +1,275 @@ +/* + * Copyright 2002-2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.argeo.osgi.boot.internal.springutil; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +/** + * Miscellaneous collection utility methods. + * Mainly for internal use within the framework. + * + * @author Juergen Hoeller + * @author Rob Harrop + * @since 1.1.3 + */ +public abstract class CollectionUtils { + + /** + * Return true if the supplied Collection is null + * or empty. Otherwise, return false. + * @param collection the Collection to check + * @return whether the given Collection is empty + */ + public static boolean isEmpty(Collection collection) { + return (collection == null || collection.isEmpty()); + } + + /** + * Return true if the supplied Map is null + * or empty. Otherwise, return false. + * @param map the Map to check + * @return whether the given Map is empty + */ + public static boolean isEmpty(Map map) { + return (map == null || map.isEmpty()); + } + + /** + * Convert the supplied array into a List. A primitive array gets + * converted into a List of the appropriate wrapper type. + *

A null source value will be converted to an + * empty List. + * @param source the (potentially primitive) array + * @return the converted List result + * @see ObjectUtils#toObjectArray(Object) + */ + public static List arrayToList(Object source) { + return Arrays.asList(ObjectUtils.toObjectArray(source)); + } + + /** + * Merge the given array into the given Collection. + * @param array the array to merge (may be null) + * @param collection the target Collection to merge the array into + */ + public static void mergeArrayIntoCollection(Object array, Collection collection) { + if (collection == null) { + throw new IllegalArgumentException("Collection must not be null"); + } + Object[] arr = ObjectUtils.toObjectArray(array); + for (int i = 0; i < arr.length; i++) { + collection.add(arr[i]); + } + } + + /** + * Merge the given Properties instance into the given Map, + * copying all properties (key-value pairs) over. + *

Uses Properties.propertyNames() to even catch + * default properties linked into the original Properties instance. + * @param props the Properties instance to merge (may be null) + * @param map the target Map to merge the properties into + */ + public static void mergePropertiesIntoMap(Properties props, Map map) { + if (map == null) { + throw new IllegalArgumentException("Map must not be null"); + } + if (props != null) { + for (Enumeration en = props.propertyNames(); en.hasMoreElements();) { + String key = (String) en.nextElement(); + map.put(key, props.getProperty(key)); + } + } + } + + + /** + * Check whether the given Iterator contains the given element. + * @param iterator the Iterator to check + * @param element the element to look for + * @return true if found, false else + */ + public static boolean contains(Iterator iterator, Object element) { + if (iterator != null) { + while (iterator.hasNext()) { + Object candidate = iterator.next(); + if (ObjectUtils.nullSafeEquals(candidate, element)) { + return true; + } + } + } + return false; + } + + /** + * Check whether the given Enumeration contains the given element. + * @param enumeration the Enumeration to check + * @param element the element to look for + * @return true if found, false else + */ + public static boolean contains(Enumeration enumeration, Object element) { + if (enumeration != null) { + while (enumeration.hasMoreElements()) { + Object candidate = enumeration.nextElement(); + if (ObjectUtils.nullSafeEquals(candidate, element)) { + return true; + } + } + } + return false; + } + + /** + * Check whether the given Collection contains the given element instance. + *

Enforces the given instance to be present, rather than returning + * true for an equal element as well. + * @param collection the Collection to check + * @param element the element to look for + * @return true if found, false else + */ + public static boolean containsInstance(Collection collection, Object element) { + if (collection != null) { + for (Iterator it = collection.iterator(); it.hasNext();) { + Object candidate = it.next(); + if (candidate == element) { + return true; + } + } + } + return false; + } + + /** + * Return true if any element in 'candidates' is + * contained in 'source'; otherwise returns false. + * @param source the source Collection + * @param candidates the candidates to search for + * @return whether any of the candidates has been found + */ + public static boolean containsAny(Collection source, Collection candidates) { + if (isEmpty(source) || isEmpty(candidates)) { + return false; + } + for (Iterator it = candidates.iterator(); it.hasNext();) { + if (source.contains(it.next())) { + return true; + } + } + return false; + } + + /** + * Return the first element in 'candidates' that is contained in + * 'source'. If no element in 'candidates' is present in + * 'source' returns null. Iteration order is + * {@link Collection} implementation specific. + * @param source the source Collection + * @param candidates the candidates to search for + * @return the first present object, or null if not found + */ + public static Object findFirstMatch(Collection source, Collection candidates) { + if (isEmpty(source) || isEmpty(candidates)) { + return null; + } + for (Iterator it = candidates.iterator(); it.hasNext();) { + Object candidate = it.next(); + if (source.contains(candidate)) { + return candidate; + } + } + return null; + } + + /** + * Find a single value of the given type in the given Collection. + * @param collection the Collection to search + * @param type the type to look for + * @return a value of the given type found if there is a clear match, + * or null if none or more than one such value found + */ + public static Object findValueOfType(Collection collection, Class type) { + if (isEmpty(collection)) { + return null; + } + Object value = null; + for (Iterator it = collection.iterator(); it.hasNext();) { + Object obj = it.next(); + if (type == null || type.isInstance(obj)) { + if (value != null) { + // More than one value found... no clear single value. + return null; + } + value = obj; + } + } + return value; + } + + /** + * Find a single value of one of the given types in the given Collection: + * searching the Collection for a value of the first type, then + * searching for a value of the second type, etc. + * @param collection the collection to search + * @param types the types to look for, in prioritized order + * @return a value of one of the given types found if there is a clear match, + * or null if none or more than one such value found + */ + public static Object findValueOfType(Collection collection, Class[] types) { + if (isEmpty(collection) || ObjectUtils.isEmpty(types)) { + return null; + } + for (int i = 0; i < types.length; i++) { + Object value = findValueOfType(collection, types[i]); + if (value != null) { + return value; + } + } + return null; + } + + /** + * Determine whether the given Collection only contains a single unique object. + * @param collection the Collection to check + * @return true if the collection contains a single reference or + * multiple references to the same instance, false else + */ + public static boolean hasUniqueObject(Collection collection) { + if (isEmpty(collection)) { + return false; + } + boolean hasCandidate = false; + Object candidate = null; + for (Iterator it = collection.iterator(); it.hasNext();) { + Object elem = it.next(); + if (!hasCandidate) { + hasCandidate = true; + candidate = elem; + } + else if (candidate != elem) { + return false; + } + } + return true; + } + +} diff --git a/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/internal/springutil/ObjectUtils.java b/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/internal/springutil/ObjectUtils.java new file mode 100644 index 000000000..223b2a1c1 --- /dev/null +++ b/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/internal/springutil/ObjectUtils.java @@ -0,0 +1,833 @@ +/* + * Copyright 2002-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.argeo.osgi.boot.internal.springutil; + +import java.lang.reflect.Array; +import java.util.Arrays; + +/** + * Miscellaneous object utility methods. Mainly for internal use within the + * framework; consider Jakarta's Commons Lang for a more comprehensive suite + * of object utilities. + * + * @author Juergen Hoeller + * @author Keith Donald + * @author Rod Johnson + * @author Rob Harrop + * @author Alex Ruiz + * @since 19.03.2004 + * @see org.apache.commons.lang.ObjectUtils + */ +public abstract class ObjectUtils { + + private static final int INITIAL_HASH = 7; + private static final int MULTIPLIER = 31; + + private static final String EMPTY_STRING = ""; + private static final String NULL_STRING = "null"; + private static final String ARRAY_START = "{"; + private static final String ARRAY_END = "}"; + private static final String EMPTY_ARRAY = ARRAY_START + ARRAY_END; + private static final String ARRAY_ELEMENT_SEPARATOR = ", "; + + + /** + * Return whether the given throwable is a checked exception: + * that is, neither a RuntimeException nor an Error. + * @param ex the throwable to check + * @return whether the throwable is a checked exception + * @see java.lang.Exception + * @see java.lang.RuntimeException + * @see java.lang.Error + */ + public static boolean isCheckedException(Throwable ex) { + return !(ex instanceof RuntimeException || ex instanceof Error); + } + + /** + * Check whether the given exception is compatible with the exceptions + * declared in a throws clause. + * @param ex the exception to checked + * @param declaredExceptions the exceptions declared in the throws clause + * @return whether the given exception is compatible + */ + public static boolean isCompatibleWithThrowsClause(Throwable ex, Class[] declaredExceptions) { + if (!isCheckedException(ex)) { + return true; + } + if (declaredExceptions != null) { + for (int i = 0; i < declaredExceptions.length; i++) { + if (declaredExceptions[i].isAssignableFrom(ex.getClass())) { + return true; + } + } + } + return false; + } + + /** + * Return whether the given array is empty: that is, null + * or of zero length. + * @param array the array to check + * @return whether the given array is empty + */ + public static boolean isEmpty(Object[] array) { + return (array == null || array.length == 0); + } + + /** + * Check whether the given array contains the given element. + * @param array the array to check (may be null, + * in which case the return value will always be false) + * @param element the element to check for + * @return whether the element has been found in the given array + */ + public static boolean containsElement(Object[] array, Object element) { + if (array == null) { + return false; + } + for (int i = 0; i < array.length; i++) { + if (nullSafeEquals(array[i], element)) { + return true; + } + } + return false; + } + + /** + * Append the given Object to the given array, returning a new array + * consisting of the input array contents plus the given Object. + * @param array the array to append to (can be null) + * @param obj the Object to append + * @return the new array (of the same component type; never null) + */ + public static Object[] addObjectToArray(Object[] array, Object obj) { + Class compType = Object.class; + if (array != null) { + compType = array.getClass().getComponentType(); + } + else if (obj != null) { + compType = obj.getClass(); + } + int newArrLength = (array != null ? array.length + 1 : 1); + Object[] newArr = (Object[]) Array.newInstance(compType, newArrLength); + if (array != null) { + System.arraycopy(array, 0, newArr, 0, array.length); + } + newArr[newArr.length - 1] = obj; + return newArr; + } + + /** + * Convert the given array (which may be a primitive array) to an + * object array (if necessary of primitive wrapper objects). + *

A null source value will be converted to an + * empty Object array. + * @param source the (potentially primitive) array + * @return the corresponding object array (never null) + * @throws IllegalArgumentException if the parameter is not an array + */ + public static Object[] toObjectArray(Object source) { + if (source instanceof Object[]) { + return (Object[]) source; + } + if (source == null) { + return new Object[0]; + } + if (!source.getClass().isArray()) { + throw new IllegalArgumentException("Source is not an array: " + source); + } + int length = Array.getLength(source); + if (length == 0) { + return new Object[0]; + } + Class wrapperType = Array.get(source, 0).getClass(); + Object[] newArray = (Object[]) Array.newInstance(wrapperType, length); + for (int i = 0; i < length; i++) { + newArray[i] = Array.get(source, i); + } + return newArray; + } + + + //--------------------------------------------------------------------- + // Convenience methods for content-based equality/hash-code handling + //--------------------------------------------------------------------- + + /** + * Determine if the given objects are equal, returning true + * if both are null or false if only one is + * null. + *

Compares arrays with Arrays.equals, performing an equality + * check based on the array elements rather than the array reference. + * @param o1 first Object to compare + * @param o2 second Object to compare + * @return whether the given objects are equal + * @see java.util.Arrays#equals + */ + public static boolean nullSafeEquals(Object o1, Object o2) { + if (o1 == o2) { + return true; + } + if (o1 == null || o2 == null) { + return false; + } + if (o1.equals(o2)) { + return true; + } + if (o1.getClass().isArray() && o2.getClass().isArray()) { + if (o1 instanceof Object[] && o2 instanceof Object[]) { + return Arrays.equals((Object[]) o1, (Object[]) o2); + } + if (o1 instanceof boolean[] && o2 instanceof boolean[]) { + return Arrays.equals((boolean[]) o1, (boolean[]) o2); + } + if (o1 instanceof byte[] && o2 instanceof byte[]) { + return Arrays.equals((byte[]) o1, (byte[]) o2); + } + if (o1 instanceof char[] && o2 instanceof char[]) { + return Arrays.equals((char[]) o1, (char[]) o2); + } + if (o1 instanceof double[] && o2 instanceof double[]) { + return Arrays.equals((double[]) o1, (double[]) o2); + } + if (o1 instanceof float[] && o2 instanceof float[]) { + return Arrays.equals((float[]) o1, (float[]) o2); + } + if (o1 instanceof int[] && o2 instanceof int[]) { + return Arrays.equals((int[]) o1, (int[]) o2); + } + if (o1 instanceof long[] && o2 instanceof long[]) { + return Arrays.equals((long[]) o1, (long[]) o2); + } + if (o1 instanceof short[] && o2 instanceof short[]) { + return Arrays.equals((short[]) o1, (short[]) o2); + } + } + return false; + } + + /** + * Return as hash code for the given object; typically the value of + * {@link Object#hashCode()}. If the object is an array, + * this method will delegate to any of the nullSafeHashCode + * methods for arrays in this class. If the object is null, + * this method returns 0. + * @see #nullSafeHashCode(Object[]) + * @see #nullSafeHashCode(boolean[]) + * @see #nullSafeHashCode(byte[]) + * @see #nullSafeHashCode(char[]) + * @see #nullSafeHashCode(double[]) + * @see #nullSafeHashCode(float[]) + * @see #nullSafeHashCode(int[]) + * @see #nullSafeHashCode(long[]) + * @see #nullSafeHashCode(short[]) + */ + public static int nullSafeHashCode(Object obj) { + if (obj == null) { + return 0; + } + if (obj.getClass().isArray()) { + if (obj instanceof Object[]) { + return nullSafeHashCode((Object[]) obj); + } + if (obj instanceof boolean[]) { + return nullSafeHashCode((boolean[]) obj); + } + if (obj instanceof byte[]) { + return nullSafeHashCode((byte[]) obj); + } + if (obj instanceof char[]) { + return nullSafeHashCode((char[]) obj); + } + if (obj instanceof double[]) { + return nullSafeHashCode((double[]) obj); + } + if (obj instanceof float[]) { + return nullSafeHashCode((float[]) obj); + } + if (obj instanceof int[]) { + return nullSafeHashCode((int[]) obj); + } + if (obj instanceof long[]) { + return nullSafeHashCode((long[]) obj); + } + if (obj instanceof short[]) { + return nullSafeHashCode((short[]) obj); + } + } + return obj.hashCode(); + } + + /** + * Return a hash code based on the contents of the specified array. + * If array is null, this method returns 0. + */ + public static int nullSafeHashCode(Object[] array) { + if (array == null) { + return 0; + } + int hash = INITIAL_HASH; + int arraySize = array.length; + for (int i = 0; i < arraySize; i++) { + hash = MULTIPLIER * hash + nullSafeHashCode(array[i]); + } + return hash; + } + + /** + * Return a hash code based on the contents of the specified array. + * If array is null, this method returns 0. + */ + public static int nullSafeHashCode(boolean[] array) { + if (array == null) { + return 0; + } + int hash = INITIAL_HASH; + int arraySize = array.length; + for (int i = 0; i < arraySize; i++) { + hash = MULTIPLIER * hash + hashCode(array[i]); + } + return hash; + } + + /** + * Return a hash code based on the contents of the specified array. + * If array is null, this method returns 0. + */ + public static int nullSafeHashCode(byte[] array) { + if (array == null) { + return 0; + } + int hash = INITIAL_HASH; + int arraySize = array.length; + for (int i = 0; i < arraySize; i++) { + hash = MULTIPLIER * hash + array[i]; + } + return hash; + } + + /** + * Return a hash code based on the contents of the specified array. + * If array is null, this method returns 0. + */ + public static int nullSafeHashCode(char[] array) { + if (array == null) { + return 0; + } + int hash = INITIAL_HASH; + int arraySize = array.length; + for (int i = 0; i < arraySize; i++) { + hash = MULTIPLIER * hash + array[i]; + } + return hash; + } + + /** + * Return a hash code based on the contents of the specified array. + * If array is null, this method returns 0. + */ + public static int nullSafeHashCode(double[] array) { + if (array == null) { + return 0; + } + int hash = INITIAL_HASH; + int arraySize = array.length; + for (int i = 0; i < arraySize; i++) { + hash = MULTIPLIER * hash + hashCode(array[i]); + } + return hash; + } + + /** + * Return a hash code based on the contents of the specified array. + * If array is null, this method returns 0. + */ + public static int nullSafeHashCode(float[] array) { + if (array == null) { + return 0; + } + int hash = INITIAL_HASH; + int arraySize = array.length; + for (int i = 0; i < arraySize; i++) { + hash = MULTIPLIER * hash + hashCode(array[i]); + } + return hash; + } + + /** + * Return a hash code based on the contents of the specified array. + * If array is null, this method returns 0. + */ + public static int nullSafeHashCode(int[] array) { + if (array == null) { + return 0; + } + int hash = INITIAL_HASH; + int arraySize = array.length; + for (int i = 0; i < arraySize; i++) { + hash = MULTIPLIER * hash + array[i]; + } + return hash; + } + + /** + * Return a hash code based on the contents of the specified array. + * If array is null, this method returns 0. + */ + public static int nullSafeHashCode(long[] array) { + if (array == null) { + return 0; + } + int hash = INITIAL_HASH; + int arraySize = array.length; + for (int i = 0; i < arraySize; i++) { + hash = MULTIPLIER * hash + hashCode(array[i]); + } + return hash; + } + + /** + * Return a hash code based on the contents of the specified array. + * If array is null, this method returns 0. + */ + public static int nullSafeHashCode(short[] array) { + if (array == null) { + return 0; + } + int hash = INITIAL_HASH; + int arraySize = array.length; + for (int i = 0; i < arraySize; i++) { + hash = MULTIPLIER * hash + array[i]; + } + return hash; + } + + /** + * Return the same value as {@link Boolean#hashCode()}. + * @see Boolean#hashCode() + */ + public static int hashCode(boolean bool) { + return bool ? 1231 : 1237; + } + + /** + * Return the same value as {@link Double#hashCode()}. + * @see Double#hashCode() + */ + public static int hashCode(double dbl) { + long bits = Double.doubleToLongBits(dbl); + return hashCode(bits); + } + + /** + * Return the same value as {@link Float#hashCode()}. + * @see Float#hashCode() + */ + public static int hashCode(float flt) { + return Float.floatToIntBits(flt); + } + + /** + * Return the same value as {@link Long#hashCode()}. + * @see Long#hashCode() + */ + public static int hashCode(long lng) { + return (int) (lng ^ (lng >>> 32)); + } + + + //--------------------------------------------------------------------- + // Convenience methods for toString output + //--------------------------------------------------------------------- + + /** + * Return a String representation of an object's overall identity. + * @param obj the object (may be null) + * @return the object's identity as String representation, + * or an empty String if the object was null + */ + public static String identityToString(Object obj) { + if (obj == null) { + return EMPTY_STRING; + } + return obj.getClass().getName() + "@" + getIdentityHexString(obj); + } + + /** + * Return a hex String form of an object's identity hash code. + * @param obj the object + * @return the object's identity code in hex notation + */ + public static String getIdentityHexString(Object obj) { + return Integer.toHexString(System.identityHashCode(obj)); + } + + /** + * Return a content-based String representation if obj is + * not null; otherwise returns an empty String. + *

Differs from {@link #nullSafeToString(Object)} in that it returns + * an empty String rather than "null" for a null value. + * @param obj the object to build a display String for + * @return a display String representation of obj + * @see #nullSafeToString(Object) + */ + public static String getDisplayString(Object obj) { + if (obj == null) { + return EMPTY_STRING; + } + return nullSafeToString(obj); + } + + /** + * Determine the class name for the given object. + *

Returns "null" if obj is null. + * @param obj the object to introspect (may be null) + * @return the corresponding class name + */ + public static String nullSafeClassName(Object obj) { + return (obj != null ? obj.getClass().getName() : NULL_STRING); + } + + /** + * Return a String representation of the specified Object. + *

Builds a String representation of the contents in case of an array. + * Returns "null" if obj is null. + * @param obj the object to build a String representation for + * @return a String representation of obj + */ + public static String nullSafeToString(Object obj) { + if (obj == null) { + return NULL_STRING; + } + if (obj instanceof String) { + return (String) obj; + } + if (obj instanceof Object[]) { + return nullSafeToString((Object[]) obj); + } + if (obj instanceof boolean[]) { + return nullSafeToString((boolean[]) obj); + } + if (obj instanceof byte[]) { + return nullSafeToString((byte[]) obj); + } + if (obj instanceof char[]) { + return nullSafeToString((char[]) obj); + } + if (obj instanceof double[]) { + return nullSafeToString((double[]) obj); + } + if (obj instanceof float[]) { + return nullSafeToString((float[]) obj); + } + if (obj instanceof int[]) { + return nullSafeToString((int[]) obj); + } + if (obj instanceof long[]) { + return nullSafeToString((long[]) obj); + } + if (obj instanceof short[]) { + return nullSafeToString((short[]) obj); + } + String str = obj.toString(); + return (str != null ? str : EMPTY_STRING); + } + + /** + * Return a String representation of the contents of the specified array. + *

The String representation consists of a list of the array's elements, + * enclosed in curly braces ("{}"). Adjacent elements are separated + * by the characters ", " (a comma followed by a space). Returns + * "null" if array is null. + * @param array the array to build a String representation for + * @return a String representation of array + */ + public static String nullSafeToString(Object[] array) { + if (array == null) { + return NULL_STRING; + } + int length = array.length; + if (length == 0) { + return EMPTY_ARRAY; + } + StringBuffer buffer = new StringBuffer(); + for (int i = 0; i < length; i++) { + if (i == 0) { + buffer.append(ARRAY_START); + } + else { + buffer.append(ARRAY_ELEMENT_SEPARATOR); + } + buffer.append(String.valueOf(array[i])); + } + buffer.append(ARRAY_END); + return buffer.toString(); + } + + /** + * Return a String representation of the contents of the specified array. + *

The String representation consists of a list of the array's elements, + * enclosed in curly braces ("{}"). Adjacent elements are separated + * by the characters ", " (a comma followed by a space). Returns + * "null" if array is null. + * @param array the array to build a String representation for + * @return a String representation of array + */ + public static String nullSafeToString(boolean[] array) { + if (array == null) { + return NULL_STRING; + } + int length = array.length; + if (length == 0) { + return EMPTY_ARRAY; + } + StringBuffer buffer = new StringBuffer(); + for (int i = 0; i < length; i++) { + if (i == 0) { + buffer.append(ARRAY_START); + } + else { + buffer.append(ARRAY_ELEMENT_SEPARATOR); + } + + buffer.append(array[i]); + } + buffer.append(ARRAY_END); + return buffer.toString(); + } + + /** + * Return a String representation of the contents of the specified array. + *

The String representation consists of a list of the array's elements, + * enclosed in curly braces ("{}"). Adjacent elements are separated + * by the characters ", " (a comma followed by a space). Returns + * "null" if array is null. + * @param array the array to build a String representation for + * @return a String representation of array + */ + public static String nullSafeToString(byte[] array) { + if (array == null) { + return NULL_STRING; + } + int length = array.length; + if (length == 0) { + return EMPTY_ARRAY; + } + StringBuffer buffer = new StringBuffer(); + for (int i = 0; i < length; i++) { + if (i == 0) { + buffer.append(ARRAY_START); + } + else { + buffer.append(ARRAY_ELEMENT_SEPARATOR); + } + buffer.append(array[i]); + } + buffer.append(ARRAY_END); + return buffer.toString(); + } + + /** + * Return a String representation of the contents of the specified array. + *

The String representation consists of a list of the array's elements, + * enclosed in curly braces ("{}"). Adjacent elements are separated + * by the characters ", " (a comma followed by a space). Returns + * "null" if array is null. + * @param array the array to build a String representation for + * @return a String representation of array + */ + public static String nullSafeToString(char[] array) { + if (array == null) { + return NULL_STRING; + } + int length = array.length; + if (length == 0) { + return EMPTY_ARRAY; + } + StringBuffer buffer = new StringBuffer(); + for (int i = 0; i < length; i++) { + if (i == 0) { + buffer.append(ARRAY_START); + } + else { + buffer.append(ARRAY_ELEMENT_SEPARATOR); + } + buffer.append("'").append(array[i]).append("'"); + } + buffer.append(ARRAY_END); + return buffer.toString(); + } + + /** + * Return a String representation of the contents of the specified array. + *

The String representation consists of a list of the array's elements, + * enclosed in curly braces ("{}"). Adjacent elements are separated + * by the characters ", " (a comma followed by a space). Returns + * "null" if array is null. + * @param array the array to build a String representation for + * @return a String representation of array + */ + public static String nullSafeToString(double[] array) { + if (array == null) { + return NULL_STRING; + } + int length = array.length; + if (length == 0) { + return EMPTY_ARRAY; + } + StringBuffer buffer = new StringBuffer(); + for (int i = 0; i < length; i++) { + if (i == 0) { + buffer.append(ARRAY_START); + } + else { + buffer.append(ARRAY_ELEMENT_SEPARATOR); + } + + buffer.append(array[i]); + } + buffer.append(ARRAY_END); + return buffer.toString(); + } + + /** + * Return a String representation of the contents of the specified array. + *

The String representation consists of a list of the array's elements, + * enclosed in curly braces ("{}"). Adjacent elements are separated + * by the characters ", " (a comma followed by a space). Returns + * "null" if array is null. + * @param array the array to build a String representation for + * @return a String representation of array + */ + public static String nullSafeToString(float[] array) { + if (array == null) { + return NULL_STRING; + } + int length = array.length; + if (length == 0) { + return EMPTY_ARRAY; + } + StringBuffer buffer = new StringBuffer(); + for (int i = 0; i < length; i++) { + if (i == 0) { + buffer.append(ARRAY_START); + } + else { + buffer.append(ARRAY_ELEMENT_SEPARATOR); + } + + buffer.append(array[i]); + } + buffer.append(ARRAY_END); + return buffer.toString(); + } + + /** + * Return a String representation of the contents of the specified array. + *

The String representation consists of a list of the array's elements, + * enclosed in curly braces ("{}"). Adjacent elements are separated + * by the characters ", " (a comma followed by a space). Returns + * "null" if array is null. + * @param array the array to build a String representation for + * @return a String representation of array + */ + public static String nullSafeToString(int[] array) { + if (array == null) { + return NULL_STRING; + } + int length = array.length; + if (length == 0) { + return EMPTY_ARRAY; + } + StringBuffer buffer = new StringBuffer(); + for (int i = 0; i < length; i++) { + if (i == 0) { + buffer.append(ARRAY_START); + } + else { + buffer.append(ARRAY_ELEMENT_SEPARATOR); + } + buffer.append(array[i]); + } + buffer.append(ARRAY_END); + return buffer.toString(); + } + + /** + * Return a String representation of the contents of the specified array. + *

The String representation consists of a list of the array's elements, + * enclosed in curly braces ("{}"). Adjacent elements are separated + * by the characters ", " (a comma followed by a space). Returns + * "null" if array is null. + * @param array the array to build a String representation for + * @return a String representation of array + */ + public static String nullSafeToString(long[] array) { + if (array == null) { + return NULL_STRING; + } + int length = array.length; + if (length == 0) { + return EMPTY_ARRAY; + } + StringBuffer buffer = new StringBuffer(); + for (int i = 0; i < length; i++) { + if (i == 0) { + buffer.append(ARRAY_START); + } + else { + buffer.append(ARRAY_ELEMENT_SEPARATOR); + } + buffer.append(array[i]); + } + buffer.append(ARRAY_END); + return buffer.toString(); + } + + /** + * Return a String representation of the contents of the specified array. + *

The String representation consists of a list of the array's elements, + * enclosed in curly braces ("{}"). Adjacent elements are separated + * by the characters ", " (a comma followed by a space). Returns + * "null" if array is null. + * @param array the array to build a String representation for + * @return a String representation of array + */ + public static String nullSafeToString(short[] array) { + if (array == null) { + return NULL_STRING; + } + int length = array.length; + if (length == 0) { + return EMPTY_ARRAY; + } + StringBuffer buffer = new StringBuffer(); + for (int i = 0; i < length; i++) { + if (i == 0) { + buffer.append(ARRAY_START); + } + else { + buffer.append(ARRAY_ELEMENT_SEPARATOR); + } + buffer.append(array[i]); + } + buffer.append(ARRAY_END); + return buffer.toString(); + } + +} diff --git a/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/internal/springutil/PathMatcher.java b/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/internal/springutil/PathMatcher.java new file mode 100644 index 000000000..d7a23221b --- /dev/null +++ b/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/internal/springutil/PathMatcher.java @@ -0,0 +1,91 @@ +/* + * Copyright 2002-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.argeo.osgi.boot.internal.springutil; + +/** + * Strategy interface for String-based path matching. + * + *

Used by {@link org.springframework.core.io.support.PathMatchingResourcePatternResolver}, + * {@link org.springframework.web.servlet.handler.AbstractUrlHandlerMapping}, + * {@link org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver}, + * and {@link org.springframework.web.servlet.mvc.WebContentInterceptor}. + * + *

The default implementation is {@link AntPathMatcher}, supporting the + * Ant-style pattern syntax. + * + * @author Juergen Hoeller + * @since 1.2 + * @see AntPathMatcher + */ +public interface PathMatcher { + + /** + * Does the given path represent a pattern that can be matched + * by an implementation of this interface? + *

If the return value is false, then the {@link #match} + * method does not have to be used because direct equality comparisons + * on the static path Strings will lead to the same result. + * @param path the path String to check + * @return true if the given path represents a pattern + */ + boolean isPattern(String path); + + /** + * Match the given path against the given pattern, + * according to this PathMatcher's matching strategy. + * @param pattern the pattern to match against + * @param path the path String to test + * @return true if the supplied path matched, + * false if it didn't + */ + boolean match(String pattern, String path); + + /** + * Match the given path against the corresponding part of the given + * pattern, according to this PathMatcher's matching strategy. + *

Determines whether the pattern at least matches as far as the given base + * path goes, assuming that a full path may then match as well. + * @param pattern the pattern to match against + * @param path the path String to test + * @return true if the supplied path matched, + * false if it didn't + */ + boolean matchStart(String pattern, String path); + + /** + * Given a pattern and a full path, determine the pattern-mapped part. + *

This method is supposed to find out which part of the path is matched + * dynamically through an actual pattern, that is, it strips off a statically + * defined leading path from the given full path, returning only the actually + * pattern-matched part of the path. + *

For example: For "myroot/*.html" as pattern and "myroot/myfile.html" + * as full path, this method should return "myfile.html". The detailed + * determination rules are specified to this PathMatcher's matching strategy. + *

A simple implementation may return the given full path as-is in case + * of an actual pattern, and the empty String in case of the pattern not + * containing any dynamic parts (i.e. the pattern parameter being + * a static path that wouldn't qualify as an actual {@link #isPattern pattern}). + * A sophisticated implementation will differentiate between the static parts + * and the dynamic parts of the given path pattern. + * @param pattern the path pattern + * @param path the full path to introspect + * @return the pattern-mapped part of the given path + * (never null) + */ + String extractPathWithinPattern(String pattern, String path); + +} diff --git a/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/internal/springutil/StringUtils.java b/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/internal/springutil/StringUtils.java new file mode 100644 index 000000000..262659044 --- /dev/null +++ b/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/internal/springutil/StringUtils.java @@ -0,0 +1,1113 @@ +/* + * Copyright 2002-2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.argeo.osgi.boot.internal.springutil; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Locale; +import java.util.Properties; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.TreeSet; + +/** + * Miscellaneous {@link String} utility methods. + * + *

Mainly for internal use within the framework; consider + * Jakarta's Commons Lang + * for a more comprehensive suite of String utilities. + * + *

This class delivers some simple functionality that should really + * be provided by the core Java String and {@link StringBuffer} + * classes, such as the ability to {@link #replace} all occurrences of a given + * substring in a target string. It also provides easy-to-use methods to convert + * between delimited strings, such as CSV strings, and collections and arrays. + * + * @author Rod Johnson + * @author Juergen Hoeller + * @author Keith Donald + * @author Rob Harrop + * @author Rick Evans + * @since 16 April 2001 + * @see org.apache.commons.lang.StringUtils + */ +public abstract class StringUtils { + + private static final String FOLDER_SEPARATOR = "/"; + + private static final String WINDOWS_FOLDER_SEPARATOR = "\\"; + + private static final String TOP_PATH = ".."; + + private static final String CURRENT_PATH = "."; + + private static final char EXTENSION_SEPARATOR = '.'; + + + //--------------------------------------------------------------------- + // General convenience methods for working with Strings + //--------------------------------------------------------------------- + + /** + * Check that the given CharSequence is neither null nor of length 0. + * Note: Will return true for a CharSequence that purely consists of whitespace. + *

+	 * StringUtils.hasLength(null) = false
+	 * StringUtils.hasLength("") = false
+	 * StringUtils.hasLength(" ") = true
+	 * StringUtils.hasLength("Hello") = true
+	 * 
+ * @param str the CharSequence to check (may be null) + * @return true if the CharSequence is not null and has length + * @see #hasText(String) + */ + public static boolean hasLength(CharSequence str) { + return (str != null && str.length() > 0); + } + + /** + * Check that the given String is neither null nor of length 0. + * Note: Will return true for a String that purely consists of whitespace. + * @param str the String to check (may be null) + * @return true if the String is not null and has length + * @see #hasLength(CharSequence) + */ + public static boolean hasLength(String str) { + return hasLength((CharSequence) str); + } + + /** + * Check whether the given CharSequence has actual text. + * More specifically, returns true if the string not null, + * its length is greater than 0, and it contains at least one non-whitespace character. + *

+	 * StringUtils.hasText(null) = false
+	 * StringUtils.hasText("") = false
+	 * StringUtils.hasText(" ") = false
+	 * StringUtils.hasText("12345") = true
+	 * StringUtils.hasText(" 12345 ") = true
+	 * 
+ * @param str the CharSequence to check (may be null) + * @return true if the CharSequence is not null, + * its length is greater than 0, and it does not contain whitespace only + * @see java.lang.Character#isWhitespace + */ + public static boolean hasText(CharSequence str) { + if (!hasLength(str)) { + return false; + } + int strLen = str.length(); + for (int i = 0; i < strLen; i++) { + if (!Character.isWhitespace(str.charAt(i))) { + return true; + } + } + return false; + } + + /** + * Check whether the given String has actual text. + * More specifically, returns true if the string not null, + * its length is greater than 0, and it contains at least one non-whitespace character. + * @param str the String to check (may be null) + * @return true if the String is not null, its length is + * greater than 0, and it does not contain whitespace only + * @see #hasText(CharSequence) + */ + public static boolean hasText(String str) { + return hasText((CharSequence) str); + } + + /** + * Check whether the given CharSequence contains any whitespace characters. + * @param str the CharSequence to check (may be null) + * @return true if the CharSequence is not empty and + * contains at least 1 whitespace character + * @see java.lang.Character#isWhitespace + */ + public static boolean containsWhitespace(CharSequence str) { + if (!hasLength(str)) { + return false; + } + int strLen = str.length(); + for (int i = 0; i < strLen; i++) { + if (Character.isWhitespace(str.charAt(i))) { + return true; + } + } + return false; + } + + /** + * Check whether the given String contains any whitespace characters. + * @param str the String to check (may be null) + * @return true if the String is not empty and + * contains at least 1 whitespace character + * @see #containsWhitespace(CharSequence) + */ + public static boolean containsWhitespace(String str) { + return containsWhitespace((CharSequence) str); + } + + /** + * Trim leading and trailing whitespace from the given String. + * @param str the String to check + * @return the trimmed String + * @see java.lang.Character#isWhitespace + */ + public static String trimWhitespace(String str) { + if (!hasLength(str)) { + return str; + } + StringBuffer buf = new StringBuffer(str); + while (buf.length() > 0 && Character.isWhitespace(buf.charAt(0))) { + buf.deleteCharAt(0); + } + while (buf.length() > 0 && Character.isWhitespace(buf.charAt(buf.length() - 1))) { + buf.deleteCharAt(buf.length() - 1); + } + return buf.toString(); + } + + /** + * Trim all whitespace from the given String: + * leading, trailing, and inbetween characters. + * @param str the String to check + * @return the trimmed String + * @see java.lang.Character#isWhitespace + */ + public static String trimAllWhitespace(String str) { + if (!hasLength(str)) { + return str; + } + StringBuffer buf = new StringBuffer(str); + int index = 0; + while (buf.length() > index) { + if (Character.isWhitespace(buf.charAt(index))) { + buf.deleteCharAt(index); + } + else { + index++; + } + } + return buf.toString(); + } + + /** + * Trim leading whitespace from the given String. + * @param str the String to check + * @return the trimmed String + * @see java.lang.Character#isWhitespace + */ + public static String trimLeadingWhitespace(String str) { + if (!hasLength(str)) { + return str; + } + StringBuffer buf = new StringBuffer(str); + while (buf.length() > 0 && Character.isWhitespace(buf.charAt(0))) { + buf.deleteCharAt(0); + } + return buf.toString(); + } + + /** + * Trim trailing whitespace from the given String. + * @param str the String to check + * @return the trimmed String + * @see java.lang.Character#isWhitespace + */ + public static String trimTrailingWhitespace(String str) { + if (!hasLength(str)) { + return str; + } + StringBuffer buf = new StringBuffer(str); + while (buf.length() > 0 && Character.isWhitespace(buf.charAt(buf.length() - 1))) { + buf.deleteCharAt(buf.length() - 1); + } + return buf.toString(); + } + + /** + * Trim all occurences of the supplied leading character from the given String. + * @param str the String to check + * @param leadingCharacter the leading character to be trimmed + * @return the trimmed String + */ + public static String trimLeadingCharacter(String str, char leadingCharacter) { + if (!hasLength(str)) { + return str; + } + StringBuffer buf = new StringBuffer(str); + while (buf.length() > 0 && buf.charAt(0) == leadingCharacter) { + buf.deleteCharAt(0); + } + return buf.toString(); + } + + /** + * Trim all occurences of the supplied trailing character from the given String. + * @param str the String to check + * @param trailingCharacter the trailing character to be trimmed + * @return the trimmed String + */ + public static String trimTrailingCharacter(String str, char trailingCharacter) { + if (!hasLength(str)) { + return str; + } + StringBuffer buf = new StringBuffer(str); + while (buf.length() > 0 && buf.charAt(buf.length() - 1) == trailingCharacter) { + buf.deleteCharAt(buf.length() - 1); + } + return buf.toString(); + } + + + /** + * Test if the given String starts with the specified prefix, + * ignoring upper/lower case. + * @param str the String to check + * @param prefix the prefix to look for + * @see java.lang.String#startsWith + */ + public static boolean startsWithIgnoreCase(String str, String prefix) { + if (str == null || prefix == null) { + return false; + } + if (str.startsWith(prefix)) { + return true; + } + if (str.length() < prefix.length()) { + return false; + } + String lcStr = str.substring(0, prefix.length()).toLowerCase(); + String lcPrefix = prefix.toLowerCase(); + return lcStr.equals(lcPrefix); + } + + /** + * Test if the given String ends with the specified suffix, + * ignoring upper/lower case. + * @param str the String to check + * @param suffix the suffix to look for + * @see java.lang.String#endsWith + */ + public static boolean endsWithIgnoreCase(String str, String suffix) { + if (str == null || suffix == null) { + return false; + } + if (str.endsWith(suffix)) { + return true; + } + if (str.length() < suffix.length()) { + return false; + } + + String lcStr = str.substring(str.length() - suffix.length()).toLowerCase(); + String lcSuffix = suffix.toLowerCase(); + return lcStr.equals(lcSuffix); + } + + /** + * Test whether the given string matches the given substring + * at the given index. + * @param str the original string (or StringBuffer) + * @param index the index in the original string to start matching against + * @param substring the substring to match at the given index + */ + public static boolean substringMatch(CharSequence str, int index, CharSequence substring) { + for (int j = 0; j < substring.length(); j++) { + int i = index + j; + if (i >= str.length() || str.charAt(i) != substring.charAt(j)) { + return false; + } + } + return true; + } + + /** + * Count the occurrences of the substring in string s. + * @param str string to search in. Return 0 if this is null. + * @param sub string to search for. Return 0 if this is null. + */ + public static int countOccurrencesOf(String str, String sub) { + if (str == null || sub == null || str.length() == 0 || sub.length() == 0) { + return 0; + } + int count = 0, pos = 0, idx = 0; + while ((idx = str.indexOf(sub, pos)) != -1) { + ++count; + pos = idx + sub.length(); + } + return count; + } + + /** + * Replace all occurences of a substring within a string with + * another string. + * @param inString String to examine + * @param oldPattern String to replace + * @param newPattern String to insert + * @return a String with the replacements + */ + public static String replace(String inString, String oldPattern, String newPattern) { + if (!hasLength(inString) || !hasLength(oldPattern) || newPattern == null) { + return inString; + } + StringBuffer sbuf = new StringBuffer(); + // output StringBuffer we'll build up + int pos = 0; // our position in the old string + int index = inString.indexOf(oldPattern); + // the index of an occurrence we've found, or -1 + int patLen = oldPattern.length(); + while (index >= 0) { + sbuf.append(inString.substring(pos, index)); + sbuf.append(newPattern); + pos = index + patLen; + index = inString.indexOf(oldPattern, pos); + } + sbuf.append(inString.substring(pos)); + // remember to append any characters to the right of a match + return sbuf.toString(); + } + + /** + * Delete all occurrences of the given substring. + * @param inString the original String + * @param pattern the pattern to delete all occurrences of + * @return the resulting String + */ + public static String delete(String inString, String pattern) { + return replace(inString, pattern, ""); + } + + /** + * Delete any character in a given String. + * @param inString the original String + * @param charsToDelete a set of characters to delete. + * E.g. "az\n" will delete 'a's, 'z's and new lines. + * @return the resulting String + */ + public static String deleteAny(String inString, String charsToDelete) { + if (!hasLength(inString) || !hasLength(charsToDelete)) { + return inString; + } + StringBuffer out = new StringBuffer(); + for (int i = 0; i < inString.length(); i++) { + char c = inString.charAt(i); + if (charsToDelete.indexOf(c) == -1) { + out.append(c); + } + } + return out.toString(); + } + + + //--------------------------------------------------------------------- + // Convenience methods for working with formatted Strings + //--------------------------------------------------------------------- + + /** + * Quote the given String with single quotes. + * @param str the input String (e.g. "myString") + * @return the quoted String (e.g. "'myString'"), + * or null if the input was null + */ + public static String quote(String str) { + return (str != null ? "'" + str + "'" : null); + } + + /** + * Turn the given Object into a String with single quotes + * if it is a String; keeping the Object as-is else. + * @param obj the input Object (e.g. "myString") + * @return the quoted String (e.g. "'myString'"), + * or the input object as-is if not a String + */ + public static Object quoteIfString(Object obj) { + return (obj instanceof String ? quote((String) obj) : obj); + } + + /** + * Unqualify a string qualified by a '.' dot character. For example, + * "this.name.is.qualified", returns "qualified". + * @param qualifiedName the qualified name + */ + public static String unqualify(String qualifiedName) { + return unqualify(qualifiedName, '.'); + } + + /** + * Unqualify a string qualified by a separator character. For example, + * "this:name:is:qualified" returns "qualified" if using a ':' separator. + * @param qualifiedName the qualified name + * @param separator the separator + */ + public static String unqualify(String qualifiedName, char separator) { + return qualifiedName.substring(qualifiedName.lastIndexOf(separator) + 1); + } + + /** + * Capitalize a String, changing the first letter to + * upper case as per {@link Character#toUpperCase(char)}. + * No other letters are changed. + * @param str the String to capitalize, may be null + * @return the capitalized String, null if null + */ + public static String capitalize(String str) { + return changeFirstCharacterCase(str, true); + } + + /** + * Uncapitalize a String, changing the first letter to + * lower case as per {@link Character#toLowerCase(char)}. + * No other letters are changed. + * @param str the String to uncapitalize, may be null + * @return the uncapitalized String, null if null + */ + public static String uncapitalize(String str) { + return changeFirstCharacterCase(str, false); + } + + private static String changeFirstCharacterCase(String str, boolean capitalize) { + if (str == null || str.length() == 0) { + return str; + } + StringBuffer buf = new StringBuffer(str.length()); + if (capitalize) { + buf.append(Character.toUpperCase(str.charAt(0))); + } + else { + buf.append(Character.toLowerCase(str.charAt(0))); + } + buf.append(str.substring(1)); + return buf.toString(); + } + + /** + * Extract the filename from the given path, + * e.g. "mypath/myfile.txt" -> "myfile.txt". + * @param path the file path (may be null) + * @return the extracted filename, or null if none + */ + public static String getFilename(String path) { + if (path == null) { + return null; + } + int separatorIndex = path.lastIndexOf(FOLDER_SEPARATOR); + return (separatorIndex != -1 ? path.substring(separatorIndex + 1) : path); + } + + /** + * Extract the filename extension from the given path, + * e.g. "mypath/myfile.txt" -> "txt". + * @param path the file path (may be null) + * @return the extracted filename extension, or null if none + */ + public static String getFilenameExtension(String path) { + if (path == null) { + return null; + } + int sepIndex = path.lastIndexOf(EXTENSION_SEPARATOR); + return (sepIndex != -1 ? path.substring(sepIndex + 1) : null); + } + + /** + * Strip the filename extension from the given path, + * e.g. "mypath/myfile.txt" -> "mypath/myfile". + * @param path the file path (may be null) + * @return the path with stripped filename extension, + * or null if none + */ + public static String stripFilenameExtension(String path) { + if (path == null) { + return null; + } + int sepIndex = path.lastIndexOf(EXTENSION_SEPARATOR); + return (sepIndex != -1 ? path.substring(0, sepIndex) : path); + } + + /** + * Apply the given relative path to the given path, + * assuming standard Java folder separation (i.e. "/" separators); + * @param path the path to start from (usually a full file path) + * @param relativePath the relative path to apply + * (relative to the full file path above) + * @return the full file path that results from applying the relative path + */ + public static String applyRelativePath(String path, String relativePath) { + int separatorIndex = path.lastIndexOf(FOLDER_SEPARATOR); + if (separatorIndex != -1) { + String newPath = path.substring(0, separatorIndex); + if (!relativePath.startsWith(FOLDER_SEPARATOR)) { + newPath += FOLDER_SEPARATOR; + } + return newPath + relativePath; + } + else { + return relativePath; + } + } + + /** + * Normalize the path by suppressing sequences like "path/.." and + * inner simple dots. + *

The result is convenient for path comparison. For other uses, + * notice that Windows separators ("\") are replaced by simple slashes. + * @param path the original path + * @return the normalized path + */ + public static String cleanPath(String path) { + if (path == null) { + return null; + } + String pathToUse = replace(path, WINDOWS_FOLDER_SEPARATOR, FOLDER_SEPARATOR); + + // Strip prefix from path to analyze, to not treat it as part of the + // first path element. This is necessary to correctly parse paths like + // "file:core/../core/io/Resource.class", where the ".." should just + // strip the first "core" directory while keeping the "file:" prefix. + int prefixIndex = pathToUse.indexOf(":"); + String prefix = ""; + if (prefixIndex != -1) { + prefix = pathToUse.substring(0, prefixIndex + 1); + pathToUse = pathToUse.substring(prefixIndex + 1); + } + if (pathToUse.startsWith(FOLDER_SEPARATOR)) { + prefix = prefix + FOLDER_SEPARATOR; + pathToUse = pathToUse.substring(1); + } + + String[] pathArray = delimitedListToStringArray(pathToUse, FOLDER_SEPARATOR); + List pathElements = new LinkedList(); + int tops = 0; + + for (int i = pathArray.length - 1; i >= 0; i--) { + String element = pathArray[i]; + if (CURRENT_PATH.equals(element)) { + // Points to current directory - drop it. + } + else if (TOP_PATH.equals(element)) { + // Registering top path found. + tops++; + } + else { + if (tops > 0) { + // Merging path element with element corresponding to top path. + tops--; + } + else { + // Normal path element found. + pathElements.add(0, element); + } + } + } + + // Remaining top paths need to be retained. + for (int i = 0; i < tops; i++) { + pathElements.add(0, TOP_PATH); + } + + return prefix + collectionToDelimitedString(pathElements, FOLDER_SEPARATOR); + } + + /** + * Compare two paths after normalization of them. + * @param path1 first path for comparison + * @param path2 second path for comparison + * @return whether the two paths are equivalent after normalization + */ + public static boolean pathEquals(String path1, String path2) { + return cleanPath(path1).equals(cleanPath(path2)); + } + + /** + * Parse the given localeString into a {@link Locale}. + *

This is the inverse operation of {@link Locale#toString Locale's toString}. + * @param localeString the locale string, following Locale's + * toString() format ("en", "en_UK", etc); + * also accepts spaces as separators, as an alternative to underscores + * @return a corresponding Locale instance + */ + public static Locale parseLocaleString(String localeString) { + String[] parts = tokenizeToStringArray(localeString, "_ ", false, false); + String language = (parts.length > 0 ? parts[0] : ""); + String country = (parts.length > 1 ? parts[1] : ""); + String variant = ""; + if (parts.length >= 2) { + // There is definitely a variant, and it is everything after the country + // code sans the separator between the country code and the variant. + int endIndexOfCountryCode = localeString.indexOf(country) + country.length(); + // Strip off any leading '_' and whitespace, what's left is the variant. + variant = trimLeadingWhitespace(localeString.substring(endIndexOfCountryCode)); + if (variant.startsWith("_")) { + variant = trimLeadingCharacter(variant, '_'); + } + } + return (language.length() > 0 ? new Locale(language, country, variant) : null); + } + + /** + * Determine the RFC 3066 compliant language tag, + * as used for the HTTP "Accept-Language" header. + * @param locale the Locale to transform to a language tag + * @return the RFC 3066 compliant language tag as String + */ + public static String toLanguageTag(Locale locale) { + return locale.getLanguage() + (hasText(locale.getCountry()) ? "-" + locale.getCountry() : ""); + } + + + //--------------------------------------------------------------------- + // Convenience methods for working with String arrays + //--------------------------------------------------------------------- + + /** + * Append the given String to the given String array, returning a new array + * consisting of the input array contents plus the given String. + * @param array the array to append to (can be null) + * @param str the String to append + * @return the new array (never null) + */ + public static String[] addStringToArray(String[] array, String str) { + if (ObjectUtils.isEmpty(array)) { + return new String[] {str}; + } + String[] newArr = new String[array.length + 1]; + System.arraycopy(array, 0, newArr, 0, array.length); + newArr[array.length] = str; + return newArr; + } + + /** + * Concatenate the given String arrays into one, + * with overlapping array elements included twice. + *

The order of elements in the original arrays is preserved. + * @param array1 the first array (can be null) + * @param array2 the second array (can be null) + * @return the new array (null if both given arrays were null) + */ + public static String[] concatenateStringArrays(String[] array1, String[] array2) { + if (ObjectUtils.isEmpty(array1)) { + return array2; + } + if (ObjectUtils.isEmpty(array2)) { + return array1; + } + String[] newArr = new String[array1.length + array2.length]; + System.arraycopy(array1, 0, newArr, 0, array1.length); + System.arraycopy(array2, 0, newArr, array1.length, array2.length); + return newArr; + } + + /** + * Merge the given String arrays into one, with overlapping + * array elements only included once. + *

The order of elements in the original arrays is preserved + * (with the exception of overlapping elements, which are only + * included on their first occurence). + * @param array1 the first array (can be null) + * @param array2 the second array (can be null) + * @return the new array (null if both given arrays were null) + */ + public static String[] mergeStringArrays(String[] array1, String[] array2) { + if (ObjectUtils.isEmpty(array1)) { + return array2; + } + if (ObjectUtils.isEmpty(array2)) { + return array1; + } + List result = new ArrayList(); + result.addAll(Arrays.asList(array1)); + for (int i = 0; i < array2.length; i++) { + String str = array2[i]; + if (!result.contains(str)) { + result.add(str); + } + } + return toStringArray(result); + } + + /** + * Turn given source String array into sorted array. + * @param array the source array + * @return the sorted array (never null) + */ + public static String[] sortStringArray(String[] array) { + if (ObjectUtils.isEmpty(array)) { + return new String[0]; + } + Arrays.sort(array); + return array; + } + + /** + * Copy the given Collection into a String array. + * The Collection must contain String elements only. + * @param collection the Collection to copy + * @return the String array (null if the passed-in + * Collection was null) + */ + public static String[] toStringArray(Collection collection) { + if (collection == null) { + return null; + } + return (String[]) collection.toArray(new String[collection.size()]); + } + + /** + * Copy the given Enumeration into a String array. + * The Enumeration must contain String elements only. + * @param enumeration the Enumeration to copy + * @return the String array (null if the passed-in + * Enumeration was null) + */ + public static String[] toStringArray(Enumeration enumeration) { + if (enumeration == null) { + return null; + } + List list = Collections.list(enumeration); + return (String[]) list.toArray(new String[list.size()]); + } + + /** + * Trim the elements of the given String array, + * calling String.trim() on each of them. + * @param array the original String array + * @return the resulting array (of the same size) with trimmed elements + */ + public static String[] trimArrayElements(String[] array) { + if (ObjectUtils.isEmpty(array)) { + return new String[0]; + } + String[] result = new String[array.length]; + for (int i = 0; i < array.length; i++) { + String element = array[i]; + result[i] = (element != null ? element.trim() : null); + } + return result; + } + + /** + * Remove duplicate Strings from the given array. + * Also sorts the array, as it uses a TreeSet. + * @param array the String array + * @return an array without duplicates, in natural sort order + */ + public static String[] removeDuplicateStrings(String[] array) { + if (ObjectUtils.isEmpty(array)) { + return array; + } + Set set = new TreeSet(); + for (int i = 0; i < array.length; i++) { + set.add(array[i]); + } + return toStringArray(set); + } + + /** + * Split a String at the first occurrence of the delimiter. + * Does not include the delimiter in the result. + * @param toSplit the string to split + * @param delimiter to split the string up with + * @return a two element array with index 0 being before the delimiter, and + * index 1 being after the delimiter (neither element includes the delimiter); + * or null if the delimiter wasn't found in the given input String + */ + public static String[] split(String toSplit, String delimiter) { + if (!hasLength(toSplit) || !hasLength(delimiter)) { + return null; + } + int offset = toSplit.indexOf(delimiter); + if (offset < 0) { + return null; + } + String beforeDelimiter = toSplit.substring(0, offset); + String afterDelimiter = toSplit.substring(offset + delimiter.length()); + return new String[] {beforeDelimiter, afterDelimiter}; + } + + /** + * Take an array Strings and split each element based on the given delimiter. + * A Properties instance is then generated, with the left of the + * delimiter providing the key, and the right of the delimiter providing the value. + *

Will trim both the key and value before adding them to the + * Properties instance. + * @param array the array to process + * @param delimiter to split each element using (typically the equals symbol) + * @return a Properties instance representing the array contents, + * or null if the array to process was null or empty + */ + public static Properties splitArrayElementsIntoProperties(String[] array, String delimiter) { + return splitArrayElementsIntoProperties(array, delimiter, null); + } + + /** + * Take an array Strings and split each element based on the given delimiter. + * A Properties instance is then generated, with the left of the + * delimiter providing the key, and the right of the delimiter providing the value. + *

Will trim both the key and value before adding them to the + * Properties instance. + * @param array the array to process + * @param delimiter to split each element using (typically the equals symbol) + * @param charsToDelete one or more characters to remove from each element + * prior to attempting the split operation (typically the quotation mark + * symbol), or null if no removal should occur + * @return a Properties instance representing the array contents, + * or null if the array to process was null or empty + */ + public static Properties splitArrayElementsIntoProperties( + String[] array, String delimiter, String charsToDelete) { + + if (ObjectUtils.isEmpty(array)) { + return null; + } + Properties result = new Properties(); + for (int i = 0; i < array.length; i++) { + String element = array[i]; + if (charsToDelete != null) { + element = deleteAny(array[i], charsToDelete); + } + String[] splittedElement = split(element, delimiter); + if (splittedElement == null) { + continue; + } + result.setProperty(splittedElement[0].trim(), splittedElement[1].trim()); + } + return result; + } + + /** + * Tokenize the given String into a String array via a StringTokenizer. + * Trims tokens and omits empty tokens. + *

The given delimiters string is supposed to consist of any number of + * delimiter characters. Each of those characters can be used to separate + * tokens. A delimiter is always a single character; for multi-character + * delimiters, consider using delimitedListToStringArray + * @param str the String to tokenize + * @param delimiters the delimiter characters, assembled as String + * (each of those characters is individually considered as delimiter). + * @return an array of the tokens + * @see java.util.StringTokenizer + * @see java.lang.String#trim() + * @see #delimitedListToStringArray + */ + public static String[] tokenizeToStringArray(String str, String delimiters) { + return tokenizeToStringArray(str, delimiters, true, true); + } + + /** + * Tokenize the given String into a String array via a StringTokenizer. + *

The given delimiters string is supposed to consist of any number of + * delimiter characters. Each of those characters can be used to separate + * tokens. A delimiter is always a single character; for multi-character + * delimiters, consider using delimitedListToStringArray + * @param str the String to tokenize + * @param delimiters the delimiter characters, assembled as String + * (each of those characters is individually considered as delimiter) + * @param trimTokens trim the tokens via String's trim + * @param ignoreEmptyTokens omit empty tokens from the result array + * (only applies to tokens that are empty after trimming; StringTokenizer + * will not consider subsequent delimiters as token in the first place). + * @return an array of the tokens (null if the input String + * was null) + * @see java.util.StringTokenizer + * @see java.lang.String#trim() + * @see #delimitedListToStringArray + */ + public static String[] tokenizeToStringArray( + String str, String delimiters, boolean trimTokens, boolean ignoreEmptyTokens) { + + if (str == null) { + return null; + } + StringTokenizer st = new StringTokenizer(str, delimiters); + List tokens = new ArrayList(); + while (st.hasMoreTokens()) { + String token = st.nextToken(); + if (trimTokens) { + token = token.trim(); + } + if (!ignoreEmptyTokens || token.length() > 0) { + tokens.add(token); + } + } + return toStringArray(tokens); + } + + /** + * Take a String which is a delimited list and convert it to a String array. + *

A single delimiter can consists of more than one character: It will still + * be considered as single delimiter string, rather than as bunch of potential + * delimiter characters - in contrast to tokenizeToStringArray. + * @param str the input String + * @param delimiter the delimiter between elements (this is a single delimiter, + * rather than a bunch individual delimiter characters) + * @return an array of the tokens in the list + * @see #tokenizeToStringArray + */ + public static String[] delimitedListToStringArray(String str, String delimiter) { + return delimitedListToStringArray(str, delimiter, null); + } + + /** + * Take a String which is a delimited list and convert it to a String array. + *

A single delimiter can consists of more than one character: It will still + * be considered as single delimiter string, rather than as bunch of potential + * delimiter characters - in contrast to tokenizeToStringArray. + * @param str the input String + * @param delimiter the delimiter between elements (this is a single delimiter, + * rather than a bunch individual delimiter characters) + * @param charsToDelete a set of characters to delete. Useful for deleting unwanted + * line breaks: e.g. "\r\n\f" will delete all new lines and line feeds in a String. + * @return an array of the tokens in the list + * @see #tokenizeToStringArray + */ + public static String[] delimitedListToStringArray(String str, String delimiter, String charsToDelete) { + if (str == null) { + return new String[0]; + } + if (delimiter == null) { + return new String[] {str}; + } + List result = new ArrayList(); + if ("".equals(delimiter)) { + for (int i = 0; i < str.length(); i++) { + result.add(deleteAny(str.substring(i, i + 1), charsToDelete)); + } + } + else { + int pos = 0; + int delPos = 0; + while ((delPos = str.indexOf(delimiter, pos)) != -1) { + result.add(deleteAny(str.substring(pos, delPos), charsToDelete)); + pos = delPos + delimiter.length(); + } + if (str.length() > 0 && pos <= str.length()) { + // Add rest of String, but not in case of empty input. + result.add(deleteAny(str.substring(pos), charsToDelete)); + } + } + return toStringArray(result); + } + + /** + * Convert a CSV list into an array of Strings. + * @param str the input String + * @return an array of Strings, or the empty array in case of empty input + */ + public static String[] commaDelimitedListToStringArray(String str) { + return delimitedListToStringArray(str, ","); + } + + /** + * Convenience method to convert a CSV string list to a set. + * Note that this will suppress duplicates. + * @param str the input String + * @return a Set of String entries in the list + */ + public static Set commaDelimitedListToSet(String str) { + Set set = new TreeSet(); + String[] tokens = commaDelimitedListToStringArray(str); + for (int i = 0; i < tokens.length; i++) { + set.add(tokens[i]); + } + return set; + } + + /** + * Convenience method to return a Collection as a delimited (e.g. CSV) + * String. E.g. useful for toString() implementations. + * @param coll the Collection to display + * @param delim the delimiter to use (probably a ",") + * @param prefix the String to start each element with + * @param suffix the String to end each element with + * @return the delimited String + */ + public static String collectionToDelimitedString(Collection coll, String delim, String prefix, String suffix) { + if (CollectionUtils.isEmpty(coll)) { + return ""; + } + StringBuffer sb = new StringBuffer(); + Iterator it = coll.iterator(); + while (it.hasNext()) { + sb.append(prefix).append(it.next()).append(suffix); + if (it.hasNext()) { + sb.append(delim); + } + } + return sb.toString(); + } + + /** + * Convenience method to return a Collection as a delimited (e.g. CSV) + * String. E.g. useful for toString() implementations. + * @param coll the Collection to display + * @param delim the delimiter to use (probably a ",") + * @return the delimited String + */ + public static String collectionToDelimitedString(Collection coll, String delim) { + return collectionToDelimitedString(coll, delim, "", ""); + } + + /** + * Convenience method to return a Collection as a CSV String. + * E.g. useful for toString() implementations. + * @param coll the Collection to display + * @return the delimited String + */ + public static String collectionToCommaDelimitedString(Collection coll) { + return collectionToDelimitedString(coll, ","); + } + + /** + * Convenience method to return a String array as a delimited (e.g. CSV) + * String. E.g. useful for toString() implementations. + * @param arr the array to display + * @param delim the delimiter to use (probably a ",") + * @return the delimited String + */ + public static String arrayToDelimitedString(Object[] arr, String delim) { + if (ObjectUtils.isEmpty(arr)) { + return ""; + } + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < arr.length; i++) { + if (i > 0) { + sb.append(delim); + } + sb.append(arr[i]); + } + return sb.toString(); + } + + /** + * Convenience method to return a String array as a CSV String. + * E.g. useful for toString() implementations. + * @param arr the array to display + * @return the delimited String + */ + public static String arrayToCommaDelimitedString(Object[] arr) { + return arrayToDelimitedString(arr, ","); + } + +} diff --git a/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/internal/springutil/SystemPropertyUtils.java b/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/internal/springutil/SystemPropertyUtils.java new file mode 100644 index 000000000..f81adc25b --- /dev/null +++ b/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/internal/springutil/SystemPropertyUtils.java @@ -0,0 +1,87 @@ +/* + * Copyright 2002-2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.argeo.osgi.boot.internal.springutil; + +/** + * Helper class for resolving placeholders in texts. Usually applied to file paths. + * + *

A text may contain ${...} placeholders, to be resolved as + * system properties: e.g. ${user.dir}. + * + * @author Juergen Hoeller + * @since 1.2.5 + * @see #PLACEHOLDER_PREFIX + * @see #PLACEHOLDER_SUFFIX + * @see System#getProperty(String) + */ +public abstract class SystemPropertyUtils { + + /** Prefix for system property placeholders: "${" */ + public static final String PLACEHOLDER_PREFIX = "${"; + + /** Suffix for system property placeholders: "}" */ + public static final String PLACEHOLDER_SUFFIX = "}"; + + + /** + * Resolve ${...} placeholders in the given text, + * replacing them with corresponding system property values. + * @param text the String to resolve + * @return the resolved String + * @see #PLACEHOLDER_PREFIX + * @see #PLACEHOLDER_SUFFIX + */ + public static String resolvePlaceholders(String text) { + StringBuffer buf = new StringBuffer(text); + + int startIndex = buf.indexOf(PLACEHOLDER_PREFIX); + while (startIndex != -1) { + int endIndex = buf.indexOf(PLACEHOLDER_SUFFIX, startIndex + PLACEHOLDER_PREFIX.length()); + if (endIndex != -1) { + String placeholder = buf.substring(startIndex + PLACEHOLDER_PREFIX.length(), endIndex); + int nextIndex = endIndex + PLACEHOLDER_SUFFIX.length(); + try { + String propVal = System.getProperty(placeholder); + if (propVal == null) { + // Fall back to searching the system environment. + //propVal = System.getenv(placeholder);// mbaudier - 2009-07-26 + throw new Error("getenv no longer supported, use properties and -D instead: " + placeholder); + } + if (propVal != null) { + buf.replace(startIndex, endIndex + PLACEHOLDER_SUFFIX.length(), propVal); + nextIndex = startIndex + propVal.length(); + } + else { + System.err.println("Could not resolve placeholder '" + placeholder + "' in [" + text + + "] as system property: neither system property nor environment variable found"); + } + } + catch (Throwable ex) { + System.err.println("Could not resolve placeholder '" + placeholder + "' in [" + text + + "] as system property: " + ex); + } + startIndex = buf.indexOf(PLACEHOLDER_PREFIX, nextIndex); + } + else { + startIndex = -1; + } + } + + return buf.toString(); + } + +} diff --git a/org.argeo.osgi.boot/src/test/bundles/jars/test.jar b/org.argeo.osgi.boot/src/test/bundles/jars/test.jar new file mode 100644 index 000000000..e69de29bb diff --git a/org.argeo.osgi.boot/src/test/bundles/others/subdir/org.argeo.osgi.boot.test.bundle3/META-INF/MANIFEST.MF b/org.argeo.osgi.boot/src/test/bundles/others/subdir/org.argeo.osgi.boot.test.bundle3/META-INF/MANIFEST.MF new file mode 100644 index 000000000..f23da4422 --- /dev/null +++ b/org.argeo.osgi.boot/src/test/bundles/others/subdir/org.argeo.osgi.boot.test.bundle3/META-INF/MANIFEST.MF @@ -0,0 +1,2 @@ +Bundle-SymbolicName: org.argeo.osgi.boot.test.bundle3 +Bundle-Version: 0.1.0 diff --git a/org.argeo.osgi.boot/src/test/bundles/some/excluded/org.argeo.osgi.boot.test.bundle0/META-INF/MANIFEST.MF b/org.argeo.osgi.boot/src/test/bundles/some/excluded/org.argeo.osgi.boot.test.bundle0/META-INF/MANIFEST.MF new file mode 100644 index 000000000..9344d0735 --- /dev/null +++ b/org.argeo.osgi.boot/src/test/bundles/some/excluded/org.argeo.osgi.boot.test.bundle0/META-INF/MANIFEST.MF @@ -0,0 +1,2 @@ +Bundle-SymbolicName: org.argeo.osgi.boot.test.bundle0 +Bundle-Version: 0.1.0 diff --git a/org.argeo.osgi.boot/src/test/bundles/some/org.argeo.osgi.boot.test.bundle1/META-INF/MANIFEST.MF b/org.argeo.osgi.boot/src/test/bundles/some/org.argeo.osgi.boot.test.bundle1/META-INF/MANIFEST.MF new file mode 100644 index 000000000..0fb66dc00 --- /dev/null +++ b/org.argeo.osgi.boot/src/test/bundles/some/org.argeo.osgi.boot.test.bundle1/META-INF/MANIFEST.MF @@ -0,0 +1,2 @@ +Bundle-SymbolicName: org.argeo.osgi.boot.test.bundle1 +Bundle-Version: 0.1.0 diff --git a/org.argeo.osgi.boot/src/test/bundles/some/org.argeo.osgi.boot.test.bundle2/META-INF/MANIFEST.MF b/org.argeo.osgi.boot/src/test/bundles/some/org.argeo.osgi.boot.test.bundle2/META-INF/MANIFEST.MF new file mode 100644 index 000000000..97ecd31c9 --- /dev/null +++ b/org.argeo.osgi.boot/src/test/bundles/some/org.argeo.osgi.boot.test.bundle2/META-INF/MANIFEST.MF @@ -0,0 +1,2 @@ +Bundle-SymbolicName: org.argeo.osgi.boot.test.bundle2 +Bundle-Version: 0.1.0 diff --git a/org.argeo.osgi.boot/src/test/java/org/argeo/osgi/boot/OsgiBootNoRuntimeTest.java b/org.argeo.osgi.boot/src/test/java/org/argeo/osgi/boot/OsgiBootNoRuntimeTest.java new file mode 100644 index 000000000..638b13a6d --- /dev/null +++ b/org.argeo.osgi.boot/src/test/java/org/argeo/osgi/boot/OsgiBootNoRuntimeTest.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.osgi.boot; + +import java.io.File; +import java.util.List; + +import junit.framework.TestCase; + +import org.argeo.osgi.boot.OsgiBoot; + +/** Tests which do not require a runtime. */ +public class OsgiBootNoRuntimeTest extends TestCase { + public final static String BUNDLES = "src/test/bundles/some;in=*;ex=excluded," + + "src/test/bundles/others;in=**/org.argeo.*"; + + /** Tests that location lists are properly parsed. */ + public void testLocations() { + String baseUrl = "file:"; + String locations = "/mydir/myfile" + File.pathSeparator + + "/myotherdir/myotherfile"; + + OsgiBoot osgiBoot = new OsgiBoot(null); + osgiBoot.setExcludeSvn(true); + List urls = osgiBoot.getLocationsUrls(baseUrl, locations); + assertEquals(2, urls.size()); + assertEquals("file:/mydir/myfile", urls.get(0)); + assertEquals("file:/myotherdir/myotherfile", urls.get(1)); + } + + /** Tests that bundle lists are properly parsed. */ + public void testBundles() { + String baseUrl = "file:"; + String bundles = BUNDLES; + OsgiBoot osgiBoot = new OsgiBoot(null); + osgiBoot.setExcludeSvn(true); + List urls = osgiBoot.getBundlesUrls(baseUrl, bundles); + for (int i = 0; i < urls.size(); i++) + System.out.println(urls.get(i)); + assertEquals(3, urls.size()); + + List jarUrls = osgiBoot.getBundlesUrls(baseUrl, + "src/test/bundles/jars;in=*.jar"); + for (int i = 0; i < jarUrls.size(); i++) + System.out.println(jarUrls.get(i)); + assertEquals(1, jarUrls.size()); + } +} diff --git a/org.argeo.osgi.boot/src/test/java/org/argeo/osgi/boot/OsgiBootRuntimeTest.java b/org.argeo.osgi.boot/src/test/java/org/argeo/osgi/boot/OsgiBootRuntimeTest.java new file mode 100644 index 000000000..32b72bceb --- /dev/null +++ b/org.argeo.osgi.boot/src/test/java/org/argeo/osgi/boot/OsgiBootRuntimeTest.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.osgi.boot; + +import java.util.Iterator; +import java.util.Map; +import java.util.TreeMap; + +import junit.framework.TestCase; + +import org.eclipse.core.runtime.adaptor.EclipseStarter; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; + +/** Starts an Equinox runtime and provision it with OSGi boot. */ +public class OsgiBootRuntimeTest extends TestCase { + protected OsgiBoot osgiBoot = null; + private boolean osgiRuntimeAlreadyRunning = false; + + public void testInstallAndStart() throws Exception { + if (osgiRuntimeAlreadyRunning) { + System.out + .println("OSGi runtime already running, skipping test..."); + return; + } + osgiBoot.installUrls(osgiBoot.getBundlesUrls(OsgiBoot.DEFAULT_BASE_URL, + OsgiBootNoRuntimeTest.BUNDLES)); + Map map = new TreeMap(osgiBoot.getBundlesBySymbolicName()); + for (Iterator keys = map.keySet().iterator(); keys.hasNext();) { + Object key = keys.next(); + Bundle bundle = (Bundle) map.get(key); + System.out.println(key + " : " + bundle.getLocation()); + } + assertEquals(4, map.size()); + Iterator keys = map.keySet().iterator(); + assertEquals("org.argeo.osgi.boot.test.bundle1", keys.next()); + assertEquals("org.argeo.osgi.boot.test.bundle2", keys.next()); + assertEquals("org.argeo.osgi.boot.test.bundle3", keys.next()); + assertEquals("org.eclipse.osgi", keys.next()); + + osgiBoot.startBundles("org.argeo.osgi.boot.test.bundle2"); + long begin = System.currentTimeMillis(); + while (System.currentTimeMillis() - begin < 10000) { + Map mapBundles = osgiBoot.getBundlesBySymbolicName(); + Bundle bundle = (Bundle) mapBundles + .get("org.argeo.osgi.boot.test.bundle2"); + if (bundle.getState() == Bundle.ACTIVE) { + System.out.println("Bundle " + bundle + " started."); + return; + } + } + fail("Bundle not started after timeout limit."); + } + + protected BundleContext startRuntime() throws Exception { + String[] args = { "-console", "-clean" }; + BundleContext bundleContext = EclipseStarter.startup(args, null); + return bundleContext; + } + + protected void stopRuntime() throws Exception { + EclipseStarter.shutdown(); + } + + public void setUp() throws Exception { + osgiRuntimeAlreadyRunning = EclipseStarter.isRunning(); + if (osgiRuntimeAlreadyRunning) + return; + BundleContext bundleContext = startRuntime(); + osgiBoot = new OsgiBoot(bundleContext); + } + + public void tearDown() throws Exception { + if (osgiRuntimeAlreadyRunning) + return; + osgiBoot = null; + stopRuntime(); + } + +} diff --git a/org.argeo.osgi.ui.explorer/.classpath b/org.argeo.osgi.ui.explorer/.classpath new file mode 100644 index 000000000..c5931a083 --- /dev/null +++ b/org.argeo.osgi.ui.explorer/.classpath @@ -0,0 +1,7 @@ + + + >> + + + + diff --git a/org.argeo.osgi.ui.explorer/.project b/org.argeo.osgi.ui.explorer/.project new file mode 100644 index 000000000..1a4f4d3bd --- /dev/null +++ b/org.argeo.osgi.ui.explorer/.project @@ -0,0 +1,28 @@ + + + org.argeo.osgi.ui.explorer + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/org.argeo.osgi.ui.explorer/.settings/org.eclipse.jdt.core.prefs b/org.argeo.osgi.ui.explorer/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..9916a2282 --- /dev/null +++ b/org.argeo.osgi.ui.explorer/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +#Sun Sep 04 16:04:00 CEST 2011 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.5 diff --git a/org.argeo.osgi.ui.explorer/build.properties b/org.argeo.osgi.ui.explorer/build.properties new file mode 100644 index 000000000..4f799f2d3 --- /dev/null +++ b/org.argeo.osgi.ui.explorer/build.properties @@ -0,0 +1,6 @@ +source.. = src/main/java/ +output.. = target/classes/ +bin.includes = META-INF/,\ + .,\ + icons/,\ + plugin.xml diff --git a/org.argeo.osgi.ui.explorer/icons/active.gif b/org.argeo.osgi.ui.explorer/icons/active.gif new file mode 100644 index 000000000..7d24707ee Binary files /dev/null and b/org.argeo.osgi.ui.explorer/icons/active.gif differ diff --git a/org.argeo.osgi.ui.explorer/icons/bundles.gif b/org.argeo.osgi.ui.explorer/icons/bundles.gif new file mode 100644 index 000000000..e9a6bd966 Binary files /dev/null and b/org.argeo.osgi.ui.explorer/icons/bundles.gif differ diff --git a/org.argeo.osgi.ui.explorer/icons/installed.gif b/org.argeo.osgi.ui.explorer/icons/installed.gif new file mode 100644 index 000000000..298871653 Binary files /dev/null and b/org.argeo.osgi.ui.explorer/icons/installed.gif differ diff --git a/org.argeo.osgi.ui.explorer/icons/osgi_explorer.gif b/org.argeo.osgi.ui.explorer/icons/osgi_explorer.gif new file mode 100644 index 000000000..e9a6bd966 Binary files /dev/null and b/org.argeo.osgi.ui.explorer/icons/osgi_explorer.gif differ diff --git a/org.argeo.osgi.ui.explorer/icons/resolved.gif b/org.argeo.osgi.ui.explorer/icons/resolved.gif new file mode 100644 index 000000000..f4a1ea150 Binary files /dev/null and b/org.argeo.osgi.ui.explorer/icons/resolved.gif differ diff --git a/org.argeo.osgi.ui.explorer/icons/starting.gif b/org.argeo.osgi.ui.explorer/icons/starting.gif new file mode 100644 index 000000000..563743d39 Binary files /dev/null and b/org.argeo.osgi.ui.explorer/icons/starting.gif differ diff --git a/org.argeo.osgi.ui.explorer/plugin.xml b/org.argeo.osgi.ui.explorer/plugin.xml new file mode 100644 index 000000000..c0815cad4 --- /dev/null +++ b/org.argeo.osgi.ui.explorer/plugin.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.argeo.osgi.ui.explorer/pom.xml b/org.argeo.osgi.ui.explorer/pom.xml new file mode 100644 index 000000000..fcdc73c78 --- /dev/null +++ b/org.argeo.osgi.ui.explorer/pom.xml @@ -0,0 +1,57 @@ + + 4.0.0 + + org.argeo.commons + 2.1.12-SNAPSHOT + argeo-commons + .. + + org.argeo.osgi.ui.explorer + Commons OSGi Explorer + + + + org.apache.felix + maven-bundle-plugin + + + ${project.artifactId};singleton:=true + lazy + org.argeo.osgi.ui.explorer.OsgiExplorerPlugin + org.eclipse.ui;resolution:=optional, + org.eclipse.rap.ui;resolution:=optional, + org.eclipse.core.runtime + org.argeo.osgi.ui.explorer.* + + + + + + + + org.argeo.tp + org.eclipse.osgi + provided + + + + org.argeo.commons + org.argeo.eclipse.ui + 2.1.12-SNAPSHOT + + + + + org.argeo.commons + org.argeo.eclipse.dep.rcp + 2.1.12-SNAPSHOT + provided + + + org.argeo.commons + org.argeo.eclipse.ui.rcp + 2.1.12-SNAPSHOT + provided + + + diff --git a/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/OsgiExplorerImages.java b/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/OsgiExplorerImages.java new file mode 100644 index 000000000..77bdfe946 --- /dev/null +++ b/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/OsgiExplorerImages.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.osgi.ui.explorer; + +import org.eclipse.swt.graphics.Image; + +/** Shared icons. */ +public class OsgiExplorerImages { + public final static Image INSTALLED = OsgiExplorerPlugin + .getImageDescriptor("icons/installed.gif").createImage(); + public final static Image RESOLVED = OsgiExplorerPlugin.getImageDescriptor( + "icons/resolved.gif").createImage(); + public final static Image STARTING = OsgiExplorerPlugin.getImageDescriptor( + "icons/starting.gif").createImage(); + public final static Image ACTIVE = OsgiExplorerPlugin.getImageDescriptor( + "icons/active.gif").createImage(); +} diff --git a/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/OsgiExplorerPerspective.java b/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/OsgiExplorerPerspective.java new file mode 100644 index 000000000..153abcda2 --- /dev/null +++ b/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/OsgiExplorerPerspective.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.osgi.ui.explorer; + +import org.eclipse.ui.IPageLayout; +import org.eclipse.ui.IPerspectiveFactory; + +/** OSGi explorer perspective (to be enriched declaratively) */ +public class OsgiExplorerPerspective implements IPerspectiveFactory { + + public void createInitialLayout(IPageLayout layout) { + layout.setEditorAreaVisible(true); + layout.setFixed(false); + + } + +} diff --git a/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/OsgiExplorerPlugin.java b/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/OsgiExplorerPlugin.java new file mode 100644 index 000000000..80146d198 --- /dev/null +++ b/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/OsgiExplorerPlugin.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.osgi.ui.explorer; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class OsgiExplorerPlugin extends AbstractUIPlugin { + + // The plug-in ID + public static final String PLUGIN_ID = "org.argeo.osgi.ui.explorer"; //$NON-NLS-1$ + + // The shared instance + private static OsgiExplorerPlugin plugin; + + /** + * The constructor + */ + public OsgiExplorerPlugin() { + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext + * ) + */ + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext + * ) + */ + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static OsgiExplorerPlugin getDefault() { + return plugin; + } + + public static ImageDescriptor getImageDescriptor(String path) { + return imageDescriptorFromPlugin(PLUGIN_ID, path); + } + +} diff --git a/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/views/BundlesView.java b/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/views/BundlesView.java new file mode 100644 index 000000000..98d74a6a7 --- /dev/null +++ b/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/views/BundlesView.java @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.osgi.ui.explorer.views; + +import java.util.Comparator; + +import org.argeo.eclipse.ui.ColumnViewerComparator; +import org.argeo.eclipse.ui.specific.EclipseUiSpecificUtils; +import org.argeo.osgi.ui.explorer.OsgiExplorerImages; +import org.argeo.osgi.ui.explorer.OsgiExplorerPlugin; +import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TableViewerColumn; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.part.ViewPart; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; + +/** + * Overview of the bundles as a table. Equivalent to Equinox 'ss' console + * command. + */ +public class BundlesView extends ViewPart { + private TableViewer viewer; + + @Override + public void createPartControl(Composite parent) { + viewer = new TableViewer(parent); + viewer.setContentProvider(new BundleContentProvider()); + viewer.getTable().setHeaderVisible(true); + + EclipseUiSpecificUtils.enableToolTipSupport(viewer); + + // ID + TableViewerColumn column = new TableViewerColumn(viewer, SWT.NONE); + column.getColumn().setWidth(30); + column.getColumn().setText("ID"); + column.getColumn().setAlignment(SWT.RIGHT); + column.setLabelProvider(new ColumnLabelProvider() { + public String getText(Object element) { + return Long.toString(((Bundle) element).getBundleId()); + } + }); + new ColumnViewerComparator(column, new Comparator() { + public int compare(Bundle o1, Bundle o2) { + return (int) (o1.getBundleId() - o2.getBundleId()); + } + }); + + // State + column = new TableViewerColumn(viewer, SWT.NONE); + column.getColumn().setWidth(18); + column.getColumn().setText("State"); + column.setLabelProvider(new StateLabelProvider()); + new ColumnViewerComparator(column, new Comparator() { + public int compare(Bundle o1, Bundle o2) { + return o1.getState() - o2.getState(); + } + }); + + // Symbolic name + column = new TableViewerColumn(viewer, SWT.NONE); + column.getColumn().setWidth(300); + column.getColumn().setText("Symbolic Name"); + column.setLabelProvider(new ColumnLabelProvider() { + public String getText(Object element) { + return ((Bundle) element).getSymbolicName(); + } + }); + new ColumnViewerComparator(column, new Comparator() { + public int compare(Bundle o1, Bundle o2) { + return o1.getSymbolicName().compareTo(o2.getSymbolicName()); + } + }); + + // Version + column = new TableViewerColumn(viewer, SWT.NONE); + column.getColumn().setWidth(150); + column.getColumn().setText("Version"); + column.setLabelProvider(new ColumnLabelProvider() { + public String getText(Object element) { + return ((Bundle) element).getVersion().toString(); + } + }); + new ColumnViewerComparator(column, new Comparator() { + public int compare(Bundle o1, Bundle o2) { + return o1.getVersion().compareTo(o2.getVersion()); + } + }); + + viewer.setInput(OsgiExplorerPlugin.getDefault().getBundle() + .getBundleContext()); + + } + + @Override + public void setFocus() { + if (viewer != null) + viewer.getControl().setFocus(); + } + + /** Content provider managing the array of bundles */ + private static class BundleContentProvider implements + IStructuredContentProvider { + public Object[] getElements(Object inputElement) { + if (inputElement instanceof BundleContext) { + BundleContext bc = (BundleContext) inputElement; + return bc.getBundles(); + } + return null; + } + + public void dispose() { + } + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + + } + + /** Label provider for the state column */ + private static class StateLabelProvider extends ColumnLabelProvider { + @Override + public Image getImage(Object element) { + Integer state = ((Bundle) element).getState(); + switch (state) { + case Bundle.UNINSTALLED: + return OsgiExplorerImages.INSTALLED; + case Bundle.INSTALLED: + return OsgiExplorerImages.INSTALLED; + case Bundle.RESOLVED: + return OsgiExplorerImages.RESOLVED; + case Bundle.STARTING: + return OsgiExplorerImages.STARTING; + case Bundle.STOPPING: + return OsgiExplorerImages.STARTING; + case Bundle.ACTIVE: + return OsgiExplorerImages.ACTIVE; + default: + return null; + } + } + + @Override + public String getText(Object element) { + return null; + } + + @Override + public String getToolTipText(Object element) { + Bundle bundle = (Bundle) element; + Integer state = bundle.getState(); + switch (state) { + case Bundle.UNINSTALLED: + return "UNINSTALLED"; + case Bundle.INSTALLED: + return "INSTALLED"; + case Bundle.RESOLVED: + return "RESOLVED"; + case Bundle.STARTING: + String activationPolicy = bundle.getHeaders() + .get(Constants.BUNDLE_ACTIVATIONPOLICY).toString(); + if (activationPolicy != null + && activationPolicy.equals(Constants.ACTIVATION_LAZY)) + return "<>"; + return "STARTING"; + case Bundle.STOPPING: + return "STOPPING"; + case Bundle.ACTIVE: + return "ACTIVE"; + default: + return null; + } + } + + } +} diff --git a/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/views/ModulesView.java b/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/views/ModulesView.java new file mode 100644 index 000000000..5d67bd458 --- /dev/null +++ b/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/views/ModulesView.java @@ -0,0 +1,379 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.osgi.ui.explorer.views; + +import java.util.Comparator; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.eclipse.ui.TreeParent; +import org.argeo.osgi.ui.explorer.OsgiExplorerPlugin; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.part.ViewPart; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.osgi.service.packageadmin.ExportedPackage; +import org.osgi.service.packageadmin.PackageAdmin; + +/** Experimental The OSGi runtime from a module perspective. */ +public class ModulesView extends ViewPart { + private final static Log log = LogFactory.getLog(ModulesView.class); + + private TreeViewer viewer; + + private PackageAdmin packageAdmin; + + private Comparator exportedPackageComparator = new Comparator() { + + public int compare(ExportedPackage o1, ExportedPackage o2) { + if (!o1.getName().equals(o2.getName())) + return o1.getName().compareTo(o2.getName()); + else + return o1.getVersion().compareTo(o2.getVersion()); + } + }; + + @Override + public void createPartControl(Composite parent) { + viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); + viewer.setContentProvider(new ModulesContentProvider()); + viewer.setLabelProvider(new ModulesLabelProvider()); + viewer.setInput(OsgiExplorerPlugin.getDefault().getBundle() + .getBundleContext()); + } + + @Override + public void setFocus() { + viewer.getTree().setFocus(); + } + + private class ModulesContentProvider implements ITreeContentProvider { + + public Object[] getElements(Object inputElement) { + return getChildren(inputElement); + } + + public Object[] getChildren(Object parentElement) { + if (parentElement instanceof BundleContext) { + BundleContext bundleContext = (BundleContext) parentElement; + Bundle[] bundles = bundleContext.getBundles(); + + TreeParent bundlesNode = new TreeParent("Bundles"); + for (Bundle bundle : bundles) { + if (bundle.getState() == Bundle.ACTIVE) + bundlesNode.addChild(new BundleNode(bundle)); + } + + // scan packages + ServiceReference paSr = bundleContext + .getServiceReference(PackageAdmin.class.getName()); + // TODO: make a cleaner referencing + packageAdmin = (PackageAdmin) bundleContext.getService(paSr); + + Bundle bundle1 = null; + Bundle bundle2 = null; + + Map> importedPackages = new HashMap>(); + Map> packages = new TreeMap>(); + for (Bundle bundle : bundles) { + if (bundle.getSymbolicName() + .equals("org.argeo.security.ui")) + bundle1 = bundle; + if (bundle.getSymbolicName().equals( + "org.argeo.security.equinox")) + bundle2 = bundle; + + ExportedPackage[] pkgs = packageAdmin + .getExportedPackages(bundle); + if (pkgs != null) + for (ExportedPackage pkg : pkgs) { + if (!packages.containsKey(pkg.getName())) + packages.put(pkg.getName(), + new TreeSet( + exportedPackageComparator)); + Set expPackages = (Set) packages + .get(pkg.getName()); + expPackages.add(pkg); + + // imported + for (Bundle b : pkg.getImportingBundles()) { + if (bundle.getBundleId() != b.getBundleId()) { + if (!importedPackages.containsKey(b)) + importedPackages + .put(b, + new TreeSet( + exportedPackageComparator)); + Set impPackages = (Set) importedPackages + .get(b); + impPackages.add(pkg); + } + } + } + } + + TreeParent mPackageNode = new TreeParent("Multiple Packages"); + // TreeParent aPackageNode = new TreeParent("All Packages"); + for (String packageName : packages.keySet()) { + Set pkgs = packages.get(packageName); + if (pkgs.size() > 1) { + MultiplePackagesNode mpn = new MultiplePackagesNode( + packageName, pkgs); + mPackageNode.addChild(mpn); + // aPackageNode.addChild(mpn); + } else { + // aPackageNode.addChild(new ExportedPackageNode(pkgs + // .iterator().next())); + } + } + + return new Object[] { bundlesNode, mPackageNode };// , + // aPackageNode + // }; + } else if (parentElement instanceof TreeParent) { + return ((TreeParent) parentElement).getChildren(); + } else { + return null; + } + } + + public Object getParent(Object element) { + // TODO Auto-generated method stub + return null; + } + + public boolean hasChildren(Object element) { + if (element instanceof TreeParent) { + return ((TreeParent) element).hasChildren(); + } + return false; + } + + public void dispose() { + // TODO Auto-generated method stub + + } + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + // TODO Auto-generated method stub + + } + + } + + protected Map dependencySpace(Bundle bundle, + Map> importedPackages, + Map> traces) { + log.debug("Dependency space for " + bundle.getSymbolicName()); + Map space = new TreeMap(); + fillDependencySpace(space, bundle, importedPackages, + bundle.getSymbolicName(), traces); + return space; + } + + /** Recursive */ + protected void fillDependencySpace(Map space, + Bundle bundle, Map> importedPackages, + String currTrace, Map> traces) { + if (importedPackages.containsKey(bundle)) { + Set imports = importedPackages.get(bundle); + // log.debug("## Fill dependency space for " + bundle + " : "); + for (ExportedPackage pkg : imports) { + if (!traces.containsKey(pkg.getName())) + traces.put(pkg.getName(), new TreeSet()); + traces.get(pkg.getName()).add(currTrace); + if (!space.containsKey(pkg.getName())) { + space.put(pkg.getName(), pkg); + Bundle exportingBundle = pkg.getExportingBundle(); + // if (bundle.getBundleId() != + // exportingBundle.getBundleId()) + fillDependencySpace(space, exportingBundle, + importedPackages, currTrace + " > " + + exportingBundle.getSymbolicName(), traces); + } + } + } + } + + private class ModulesLabelProvider extends LabelProvider implements + ITableLabelProvider { + + public Image getColumnImage(Object element, int columnIndex) { + // TODO Auto-generated method stub + return null; + } + + public String getColumnText(Object element, int columnIndex) { + return getText(element); + } + + } + + class BundleNode extends TreeParent { + private final Bundle bundle; + + public BundleNode(Bundle bundle) { + super(bundle.getSymbolicName()); + this.bundle = bundle; + + // Registered services + ServiceReference[] registeredServices = bundle + .getRegisteredServices(); + if (registeredServices != null) { + TreeParent registeredServicesNode = new TreeParent( + "Registered Services"); + addChild(registeredServicesNode); + for (ServiceReference sr : registeredServices) { + if (sr != null) + registeredServicesNode + .addChild(new ServiceReferenceNode(sr)); + } + } + + // Used services + ServiceReference[] usedServices = bundle.getRegisteredServices(); + if (usedServices != null) { + TreeParent usedServicesNode = new TreeParent("Used Services"); + addChild(usedServicesNode); + for (ServiceReference sr : usedServices) { + if (sr != null) + usedServicesNode.addChild(new ServiceReferenceNode(sr)); + } + } + } + + public Bundle getBundle() { + return bundle; + } + + } + + class ServiceReferenceNode extends TreeParent { + private final ServiceReference serviceReference; + + public ServiceReferenceNode(ServiceReference serviceReference) { + super(serviceReference.toString()); + this.serviceReference = serviceReference; + + Bundle[] usedBundles = serviceReference.getUsingBundles(); + if (usedBundles != null) { + TreeParent usingBundles = new TreeParent("Using Bundles"); + addChild(usingBundles); + for (Bundle b : usedBundles) { + if (b != null) + usingBundles.addChild(new TreeParent(b + .getSymbolicName())); + } + } + + TreeParent properties = new TreeParent("Properties"); + addChild(properties); + for (String key : serviceReference.getPropertyKeys()) { + properties.addChild(new TreeParent(key + "=" + + serviceReference.getProperty(key))); + } + + } + + public ServiceReference getServiceReference() { + return serviceReference; + } + + } + + class MultiplePackagesNode extends TreeParent { + private String packageName; + private Set exportedPackages; + + public MultiplePackagesNode(String packageName, + Set exportedPackages) { + super(packageName); + this.packageName = packageName; + this.exportedPackages = exportedPackages; + for (ExportedPackage pkg : exportedPackages) { + addChild(new ExportedPackageNode(pkg)); + } + } + + } + + class ConflictingPackageNode extends TreeParent { + private ExportedPackage exportedPackage; + + public ConflictingPackageNode(ExportedPackage exportedPackage) { + super(exportedPackage.getName() + " - " + + exportedPackage.getVersion() + " (" + + exportedPackage.getExportingBundle() + ")"); + this.exportedPackage = exportedPackage; + + TreeParent bundlesNode = new TreeParent("Dependent Bundles"); + this.addChild(bundlesNode); + Map bundles = new TreeMap(); + for (Bundle b : exportedPackage.getImportingBundles()) { + bundles.put(b.getSymbolicName(), b); + } + for (String key : bundles.keySet()) { + addDependentBundles(bundlesNode, bundles.get(key)); + } + } + } + + protected void addDependentBundles(TreeParent parent, Bundle bundle) { + TreeParent bundleNode = new TreeParent(bundle.toString()); + parent.addChild(bundleNode); + Map bundles = new TreeMap(); + ExportedPackage[] pkgs = packageAdmin.getExportedPackages(bundle); + if (pkgs != null) + for (ExportedPackage pkg : pkgs) { + for (Bundle b : pkg.getImportingBundles()) { + if (!bundles.containsKey(b.getSymbolicName()) + && b.getBundleId() != bundle.getBundleId()) { + bundles.put(b.getSymbolicName(), b); + } + } + } + + for (String key : bundles.keySet()) { + addDependentBundles(bundleNode, bundles.get(key)); + } + } + + class ExportedPackageNode extends TreeParent { + private ExportedPackage exportedPackage; + + public ExportedPackageNode(ExportedPackage exportedPackage) { + super(exportedPackage.getName() + " - " + + exportedPackage.getVersion() + " (" + + exportedPackage.getExportingBundle() + ")"); + this.exportedPackage = exportedPackage; + for (Bundle bundle : exportedPackage.getImportingBundles()) { + addChild(new BundleNode(bundle)); + } + } + } +} diff --git a/org.argeo.security.auth.ldap/.project b/org.argeo.security.auth.ldap/.project new file mode 100644 index 000000000..0c72d5914 --- /dev/null +++ b/org.argeo.security.auth.ldap/.project @@ -0,0 +1,22 @@ + + + org.argeo.security.auth.ldap + + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + + diff --git a/org.argeo.security.auth.ldap/META-INF/spring/security-ldap-jcr.xml b/org.argeo.security.auth.ldap/META-INF/spring/security-ldap-jcr.xml new file mode 100644 index 000000000..3235e66f4 --- /dev/null +++ b/org.argeo.security.auth.ldap/META-INF/spring/security-ldap-jcr.xml @@ -0,0 +1,79 @@ + + + + + + + /org/argeo/jcr/argeo.cnd + + + + + + + + + + + + + ${argeo.ldap.userClass} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.argeo.security.auth.ldap/META-INF/spring/security-ldap-osgi.xml b/org.argeo.security.auth.ldap/META-INF/spring/security-ldap-osgi.xml new file mode 100644 index 000000000..d817f9644 --- /dev/null +++ b/org.argeo.security.auth.ldap/META-INF/spring/security-ldap-osgi.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.security.auth.ldap/META-INF/spring/security-ldap-services.xml b/org.argeo.security.auth.ldap/META-INF/spring/security-ldap-services.xml new file mode 100644 index 000000000..0b9a8b8f0 --- /dev/null +++ b/org.argeo.security.auth.ldap/META-INF/spring/security-ldap-services.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.security.auth.ldap/META-INF/spring/security-ldap.xml b/org.argeo.security.auth.ldap/META-INF/spring/security-ldap.xml new file mode 100644 index 000000000..f367aba1d --- /dev/null +++ b/org.argeo.security.auth.ldap/META-INF/spring/security-ldap.xml @@ -0,0 +1,121 @@ + + + + + + + osgibundle:ldap.properties + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.argeo.security.auth.ldap/build.properties b/org.argeo.security.auth.ldap/build.properties new file mode 100644 index 000000000..5f22cdd44 --- /dev/null +++ b/org.argeo.security.auth.ldap/build.properties @@ -0,0 +1 @@ +bin.includes = META-INF/ diff --git a/org.argeo.security.auth.ldap/ldap.properties b/org.argeo.security.auth.ldap/ldap.properties new file mode 100644 index 000000000..0f5164ff3 --- /dev/null +++ b/org.argeo.security.auth.ldap/ldap.properties @@ -0,0 +1,32 @@ +argeo.security.defaultRole=ROLE_USER +argeo.security.rolePrefix=ROLE_ + +argeo.security.systemKey=argeo +argeo.security.superUsername=root + +argeo.ldap.rootdn=dc=demo,dc=example,dc=org +argeo.ldap.protocol=ldap +argeo.ldap.host=localhost +# default are for Apache Directory Server +argeo.ldap.port=10389 +argeo.ldap.manager.userdn=uid=admin,ou=system +argeo.ldap.manager.password=secret + +# USER +argeo.ldap.userClass=inetOrgPerson +argeo.ldap.osUserClass=posixAccount +argeo.ldap.userBase=ou=People +argeo.ldap.usernameAttribute=uid +argeo.ldap.passwordAttribute=userPassword +# ROLES +argeo.ldap.groupClass=groupOfNames +argeo.ldap.groupBase=ou=Roles +argeo.ldap.groupRoleAttribute=cn +argeo.ldap.groupMemberAttribute=member +# OS GROUPS +argeo.ldap.osGroupClass=posixGroup +argeo.ldap.osGroupBase=ou=Group +argeo.ldap.osGroupNameAttribute=cn +argeo.ldap.osGroupMemberAttribute=memberUid + +argeo.ldap.password.useSalt=false \ No newline at end of file diff --git a/org.argeo.security.auth.ldap/pom.xml b/org.argeo.security.auth.ldap/pom.xml new file mode 100644 index 000000000..a4410a91f --- /dev/null +++ b/org.argeo.security.auth.ldap/pom.xml @@ -0,0 +1,30 @@ + + 4.0.0 + + org.argeo.commons + 2.1.12-SNAPSHOT + argeo-commons + .. + + org.argeo.security.auth.ldap + Commons Security Auth LDAP + + + + org.apache.felix + maven-bundle-plugin + + + + *, + org.argeo.jcr, + com.sun.jndi.ldap;resolution:=optional, + org.springframework.ldap.core.support, + org.springframework.security + + + + + + + \ No newline at end of file diff --git a/org.argeo.security.core/.classpath b/org.argeo.security.core/.classpath new file mode 100644 index 000000000..b639b537c --- /dev/null +++ b/org.argeo.security.core/.classpath @@ -0,0 +1,10 @@ + + + + + + + >> + + + diff --git a/org.argeo.security.core/.project b/org.argeo.security.core/.project new file mode 100644 index 000000000..a8e385a9c --- /dev/null +++ b/org.argeo.security.core/.project @@ -0,0 +1,28 @@ + + + org.argeo.security.core + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.pde.PluginNature + + diff --git a/org.argeo.security.core/META-INF/spring/logger.xml b/org.argeo.security.core/META-INF/spring/logger.xml new file mode 100644 index 000000000..02f48c8a8 --- /dev/null +++ b/org.argeo.security.core/META-INF/spring/logger.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.argeo.security.core/META-INF/spring/osgi.xml b/org.argeo.security.core/META-INF/spring/osgi.xml new file mode 100644 index 000000000..5e1433c2f --- /dev/null +++ b/org.argeo.security.core/META-INF/spring/osgi.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/org.argeo.security.core/build.properties b/org.argeo.security.core/build.properties new file mode 100644 index 000000000..788870d98 --- /dev/null +++ b/org.argeo.security.core/build.properties @@ -0,0 +1,13 @@ +additional.bundles = org.springframework.transaction,\ + org.springframework.core,\ + junit,\ + org.apache.commons.io,\ + org.apache.commons.codec,\ + org.springframework.security.core,\ + org.apache.log4j,\ + slf4j.api,\ + slf4j.org.apache.commons.logging +source.. = src/main/java/,\ + src/main/resources/,\ + src/test/java/,\ + src/test/resources/ diff --git a/org.argeo.security.core/pom.xml b/org.argeo.security.core/pom.xml new file mode 100644 index 000000000..6a57226b9 --- /dev/null +++ b/org.argeo.security.core/pom.xml @@ -0,0 +1,138 @@ + + + 4.0.0 + + org.argeo.commons + argeo-commons + 2.1.12-SNAPSHOT + .. + + org.argeo.security.core + Commons Security Core + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-source-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + org.apache.felix + maven-bundle-plugin + + + + lazy + + org.argeo.security.* + + + + org.bouncycastle.*;resolution:=optional, + javax.jcr.security, + *, + + + + + + + + + org.argeo.commons + org.argeo.util + 2.1.12-SNAPSHOT + + + org.argeo.commons + org.argeo.server.jcr + 2.1.12-SNAPSHOT + + + + + org.argeo.tp + bcprov + true + + + org.argeo.tp + org.apache.commons.codec + + + + + org.argeo.tp + org.springframework.core + + + org.argeo.tp + org.springframework.beans + + + org.argeo.tp + org.springframework.context + + + org.argeo.tp + org.springframework.security.core + + + org.argeo.tp + org.springframework.transaction + + + + + org.argeo.tp + org.eclipse.osgi + provided + + + + + org.argeo.tp + slf4j.org.apache.commons.logging + + + + org.argeo.tp + org.apache.log4j + true + + + + + org.argeo.tp + junit + test + + + org.argeo.commons + org.argeo.dep.log4j + 2.1.12-SNAPSHOT + pom + test + + + + + + + + + org.argeo.tp + com.springsource.json + test + + + + \ No newline at end of file diff --git a/org.argeo.security.core/src/main/java/org/argeo/security/NodeAuthenticationToken.java b/org.argeo.security.core/src/main/java/org/argeo/security/NodeAuthenticationToken.java new file mode 100644 index 000000000..1870675d8 --- /dev/null +++ b/org.argeo.security.core/src/main/java/org/argeo/security/NodeAuthenticationToken.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security; + +import org.springframework.security.GrantedAuthority; +import org.springframework.security.providers.UsernamePasswordAuthenticationToken; + +/** Credentials required for the authentication to a node. */ +public class NodeAuthenticationToken extends + UsernamePasswordAuthenticationToken { + private static final long serialVersionUID = 1955222132884795213L; + private final String url; + + /** Non authenticated local constructor */ + public NodeAuthenticationToken(Object principal, Object credentials) { + super(principal, credentials); + this.url = null; + } + + /** Non authenticated remote constructor */ + public NodeAuthenticationToken(Object principal, Object credentials, + String url) { + super(principal, credentials); + this.url = url; + } + + /** Authenticated constructor */ + public NodeAuthenticationToken(NodeAuthenticationToken sat, + GrantedAuthority[] authorities) { + super(sat.getPrincipal(), sat.getCredentials(), authorities); + this.url = sat.getUrl(); + } + + public String getUrl() { + return url; + } + + public Boolean isRemote() { + return url != null; + } +} diff --git a/org.argeo.security.core/src/main/java/org/argeo/security/OsAuthenticationToken.java b/org.argeo.security.core/src/main/java/org/argeo/security/OsAuthenticationToken.java new file mode 100644 index 000000000..b3727b26f --- /dev/null +++ b/org.argeo.security.core/src/main/java/org/argeo/security/OsAuthenticationToken.java @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security; + +import java.security.AccessController; +import java.security.Principal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Set; + +import javax.security.auth.Subject; + +import org.argeo.ArgeoException; +import org.argeo.OperatingSystem; +import org.springframework.security.Authentication; +import org.springframework.security.GrantedAuthority; +import org.springframework.security.GrantedAuthorityImpl; +import org.springframework.security.userdetails.UserDetails; + +/** Abstracts principals provided by com.sun.security.auth.module login modules. */ +public class OsAuthenticationToken implements Authentication { + private static final long serialVersionUID = -7544626794250917244L; + + final Class osUserPrincipalClass; + final Class osUserIdPrincipalClass; + final Class osGroupIdPrincipalClass; + + private List grantedAuthorities; + + private UserDetails details; + + /** Request */ + public OsAuthenticationToken(GrantedAuthority[] grantedAuthorities) { + this.grantedAuthorities = grantedAuthorities != null ? Arrays + .asList(grantedAuthorities) : null; + ClassLoader cl = getClass().getClassLoader(); + switch (OperatingSystem.os) { + case OperatingSystem.WINDOWS: + osUserPrincipalClass = getPrincipalClass(cl, + "com.sun.security.auth.NTUserPrincipal"); + osUserIdPrincipalClass = getPrincipalClass(cl, + "com.sun.security.auth.NTSidUserPrincipal"); + osGroupIdPrincipalClass = getPrincipalClass(cl, + "com.sun.security.auth.NTSidGroupPrincipal"); + break; + case OperatingSystem.NIX: + osUserPrincipalClass = getPrincipalClass(cl, + "com.sun.security.auth.UnixPrincipal"); + osUserIdPrincipalClass = getPrincipalClass(cl, + "com.sun.security.auth.UnixNumericUserPrincipal"); + osGroupIdPrincipalClass = getPrincipalClass(cl, + "com.sun.security.auth.UnixNumericGroupPrincipal"); + break; + case OperatingSystem.SOLARIS: + osUserPrincipalClass = getPrincipalClass(cl, + "com.sun.security.auth.SolarisPrincipal"); + osUserIdPrincipalClass = getPrincipalClass(cl, + "com.sun.security.auth.SolarisNumericUserPrincipal"); + osGroupIdPrincipalClass = getPrincipalClass(cl, + "com.sun.security.auth.SolarisNumericGroupPrincipal"); + break; + + default: + throw new ArgeoException("Unsupported operating system " + + OperatingSystem.os); + } + + } + + /** Authenticated */ + public OsAuthenticationToken() { + this(null); + } + + /** @return the name, or null if not yet logged */ + public String getName() { + Subject subject = Subject.getSubject(AccessController.getContext()); + if (subject == null) + return null; + return getUser().getName(); + } + + /** + * Should not be called during authentication since group IDs are not yet + * available {@link Subject} has been set + */ + public GrantedAuthority[] getAuthorities() { + // grantedAuthorities should not be null at this stage + List gas = new ArrayList( + grantedAuthorities); + for (Principal groupPrincipal : getGroupsIds()) { + gas.add(new GrantedAuthorityImpl("OSGROUP_" + + groupPrincipal.getName())); + } + return gas.toArray(new GrantedAuthority[gas.size()]); + } + + public UserDetails getDetails() { + return details; + } + + public void setDetails(UserDetails details) { + this.details = details; + } + + public boolean isAuthenticated() { + return grantedAuthorities != null; + } + + public void setAuthenticated(boolean isAuthenticated) + throws IllegalArgumentException { + if (grantedAuthorities != null) + grantedAuthorities.clear(); + grantedAuthorities = null; + } + + @SuppressWarnings("unchecked") + protected static Class getPrincipalClass( + ClassLoader cl, String className) { + try { + return (Class) cl.loadClass(className); + } catch (ClassNotFoundException e) { + throw new ArgeoException("Cannot load principal class", e); + } + } + + public Object getPrincipal() { + return getUser(); + } + + public Principal getUser() { + Subject subject = getSubject(); + Set userPrincipals = subject + .getPrincipals(osUserPrincipalClass); + if (userPrincipals == null || userPrincipals.size() == 0) + throw new ArgeoException("No OS principal"); + if (userPrincipals.size() > 1) + throw new ArgeoException("More than one OS principal"); + Principal user = userPrincipals.iterator().next(); + return user; + } + + public Principal getUserId() { + Subject subject = getSubject(); + Set userIdsPrincipals = subject + .getPrincipals(osUserIdPrincipalClass); + if (userIdsPrincipals == null || userIdsPrincipals.size() == 0) + throw new ArgeoException("No user id principal"); + if (userIdsPrincipals.size() > 1) + throw new ArgeoException("More than one user id principal"); + Principal userId = userIdsPrincipals.iterator().next(); + return userId; + } + + public Set getGroupsIds() { + Subject subject = getSubject(); + return (Set) subject + .getPrincipals(osGroupIdPrincipalClass); + } + + /** @return the subject always non null */ + protected Subject getSubject() { + Subject subject = Subject.getSubject(AccessController.getContext()); + if (subject == null) + throw new ArgeoException("No subject in JAAS context"); + return subject; + } + + public Object getCredentials() { + return ""; + } + +} diff --git a/org.argeo.security.core/src/main/java/org/argeo/security/SecurityUtils.java b/org.argeo.security.core/src/main/java/org/argeo/security/SecurityUtils.java new file mode 100644 index 000000000..e5b8ae79c --- /dev/null +++ b/org.argeo.security.core/src/main/java/org/argeo/security/SecurityUtils.java @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.springframework.security.Authentication; +import org.springframework.security.GrantedAuthority; +import org.springframework.security.context.SecurityContext; +import org.springframework.security.context.SecurityContextHolder; +import org.springframework.security.providers.anonymous.AnonymousAuthenticationToken; + +/** Static utilities */ +public class SecurityUtils { + + private SecurityUtils() { + } + + /** Whether the current thread has the admin role */ + public static boolean hasCurrentThreadAuthority(String authority) { + SecurityContext securityContext = SecurityContextHolder.getContext(); + if (securityContext != null) { + Authentication authentication = securityContext.getAuthentication(); + if (authentication != null) { + for (GrantedAuthority ga : authentication.getAuthorities()) + if (ga.getAuthority().equals(authority)) + return true; + } + } + return false; + } + + /** + * @return the authenticated username or null if not authenticated / + * anonymous + */ + public static String getCurrentThreadUsername() { + SecurityContext securityContext = SecurityContextHolder.getContext(); + if (securityContext != null) { + Authentication authentication = securityContext.getAuthentication(); + if (authentication != null) { + if (authentication instanceof AnonymousAuthenticationToken) { + return null; + } + return authentication.getName(); + } + } + return null; + } + + /** + * Returns the display name of the user details (by calling toString() on + * it) + */ + public static String getUserDetailsDisplayName() { + SecurityContext securityContext = SecurityContextHolder.getContext(); + if (securityContext != null) { + Authentication authentication = securityContext.getAuthentication(); + if (authentication != null) { + if (authentication instanceof AnonymousAuthenticationToken) { + return null; + } + Object details = authentication.getDetails(); + if (details != null) + return details.toString(); + return authentication.getName(); + } + } + return null; + } + + /** + * Converts an array of Spring Security {@link GrantedAuthority} to a + * read-only list of strings, for portability and integration + */ + public static List authoritiesToStringList( + GrantedAuthority[] authorities) { + List lst = new ArrayList(); + for (GrantedAuthority ga : authorities) + lst.add(ga.getAuthority()); + return Collections.unmodifiableList(lst); + } +} diff --git a/org.argeo.security.core/src/main/java/org/argeo/security/SystemAuthentication.java b/org.argeo.security.core/src/main/java/org/argeo/security/SystemAuthentication.java new file mode 100644 index 000000000..2722c1f7d --- /dev/null +++ b/org.argeo.security.core/src/main/java/org/argeo/security/SystemAuthentication.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security; + +/** + * Marks a system authentication, that is which did not require a login process. + */ +public interface SystemAuthentication { + +} diff --git a/org.argeo.security.core/src/main/java/org/argeo/security/SystemExecutionService.java b/org.argeo.security.core/src/main/java/org/argeo/security/SystemExecutionService.java new file mode 100644 index 000000000..075a6c3d8 --- /dev/null +++ b/org.argeo.security.core/src/main/java/org/argeo/security/SystemExecutionService.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security; + +import java.util.concurrent.Callable; +import java.util.concurrent.Executor; +import java.util.concurrent.Future; + +/** + * Allows to execute code authenticated as a system user (that is not a real + * person). The {@link Executor} interface is not used directly in order to + * allow future extension of this interface and to simplify its publication + * (e.g. as an OSGi service) and interception. + */ +public interface SystemExecutionService extends Executor { + /** + * Executes this {@link Runnable} within a system authenticated context. + * Implementations should make sure that this method is properly secured via + * Java permissions since it could access everything without credentials. + */ + public void execute(Runnable runnable); + + /** + * Executes this {@link Callable} within a system authenticated context. + * Implementations should make sure that this method is properly secured via + * Java permissions since it could access everything without credentials. + */ + public Future submit(Callable task); +} diff --git a/org.argeo.security.core/src/main/java/org/argeo/security/UserAdminService.java b/org.argeo.security.core/src/main/java/org/argeo/security/UserAdminService.java new file mode 100644 index 000000000..0a84cf66f --- /dev/null +++ b/org.argeo.security.core/src/main/java/org/argeo/security/UserAdminService.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security; + +import java.util.Set; + +import org.springframework.security.userdetails.UserDetailsManager; + +/** Enrich {@link UserDetailsManager} in order to provide roles semantics. */ +public interface UserAdminService extends UserDetailsManager { + /** + * Usernames must match this regexp pattern ({@value #USERNAME_PATTERN}). + * Thanks to this tip (modified to add upper-case, add '@') + */ + //public final static String USERNAME_PATTERN = "^[a-zA-Z0-9_-@]{3,64}$"; + + /** + * Email addresses must match this regexp pattern ({@value #EMAIL_PATTERN}. + * Thanks to this tip. + */ + public final static String EMAIL_PATTERN = "^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$"; + + /* + * USERS + */ + /** List all users. */ + public Set listUsers(); + + /** List users having this role (except the super user). */ + public Set listUsersInRole(String role); + + /** Synchronize with the underlying DAO. */ + public void synchronize(); + + /* + * ROLES + */ + public void newRole(String role); + + public Set listEditableRoles(); + + public void deleteRole(String role); +} diff --git a/org.argeo.security.core/src/main/java/org/argeo/security/core/AbstractSystemExecution.java b/org.argeo.security.core/src/main/java/org/argeo/security/core/AbstractSystemExecution.java new file mode 100644 index 000000000..b84f3de00 --- /dev/null +++ b/org.argeo.security.core/src/main/java/org/argeo/security/core/AbstractSystemExecution.java @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.core; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; +import org.argeo.security.SystemAuthentication; +import org.springframework.security.Authentication; +import org.springframework.security.AuthenticationManager; +import org.springframework.security.context.SecurityContext; +import org.springframework.security.context.SecurityContextHolder; + +/** Provides base method for executing code with system authorization. */ +public abstract class AbstractSystemExecution { + static { + // Forces Spring Security to use inheritable strategy + // FIXME find a better place for forcing spring security mode + // doesn't work for the time being +// if (System.getProperty(SecurityContextHolder.SYSTEM_PROPERTY) == null) +// SecurityContextHolder +// .setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL); + } + + private final static Log log = LogFactory + .getLog(AbstractSystemExecution.class); + private AuthenticationManager authenticationManager; + private String systemAuthenticationKey; + + /** Whether the current thread was authenticated by this component. */ + private ThreadLocal authenticatedBySelf = new ThreadLocal() { + protected Boolean initialValue() { + return false; + } + }; + + /** + * Authenticate the calling thread to the underlying + * {@link AuthenticationManager} + */ + protected void authenticateAsSystem() { + if (authenticatedBySelf.get()) + return; + SecurityContext securityContext = SecurityContextHolder.getContext(); + Authentication currentAuth = securityContext.getAuthentication(); + if (currentAuth != null) { + if (!(currentAuth instanceof SystemAuthentication)) + throw new ArgeoException( + "System execution on an already authenticated thread: " + + currentAuth + ", THREAD=" + + Thread.currentThread().getId()); + return; + } + // Subject subject = Subject.getSubject(AccessController.getContext()); + // if (subject != null + // && !subject.getPrincipals(Authentication.class).isEmpty()) + // throw new ArgeoException( + // "There is already an authenticated subject: " + subject); + + String key = systemAuthenticationKey != null ? systemAuthenticationKey + : System.getProperty( + InternalAuthentication.SYSTEM_KEY_PROPERTY, + InternalAuthentication.SYSTEM_KEY_DEFAULT); + if (key == null) + throw new ArgeoException("No system key defined"); + Authentication auth = authenticationManager + .authenticate(new InternalAuthentication(key)); + securityContext.setAuthentication(auth); + authenticatedBySelf.set(true); + if (log.isTraceEnabled()) + log.trace("System authenticated"); + } + + // /** Removes the authentication from the calling thread. */ + // protected void deauthenticateAsSystem() { + // // remove the authentication + // // SecurityContext securityContext = SecurityContextHolder.getContext(); + // // securityContext.setAuthentication(null); + // // authenticatedBySelf.set(false); + // if (log.isTraceEnabled()) { + // log.trace("System deauthenticated"); + // // Thread.dumpStack(); + // } + // } + + /** + * Whether the current thread was authenticated by this component or a + * parent thread. + */ + protected Boolean isAuthenticatedBySelf() { + return authenticatedBySelf.get(); + } + + public void setAuthenticationManager( + AuthenticationManager authenticationManager) { + this.authenticationManager = authenticationManager; + } + + public void setSystemAuthenticationKey(String systemAuthenticationKey) { + this.systemAuthenticationKey = systemAuthenticationKey; + } + +} diff --git a/org.argeo.security.core/src/main/java/org/argeo/security/core/AsyncSystemTaskExecutor.java b/org.argeo.security.core/src/main/java/org/argeo/security/core/AsyncSystemTaskExecutor.java new file mode 100644 index 000000000..0e400c82d --- /dev/null +++ b/org.argeo.security.core/src/main/java/org/argeo/security/core/AsyncSystemTaskExecutor.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.core; + +import org.argeo.security.SystemExecutionService; +import org.springframework.core.task.SimpleAsyncTaskExecutor; + +/** + * Asynchronous Spring TaskExecutor (for use in JMS for example) wrapping a + * {@link SystemExecutionService}. + */ +public class AsyncSystemTaskExecutor extends SimpleAsyncTaskExecutor { + private static final long serialVersionUID = -8035527542087963068L; + + private SystemExecutionService systemExecutionService; + + public AsyncSystemTaskExecutor() { + super(); + } + + public AsyncSystemTaskExecutor(String threadNamePrefix) { + super(threadNamePrefix); + } + + @Override + public Thread createThread(final Runnable runnable) { + Runnable systemExecutionRunnable = new Runnable() { + + public void run() { + systemExecutionService.execute(runnable); + + } + }; + return super.createThread(systemExecutionRunnable); + } + + public void setSystemExecutionService( + SystemExecutionService systemExecutionService) { + this.systemExecutionService = systemExecutionService; + } + +} diff --git a/org.argeo.security.core/src/main/java/org/argeo/security/core/AuthenticatedApplicationContextInitialization.java b/org.argeo.security.core/src/main/java/org/argeo/security/core/AuthenticatedApplicationContextInitialization.java new file mode 100644 index 000000000..97dd6cae0 --- /dev/null +++ b/org.argeo.security.core/src/main/java/org/argeo/security/core/AuthenticatedApplicationContextInitialization.java @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.core; + +import java.beans.PropertyDescriptor; +import java.util.ArrayList; +import java.util.List; + +import org.springframework.beans.BeansException; +import org.springframework.beans.PropertyValues; +import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor; +import org.springframework.context.ApplicationEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.context.event.ContextRefreshedEvent; + +/** + * Executes with a system authentication the instantiation and initialization + * methods of the application context where it has been defined. + */ +public class AuthenticatedApplicationContextInitialization extends + AbstractSystemExecution implements InstantiationAwareBeanPostProcessor, + ApplicationListener { + // private Log log = LogFactory + // .getLog(AuthenticatedApplicationContextInitialization.class); + /** If non empty, restricts to these beans */ + private List beanNames = new ArrayList(); + + @SuppressWarnings("rawtypes") + public Object postProcessBeforeInstantiation(Class beanClass, + String beanName) throws BeansException { + // we authenticate when any bean is instantiated + // we will deauthenticate only when the application context has been + // refreshed in order to be able to deal with factory beans has well + if (!isAuthenticatedBySelf()) { + if (beanNames.size() == 0) + authenticateAsSystem(); + else if (beanNames.contains(beanName)) + authenticateAsSystem(); + } + return null; + } + + public boolean postProcessAfterInstantiation(Object bean, String beanName) + throws BeansException { + return true; + } + + public PropertyValues postProcessPropertyValues(PropertyValues pvs, + PropertyDescriptor[] pds, Object bean, String beanName) + throws BeansException { + return pvs; + } + + public Object postProcessBeforeInitialization(Object bean, String beanName) + throws BeansException { + // authenticateAsSystem(); + return bean; + } + + public Object postProcessAfterInitialization(Object bean, String beanName) + throws BeansException { + // NOTE: in case there was an exception in on the initialization method + // we expect the underlying thread to die and thus the system + // authentication to be lost. We have currently no way to catch the + // exception and perform the deauthentication by ourselves. + // deauthenticateAsSystem(); + return bean; + } + + public void onApplicationEvent(ApplicationEvent event) { + if (event instanceof ContextRefreshedEvent) { + // make sure that we have deauthenticated after the application + // context was initialized/refreshed + // deauthenticateAsSystem(); + } + } + + public void setBeanNames(List beanNames) { + this.beanNames = beanNames; + } + +} diff --git a/org.argeo.security.core/src/main/java/org/argeo/security/core/AuthenticationProvidersRegister.java b/org.argeo.security.core/src/main/java/org/argeo/security/core/AuthenticationProvidersRegister.java new file mode 100644 index 000000000..317815e8b --- /dev/null +++ b/org.argeo.security.core/src/main/java/org/argeo/security/core/AuthenticationProvidersRegister.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.core; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.InitializingBean; + +/** + * Maintains a list of authentication providers injected in to a provider + * manager, in order to avoid issues with OSGi services and use packages. + */ +public class AuthenticationProvidersRegister implements InitializingBean { + private Log log = LogFactory.getLog(AuthenticationProvidersRegister.class); + + private List providers = new ArrayList(); + private List defaultProviders = new ArrayList(); + + public void register(Object authenticationProvider, + Map parameters) { + providers.add(authenticationProvider); + if (log.isTraceEnabled()) + log.trace("Registered authentication provider " + parameters); + } + + public void unregister(Object authenticationProvider, + Map parameters) { + providers.remove(authenticationProvider); + if (log.isTraceEnabled()) + log.trace("Unregistered authentication provider " + parameters); + } + + public List getProviders() { + return providers; + } + + public void setDefaultProviders( + List defaultProviders) { + this.defaultProviders = defaultProviders; + } + + public void afterPropertiesSet() throws Exception { + providers.addAll(defaultProviders); + } + +} diff --git a/org.argeo.security.core/src/main/java/org/argeo/security/core/ConsoleCallbackHandler.java b/org.argeo.security.core/src/main/java/org/argeo/security/core/ConsoleCallbackHandler.java new file mode 100644 index 000000000..faa81b004 --- /dev/null +++ b/org.argeo.security.core/src/main/java/org/argeo/security/core/ConsoleCallbackHandler.java @@ -0,0 +1,70 @@ +package org.argeo.security.core; + +import java.io.Console; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Arrays; +import java.util.Locale; + +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.NameCallback; +import javax.security.auth.callback.PasswordCallback; +import javax.security.auth.callback.TextOutputCallback; +import javax.security.auth.callback.UnsupportedCallbackException; + +import org.argeo.ArgeoException; +import org.argeo.util.LocaleCallback; + +/** Callback handler to be used with a command line UI. */ +public class ConsoleCallbackHandler implements CallbackHandler { + + @Override + public void handle(Callback[] callbacks) throws IOException, + UnsupportedCallbackException { + Console console = System.console(); + if (console == null) + throw new ArgeoException("No console available"); + + PrintWriter writer = console.writer(); + for (int i = 0; i < callbacks.length; i++) { + if (callbacks[i] instanceof TextOutputCallback) { + TextOutputCallback callback = (TextOutputCallback) callbacks[i]; + writer.write(callback.getMessage()); + } else if (callbacks[i] instanceof NameCallback) { + NameCallback callback = (NameCallback) callbacks[i]; + writer.write(callback.getPrompt()); + if (callback.getDefaultName() != null) + writer.write(" (" + callback.getDefaultName() + ")"); + writer.write(" : "); + String answer = console.readLine(); + if (callback.getDefaultName() != null + && answer.trim().equals("")) + callback.setName(callback.getDefaultName()); + else + callback.setName(answer); + } else if (callbacks[i] instanceof PasswordCallback) { + PasswordCallback callback = (PasswordCallback) callbacks[i]; + writer.write(callback.getPrompt()); + char[] answer = console.readPassword(); + callback.setPassword(answer); + Arrays.fill(answer, ' '); + } else if (callbacks[i] instanceof LocaleCallback) { + LocaleCallback callback = (LocaleCallback) callbacks[i]; + writer.write(callback.getPrompt()); + writer.write("\n"); + for (int j = 0; j < callback.getAvailableLocales().size(); j++) { + Locale locale = callback.getAvailableLocales().get(j); + writer.print(j + " : " + locale.getDisplayName() + "\n"); + } + writer.write("(" + callback.getDefaultIndex() + ") : "); + String answer = console.readLine(); + if (answer.trim().equals("")) + callback.setSelectedIndex(callback.getDefaultIndex()); + else + callback.setSelectedIndex(new Integer(answer.trim())); + } + } + } + +} diff --git a/org.argeo.security.core/src/main/java/org/argeo/security/core/InternalAuthentication.java b/org.argeo.security.core/src/main/java/org/argeo/security/core/InternalAuthentication.java new file mode 100644 index 000000000..267ddd312 --- /dev/null +++ b/org.argeo.security.core/src/main/java/org/argeo/security/core/InternalAuthentication.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.core; + +import org.argeo.security.SystemAuthentication; +import org.springframework.security.GrantedAuthority; +import org.springframework.security.GrantedAuthorityImpl; +import org.springframework.security.adapters.PrincipalSpringSecurityUserToken; + +/** A token base on a system key used to request a system authentication. */ +public class InternalAuthentication extends PrincipalSpringSecurityUserToken + implements SystemAuthentication { + private static final long serialVersionUID = -6783376375615949315L; + /** 'admin' for consistency with JCR */ + public final static String DEFAULT_SYSTEM_USERNAME = "admin"; + public final static String DEFAULT_SYSTEM_ROLE = "ROLE_SYSTEM"; + public final static String SYSTEM_KEY_PROPERTY = "argeo.security.systemKey"; + public final static String SYSTEM_KEY_DEFAULT = "argeo"; + + public InternalAuthentication(String key, String systemUsername, + String systemRole) { + super( + key, + systemUsername, + key, + new GrantedAuthority[] { new GrantedAuthorityImpl(systemRole) }, + systemUsername); + } + + public InternalAuthentication(String key) { + this(key, DEFAULT_SYSTEM_USERNAME, DEFAULT_SYSTEM_ROLE); + } + +} diff --git a/org.argeo.security.core/src/main/java/org/argeo/security/core/KeyBasedSystemExecutionService.java b/org.argeo.security.core/src/main/java/org/argeo/security/core/KeyBasedSystemExecutionService.java new file mode 100644 index 000000000..6c85df1d1 --- /dev/null +++ b/org.argeo.security.core/src/main/java/org/argeo/security/core/KeyBasedSystemExecutionService.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.core; + +import java.util.concurrent.Callable; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.FutureTask; + +import org.argeo.ArgeoException; +import org.argeo.security.SystemExecutionService; + +/** + * Implementation of a {@link SystemExecutionService} using a key-based + * {@link InternalAuthentication} + */ +public class KeyBasedSystemExecutionService extends AbstractSystemExecution + implements SystemExecutionService { + public void execute(Runnable runnable) { + try { + wrapWithSystemAuthentication(Executors.callable(runnable)).call(); + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new ArgeoException( + "Exception when running system authenticated task", e); + } + } + + public Future submit(Callable task) { + FutureTask future = new FutureTask( + wrapWithSystemAuthentication(task)); + future.run(); + return future; + } + + protected Callable wrapWithSystemAuthentication( + final Callable runnable) { + return new Callable() { + + public T call() throws Exception { + authenticateAsSystem(); + try { + return runnable.call(); + } finally { +// deauthenticateAsSystem(); + } + } + }; + } +} diff --git a/org.argeo.security.core/src/main/java/org/argeo/security/core/MatchingAuthenticationProvider.java b/org.argeo.security.core/src/main/java/org/argeo/security/core/MatchingAuthenticationProvider.java new file mode 100644 index 000000000..0471151a2 --- /dev/null +++ b/org.argeo.security.core/src/main/java/org/argeo/security/core/MatchingAuthenticationProvider.java @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.core; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import org.springframework.core.io.Resource; +import org.springframework.security.AuthenticationException; +import org.springframework.security.BadCredentialsException; +import org.springframework.security.GrantedAuthority; +import org.springframework.security.GrantedAuthorityImpl; +import org.springframework.security.providers.UsernamePasswordAuthenticationToken; +import org.springframework.security.providers.dao.AbstractUserDetailsAuthenticationProvider; +import org.springframework.security.userdetails.User; +import org.springframework.security.userdetails.UserDetails; + +/** @deprecated */ +@Deprecated +public class MatchingAuthenticationProvider extends + AbstractUserDetailsAuthenticationProvider { + + private Resource mapping; + private Properties properties; + + private List defaultRoles = new ArrayList(); + + @Override + protected void doAfterPropertiesSet() throws Exception { + properties = new Properties(); + InputStream propIn = mapping.getInputStream(); + try { + properties.load(propIn); + } finally { + propIn.close(); + } + } + + @Override + protected void additionalAuthenticationChecks(UserDetails userDetails, + UsernamePasswordAuthenticationToken authentication) + throws AuthenticationException { + if (!userDetails.getPassword().equals(authentication.getCredentials())) + throw new BadCredentialsException( + "Invalid credentails provided by " + + authentication.getName()); + } + + @Override + protected UserDetails retrieveUser(String username, + UsernamePasswordAuthenticationToken authentication) + throws AuthenticationException { + String value = properties.getProperty(username); + if (value == null) + throw new BadCredentialsException("User " + username + + " is not registered"); + List grantedAuthorities = new ArrayList(); + for (String role : defaultRoles) + grantedAuthorities.add(new GrantedAuthorityImpl(role)); + return new User( + username, + value, + true, + true, + true, + true, + grantedAuthorities + .toArray(new GrantedAuthority[grantedAuthorities.size()])); + } + + public void setMapping(Resource mapping) { + this.mapping = mapping; + } + + public void setDefaultRoles(List defaultRoles) { + this.defaultRoles = defaultRoles; + } + +} diff --git a/org.argeo.security.core/src/main/java/org/argeo/security/core/OsAuthenticationProvider.java b/org.argeo.security.core/src/main/java/org/argeo/security/core/OsAuthenticationProvider.java new file mode 100644 index 000000000..0e29ecd59 --- /dev/null +++ b/org.argeo.security.core/src/main/java/org/argeo/security/core/OsAuthenticationProvider.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.core; + +import java.util.ArrayList; +import java.util.List; + +import org.argeo.security.OsAuthenticationToken; +import org.springframework.security.Authentication; +import org.springframework.security.AuthenticationException; +import org.springframework.security.GrantedAuthority; +import org.springframework.security.GrantedAuthorityImpl; +import org.springframework.security.providers.AuthenticationProvider; + +/** + * Validates an OS authentication. The id is that it will always be + * authenticated since we are always runnign within an OS, but the fact that the + * {@link Authentication} works properly depends on the proper OS login module + * having been called as well. TODO make it more configurable (base roles, is + * admin) + */ +public class OsAuthenticationProvider implements AuthenticationProvider { + final static String osUserRole = "ROLE_OS_USER"; + final static String userRole = "ROLE_USER"; + final static String adminRole = "ROLE_ADMIN"; + + final static Boolean isAdmin = true; + + public Authentication authenticate(Authentication authentication) + throws AuthenticationException { + return new OsAuthenticationToken(getBaseAuthorities()); + } + + public static GrantedAuthority[] getBaseAuthorities() { + List auths = new ArrayList(); + auths.add(new GrantedAuthorityImpl(osUserRole)); + auths.add(new GrantedAuthorityImpl(userRole)); + if (isAdmin) + auths.add(new GrantedAuthorityImpl(adminRole)); + return auths.toArray(new GrantedAuthority[auths.size()]); + } + + @SuppressWarnings("rawtypes") + public boolean supports(Class authentication) { + return OsAuthenticationToken.class.isAssignableFrom(authentication); + } + +} diff --git a/org.argeo.security.core/src/main/java/org/argeo/security/core/OsgiModuleLabel.java b/org.argeo.security.core/src/main/java/org/argeo/security/core/OsgiModuleLabel.java new file mode 100644 index 000000000..45c9e16b0 --- /dev/null +++ b/org.argeo.security.core/src/main/java/org/argeo/security/core/OsgiModuleLabel.java @@ -0,0 +1,41 @@ +package org.argeo.security.core; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; + +/** + * Logs the name and version of an OSGi bundle based on its + * {@link BundleContext}. + */ +public class OsgiModuleLabel { + private final static Log log = LogFactory.getLog(OsgiModuleLabel.class); + + private Bundle bundle; + + public OsgiModuleLabel() { + } + + /** Sets without logging. */ + public OsgiModuleLabel(Bundle bundle) { + this.bundle = bundle; + } + + /** + * Retrieved bundle from a bundle context and logs it. Typically to be set + * as a Spring bean. + */ + public void setBundleContext(BundleContext bundleContext) { + this.bundle = bundleContext.getBundle(); + log.info(msg()); + } + + public String msg() { + String name = bundle.getHeaders().get(Constants.BUNDLE_NAME).toString(); + String symbolicName = bundle.getSymbolicName(); + String version = bundle.getVersion().toString(); + return name + " v" + version + " (" + symbolicName + ")"; + } +} diff --git a/org.argeo.security.core/src/main/java/org/argeo/security/core/SimpleRoleRegistration.java b/org.argeo.security.core/src/main/java/org/argeo/security/core/SimpleRoleRegistration.java new file mode 100644 index 000000000..aa8a5f06e --- /dev/null +++ b/org.argeo.security.core/src/main/java/org/argeo/security/core/SimpleRoleRegistration.java @@ -0,0 +1,57 @@ +package org.argeo.security.core; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.security.UserAdminService; + +/** + * Register one or many roles via a user admin service. Does nothing if the role + * is already registered. + */ +public class SimpleRoleRegistration implements Runnable { + private final static Log log = LogFactory + .getLog(SimpleRoleRegistration.class); + + private String role; + private List roles = new ArrayList(); + private UserAdminService userAdminService; + + @Override + public void run() { + Set existingRoles = userAdminService.listEditableRoles(); + if (role != null && !existingRoles.contains(role)) + newRole(role); + for (String r : roles) { + if (!existingRoles.contains(r)) + newRole(r); + } + } + + protected void newRole(String r) { + userAdminService.newRole(r); + log.info("Added role " + r + " required by application."); + } + + public void register(UserAdminService userAdminService, Map properties) { + this.userAdminService = userAdminService; + run(); + } + + public void setRole(String role) { + this.role = role; + } + + public void setRoles(List roles) { + this.roles = roles; + } + + public void setUserAdminService(UserAdminService userAdminService) { + this.userAdminService = userAdminService; + } + +} diff --git a/org.argeo.security.core/src/main/java/org/argeo/security/crypto/AbstractKeyring.java b/org.argeo.security.core/src/main/java/org/argeo/security/crypto/AbstractKeyring.java new file mode 100644 index 000000000..daa1ebd12 --- /dev/null +++ b/org.argeo.security.core/src/main/java/org/argeo/security/crypto/AbstractKeyring.java @@ -0,0 +1,282 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.crypto; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.CharArrayWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.Writer; +import java.security.AccessController; +import java.security.MessageDigest; +import java.security.Provider; +import java.security.Security; +import java.util.Arrays; +import java.util.Iterator; + +import javax.crypto.SecretKey; +import javax.security.auth.Subject; +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.PasswordCallback; +import javax.security.auth.callback.TextOutputCallback; +import javax.security.auth.callback.UnsupportedCallbackException; +import javax.security.auth.login.LoginContext; +import javax.security.auth.login.LoginException; + +import org.argeo.ArgeoException; +import org.argeo.StreamUtils; +import org.argeo.util.security.Keyring; +import org.bouncycastle.jce.provider.BouncyCastleProvider; + +/** username / password based keyring. TODO internationalize */ +public abstract class AbstractKeyring implements Keyring, CryptoKeyring { + static { + Security.addProvider(new BouncyCastleProvider()); + } + + public final static String DEFAULT_KEYRING_LOGIN_CONTEXT = "KEYRING"; + + private String loginContextName = DEFAULT_KEYRING_LOGIN_CONTEXT; + private CallbackHandler defaultCallbackHandler; + + private String charset = "UTF-8"; + + /** + * Default provider is bouncy castle, in order to have consistent behaviour + * across implementations + */ + private String securityProviderName = "BC"; + + /** + * Whether the keyring has already been created in the past with a master + * password + */ + protected abstract Boolean isSetup(); + + /** + * Setup the keyring persistently, {@link #isSetup()} must return true + * afterwards + */ + protected abstract void setup(char[] password); + + /** Populates the key spec callback */ + protected abstract void handleKeySpecCallback(PBEKeySpecCallback pbeCallback); + + protected abstract void encrypt(String path, InputStream unencrypted); + + protected abstract InputStream decrypt(String path); + + /** Triggers lazy initialization */ + protected SecretKey getSecretKey() { + Subject subject = Subject.getSubject(AccessController.getContext()); + // we assume only one secrete key is available + Iterator iterator = subject.getPrivateCredentials( + SecretKey.class).iterator(); + if (!iterator.hasNext()) {// not initialized + CallbackHandler callbackHandler = new KeyringCallbackHandler(); + try { + LoginContext loginContext = new LoginContext(loginContextName, + subject, callbackHandler); + loginContext.login(); + // FIXME will login even if password is wrong + iterator = subject.getPrivateCredentials(SecretKey.class) + .iterator(); + return iterator.next(); + } catch (LoginException e) { + throw new ArgeoException("Keyring login failed", e); + } + + } else { + SecretKey secretKey = iterator.next(); + if (iterator.hasNext()) + throw new ArgeoException( + "More than one secret key in private credentials"); + return secretKey; + } + } + + public InputStream getAsStream(String path) { + return decrypt(path); + } + + public void set(String path, InputStream in) { + encrypt(path, in); + } + + public char[] getAsChars(String path) { + InputStream in = getAsStream(path); + CharArrayWriter writer = null; + Reader reader = null; + try { + writer = new CharArrayWriter(); + reader = new InputStreamReader(in, charset); + StreamUtils.copy(reader, writer); + return writer.toCharArray(); + } catch (IOException e) { + throw new ArgeoException("Cannot decrypt to char array", e); + } finally { + StreamUtils.closeQuietly(reader); + StreamUtils.closeQuietly(in); + StreamUtils.closeQuietly(writer); + } + } + + public void set(String path, char[] arr) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ByteArrayInputStream in = null; + Writer writer = null; + try { + writer = new OutputStreamWriter(out, charset); + writer.write(arr); + writer.flush(); + in = new ByteArrayInputStream(out.toByteArray()); + set(path, in); + } catch (IOException e) { + throw new ArgeoException("Cannot encrypt to char array", e); + } finally { + StreamUtils.closeQuietly(writer); + StreamUtils.closeQuietly(out); + StreamUtils.closeQuietly(in); + } + } + + protected Provider getSecurityProvider() { + return Security.getProvider(securityProviderName); + } + + public void setLoginContextName(String loginContextName) { + this.loginContextName = loginContextName; + } + + public void setDefaultCallbackHandler(CallbackHandler defaultCallbackHandler) { + this.defaultCallbackHandler = defaultCallbackHandler; + } + + public void setCharset(String charset) { + this.charset = charset; + } + + public void setSecurityProviderName(String securityProviderName) { + this.securityProviderName = securityProviderName; + } + + @Deprecated + protected static byte[] hash(char[] password, byte[] salt, + Integer iterationCount) { + ByteArrayOutputStream out = null; + OutputStreamWriter writer = null; + try { + out = new ByteArrayOutputStream(); + writer = new OutputStreamWriter(out, "UTF-8"); + writer.write(password); + MessageDigest pwDigest = MessageDigest.getInstance("SHA-256"); + pwDigest.reset(); + pwDigest.update(salt); + byte[] btPass = pwDigest.digest(out.toByteArray()); + for (int i = 0; i < iterationCount; i++) { + pwDigest.reset(); + btPass = pwDigest.digest(btPass); + } + return btPass; + } catch (Exception e) { + throw new ArgeoException("Cannot hash", e); + } finally { + StreamUtils.closeQuietly(out); + StreamUtils.closeQuietly(writer); + } + + } + + /** + * Convenience method using the underlying callback to ask for a password + * (typically used when the password is not saved in the keyring) + */ + protected char[] ask() { + PasswordCallback passwordCb = new PasswordCallback("Password", false); + Callback[] dialogCbs = new Callback[] { passwordCb }; + try { + defaultCallbackHandler.handle(dialogCbs); + char[] password = passwordCb.getPassword(); + return password; + } catch (Exception e) { + throw new ArgeoException("Cannot ask for a password", e); + } + + } + + class KeyringCallbackHandler implements CallbackHandler { + public void handle(Callback[] callbacks) throws IOException, + UnsupportedCallbackException { + // checks + if (callbacks.length != 2) + throw new IllegalArgumentException( + "Keyring required 2 and only 2 callbacks: {PasswordCallback,PBEKeySpecCallback}"); + if (!(callbacks[0] instanceof PasswordCallback)) + throw new UnsupportedCallbackException(callbacks[0]); + if (!(callbacks[1] instanceof PBEKeySpecCallback)) + throw new UnsupportedCallbackException(callbacks[0]); + + PasswordCallback passwordCb = (PasswordCallback) callbacks[0]; + PBEKeySpecCallback pbeCb = (PBEKeySpecCallback) callbacks[1]; + + if (isSetup()) { + Callback[] dialogCbs = new Callback[] { passwordCb }; + defaultCallbackHandler.handle(dialogCbs); + } else {// setup keyring + TextOutputCallback textCb1 = new TextOutputCallback( + TextOutputCallback.INFORMATION, + "Enter a master password which will protect your private data"); + TextOutputCallback textCb2 = new TextOutputCallback( + TextOutputCallback.INFORMATION, + "(for example your credentials to third-party services)"); + TextOutputCallback textCb3 = new TextOutputCallback( + TextOutputCallback.INFORMATION, + "Don't forget this password since the data cannot be read without it"); + PasswordCallback confirmPasswordCb = new PasswordCallback( + "Confirm password", false); + // first try + Callback[] dialogCbs = new Callback[] { textCb1, textCb2, + textCb3, passwordCb, confirmPasswordCb }; + defaultCallbackHandler.handle(dialogCbs); + + // if passwords different, retry (except if cancelled) + while (passwordCb.getPassword() != null + && !Arrays.equals(passwordCb.getPassword(), + confirmPasswordCb.getPassword())) { + TextOutputCallback textCb = new TextOutputCallback( + TextOutputCallback.ERROR, + "The passwords do not match"); + dialogCbs = new Callback[] { textCb, passwordCb, + confirmPasswordCb }; + defaultCallbackHandler.handle(dialogCbs); + } + + if (passwordCb.getPassword() != null) {// not cancelled + setup(passwordCb.getPassword()); + } + } + + if (passwordCb.getPassword() != null) + handleKeySpecCallback(pbeCb); + } + + } +} diff --git a/org.argeo.security.core/src/main/java/org/argeo/security/crypto/CryptoKeyring.java b/org.argeo.security.core/src/main/java/org/argeo/security/crypto/CryptoKeyring.java new file mode 100644 index 000000000..d25eccd22 --- /dev/null +++ b/org.argeo.security.core/src/main/java/org/argeo/security/crypto/CryptoKeyring.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.crypto; + +import org.argeo.util.security.Keyring; + +/** + * Advanced keyring based on cryptography that can easily be centralized and + * coordinated with {@link KeyringLoginModule} (since they ar ein the same + * package) + */ +public interface CryptoKeyring extends Keyring { + +} diff --git a/org.argeo.security.core/src/main/java/org/argeo/security/crypto/KeyringLoginModule.java b/org.argeo.security.core/src/main/java/org/argeo/security/crypto/KeyringLoginModule.java new file mode 100644 index 000000000..34b7d4015 --- /dev/null +++ b/org.argeo.security.core/src/main/java/org/argeo/security/crypto/KeyringLoginModule.java @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.crypto; + +import java.security.AccessController; +import java.util.Map; +import java.util.Set; + +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.SecretKeySpec; +import javax.security.auth.Subject; +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.PasswordCallback; +import javax.security.auth.login.LoginException; +import javax.security.auth.spi.LoginModule; + +/** Adds a secret key to the private credentials */ +public class KeyringLoginModule implements LoginModule { + private Subject subject; + private CallbackHandler callbackHandler; + private SecretKey secretKey; + + public void initialize(Subject subject, CallbackHandler callbackHandler, + Map sharedState, Map options) { + this.subject = subject; + if (subject == null) { + subject = Subject.getSubject(AccessController.getContext()); + } + this.callbackHandler = callbackHandler; + } + + public boolean login() throws LoginException { + Set pbes = subject.getPrivateCredentials(SecretKey.class); + if (pbes.size() > 0) + return true; + PasswordCallback pc = new PasswordCallback("Master password", false); + PBEKeySpecCallback pbeCb = new PBEKeySpecCallback(); + Callback[] callbacks = { pc, pbeCb }; + try { + callbackHandler.handle(callbacks); + char[] password = pc.getPassword(); + + SecretKeyFactory keyFac = SecretKeyFactory.getInstance(pbeCb + .getSecretKeyFactory()); + PBEKeySpec keySpec; + if (pbeCb.getKeyLength() != null) + keySpec = new PBEKeySpec(password, pbeCb.getSalt(), + pbeCb.getIterationCount(), pbeCb.getKeyLength()); + else + keySpec = new PBEKeySpec(password, pbeCb.getSalt(), + pbeCb.getIterationCount()); + + String secKeyEncryption = pbeCb.getSecretKeyEncryption(); + if (secKeyEncryption != null) { + SecretKey tmp = keyFac.generateSecret(keySpec); + secretKey = new SecretKeySpec(tmp.getEncoded(), + secKeyEncryption); + } else { + secretKey = keyFac.generateSecret(keySpec); + } + } catch (Exception e) { + LoginException le = new LoginException("Cannot login keyring"); + le.initCause(e); + throw le; + } + return true; + } + + public boolean commit() throws LoginException { + if (secretKey != null) + subject.getPrivateCredentials().add(secretKey); + return true; + } + + public boolean abort() throws LoginException { + return true; + } + + public boolean logout() throws LoginException { + Set pbes = subject + .getPrivateCredentials(PasswordBasedEncryption.class); + pbes.clear(); + return true; + } + +} diff --git a/org.argeo.security.core/src/main/java/org/argeo/security/crypto/PBEKeySpecCallback.java b/org.argeo.security.core/src/main/java/org/argeo/security/crypto/PBEKeySpecCallback.java new file mode 100644 index 000000000..e96436664 --- /dev/null +++ b/org.argeo.security.core/src/main/java/org/argeo/security/crypto/PBEKeySpecCallback.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.crypto; + +import javax.crypto.spec.PBEKeySpec; +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.PasswordCallback; + +/** + * All information required to set up a {@link PBEKeySpec} bar the password + * itself (use a {@link PasswordCallback}) + */ +public class PBEKeySpecCallback implements Callback { + private String secretKeyFactory; + private byte[] salt; + private Integer iterationCount; + /** Can be null for some algorithms */ + private Integer keyLength; + /** Can be null, will trigger secret key encryption if not */ + private String secretKeyEncryption; + + private String encryptedPasswordHashCipher; + private byte[] encryptedPasswordHash; + + public void set(String secretKeyFactory, byte[] salt, + Integer iterationCount, Integer keyLength, + String secretKeyEncryption) { + this.secretKeyFactory = secretKeyFactory; + this.salt = salt; + this.iterationCount = iterationCount; + this.keyLength = keyLength; + this.secretKeyEncryption = secretKeyEncryption; +// this.encryptedPasswordHashCipher = encryptedPasswordHashCipher; +// this.encryptedPasswordHash = encryptedPasswordHash; + } + + public String getSecretKeyFactory() { + return secretKeyFactory; + } + + public byte[] getSalt() { + return salt; + } + + public Integer getIterationCount() { + return iterationCount; + } + + public Integer getKeyLength() { + return keyLength; + } + + public String getSecretKeyEncryption() { + return secretKeyEncryption; + } + + public String getEncryptedPasswordHashCipher() { + return encryptedPasswordHashCipher; + } + + public byte[] getEncryptedPasswordHash() { + return encryptedPasswordHash; + } + +} diff --git a/org.argeo.security.core/src/main/java/org/argeo/security/crypto/PasswordBasedEncryption.java b/org.argeo.security.core/src/main/java/org/argeo/security/crypto/PasswordBasedEncryption.java new file mode 100644 index 000000000..aec25ac17 --- /dev/null +++ b/org.argeo.security.core/src/main/java/org/argeo/security/crypto/PasswordBasedEncryption.java @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.crypto; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.security.GeneralSecurityException; +import java.security.InvalidKeyException; +import java.security.Key; +import java.security.Security; + +import javax.crypto.Cipher; +import javax.crypto.CipherInputStream; +import javax.crypto.CipherOutputStream; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.SecretKeySpec; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; +import org.argeo.StreamUtils; +import org.bouncycastle.jce.provider.BouncyCastleProvider; + +/** Simple password based encryption / decryption */ +public class PasswordBasedEncryption { + private final static Log log = LogFactory + .getLog(PasswordBasedEncryption.class); + + static { + Security.addProvider(new BouncyCastleProvider()); + } + + public final static Integer DEFAULT_ITERATION_COUNT = 1024; + /** Stronger with 256, but causes problem with Oracle JVM */ + public final static Integer DEFAULT_SECRETE_KEY_LENGTH = 256; + public final static Integer DEFAULT_SECRETE_KEY_LENGTH_RESTRICTED = 128; + public final static String DEFAULT_SECRETE_KEY_FACTORY = "PBKDF2WithHmacSHA1"; + public final static String DEFAULT_SECRETE_KEY_ENCRYPTION = "AES"; + public final static String DEFAULT_CIPHER_NAME = "AES/CBC/PKCS5Padding"; + public final static String DEFAULT_CHARSET = "UTF-8"; + + private Integer iterationCount = DEFAULT_ITERATION_COUNT; + private Integer secreteKeyLength = DEFAULT_SECRETE_KEY_LENGTH; + private String secreteKeyFactoryName = DEFAULT_SECRETE_KEY_FACTORY; + private String secreteKeyEncryption = DEFAULT_SECRETE_KEY_ENCRYPTION; + private String cipherName = DEFAULT_CIPHER_NAME; + + private static byte[] DEFAULT_SALT_8 = { (byte) 0xA9, (byte) 0x9B, + (byte) 0xC8, (byte) 0x32, (byte) 0x56, (byte) 0x35, (byte) 0xE3, + (byte) 0x03 }; + private static byte[] DEFAULT_IV_16 = { (byte) 0xA9, (byte) 0x9B, + (byte) 0xC8, (byte) 0x32, (byte) 0x56, (byte) 0x35, (byte) 0xE3, + (byte) 0x03, (byte) 0xA9, (byte) 0x9B, (byte) 0xC8, (byte) 0x32, + (byte) 0x56, (byte) 0x35, (byte) 0xE3, (byte) 0x03 }; + + private Key key; + private Cipher ecipher; + private Cipher dcipher; + + /** + * Default provider is bouncy castle, in order to have consistent behaviour + * across implementations + */ + private String securityProviderName = "BC"; + + /** + * This is up to the caller to clear the passed array. Neither copy of nor + * reference to the passed array is kept + */ + public PasswordBasedEncryption(char[] password) { + this(password, DEFAULT_SALT_8, DEFAULT_IV_16); + } + + /** + * This is up to the caller to clear the passed array. Neither copies of nor + * references to the passed arrays are kept + */ + public PasswordBasedEncryption(char[] password, byte[] passwordSalt, + byte[] initializationVector) { + try { + initKeyAndCiphers(password, passwordSalt, initializationVector); + } catch (InvalidKeyException e) { + Integer previousSecreteKeyLength = secreteKeyLength; + secreteKeyLength = DEFAULT_SECRETE_KEY_LENGTH_RESTRICTED; + log.warn("'" + e.getMessage() + "', will use " + secreteKeyLength + + " secrete key length instead of " + + previousSecreteKeyLength); + try { + initKeyAndCiphers(password, passwordSalt, initializationVector); + } catch (Exception e1) { + throw new ArgeoException( + "Cannot get secret key (with restricted length)", e1); + } + } catch (Exception e) { + throw new ArgeoException("Cannot get secret key", e); + } + } + + protected void initKeyAndCiphers(char[] password, byte[] passwordSalt, + byte[] initializationVector) throws GeneralSecurityException { + byte[] salt = new byte[8]; + System.arraycopy(passwordSalt, 0, salt, 0, salt.length); + // for (int i = 0; i < password.length && i < salt.length; i++) + // salt[i] = (byte) password[i]; + byte[] iv = new byte[16]; + System.arraycopy(initializationVector, 0, iv, 0, iv.length); + + SecretKeyFactory keyFac = SecretKeyFactory + .getInstance(getSecretKeyFactoryName()); + PBEKeySpec keySpec = new PBEKeySpec(password, salt, + getIterationCount(), getKeyLength()); + String secKeyEncryption = getSecretKeyEncryption(); + if (secKeyEncryption != null) { + SecretKey tmp = keyFac.generateSecret(keySpec); + key = new SecretKeySpec(tmp.getEncoded(), getSecretKeyEncryption()); + } else { + key = keyFac.generateSecret(keySpec); + } + ecipher = Cipher.getInstance(getCipherName(), securityProviderName); + ecipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv)); + dcipher = Cipher.getInstance(getCipherName()); + dcipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv)); + } + + public void encrypt(InputStream decryptedIn, OutputStream encryptedOut) + throws IOException { + try { + CipherOutputStream out = new CipherOutputStream(encryptedOut, + ecipher); + StreamUtils.copy(decryptedIn, out); + StreamUtils.closeQuietly(out); + } catch (IOException e) { + throw e; + } catch (Exception e) { + throw new ArgeoException("Cannot encrypt", e); + } finally { + StreamUtils.closeQuietly(decryptedIn); + } + } + + public void decrypt(InputStream encryptedIn, OutputStream decryptedOut) + throws IOException { + try { + CipherInputStream decryptedIn = new CipherInputStream(encryptedIn, + dcipher); + StreamUtils.copy(decryptedIn, decryptedOut); + } catch (IOException e) { + throw e; + } catch (Exception e) { + throw new ArgeoException("Cannot decrypt", e); + } finally { + StreamUtils.closeQuietly(encryptedIn); + } + } + + public byte[] encryptString(String str) { + ByteArrayOutputStream out = null; + ByteArrayInputStream in = null; + try { + out = new ByteArrayOutputStream(); + in = new ByteArrayInputStream(str.getBytes(DEFAULT_CHARSET)); + encrypt(in, out); + return out.toByteArray(); + } catch (Exception e) { + throw new ArgeoException("Cannot encrypt", e); + } finally { + StreamUtils.closeQuietly(out); + } + } + + /** Closes the input stream */ + public String decryptAsString(InputStream in) { + ByteArrayOutputStream out = null; + try { + out = new ByteArrayOutputStream(); + decrypt(in, out); + return new String(out.toByteArray(), DEFAULT_CHARSET); + } catch (Exception e) { + throw new ArgeoException("Cannot decrypt", e); + } finally { + StreamUtils.closeQuietly(out); + } + } + + protected Key getKey() { + return key; + } + + protected Cipher getEcipher() { + return ecipher; + } + + protected Cipher getDcipher() { + return dcipher; + } + + protected Integer getIterationCount() { + return iterationCount; + } + + protected Integer getKeyLength() { + return secreteKeyLength; + } + + protected String getSecretKeyFactoryName() { + return secreteKeyFactoryName; + } + + protected String getSecretKeyEncryption() { + return secreteKeyEncryption; + } + + protected String getCipherName() { + return cipherName; + } + + public void setIterationCount(Integer iterationCount) { + this.iterationCount = iterationCount; + } + + public void setSecreteKeyLength(Integer keyLength) { + this.secreteKeyLength = keyLength; + } + + public void setSecreteKeyFactoryName(String secreteKeyFactoryName) { + this.secreteKeyFactoryName = secreteKeyFactoryName; + } + + public void setSecreteKeyEncryption(String secreteKeyEncryption) { + this.secreteKeyEncryption = secreteKeyEncryption; + } + + public void setCipherName(String cipherName) { + this.cipherName = cipherName; + } + + public void setSecurityProviderName(String securityProviderName) { + this.securityProviderName = securityProviderName; + } +} diff --git a/org.argeo.security.core/src/main/java/org/argeo/security/jcr/JcrKeyring.java b/org.argeo.security.core/src/main/java/org/argeo/security/jcr/JcrKeyring.java new file mode 100644 index 000000000..1b9f24426 --- /dev/null +++ b/org.argeo.security.core/src/main/java/org/argeo/security/jcr/JcrKeyring.java @@ -0,0 +1,294 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.jcr; + +import java.io.ByteArrayInputStream; +import java.io.CharArrayReader; +import java.io.InputStream; +import java.io.Reader; +import java.security.SecureRandom; + +import javax.crypto.Cipher; +import javax.crypto.CipherInputStream; +import javax.crypto.SecretKey; +import javax.crypto.spec.IvParameterSpec; +import javax.jcr.Binary; +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.apache.commons.io.IOUtils; +import org.argeo.ArgeoException; +import org.argeo.jcr.ArgeoNames; +import org.argeo.jcr.ArgeoTypes; +import org.argeo.jcr.JcrUtils; +import org.argeo.jcr.UserJcrUtils; +import org.argeo.security.crypto.AbstractKeyring; +import org.argeo.security.crypto.PBEKeySpecCallback; + +/** JCR based implementation of a keyring */ +public class JcrKeyring extends AbstractKeyring implements ArgeoNames { + /** + * Stronger with 256, but causes problem with Oracle JVM, force 128 in this + * case + */ + public final static Long DEFAULT_SECRETE_KEY_LENGTH = 256l; + public final static String DEFAULT_SECRETE_KEY_FACTORY = "PBKDF2WithHmacSHA1"; + public final static String DEFAULT_SECRETE_KEY_ENCRYPTION = "AES"; + public final static String DEFAULT_CIPHER_NAME = "AES/CBC/PKCS5Padding"; + + private Integer iterationCountFactor = 200; + private Long secreteKeyLength = DEFAULT_SECRETE_KEY_LENGTH; + private String secreteKeyFactoryName = DEFAULT_SECRETE_KEY_FACTORY; + private String secreteKeyEncryption = DEFAULT_SECRETE_KEY_ENCRYPTION; + private String cipherName = DEFAULT_CIPHER_NAME; + + private Session session; + + /** + * When setup is called the session has not yet been saved and we don't want + * to save it since there maybe other data which would be inconsistent. So + * we keep a reference to this node which will then be used (an reset to + * null) when handling the PBE callback. We keep one per thread in case + * multiple users are accessing the same instance of a keyring. + */ + private ThreadLocal notYetSavedKeyring = new ThreadLocal() { + + @Override + protected Node initialValue() { + return null; + } + }; + + @Override + protected Boolean isSetup() { + try { + if (notYetSavedKeyring.get() != null) + return true; + + Node userHome = UserJcrUtils.getUserHome(session); + return userHome.hasNode(ARGEO_KEYRING); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot check whether keyring is setup", e); + } + } + + @Override + protected void setup(char[] password) { + Binary binary = null; + InputStream in = null; + try { + Node userHome = UserJcrUtils.getUserHome(session); + if (userHome.hasNode(ARGEO_KEYRING)) + throw new ArgeoException("Keyring already setup"); + Node keyring = userHome.addNode(ARGEO_KEYRING); + keyring.addMixin(ArgeoTypes.ARGEO_PBE_SPEC); + + // deterministic salt and iteration count based on username + String username = session.getUserID(); + byte[] salt = new byte[8]; + byte[] usernameBytes = username.getBytes(); + for (int i = 0; i < salt.length; i++) { + if (i < usernameBytes.length) + salt[i] = usernameBytes[i]; + else + salt[i] = 0; + } + in = new ByteArrayInputStream(salt); + binary = session.getValueFactory().createBinary(in); + keyring.setProperty(ARGEO_SALT, binary); + + Integer iterationCount = username.length() * iterationCountFactor; + keyring.setProperty(ARGEO_ITERATION_COUNT, iterationCount); + + // default algo + // TODO check if algo and key length are available, use DES if not + keyring.setProperty(ARGEO_SECRET_KEY_FACTORY, secreteKeyFactoryName); + keyring.setProperty(ARGEO_KEY_LENGTH, secreteKeyLength); + keyring.setProperty(ARGEO_SECRET_KEY_ENCRYPTION, + secreteKeyEncryption); + keyring.setProperty(ARGEO_CIPHER, cipherName); + + // encrypted password hash + // IOUtils.closeQuietly(in); + // JcrUtils.closeQuietly(binary); + // byte[] btPass = hash(password, salt, iterationCount); + // in = new ByteArrayInputStream(btPass); + // binary = session.getValueFactory().createBinary(in); + // keyring.setProperty(ARGEO_PASSWORD, binary); + + notYetSavedKeyring.set(keyring); + } catch (Exception e) { + throw new ArgeoException("Cannot setup keyring", e); + } finally { + JcrUtils.closeQuietly(binary); + IOUtils.closeQuietly(in); + // JcrUtils.discardQuietly(session); + } + } + + @Override + protected void handleKeySpecCallback(PBEKeySpecCallback pbeCallback) { + try { + Node userHome = UserJcrUtils.getUserHome(session); + Node keyring; + if (userHome.hasNode(ARGEO_KEYRING)) + keyring = userHome.getNode(ARGEO_KEYRING); + else if (notYetSavedKeyring.get() != null) + keyring = notYetSavedKeyring.get(); + else + throw new ArgeoException("Keyring not setup"); + + pbeCallback.set(keyring.getProperty(ARGEO_SECRET_KEY_FACTORY) + .getString(), JcrUtils.getBinaryAsBytes(keyring + .getProperty(ARGEO_SALT)), + (int) keyring.getProperty(ARGEO_ITERATION_COUNT).getLong(), + (int) keyring.getProperty(ARGEO_KEY_LENGTH).getLong(), + keyring.getProperty(ARGEO_SECRET_KEY_ENCRYPTION) + .getString()); + + if (notYetSavedKeyring.get() != null) + notYetSavedKeyring.remove(); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot handle key spec callback", e); + } + } + + /** The parent node must already exist at this path. */ + @Override + protected synchronized void encrypt(String path, InputStream unencrypted) { + // should be called first for lazy initialization + SecretKey secretKey = getSecretKey(); + + Binary binary = null; + InputStream in = null; + try { + Cipher cipher = createCipher(); + Node node; + if (!session.nodeExists(path)) { + String parentPath = JcrUtils.parentPath(path); + if (!session.nodeExists(parentPath)) + throw new ArgeoException("No parent node of " + path); + Node parentNode = session.getNode(parentPath); + node = parentNode.addNode(JcrUtils.nodeNameFromPath(path)); + } else { + node = session.getNode(path); + } + node.addMixin(ArgeoTypes.ARGEO_ENCRYPTED); + SecureRandom random = new SecureRandom(); + byte[] iv = new byte[16]; + random.nextBytes(iv); + cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(iv)); + JcrUtils.setBinaryAsBytes(node, ARGEO_IV, iv); + + in = new CipherInputStream(unencrypted, cipher); + binary = session.getValueFactory().createBinary(in); + node.setProperty(Property.JCR_DATA, binary); + session.save(); + } catch (Exception e) { + throw new ArgeoException("Cannot encrypt", e); + } finally { + IOUtils.closeQuietly(unencrypted); + IOUtils.closeQuietly(in); + JcrUtils.closeQuietly(binary); + } + } + + @Override + protected synchronized InputStream decrypt(String path) { + Binary binary = null; + InputStream encrypted = null; + Reader reader = null; + try { + if (!session.nodeExists(path)) { + char[] password = ask(); + reader = new CharArrayReader(password); + return new ByteArrayInputStream(IOUtils.toByteArray(reader)); + } else { + // should be called first for lazy initialisation + SecretKey secretKey = getSecretKey(); + + Cipher cipher = createCipher(); + + Node node = session.getNode(path); + if (node.hasProperty(ARGEO_IV)) { + byte[] iv = JcrUtils.getBinaryAsBytes(node + .getProperty(ARGEO_IV)); + cipher.init(Cipher.DECRYPT_MODE, secretKey, + new IvParameterSpec(iv)); + } else { + cipher.init(Cipher.DECRYPT_MODE, secretKey); + } + + binary = node.getProperty(Property.JCR_DATA).getBinary(); + encrypted = binary.getStream(); + return new CipherInputStream(encrypted, cipher); + } + } catch (Exception e) { + throw new ArgeoException("Cannot decrypt", e); + } finally { + IOUtils.closeQuietly(encrypted); + IOUtils.closeQuietly(reader); + JcrUtils.closeQuietly(binary); + } + } + + protected Cipher createCipher() { + try { + Node userHome = UserJcrUtils.getUserHome(session); + if (!userHome.hasNode(ARGEO_KEYRING)) + throw new ArgeoException("Keyring not setup"); + Node keyring = userHome.getNode(ARGEO_KEYRING); + Cipher cipher = Cipher.getInstance(keyring + .getProperty(ARGEO_CIPHER).getString(), + getSecurityProvider()); + return cipher; + } catch (Exception e) { + throw new ArgeoException("Cannot get cipher", e); + } + } + + public synchronized void changePassword(char[] oldPassword, + char[] newPassword) { + // TODO decrypt with old pw / encrypt with new pw all argeo:encrypted + } + + public synchronized void setSession(Session session) { + this.session = session; + } + + public void setIterationCountFactor(Integer iterationCountFactor) { + this.iterationCountFactor = iterationCountFactor; + } + + public void setSecreteKeyLength(Long keyLength) { + this.secreteKeyLength = keyLength; + } + + public void setSecreteKeyFactoryName(String secreteKeyFactoryName) { + this.secreteKeyFactoryName = secreteKeyFactoryName; + } + + public void setSecreteKeyEncryption(String secreteKeyEncryption) { + this.secreteKeyEncryption = secreteKeyEncryption; + } + + public void setCipherName(String cipherName) { + this.cipherName = cipherName; + } + +} \ No newline at end of file diff --git a/org.argeo.security.core/src/main/java/org/argeo/security/jcr/JcrSecurityModel.java b/org.argeo.security.core/src/main/java/org/argeo/security/jcr/JcrSecurityModel.java new file mode 100644 index 000000000..e9ab89c2a --- /dev/null +++ b/org.argeo.security.core/src/main/java/org/argeo/security/jcr/JcrSecurityModel.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.jcr; + +import java.util.List; + +import javax.jcr.Node; +import javax.jcr.Session; + +/** + * Manages data expected by the Argeo security model, such as user home and + * profile. + */ +public interface JcrSecurityModel { + /** + * To be called before user details are loaded. Make sure than any logged in + * user has a home directory with full access and a profile with information + * about him (read access) + * + * @return the user profile (whose parent is the user home), never null + */ + public Node sync(Session session, String username, List roles); +} diff --git a/org.argeo.security.core/src/main/java/org/argeo/security/jcr/JcrUserDetails.java b/org.argeo.security.core/src/main/java/org/argeo/security/jcr/JcrUserDetails.java new file mode 100644 index 000000000..2f7b97b78 --- /dev/null +++ b/org.argeo.security.core/src/main/java/org/argeo/security/jcr/JcrUserDetails.java @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.jcr; + +import java.util.ArrayList; +import java.util.List; + +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.argeo.jcr.ArgeoNames; +import org.argeo.jcr.UserJcrUtils; +import org.springframework.security.BadCredentialsException; +import org.springframework.security.DisabledException; +import org.springframework.security.GrantedAuthority; +import org.springframework.security.GrantedAuthorityImpl; +import org.springframework.security.LockedException; +import org.springframework.security.userdetails.User; + +/** User details based on a user profile node. */ +public class JcrUserDetails extends User implements ArgeoNames { + private static final long serialVersionUID = -8142764995842559646L; + private final String homePath; + private final String securityWorkspace; + + /** Human readable user name */ + private String displayName; + + protected JcrUserDetails(String securityWorkspace, String homePath, + String username, String password, boolean enabled, + boolean accountNonExpired, boolean credentialsNonExpired, + boolean accountNonLocked, GrantedAuthority[] authorities) + throws IllegalArgumentException { + super(username, password, enabled, accountNonExpired, + credentialsNonExpired, accountNonLocked, authorities); + this.homePath = homePath; + this.securityWorkspace = securityWorkspace; + } + + public JcrUserDetails(Node userProfile, String password, + GrantedAuthority[] authorities) throws RepositoryException { + super( + userProfile.getProperty(ARGEO_USER_ID).getString(), + password, + userProfile.getProperty(ARGEO_ENABLED).getBoolean(), + userProfile.getProperty(ARGEO_ACCOUNT_NON_EXPIRED).getBoolean(), + userProfile.getProperty(ARGEO_CREDENTIALS_NON_EXPIRED) + .getBoolean(), userProfile.getProperty( + ARGEO_ACCOUNT_NON_LOCKED).getBoolean(), authorities); + // human readable name + if (userProfile.hasProperty(Property.JCR_TITLE)) { + displayName = userProfile.getProperty(Property.JCR_TITLE) + .getString(); + if (displayName.trim().equals("")) + displayName = null; + } + if (displayName == null) + displayName = userProfile.getProperty(ARGEO_USER_ID).getString(); + // home is defined as the parent of the profile + homePath = userProfile.getParent().getPath(); + securityWorkspace = userProfile.getSession().getWorkspace().getName(); + } + + /** + * Convenience constructor + * + * @param session + * the security session + * @param username + * the username + * @param password + * the password, can be null + * @param authorities + * the granted authorities + */ + public JcrUserDetails(Session session, String username, String password, + GrantedAuthority[] authorities) throws RepositoryException { + this(UserJcrUtils.getUserProfile(session, username), + password != null ? password : "", authorities); + } + + /** + * Check the account status in JCR, throwing the exceptions expected by + * Spring security if needed. + */ + public static void checkAccountStatus(Node userProfile) { + try { + if (!userProfile.getProperty(ARGEO_ENABLED).getBoolean()) + throw new DisabledException(userProfile.getPath() + + " is disabled"); + if (!userProfile.getProperty(ARGEO_ACCOUNT_NON_LOCKED).getBoolean()) + throw new LockedException(userProfile.getPath() + " is locked"); + } catch (RepositoryException e) { + throw new BadCredentialsException("Cannot check account status", e); + } + } + + /** Clone immutable with new roles */ + public JcrUserDetails cloneWithNewRoles(List roles) { + List authorities = new ArrayList(); + for (String role : roles) { + authorities.add(new GrantedAuthorityImpl(role)); + } + return new JcrUserDetails(securityWorkspace, homePath, getUsername(), + getPassword(), isEnabled(), isAccountNonExpired(), + isAccountNonExpired(), isAccountNonLocked(), + authorities.toArray(new GrantedAuthority[authorities.size()])); + } + + /** Clone immutable with new password */ + public JcrUserDetails cloneWithNewPassword(String password) { + return new JcrUserDetails(securityWorkspace, homePath, getUsername(), + password, isEnabled(), isAccountNonExpired(), + isAccountNonExpired(), isAccountNonLocked(), getAuthorities()); + } + + public String getHomePath() { + return homePath; + } + + /** Not yet API */ + public String getSecurityWorkspace() { + return securityWorkspace; + } + + /** The human readable name of this user */ + public String getDisplayName() { + return displayName; + } + + @Override + public String toString() { + return getDisplayName(); + } + +} diff --git a/org.argeo.security.core/src/main/java/org/argeo/security/jcr/OsJcrAuthenticationProvider.java b/org.argeo.security.core/src/main/java/org/argeo/security/jcr/OsJcrAuthenticationProvider.java new file mode 100644 index 000000000..aa95e322d --- /dev/null +++ b/org.argeo.security.core/src/main/java/org/argeo/security/jcr/OsJcrAuthenticationProvider.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.jcr; + +import javax.jcr.Node; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.argeo.ArgeoException; +import org.argeo.jcr.JcrUtils; +import org.argeo.security.OsAuthenticationToken; +import org.argeo.security.SecurityUtils; +import org.argeo.security.core.OsAuthenticationProvider; +import org.springframework.security.Authentication; +import org.springframework.security.AuthenticationException; +import org.springframework.security.BadCredentialsException; +import org.springframework.security.GrantedAuthority; +import org.springframework.security.providers.UsernamePasswordAuthenticationToken; +import org.springframework.security.userdetails.UserDetails; + +/** Relies on OS to authenticate and additionally setup JCR */ +public class OsJcrAuthenticationProvider extends OsAuthenticationProvider { + private Repository repository; + private Session nodeSession; + + private UserDetails userDetails; + private JcrSecurityModel jcrSecurityModel = new SimpleJcrSecurityModel(); + + private final static String JVM_OSUSER = System.getProperty("user.name"); + + public void init() { + try { + nodeSession = repository.login(); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot initialize", e); + } + } + + public void destroy() { + JcrUtils.logoutQuietly(nodeSession); + } + + public Authentication authenticate(Authentication authentication) + throws AuthenticationException { + if (authentication instanceof UsernamePasswordAuthenticationToken) { + // deal with remote access to internal server + // FIXME very primitive and unsecure at this sSession adminSession + // =tage + // consider using the keyring for username / password authentication + // or certificate + UsernamePasswordAuthenticationToken upat = (UsernamePasswordAuthenticationToken) authentication; + if (!upat.getPrincipal().toString().equals(JVM_OSUSER)) + throw new BadCredentialsException("Wrong credentials"); + UsernamePasswordAuthenticationToken authen = new UsernamePasswordAuthenticationToken( + authentication.getPrincipal(), + authentication.getCredentials(), getBaseAuthorities()); + authen.setDetails(userDetails); + return authen; + } else if (authentication instanceof OsAuthenticationToken) { + OsAuthenticationToken authen = (OsAuthenticationToken) super + .authenticate(authentication); + try { + // WARNING: at this stage we assume that the java properties + // will have the same value + GrantedAuthority[] authorities = getBaseAuthorities(); + String username = JVM_OSUSER; + Node userProfile = jcrSecurityModel.sync(nodeSession, username, + SecurityUtils.authoritiesToStringList(authorities)); + JcrUserDetails.checkAccountStatus(userProfile); + + userDetails = new JcrUserDetails(userProfile, authen + .getCredentials().toString(), authorities); + authen.setDetails(userDetails); + return authen; + } catch (RepositoryException e) { + JcrUtils.discardQuietly(nodeSession); + throw new ArgeoException( + "Unexpected exception when synchronizing OS and JCR security ", + e); + } + } else { + throw new ArgeoException("Unsupported authentication " + + authentication.getClass()); + } + } + + public void setRepository(Repository repository) { + this.repository = repository; + } + + public void setJcrSecurityModel(JcrSecurityModel jcrSecurityModel) { + this.jcrSecurityModel = jcrSecurityModel; + } + + @SuppressWarnings("rawtypes") + public boolean supports(Class authentication) { + return OsAuthenticationToken.class.isAssignableFrom(authentication) + || UsernamePasswordAuthenticationToken.class + .isAssignableFrom(authentication); + } +} \ No newline at end of file diff --git a/org.argeo.security.core/src/main/java/org/argeo/security/jcr/OsJcrUserAdminService.java b/org.argeo.security.core/src/main/java/org/argeo/security/jcr/OsJcrUserAdminService.java new file mode 100644 index 000000000..c25bdb865 --- /dev/null +++ b/org.argeo.security.core/src/main/java/org/argeo/security/jcr/OsJcrUserAdminService.java @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.jcr; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.jcr.Node; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.argeo.ArgeoException; +import org.argeo.jcr.JcrUtils; +import org.argeo.jcr.UserJcrUtils; +import org.argeo.security.UserAdminService; +import org.springframework.dao.DataAccessException; +import org.springframework.security.userdetails.User; +import org.springframework.security.userdetails.UserDetails; +import org.springframework.security.userdetails.UsernameNotFoundException; + +/** + * Dummy user service to be used when running as a single OS user (typically + * desktop). TODO integrate with JCR user / groups + */ +public class OsJcrUserAdminService implements UserAdminService { + private Repository repository; + + /** In memory roles provided by applications. */ + private List roles = new ArrayList(); + + // private Session adminSession; + + public void init() { + // try { + // adminSession = repository.login(); + // } catch (RepositoryException e) { + // throw new ArgeoException("Cannot initialize", e); + // } + } + + public void destroy() { + // JcrUtils.logoutQuietly(adminSession); + } + + /** Unsupported */ + public void createUser(UserDetails user) { + throw new UnsupportedOperationException(); + } + + /** Does nothing */ + public void updateUser(UserDetails user) { + + } + + /** Unsupported */ + public void deleteUser(String username) { + throw new UnsupportedOperationException(); + } + + /** Unsupported */ + public void changePassword(String oldPassword, String newPassword) { + throw new UnsupportedOperationException(); + } + + public boolean userExists(String username) { + if (getSPropertyUsername().equals(username)) + return true; + else + return false; + } + + public UserDetails loadUserByUsername(String username) + throws UsernameNotFoundException, DataAccessException { + if (getSPropertyUsername().equals(username)) { + UserDetails userDetails; + if (repository != null) { + Session adminSession = null; + try { + adminSession = repository.login(); + Node userProfile = UserJcrUtils.getUserProfile( + adminSession, username); + userDetails = new JcrUserDetails(userProfile, "", + OsJcrAuthenticationProvider.getBaseAuthorities()); + } catch (RepositoryException e) { + throw new ArgeoException( + "Cannot retrieve user profile for " + username, e); + } finally { + JcrUtils.logoutQuietly(adminSession); + } + } else { + userDetails = new User(username, "", true, true, true, true, + OsJcrAuthenticationProvider.getBaseAuthorities()); + } + return userDetails; + } else { + throw new UnsupportedOperationException(); + } + } + + protected final String getSPropertyUsername() { + return System.getProperty("user.name"); + } + + public Set listUsers() { + Set set = new HashSet(); + set.add(getSPropertyUsername()); + return set; + } + + public Set listUsersInRole(String role) { + Set set = new HashSet(); + set.add(getSPropertyUsername()); + return set; + } + + /** Does nothing */ + public void synchronize() { + } + + /** Unsupported */ + public void newRole(String role) { + roles.add(role); + } + + public Set listEditableRoles() { + return new HashSet(roles); + } + + /** Unsupported */ + public void deleteRole(String role) { + roles.remove(role); + } + + public void setRepository(Repository repository) { + this.repository = repository; + } +} diff --git a/org.argeo.security.core/src/main/java/org/argeo/security/jcr/RemoteJcrAuthenticationProvider.java b/org.argeo.security.core/src/main/java/org/argeo/security/jcr/RemoteJcrAuthenticationProvider.java new file mode 100644 index 000000000..87208b2a3 --- /dev/null +++ b/org.argeo.security.core/src/main/java/org/argeo/security/jcr/RemoteJcrAuthenticationProvider.java @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.jcr; + +import java.util.ArrayList; +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.List; + +import javax.jcr.Node; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.RepositoryFactory; +import javax.jcr.Session; +import javax.jcr.SimpleCredentials; +import javax.jcr.Value; + +import org.argeo.ArgeoException; +import org.argeo.jcr.ArgeoJcrConstants; +import org.argeo.jcr.ArgeoNames; +import org.argeo.jcr.UserJcrUtils; +import org.argeo.security.NodeAuthenticationToken; +import org.osgi.framework.BundleContext; +import org.springframework.security.Authentication; +import org.springframework.security.AuthenticationException; +import org.springframework.security.BadCredentialsException; +import org.springframework.security.GrantedAuthority; +import org.springframework.security.GrantedAuthorityImpl; +import org.springframework.security.providers.AuthenticationProvider; + +/** Connects to a JCR repository and delegates authentication to it. */ +public class RemoteJcrAuthenticationProvider implements AuthenticationProvider, + ArgeoNames { + private RepositoryFactory repositoryFactory; + private BundleContext bundleContext; + + public final static String ROLE_REMOTE = "ROLE_REMOTE"; + + public Authentication authenticate(Authentication authentication) + throws AuthenticationException { + NodeAuthenticationToken siteAuth = (NodeAuthenticationToken) authentication; + String url = siteAuth.getUrl(); + if (url == null)// TODO? login on own node + throw new ArgeoException("No url set in " + siteAuth); + Session session; + + Node userProfile; + try { + SimpleCredentials sp = new SimpleCredentials(siteAuth.getName(), + siteAuth.getCredentials().toString().toCharArray()); + // get repository + Repository repository = new RemoteJcrRepositoryWrapper( + repositoryFactory, url, sp); + if (bundleContext != null) { + Dictionary serviceProperties = new Hashtable(); + serviceProperties.put(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS, + ArgeoJcrConstants.ALIAS_NODE); + serviceProperties + .put(ArgeoJcrConstants.JCR_REPOSITORY_URI, url); + bundleContext.registerService(Repository.class.getName(), + repository, serviceProperties); + } + // Repository repository = ArgeoJcrUtils.getRepositoryByUri( + // repositoryFactory, url); + // if (repository == null) + // throw new ArgeoException("Cannot connect to " + url); + + session = repository.login(sp, null); + + userProfile = UserJcrUtils.getUserProfile(session, sp.getUserID()); + JcrUserDetails.checkAccountStatus(userProfile); + + // Node userHome = UserJcrUtils.getUserHome(session); + // if (userHome == null || + // !userHome.hasNode(ArgeoNames.ARGEO_PROFILE)) + // throw new ArgeoException("No profile for user " + // + siteAuth.getName() + " in security workspace " + // + siteAuth.getSecurityWorkspace() + " of " + // + siteAuth.getUrl()); + // userProfile = userHome.getNode(ArgeoNames.ARGEO_PROFILE); + } catch (RepositoryException e) { + throw new BadCredentialsException( + "Cannot authenticate " + siteAuth, e); + } + + try { + // Node userHome = UserJcrUtils.getUserHome(session); + // retrieve remote roles + List authoritiesList = new ArrayList(); + if (userProfile != null + && userProfile.hasProperty(ArgeoNames.ARGEO_REMOTE_ROLES)) { + Value[] roles = userProfile.getProperty( + ArgeoNames.ARGEO_REMOTE_ROLES).getValues(); + for (int i = 0; i < roles.length; i++) + authoritiesList.add(new GrantedAuthorityImpl(roles[i] + .getString())); + } + authoritiesList.add(new GrantedAuthorityImpl(ROLE_REMOTE)); + + // create authenticated objects + GrantedAuthority[] authorities = authoritiesList + .toArray(new GrantedAuthority[authoritiesList.size()]); + JcrUserDetails userDetails = new JcrUserDetails(userProfile, + siteAuth.getCredentials().toString(), authorities); + NodeAuthenticationToken authenticated = new NodeAuthenticationToken( + siteAuth, authorities); + authenticated.setDetails(userDetails); + return authenticated; + } catch (RepositoryException e) { + throw new ArgeoException( + "Unexpected exception when authenticating to " + url, e); + } + } + + @SuppressWarnings("rawtypes") + public boolean supports(Class authentication) { + return NodeAuthenticationToken.class.isAssignableFrom(authentication); + } + + public void setRepositoryFactory(RepositoryFactory repositoryFactory) { + this.repositoryFactory = repositoryFactory; + } + + public void setBundleContext(BundleContext bundleContext) { + this.bundleContext = bundleContext; + } + +} diff --git a/org.argeo.security.core/src/main/java/org/argeo/security/jcr/RemoteJcrRepositoryWrapper.java b/org.argeo.security.core/src/main/java/org/argeo/security/jcr/RemoteJcrRepositoryWrapper.java new file mode 100644 index 000000000..f0ad3a3a9 --- /dev/null +++ b/org.argeo.security.core/src/main/java/org/argeo/security/jcr/RemoteJcrRepositoryWrapper.java @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.jcr; + +import javax.jcr.Credentials; +import javax.jcr.LoginException; +import javax.jcr.NoSuchWorkspaceException; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.RepositoryFactory; +import javax.jcr.Session; +import javax.jcr.SimpleCredentials; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; +import org.argeo.jcr.ArgeoJcrUtils; +import org.argeo.jcr.JcrRepositoryWrapper; +import org.argeo.security.NodeAuthenticationToken; +import org.argeo.security.SystemAuthentication; +import org.springframework.security.Authentication; +import org.springframework.security.context.SecurityContextHolder; +import org.springframework.security.providers.UsernamePasswordAuthenticationToken; + +/** + * Wrapper around a remote Jackrabbit repository which allows to simplify + * configuration and intercept some actions. It exposes itself as a + * {@link Repository}. + */ +public class RemoteJcrRepositoryWrapper extends JcrRepositoryWrapper { + private final static Log log = LogFactory + .getLog(RemoteJcrRepositoryWrapper.class); + + private String uri = null; + + private RepositoryFactory repositoryFactory; + + // remote + private Credentials remoteSystemCredentials = null; + + /** + * Empty constructor, {@link #init()} should be called after properties have + * been set + */ + public RemoteJcrRepositoryWrapper() { + } + + /** + * Embedded constructor, calling the {@link #init()} method. + * + * @param alias + * if not null the repository will be published under this alias + */ + public RemoteJcrRepositoryWrapper(RepositoryFactory repositoryFactory, + String uri, Credentials remoteSystemCredentials) { + this.repositoryFactory = repositoryFactory; + this.uri = uri; + this.remoteSystemCredentials = remoteSystemCredentials; + init(); + } + + public void init() { + Repository repository = createJackrabbitRepository(); + setRepository(repository); + } + + /** Actually creates the new repository. */ + protected Repository createJackrabbitRepository() { + long begin = System.currentTimeMillis(); + try { + if (uri == null || uri.trim().equals("")) + throw new ArgeoException("Remote URI not set"); + + Repository repository = ArgeoJcrUtils.getRepositoryByUri( + repositoryFactory, uri); + if (repository == null) + throw new ArgeoException("Remote JCR repository " + uri + + " not found"); + double duration = ((double) (System.currentTimeMillis() - begin)) / 1000; + log.info("Created remote JCR repository in " + duration + + " s from URI " + uri); + // we assume that the data model of the remote repository has + // been properly initialized + return repository; + } catch (Exception e) { + throw new ArgeoException("Cannot create remote JCR repository " + + uri, e); + } + } + + /** Shutdown the repository */ + public void destroy() throws Exception { + super.destroy(); + } + + /** Central login method */ + public Session login(Credentials credentials, String workspaceName) + throws LoginException, NoSuchWorkspaceException, + RepositoryException { + + // retrieve credentials for remote + if (credentials == null) { + Authentication authentication = SecurityContextHolder.getContext() + .getAuthentication(); + if (authentication != null) { + if (authentication instanceof UsernamePasswordAuthenticationToken) { + UsernamePasswordAuthenticationToken upat = (UsernamePasswordAuthenticationToken) authentication; + credentials = new SimpleCredentials(upat.getName(), upat + .getCredentials().toString().toCharArray()); + } else if ((authentication instanceof SystemAuthentication) + || (authentication instanceof NodeAuthenticationToken)) { + credentials = remoteSystemCredentials; + } + } + } + + return super.login(credentials, workspaceName); + } + + public void setUri(String uri) { + this.uri = uri; + } + + public void setRepositoryFactory(RepositoryFactory repositoryFactory) { + this.repositoryFactory = repositoryFactory; + } + + public void setRemoteSystemCredentials(Credentials remoteSystemCredentials) { + this.remoteSystemCredentials = remoteSystemCredentials; + } + +} diff --git a/org.argeo.security.core/src/main/java/org/argeo/security/jcr/SecureThreadBoundSession.java b/org.argeo.security.core/src/main/java/org/argeo/security/jcr/SecureThreadBoundSession.java new file mode 100644 index 000000000..b39877420 --- /dev/null +++ b/org.argeo.security.core/src/main/java/org/argeo/security/jcr/SecureThreadBoundSession.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.jcr; + +import javax.jcr.Session; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.jcr.spring.ThreadBoundSession; +import org.springframework.security.Authentication; +import org.springframework.security.context.SecurityContextHolder; + +/** + * Thread bounded JCR session factory which checks authentication and is + * autoconfigured in Spring. + */ +public class SecureThreadBoundSession extends ThreadBoundSession { + private final static Log log = LogFactory + .getLog(SecureThreadBoundSession.class); + + @Override + protected Session preCall(Session session) { + Authentication authentication = SecurityContextHolder.getContext() + .getAuthentication(); + if (authentication != null) { + String userID = session.getUserID(); + String currentUserName = authentication.getName(); + if (currentUserName != null) { + if (!userID.equals(currentUserName)) { + log.warn("Current session has user ID " + userID + + " while logged is user is " + currentUserName + + "(authentication=" + authentication + ")" + + ". Re-login."); + // TODO throw an exception + return login(); + } + } + } + return super.preCall(session); + } + +} diff --git a/org.argeo.security.core/src/main/java/org/argeo/security/jcr/SimpleJcrSecurityModel.java b/org.argeo.security.core/src/main/java/org/argeo/security/jcr/SimpleJcrSecurityModel.java new file mode 100644 index 000000000..fc0158738 --- /dev/null +++ b/org.argeo.security.core/src/main/java/org/argeo/security/jcr/SimpleJcrSecurityModel.java @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.jcr; + +import java.util.List; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.Value; +import javax.jcr.security.Privilege; +import javax.jcr.version.VersionManager; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; +import org.argeo.jcr.ArgeoJcrConstants; +import org.argeo.jcr.ArgeoNames; +import org.argeo.jcr.ArgeoTypes; +import org.argeo.jcr.JcrUtils; +import org.argeo.jcr.UserJcrUtils; + +/** + * Manages data expected by the Argeo security model, such as user home and + * profile. + */ +public class SimpleJcrSecurityModel implements JcrSecurityModel { + private final static Log log = LogFactory + .getLog(SimpleJcrSecurityModel.class); + // ArgeoNames not implemented as interface in order to ease derivation by + // Jackrabbit bundles + + /** The home base path. */ + private String homeBasePath = "/home"; + + public synchronized Node sync(Session session, String username, + List roles) { + // TODO check user name validity (e.g. should not start by ROLE_) + + try { + Node userHome = UserJcrUtils.getUserHome(session, username); + if (userHome == null) { + String homePath = generateUserPath(homeBasePath, username); + userHome = JcrUtils.mkdirs(session, homePath); + // userHome = JcrUtils.mkfolders(session, homePath); + userHome.addMixin(ArgeoTypes.ARGEO_USER_HOME); + userHome.setProperty(ArgeoNames.ARGEO_USER_ID, username); + session.save(); + + JcrUtils.clearAccessControList(session, homePath, username); + JcrUtils.addPrivilege(session, homePath, username, + Privilege.JCR_ALL); + } else { + // for backward compatibility with pre 1.0 security model + if (userHome.hasNode(ArgeoNames.ARGEO_PROFILE)) { + userHome.getNode(ArgeoNames.ARGEO_PROFILE).remove(); + userHome.getSession().save(); + } + } + + // Remote roles + if (roles != null) { + // writeRemoteRoles(userHome, roles); + } + + Node userProfile = UserJcrUtils.getUserProfile(session, username); + if (userProfile == null) { + String personPath = generateUserPath( + ArgeoJcrConstants.PEOPLE_BASE_PATH, username); + Node personBase = JcrUtils.mkdirs(session, personPath); + userProfile = personBase.addNode(ArgeoNames.ARGEO_PROFILE); + userProfile.addMixin(ArgeoTypes.ARGEO_USER_PROFILE); + userProfile.setProperty(ArgeoNames.ARGEO_USER_ID, username); + userProfile.setProperty(ArgeoNames.ARGEO_ENABLED, true); + userProfile.setProperty(ArgeoNames.ARGEO_ACCOUNT_NON_EXPIRED, + true); + userProfile.setProperty(ArgeoNames.ARGEO_ACCOUNT_NON_LOCKED, + true); + userProfile.setProperty( + ArgeoNames.ARGEO_CREDENTIALS_NON_EXPIRED, true); + session.save(); + + JcrUtils.clearAccessControList(session, userProfile.getPath(), + username); + JcrUtils.addPrivilege(session, userProfile.getPath(), username, + Privilege.JCR_READ); + + VersionManager versionManager = session.getWorkspace() + .getVersionManager(); + if (versionManager.isCheckedOut(userProfile.getPath())) + versionManager.checkin(userProfile.getPath()); + + } + + // Remote roles + if (roles != null) { + writeRemoteRoles(userProfile, roles); + } + return userProfile; + } catch (RepositoryException e) { + JcrUtils.discardQuietly(session); + throw new ArgeoException("Cannot sync node security model for " + + username, e); + } + } + + /** Generate path for a new user home */ + protected String generateUserPath(String base, String username) { + int atIndex = username.indexOf('@'); + if (atIndex > 0) { + String domain = username.substring(0, atIndex); + String name = username.substring(atIndex + 1); + return base + '/' + JcrUtils.firstCharsToPath(domain, 2) + '/' + + domain + '/' + JcrUtils.firstCharsToPath(name, 2) + '/' + + name; + } else if (atIndex == 0 || atIndex == (username.length() - 1)) { + throw new ArgeoException("Unsupported username " + username); + } else { + return base + '/' + JcrUtils.firstCharsToPath(username, 2) + '/' + + username; + } + } + + /** Write remote roles used by remote access in the home directory */ + protected void writeRemoteRoles(Node userHome, List roles) + throws RepositoryException { + boolean writeRoles = false; + if (userHome.hasProperty(ArgeoNames.ARGEO_REMOTE_ROLES)) { + Value[] remoteRoles = userHome.getProperty( + ArgeoNames.ARGEO_REMOTE_ROLES).getValues(); + if (remoteRoles.length != roles.size()) + writeRoles = true; + else + for (int i = 0; i < remoteRoles.length; i++) + if (!remoteRoles[i].getString().equals(roles.get(i))) + writeRoles = true; + } else + writeRoles = true; + + if (writeRoles) { + userHome.getSession().getWorkspace().getVersionManager() + .checkout(userHome.getPath()); + String[] roleIds = roles.toArray(new String[roles.size()]); + userHome.setProperty(ArgeoNames.ARGEO_REMOTE_ROLES, roleIds); + JcrUtils.updateLastModified(userHome); + userHome.getSession().save(); + userHome.getSession().getWorkspace().getVersionManager() + .checkin(userHome.getPath()); + if (log.isDebugEnabled()) + log.debug("Wrote remote roles " + roles + " for " + + userHome.getProperty(ArgeoNames.ARGEO_USER_ID)); + } + + } + + public void setHomeBasePath(String homeBasePath) { + this.homeBasePath = homeBasePath; + } + +} diff --git a/org.argeo.security.core/src/main/java/org/argeo/security/jcr/rememberme/JcrPersistentTokenRepository.java b/org.argeo.security.core/src/main/java/org/argeo/security/jcr/rememberme/JcrPersistentTokenRepository.java new file mode 100644 index 000000000..37dc98676 --- /dev/null +++ b/org.argeo.security.core/src/main/java/org/argeo/security/jcr/rememberme/JcrPersistentTokenRepository.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.jcr.rememberme; + +import java.util.Date; + +import org.springframework.security.ui.rememberme.PersistentRememberMeToken; +import org.springframework.security.ui.rememberme.PersistentTokenRepository; + +public class JcrPersistentTokenRepository implements PersistentTokenRepository { + + public void createNewToken(PersistentRememberMeToken token) { + // TODO Auto-generated method stub + + } + + public void updateToken(String series, String tokenValue, Date lastUsed) { + // TODO Auto-generated method stub + + } + + public PersistentRememberMeToken getTokenForSeries(String seriesId) { + // TODO Auto-generated method stub + return null; + } + + public void removeUserTokens(String username) { + // TODO Auto-generated method stub + + } + +} diff --git a/org.argeo.security.core/src/main/java/org/argeo/security/log4j/SecureLogger.java b/org.argeo.security.core/src/main/java/org/argeo/security/log4j/SecureLogger.java new file mode 100644 index 000000000..1da985703 --- /dev/null +++ b/org.argeo.security.core/src/main/java/org/argeo/security/log4j/SecureLogger.java @@ -0,0 +1,360 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.log4j; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +import org.apache.log4j.AppenderSkeleton; +import org.apache.log4j.Level; +import org.apache.log4j.LogManager; +import org.apache.log4j.Logger; +import org.apache.log4j.PropertyConfigurator; +import org.apache.log4j.spi.LoggingEvent; +import org.argeo.ArgeoException; +import org.argeo.ArgeoLogListener; +import org.argeo.ArgeoLogger; +import org.argeo.security.SecurityUtils; + +/** Not meant to be used directly in standard log4j config */ +public class SecureLogger implements ArgeoLogger { + + private Boolean disabled = false; + + private String level = null; + + private Level log4jLevel = null; + // private Layout layout; + + private Properties configuration; + + private AppenderImpl appender; + + private final List everythingListeners = Collections + .synchronizedList(new ArrayList()); + private final List allUsersListeners = Collections + .synchronizedList(new ArrayList()); + private final Map> userListeners = Collections + .synchronizedMap(new HashMap>()); + + private BlockingQueue events; + private LogDispatcherThread logDispatcherThread = new LogDispatcherThread(); + + private Integer maxLastEventsCount = 10 * 1000; + + /** Marker to prevent stack overflow */ + private ThreadLocal dispatching = new ThreadLocal() { + + @Override + protected Boolean initialValue() { + return false; + } + }; + + public void init() { + try { + events = new LinkedBlockingQueue(); + + // if (layout != null) + // setLayout(layout); + // else + // setLayout(new PatternLayout(pattern)); + appender = new AppenderImpl(); + reloadConfiguration(); + Logger.getRootLogger().addAppender(appender); + + logDispatcherThread = new LogDispatcherThread(); + logDispatcherThread.start(); + } catch (Exception e) { + throw new ArgeoException("Cannot initialize log4j"); + } + } + + public void destroy() throws Exception { + Logger.getRootLogger().removeAppender(appender); + allUsersListeners.clear(); + for (List lst : userListeners.values()) + lst.clear(); + userListeners.clear(); + + events.clear(); + events = null; + logDispatcherThread.interrupt(); + } + + // public void setLayout(Layout layout) { + // this.layout = layout; + // } + + public synchronized void register(ArgeoLogListener listener, + Integer numberOfPreviousEvents) { + String username = SecurityUtils.getCurrentThreadUsername(); + if (username == null) + throw new ArgeoException( + "Only authenticated users can register a log listener"); + + if (!userListeners.containsKey(username)) { + List lst = Collections + .synchronizedList(new ArrayList()); + userListeners.put(username, lst); + } + userListeners.get(username).add(listener); + List lastEvents = logDispatcherThread.getLastEvents(username, + numberOfPreviousEvents); + for (LogEvent evt : lastEvents) + dispatchEvent(listener, evt); + } + + public synchronized void registerForAll(ArgeoLogListener listener, + Integer numberOfPreviousEvents, boolean everything) { + if (everything) + everythingListeners.add(listener); + else + allUsersListeners.add(listener); + List lastEvents = logDispatcherThread.getLastEvents(null, + numberOfPreviousEvents); + for (LogEvent evt : lastEvents) + if (everything || evt.getUsername() != null) + dispatchEvent(listener, evt); + } + + public synchronized void unregister(ArgeoLogListener listener) { + String username = SecurityUtils.getCurrentThreadUsername(); + if (!userListeners.containsKey(username)) + throw new ArgeoException("No user listeners " + listener + + " registered for user " + username); + if (!userListeners.get(username).contains(listener)) + throw new ArgeoException("No user listeners " + listener + + " registered for user " + username); + userListeners.get(username).remove(listener); + if (userListeners.get(username).isEmpty()) + userListeners.remove(username); + + } + + public synchronized void unregisterForAll(ArgeoLogListener listener) { + everythingListeners.remove(listener); + allUsersListeners.remove(listener); + } + + /** For development purpose, since using regular logging is not easy here */ + static void stdOut(Object obj) { + System.out.println(obj); + } + + // public void setPattern(String pattern) { + // this.pattern = pattern; + // } + + public void setDisabled(Boolean disabled) { + this.disabled = disabled; + } + + public void setLevel(String level) { + this.level = level; + } + + public void setConfiguration(Properties configuration) { + this.configuration = configuration; + } + + public void updateConfiguration(Properties configuration) { + setConfiguration(configuration); + reloadConfiguration(); + } + + public Properties getConfiguration() { + return configuration; + } + + /** Reloads configuration (if the configuration {@link Properties} is set) */ + protected void reloadConfiguration() { + if (configuration != null) { + LogManager.resetConfiguration(); + PropertyConfigurator.configure(configuration); + } + } + + protected synchronized void processLoggingEvent(LogEvent event) { + if (disabled) + return; + + if (dispatching.get()) + return; + + if (level != null && !level.trim().equals("")) { + if (log4jLevel == null || !log4jLevel.toString().equals(level)) + try { + log4jLevel = Level.toLevel(level); + } catch (Exception e) { + System.err + .println("Log4j level could not be set for level '" + + level + "', resetting it to null."); + e.printStackTrace(); + level = null; + } + + if (log4jLevel != null + && !event.getLoggingEvent().getLevel() + .isGreaterOrEqual(log4jLevel)) { + return; + } + } + + try { + // admin listeners + Iterator everythingIt = everythingListeners + .iterator(); + while (everythingIt.hasNext()) + dispatchEvent(everythingIt.next(), event); + + if (event.getUsername() != null) { + Iterator allUsersIt = allUsersListeners + .iterator(); + while (allUsersIt.hasNext()) + dispatchEvent(allUsersIt.next(), event); + + if (userListeners.containsKey(event.getUsername())) { + Iterator userIt = userListeners.get( + event.getUsername()).iterator(); + while (userIt.hasNext()) + dispatchEvent(userIt.next(), event); + } + } + } catch (Exception e) { + stdOut("Cannot process logging event"); + e.printStackTrace(); + } + } + + protected void dispatchEvent(ArgeoLogListener logListener, LogEvent evt) { + LoggingEvent event = evt.getLoggingEvent(); + logListener.appendLog(evt.getUsername(), event.getTimeStamp(), event + .getLevel().toString(), event.getLoggerName(), event + .getThreadName(), event.getMessage(), event + .getThrowableStrRep()); + } + + private class AppenderImpl extends AppenderSkeleton { + public boolean requiresLayout() { + return false; + } + + public void close() { + } + + @Override + protected void append(LoggingEvent event) { + if (events != null) { + try { + String username = SecurityUtils.getCurrentThreadUsername(); + events.put(new LogEvent(username, event)); + } catch (InterruptedException e) { + // silent + } + } + } + + } + + private class LogDispatcherThread extends Thread { + /** encapsulated in order to simplify concurrency management */ + private LinkedList lastEvents = new LinkedList(); + + public LogDispatcherThread() { + super("Argeo Logging Dispatcher Thread"); + } + + public void run() { + while (events != null) { + try { + LogEvent loggingEvent = events.take(); + processLoggingEvent(loggingEvent); + addLastEvent(loggingEvent); + } catch (InterruptedException e) { + if (events == null) + return; + } + } + } + + protected synchronized void addLastEvent(LogEvent loggingEvent) { + if (lastEvents.size() >= maxLastEventsCount) + lastEvents.poll(); + lastEvents.add(loggingEvent); + } + + public synchronized List getLastEvents(String username, + Integer maxCount) { + LinkedList evts = new LinkedList(); + ListIterator it = lastEvents.listIterator(lastEvents + .size()); + int count = 0; + while (it.hasPrevious() && (count < maxCount)) { + LogEvent evt = it.previous(); + if (username == null || username.equals(evt.getUsername())) { + evts.push(evt); + count++; + } + } + return evts; + } + } + + private class LogEvent { + private final String username; + private final LoggingEvent loggingEvent; + + public LogEvent(String username, LoggingEvent loggingEvent) { + super(); + this.username = username; + this.loggingEvent = loggingEvent; + } + + @Override + public int hashCode() { + return loggingEvent.hashCode(); + } + + @Override + public boolean equals(Object obj) { + return loggingEvent.equals(obj); + } + + @Override + public String toString() { + return username + "@ " + loggingEvent.toString(); + } + + public String getUsername() { + return username; + } + + public LoggingEvent getLoggingEvent() { + return loggingEvent; + } + + } +} diff --git a/org.argeo.security.core/src/test/java/org/argeo/security/PasswordSandbox.java b/org.argeo.security.core/src/test/java/org/argeo/security/PasswordSandbox.java new file mode 100644 index 000000000..d8a084607 --- /dev/null +++ b/org.argeo.security.core/src/test/java/org/argeo/security/PasswordSandbox.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security; + +import org.apache.commons.codec.DecoderException; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.codec.binary.Hex; +import org.springframework.security.providers.ldap.authenticator.LdapShaPasswordEncoder; + +public class PasswordSandbox { + public static void main(String[] args) { + try { + // Tested password + String pwdPlain = "demo"; + + // Check Java generated values + LdapShaPasswordEncoder lspe = new LdapShaPasswordEncoder(); + String pwdLdapShaBase64 = lspe.encodePassword(pwdPlain, null); + System.out.println("pwdLdapShaBase64:\t\t" + pwdLdapShaBase64); + + String pwdShaBase64 = pwdLdapShaBase64.substring("{SHA}".length()); + System.out.println("pwdShaBase64:\t\t\t" + pwdShaBase64); + + byte[] pwdShaArray = Base64.decodeBase64(pwdShaBase64.getBytes()); + String pwdShaHex = new String(Hex.encodeHex(pwdShaArray)); + System.out.println("pwdShaHex:\t\t\t" + pwdShaHex); + + // Check that we can use JavaScript generated values in Hex + String jsShaHex = "89e495e7941cf9e40e6980d14a16bf023ccd4c91"; + System.out.println("jsShaHex:\t\t\t" + pwdShaHex); + System.out.println("pwdShaHex==jsShaHex:\t\t" + + (pwdShaHex.equals(jsShaHex))); + + byte[] jsShaArray = Hex.decodeHex(jsShaHex.toCharArray()); + String jsShaBase64 = new String(Base64.encodeBase64(jsShaArray)); + System.out.println("jsShaBase64:\t\t\t" + jsShaBase64); + System.out.println("pwdShaBase64==jsShaBase64:\t" + + (pwdShaBase64.equals(jsShaBase64))); + } catch (DecoderException e) { + e.printStackTrace(); + } + + } + +} \ No newline at end of file diff --git a/org.argeo.security.core/src/test/java/org/argeo/security/crypto/PasswordBasedEncryptionTest.java b/org.argeo.security.core/src/test/java/org/argeo/security/crypto/PasswordBasedEncryptionTest.java new file mode 100644 index 000000000..6973f5704 --- /dev/null +++ b/org.argeo.security.core/src/test/java/org/argeo/security/crypto/PasswordBasedEncryptionTest.java @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.crypto; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; + +import javax.crypto.Cipher; +import javax.crypto.CipherInputStream; +import javax.crypto.CipherOutputStream; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.PBEParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import javax.xml.bind.DatatypeConverter; + +import junit.framework.TestCase; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.StreamUtils; +import org.argeo.security.crypto.PasswordBasedEncryption; + +public class PasswordBasedEncryptionTest extends TestCase { + private final static Log log = LogFactory + .getLog(PasswordBasedEncryptionTest.class); + + public void testEncryptDecrypt() { + final String password = "test long password since they are safer"; + PasswordBasedEncryption pbeEnc = new PasswordBasedEncryption( + password.toCharArray()); + String message = "Hello World!"; + log.info("Password:\t'" + password + "'"); + log.info("Message:\t'" + message + "'"); + byte[] encrypted = pbeEnc.encryptString(message); + log.info("Encrypted:\t'" + + DatatypeConverter.printBase64Binary(encrypted) + "'"); + PasswordBasedEncryption pbeDec = new PasswordBasedEncryption( + password.toCharArray()); + InputStream in = null; + in = new ByteArrayInputStream(encrypted); + String decrypted = pbeDec.decryptAsString(in); + log.info("Decrypted:\t'" + decrypted + "'"); + StreamUtils.closeQuietly(in); + assertEquals(message, decrypted); + } + + public void testPBEWithMD5AndDES() throws Exception { + String password = "test"; + String message = "Hello World!"; + + byte[] salt = { (byte) 0xc7, (byte) 0x73, (byte) 0x21, (byte) 0x8c, + (byte) 0x7e, (byte) 0xc8, (byte) 0xee, (byte) 0x99 }; + + int count = 1024; + + String cipherAlgorithm = "PBEWithMD5AndDES"; + String secretKeyAlgorithm = "PBEWithMD5AndDES"; + SecretKeyFactory keyFac = SecretKeyFactory + .getInstance(secretKeyAlgorithm); + PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray()); + PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, count); + SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec); + Cipher ecipher = Cipher.getInstance(cipherAlgorithm); + ecipher.init(Cipher.ENCRYPT_MODE, pbeKey, pbeParamSpec); + Cipher dcipher = Cipher.getInstance(cipherAlgorithm); + dcipher.init(Cipher.DECRYPT_MODE, pbeKey, pbeParamSpec); + + byte[] encrypted = ecipher.doFinal(message.getBytes()); + byte[] decrypted = dcipher.doFinal(encrypted); + assertEquals(message, new String(decrypted)); + + } + + public void testPBEWithSHA1AndAES() throws Exception { + String password = "test"; + String message = "Hello World!"; + + byte[] salt = { (byte) 0xc7, (byte) 0x73, (byte) 0x21, (byte) 0x8c, + (byte) 0x7e, (byte) 0xc8, (byte) 0xee, (byte) 0x99 }; + byte[] iv = { (byte) 0xc7, (byte) 0x73, (byte) 0x21, (byte) 0x8c, + (byte) 0x7e, (byte) 0xc8, (byte) 0xee, (byte) 0x99, + (byte) 0xc7, (byte) 0x73, (byte) 0x21, (byte) 0x8c, + (byte) 0x7e, (byte) 0xc8, (byte) 0xee, (byte) 0x99 }; + + int count = 1024; + // int keyLength = 256; + int keyLength = 128; + + String cipherAlgorithm = "AES/CBC/PKCS5Padding"; + String secretKeyAlgorithm = "PBKDF2WithHmacSHA1"; + SecretKeyFactory keyFac = SecretKeyFactory + .getInstance(secretKeyAlgorithm); + PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray(), salt, + count, keyLength); + SecretKey tmp = keyFac.generateSecret(pbeKeySpec); + SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES"); + Cipher ecipher = Cipher.getInstance(cipherAlgorithm); + ecipher.init(Cipher.ENCRYPT_MODE, secret, new IvParameterSpec(iv)); + + // decrypt + keyFac = SecretKeyFactory.getInstance(secretKeyAlgorithm); + pbeKeySpec = new PBEKeySpec(password.toCharArray(), salt, count, + keyLength); + tmp = keyFac.generateSecret(pbeKeySpec); + secret = new SecretKeySpec(tmp.getEncoded(), "AES"); + // AlgorithmParameters params = ecipher.getParameters(); + // byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV(); + Cipher dcipher = Cipher.getInstance(cipherAlgorithm); + dcipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv)); + + byte[] encrypted = ecipher.doFinal(message.getBytes()); + byte[] decrypted = dcipher.doFinal(encrypted); + assertEquals(message, new String(decrypted)); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + CipherOutputStream cipherOut = new CipherOutputStream(out, ecipher); + cipherOut.write(message.getBytes()); + StreamUtils.closeQuietly(cipherOut); + byte[] enc = out.toByteArray(); + + ByteArrayInputStream in = new ByteArrayInputStream(enc); + CipherInputStream cipherIn = new CipherInputStream(in, dcipher); + ByteArrayOutputStream dec = new ByteArrayOutputStream(); + StreamUtils.copy(cipherIn, dec); + assertEquals(message, new String(dec.toByteArray())); + } +} diff --git a/org.argeo.security.core/src/test/resources/log4j.properties b/org.argeo.security.core/src/test/resources/log4j.properties new file mode 100644 index 000000000..b33daa9db --- /dev/null +++ b/org.argeo.security.core/src/test/resources/log4j.properties @@ -0,0 +1,28 @@ +log4j.rootLogger=WARN, console + +## Levels +log4j.logger.org.argeo=DEBUG + +log4j.logger.org.hibernate=WARN + +log4j.logger.org.springframework=WARN +#log4j.logger.org.springframework.web=DEBUG +#log4j.logger.org.springframework.jms=WARN +#log4j.logger.org.springframework.security=WARN + +log4j.logger.org.apache.activemq=WARN +log4j.logger.org.apache.activemq.transport=WARN +log4j.logger.org.apache.activemq.ActiveMQMessageConsumer=INFO +log4j.logger.org.apache.activemq.ActiveMQMessageProducer=INFO + +log4j.logger.org.apache.catalina=INFO +log4j.logger.org.apache.coyote=INFO +log4j.logger.org.apache.tomcat=INFO + +## Appenders +# console is set to be a ConsoleAppender. +log4j.appender.console=org.apache.log4j.ConsoleAppender + +# console uses PatternLayout. +log4j.appender.console.layout=org.apache.log4j.PatternLayout +log4j.appender.console.layout.ConversionPattern= %-5p %d{ISO8601} %m - %c%n diff --git a/org.argeo.security.core/src/test/resources/org/argeo/security/json/gandalf2.json b/org.argeo.security.core/src/test/resources/org/argeo/security/json/gandalf2.json new file mode 100644 index 000000000..73918229b --- /dev/null +++ b/org.argeo.security.core/src/test/resources/org/argeo/security/json/gandalf2.json @@ -0,0 +1 @@ +{"roles":["ROLE_ADMIN","ROLE_USER"],"userNatures":[{"description":"Superuser","email":"admin@localhost","firstName":"Gandalf","lastName":"User","type":"org.argeo.security.nature.SimpleUserNature"},{"mobile":null,"telephoneNumber":null,"type":"org.argeo.security.nature.CoworkerNature"}],"username":"gandalf2","enabled":true,"password":"{SHA}ieSV55Qc+eQOaYDRSha/AjzNTJE=","authorities":[{"authority":"ROLE_ADMIN"},{"authority":"ROLE_USER"}],"accountNonExpired":true,"accountNonLocked":true,"credentialsNonExpired":true} \ No newline at end of file diff --git a/org.argeo.security.dao.cli/.project b/org.argeo.security.dao.cli/.project new file mode 100644 index 000000000..807ba67a3 --- /dev/null +++ b/org.argeo.security.dao.cli/.project @@ -0,0 +1,22 @@ + + + org.argeo.security.dao.cli + + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + + diff --git a/org.argeo.security.dao.cli/META-INF/spring/security-cli-osgi.xml b/org.argeo.security.dao.cli/META-INF/spring/security-cli-osgi.xml new file mode 100644 index 000000000..c46f2764c --- /dev/null +++ b/org.argeo.security.dao.cli/META-INF/spring/security-cli-osgi.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.security.dao.cli/META-INF/spring/security-cli.xml b/org.argeo.security.dao.cli/META-INF/spring/security-cli.xml new file mode 100644 index 000000000..c3f6c8122 --- /dev/null +++ b/org.argeo.security.dao.cli/META-INF/spring/security-cli.xml @@ -0,0 +1,86 @@ + + + + + + + osgibundle:security.properties + + + + + + + + /org/argeo/jcr/argeo.cnd + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.security.dao.cli/pom.xml b/org.argeo.security.dao.cli/pom.xml new file mode 100644 index 000000000..c354eacbd --- /dev/null +++ b/org.argeo.security.dao.cli/pom.xml @@ -0,0 +1,27 @@ + + 4.0.0 + + org.argeo.commons + 2.1.12-SNAPSHOT + argeo-commons + .. + + org.argeo.security.dao.cli + Commons Security DAO CLI + + + + org.apache.felix + maven-bundle-plugin + + + + *, + org.argeo.jcr, + + + + + + + \ No newline at end of file diff --git a/org.argeo.security.dao.cli/security.properties b/org.argeo.security.dao.cli/security.properties new file mode 100644 index 000000000..42df9259a --- /dev/null +++ b/org.argeo.security.dao.cli/security.properties @@ -0,0 +1,3 @@ +argeo.security.systemKey=argeo +argeo.node.repo.securityWorkspace=security +argeo.keyring.secreteKeyLength=256 diff --git a/org.argeo.security.dao.jackrabbit/.project b/org.argeo.security.dao.jackrabbit/.project new file mode 100644 index 000000000..b537a75a5 --- /dev/null +++ b/org.argeo.security.dao.jackrabbit/.project @@ -0,0 +1,22 @@ + + + org.argeo.security.dao.jackrabbit + + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + + diff --git a/org.argeo.security.dao.jackrabbit/META-INF/spring/repofactory.xml b/org.argeo.security.dao.jackrabbit/META-INF/spring/repofactory.xml new file mode 100644 index 000000000..a00c9b00d --- /dev/null +++ b/org.argeo.security.dao.jackrabbit/META-INF/spring/repofactory.xml @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/org.argeo.security.dao.jackrabbit/META-INF/spring/security-jcr-osgi.xml b/org.argeo.security.dao.jackrabbit/META-INF/spring/security-jcr-osgi.xml new file mode 100644 index 000000000..9f6d43256 --- /dev/null +++ b/org.argeo.security.dao.jackrabbit/META-INF/spring/security-jcr-osgi.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.security.dao.jackrabbit/META-INF/spring/security-jcr-services.xml b/org.argeo.security.dao.jackrabbit/META-INF/spring/security-jcr-services.xml new file mode 100644 index 000000000..1300a0550 --- /dev/null +++ b/org.argeo.security.dao.jackrabbit/META-INF/spring/security-jcr-services.xml @@ -0,0 +1,40 @@ + + + + + + + osgibundle:security.properties + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.security.dao.jackrabbit/build.properties b/org.argeo.security.dao.jackrabbit/build.properties new file mode 100644 index 000000000..5f22cdd44 --- /dev/null +++ b/org.argeo.security.dao.jackrabbit/build.properties @@ -0,0 +1 @@ +bin.includes = META-INF/ diff --git a/org.argeo.security.dao.jackrabbit/pom.xml b/org.argeo.security.dao.jackrabbit/pom.xml new file mode 100644 index 000000000..86f837e6a --- /dev/null +++ b/org.argeo.security.dao.jackrabbit/pom.xml @@ -0,0 +1,19 @@ + + 4.0.0 + + org.argeo.commons + 2.1.12-SNAPSHOT + argeo-commons + .. + + org.argeo.security.dao.jackrabbit + Commons Security DAO Jackrabbit + + + + org.apache.felix + maven-bundle-plugin + + + + \ No newline at end of file diff --git a/org.argeo.security.dao.jackrabbit/security.properties b/org.argeo.security.dao.jackrabbit/security.properties new file mode 100644 index 000000000..beebcb5dc --- /dev/null +++ b/org.argeo.security.dao.jackrabbit/security.properties @@ -0,0 +1,2 @@ +argeo.security.systemKey=argeo +argeo.node.repo.alias=node diff --git a/org.argeo.security.dao.ldap/.project b/org.argeo.security.dao.ldap/.project new file mode 100644 index 000000000..cd8b39380 --- /dev/null +++ b/org.argeo.security.dao.ldap/.project @@ -0,0 +1,22 @@ + + + org.argeo.security.dao.ldap + + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + + diff --git a/org.argeo.security.dao.ldap/META-INF/spring/security-ldap-jcr.xml b/org.argeo.security.dao.ldap/META-INF/spring/security-ldap-jcr.xml new file mode 100644 index 000000000..3235e66f4 --- /dev/null +++ b/org.argeo.security.dao.ldap/META-INF/spring/security-ldap-jcr.xml @@ -0,0 +1,79 @@ + + + + + + + /org/argeo/jcr/argeo.cnd + + + + + + + + + + + + + ${argeo.ldap.userClass} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.argeo.security.dao.ldap/META-INF/spring/security-ldap-osgi.xml b/org.argeo.security.dao.ldap/META-INF/spring/security-ldap-osgi.xml new file mode 100644 index 000000000..aa3b67ac6 --- /dev/null +++ b/org.argeo.security.dao.ldap/META-INF/spring/security-ldap-osgi.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.security.dao.ldap/META-INF/spring/security-ldap-services.xml b/org.argeo.security.dao.ldap/META-INF/spring/security-ldap-services.xml new file mode 100644 index 000000000..36dedf389 --- /dev/null +++ b/org.argeo.security.dao.ldap/META-INF/spring/security-ldap-services.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.security.dao.ldap/META-INF/spring/security-ldap.xml b/org.argeo.security.dao.ldap/META-INF/spring/security-ldap.xml new file mode 100644 index 000000000..3777f8853 --- /dev/null +++ b/org.argeo.security.dao.ldap/META-INF/spring/security-ldap.xml @@ -0,0 +1,121 @@ + + + + + + + osgibundle:ldap.properties + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + top + ${argeo.ldap.groupClass} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.argeo.security.dao.ldap/build.properties b/org.argeo.security.dao.ldap/build.properties new file mode 100644 index 000000000..5f22cdd44 --- /dev/null +++ b/org.argeo.security.dao.ldap/build.properties @@ -0,0 +1 @@ +bin.includes = META-INF/ diff --git a/org.argeo.security.dao.ldap/ldap.properties b/org.argeo.security.dao.ldap/ldap.properties new file mode 100644 index 000000000..0f5164ff3 --- /dev/null +++ b/org.argeo.security.dao.ldap/ldap.properties @@ -0,0 +1,32 @@ +argeo.security.defaultRole=ROLE_USER +argeo.security.rolePrefix=ROLE_ + +argeo.security.systemKey=argeo +argeo.security.superUsername=root + +argeo.ldap.rootdn=dc=demo,dc=example,dc=org +argeo.ldap.protocol=ldap +argeo.ldap.host=localhost +# default are for Apache Directory Server +argeo.ldap.port=10389 +argeo.ldap.manager.userdn=uid=admin,ou=system +argeo.ldap.manager.password=secret + +# USER +argeo.ldap.userClass=inetOrgPerson +argeo.ldap.osUserClass=posixAccount +argeo.ldap.userBase=ou=People +argeo.ldap.usernameAttribute=uid +argeo.ldap.passwordAttribute=userPassword +# ROLES +argeo.ldap.groupClass=groupOfNames +argeo.ldap.groupBase=ou=Roles +argeo.ldap.groupRoleAttribute=cn +argeo.ldap.groupMemberAttribute=member +# OS GROUPS +argeo.ldap.osGroupClass=posixGroup +argeo.ldap.osGroupBase=ou=Group +argeo.ldap.osGroupNameAttribute=cn +argeo.ldap.osGroupMemberAttribute=memberUid + +argeo.ldap.password.useSalt=false \ No newline at end of file diff --git a/org.argeo.security.dao.ldap/pom.xml b/org.argeo.security.dao.ldap/pom.xml new file mode 100644 index 000000000..d4ca96c6b --- /dev/null +++ b/org.argeo.security.dao.ldap/pom.xml @@ -0,0 +1,30 @@ + + 4.0.0 + + org.argeo.commons + 2.1.12-SNAPSHOT + argeo-commons + .. + + org.argeo.security.dao.ldap + Commons Security DAO LDAP + + + + org.apache.felix + maven-bundle-plugin + + + + *, + org.argeo.jcr, + com.sun.jndi.ldap;resolution:=optional, + org.springframework.ldap.core.support, + org.springframework.security + + + + + + + \ No newline at end of file diff --git a/org.argeo.security.dao.os/.project b/org.argeo.security.dao.os/.project new file mode 100644 index 000000000..cefcc33f3 --- /dev/null +++ b/org.argeo.security.dao.os/.project @@ -0,0 +1,22 @@ + + + org.argeo.security.dao.os + + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + + diff --git a/org.argeo.security.dao.os/META-INF/spring/security-os-osgi.xml b/org.argeo.security.dao.os/META-INF/spring/security-os-osgi.xml new file mode 100644 index 000000000..5d827b4a5 --- /dev/null +++ b/org.argeo.security.dao.os/META-INF/spring/security-os-osgi.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.security.dao.os/META-INF/spring/security-os.xml b/org.argeo.security.dao.os/META-INF/spring/security-os.xml new file mode 100644 index 000000000..3d94f502d --- /dev/null +++ b/org.argeo.security.dao.os/META-INF/spring/security-os.xml @@ -0,0 +1,75 @@ + + + + + + + osgibundle:security.properties + + + + + + + + /org/argeo/jcr/argeo.cnd + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.security.dao.os/build.properties b/org.argeo.security.dao.os/build.properties new file mode 100644 index 000000000..5f22cdd44 --- /dev/null +++ b/org.argeo.security.dao.os/build.properties @@ -0,0 +1 @@ +bin.includes = META-INF/ diff --git a/org.argeo.security.dao.os/pom.xml b/org.argeo.security.dao.os/pom.xml new file mode 100644 index 000000000..7ec6fe6c3 --- /dev/null +++ b/org.argeo.security.dao.os/pom.xml @@ -0,0 +1,27 @@ + + 4.0.0 + + org.argeo.commons + 2.1.12-SNAPSHOT + argeo-commons + .. + + org.argeo.security.dao.os + Commons Security DAO OS + + + + org.apache.felix + maven-bundle-plugin + + + + *, + org.argeo.jcr, + + + + + + + \ No newline at end of file diff --git a/org.argeo.security.dao.os/security.properties b/org.argeo.security.dao.os/security.properties new file mode 100644 index 000000000..ae77bf04d --- /dev/null +++ b/org.argeo.security.dao.os/security.properties @@ -0,0 +1,2 @@ +argeo.security.systemKey=argeo +argeo.node.repo.securityWorkspace=security diff --git a/org.argeo.security.equinox/.classpath b/org.argeo.security.equinox/.classpath new file mode 100644 index 000000000..848725036 --- /dev/null +++ b/org.argeo.security.equinox/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/org.argeo.security.equinox/.project b/org.argeo.security.equinox/.project new file mode 100644 index 000000000..e4dd594e8 --- /dev/null +++ b/org.argeo.security.equinox/.project @@ -0,0 +1,28 @@ + + + org.argeo.security.equinox + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/org.argeo.security.equinox/.settings/org.eclipse.pde.core.prefs b/org.argeo.security.equinox/.settings/org.eclipse.pde.core.prefs new file mode 100644 index 000000000..87ab38102 --- /dev/null +++ b/org.argeo.security.equinox/.settings/org.eclipse.pde.core.prefs @@ -0,0 +1,4 @@ +#Sun Jan 16 11:19:07 CET 2011 +eclipse.preferences.version=1 +pluginProject.extensions=false +resolve.requirebundle=false diff --git a/org.argeo.security.equinox/META-INF/spring/loginModules.xml b/org.argeo.security.equinox/META-INF/spring/loginModules.xml new file mode 100644 index 000000000..7a3e8025a --- /dev/null +++ b/org.argeo.security.equinox/META-INF/spring/loginModules.xml @@ -0,0 +1,39 @@ + + + + + + + osgibundle:security.properties + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.argeo.security.equinox/META-INF/spring/osgi.xml b/org.argeo.security.equinox/META-INF/spring/osgi.xml new file mode 100644 index 000000000..8003fb277 --- /dev/null +++ b/org.argeo.security.equinox/META-INF/spring/osgi.xml @@ -0,0 +1,14 @@ + + + + + \ No newline at end of file diff --git a/org.argeo.security.equinox/build.properties b/org.argeo.security.equinox/build.properties new file mode 100644 index 000000000..3e2615fae --- /dev/null +++ b/org.argeo.security.equinox/build.properties @@ -0,0 +1,4 @@ +bin.includes = META-INF/,\ + plugin.xml +source.. = src/main/java/ +output.. = target/classes/ diff --git a/org.argeo.security.equinox/plugin.xml b/org.argeo.security.equinox/plugin.xml new file mode 100644 index 000000000..2cc81f137 --- /dev/null +++ b/org.argeo.security.equinox/plugin.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.argeo.security.equinox/pom.xml b/org.argeo.security.equinox/pom.xml new file mode 100644 index 000000000..834e1c4ef --- /dev/null +++ b/org.argeo.security.equinox/pom.xml @@ -0,0 +1,77 @@ + + + 4.0.0 + + org.argeo.commons + 2.1.12-SNAPSHOT + argeo-commons + .. + + org.argeo.security.equinox + Commons Security Equinox + jar + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-source-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + org.apache.felix + maven-bundle-plugin + + + ${project.artifactId};singleton:=true + *, + org.springframework.core, + org.argeo.eclipse.spring + + + + + + + + + + + org.argeo.tp + org.eclipse.osgi + + + + + org.argeo.commons + org.argeo.eclipse.dep.rcp + 2.1.12-SNAPSHOT + provided + + + + + org.argeo.commons + org.argeo.util + 2.1.12-SNAPSHOT + + + org.argeo.commons + org.argeo.security.core + 2.1.12-SNAPSHOT + + + + + org.argeo.tp + org.springframework.security.core + + + \ No newline at end of file diff --git a/org.argeo.security.equinox/security.properties b/org.argeo.security.equinox/security.properties new file mode 100644 index 000000000..70e75cce2 --- /dev/null +++ b/org.argeo.security.equinox/security.properties @@ -0,0 +1,5 @@ +argeo.security.systemKey=argeo + +argeo.security.anonymousRole=ROLE_ANONYMOUS + +argeo.i18n.availableLocales= \ No newline at end of file diff --git a/org.argeo.security.equinox/src/main/java/org/argeo/security/equinox/OsSpringLoginModule.java b/org.argeo.security.equinox/src/main/java/org/argeo/security/equinox/OsSpringLoginModule.java new file mode 100644 index 000000000..1a7ebb4d7 --- /dev/null +++ b/org.argeo.security.equinox/src/main/java/org/argeo/security/equinox/OsSpringLoginModule.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.equinox; + +import java.util.Map; + +import javax.security.auth.Subject; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.login.LoginException; + +import org.argeo.security.OsAuthenticationToken; +import org.springframework.security.Authentication; +import org.springframework.security.AuthenticationManager; +import org.springframework.security.context.SecurityContextHolder; +import org.springframework.security.providers.jaas.SecurityContextLoginModule; + +/** Login module which caches one subject per thread. */ +public class OsSpringLoginModule extends SecurityContextLoginModule { + // private final static Log log = + // LogFactory.getLog(OsSpringLoginModule.class); + + private AuthenticationManager authenticationManager; + + private Subject subject; + + public OsSpringLoginModule() { + + } + + @SuppressWarnings("rawtypes") + public void initialize(Subject subject, CallbackHandler callbackHandler, + Map sharedState, Map options) { + super.initialize(subject, callbackHandler, sharedState, options); + this.subject = subject; + } + + public boolean login() throws LoginException { + // thread already logged in + if (SecurityContextHolder.getContext().getAuthentication() != null) + return super.login(); + + OsAuthenticationToken oat = new OsAuthenticationToken(); + Authentication authentication = authenticationManager.authenticate(oat); + registerAuthentication(authentication); + return super.login(); + } + + @Override + public boolean logout() throws LoginException { + subject.getPrincipals().clear(); + return super.logout(); + } + + /** + * Register an {@link Authentication} in the security context. + * + * @param authentication + * has to implement {@link Authentication}. + */ + protected void registerAuthentication(Object authentication) { + SecurityContextHolder.getContext().setAuthentication( + (Authentication) authentication); + } + + public void setAuthenticationManager( + AuthenticationManager authenticationManager) { + this.authenticationManager = authenticationManager; + } +} diff --git a/org.argeo.security.equinox/src/main/java/org/argeo/security/equinox/SpringLoginModule.java b/org.argeo.security.equinox/src/main/java/org/argeo/security/equinox/SpringLoginModule.java new file mode 100644 index 000000000..6fd179ead --- /dev/null +++ b/org.argeo.security.equinox/src/main/java/org/argeo/security/equinox/SpringLoginModule.java @@ -0,0 +1,243 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.equinox; + +import java.util.Locale; +import java.util.Map; +import java.util.UUID; + +import javax.security.auth.Subject; +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.NameCallback; +import javax.security.auth.callback.PasswordCallback; +import javax.security.auth.login.LoginException; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.security.NodeAuthenticationToken; +import org.argeo.util.LocaleCallback; +import org.argeo.util.LocaleUtils; +import org.springframework.security.Authentication; +import org.springframework.security.AuthenticationManager; +import org.springframework.security.BadCredentialsException; +import org.springframework.security.GrantedAuthority; +import org.springframework.security.GrantedAuthorityImpl; +import org.springframework.security.context.SecurityContextHolder; +import org.springframework.security.providers.anonymous.AnonymousAuthenticationToken; +import org.springframework.security.providers.jaas.SecurityContextLoginModule; + +/** Login module which caches one subject per thread. */ +public class SpringLoginModule extends SecurityContextLoginModule { + final static String NODE_REPO_URI = "argeo.node.repo.uri"; + + private final static Log log = LogFactory.getLog(SpringLoginModule.class); + + private AuthenticationManager authenticationManager; + + private CallbackHandler callbackHandler; + + private Subject subject; + + private Long waitBetweenFailedLoginAttempts = 5 * 1000l; + + private Boolean remote = false; + private Boolean anonymous = false; + /** Comma separated list of locales */ + private String availableLocales = ""; + + private String key = null; + private String anonymousRole = "ROLE_ANONYMOUS"; + + public SpringLoginModule() { + + } + + @SuppressWarnings("rawtypes") + public void initialize(Subject subject, CallbackHandler callbackHandler, + Map sharedState, Map options) { + super.initialize(subject, callbackHandler, sharedState, options); + this.callbackHandler = callbackHandler; + this.subject = subject; + } + + public boolean login() throws LoginException { + try { + // thread already logged in + if (SecurityContextHolder.getContext().getAuthentication() != null) + return super.login(); + + if (remote && anonymous) + throw new LoginException( + "Cannot have a Spring login module which is remote and anonymous"); + + // reset all principals and credentials + if (log.isTraceEnabled()) + log.trace("Resetting all principals and credentials of " + + subject); + if (subject.getPrincipals() != null) + subject.getPrincipals().clear(); + if (subject.getPrivateCredentials() != null) + subject.getPrivateCredentials().clear(); + if (subject.getPublicCredentials() != null) + subject.getPublicCredentials().clear(); + + Locale selectedLocale = null; + // deals first with public access since it's simple + if (anonymous) { + // multi locale + if (callbackHandler != null && availableLocales != null + && !availableLocales.trim().equals("")) { + LocaleCallback localeCallback = new LocaleCallback( + availableLocales); + callbackHandler.handle(new Callback[] { localeCallback }); + selectedLocale = localeCallback.getSelectedLocale(); + } + + // TODO integrate with JCR? + Object principal = UUID.randomUUID().toString(); + GrantedAuthority[] authorities = { new GrantedAuthorityImpl( + anonymousRole) }; + AnonymousAuthenticationToken anonymousToken = new AnonymousAuthenticationToken( + key, principal, authorities); + Authentication auth = authenticationManager + .authenticate(anonymousToken); + registerAuthentication(auth); + } else { + if (callbackHandler == null) + throw new LoginException("No call back handler available"); + + // ask for username and password + NameCallback nameCallback = new NameCallback("User"); + PasswordCallback passwordCallback = new PasswordCallback( + "Password", false); + final String defaultNodeUrl = System + .getProperty(NODE_REPO_URI, + "http://localhost:7070/org.argeo.jcr.webapp/remoting/node"); + NameCallback urlCallback = new NameCallback("Site URL", + defaultNodeUrl); + LocaleCallback localeCallback = new LocaleCallback( + availableLocales); + + // handle callbacks + if (remote) + callbackHandler.handle(new Callback[] { nameCallback, + passwordCallback, urlCallback, localeCallback }); + else + callbackHandler.handle(new Callback[] { nameCallback, + passwordCallback, localeCallback }); + + selectedLocale = localeCallback.getSelectedLocale(); + + // create credentials + String username = nameCallback.getName(); + if (username == null || username.trim().equals("")) + return false; + + String password = ""; + if (passwordCallback.getPassword() != null) + password = String.valueOf(passwordCallback.getPassword()); + + NodeAuthenticationToken credentials; + if (remote) { + String url = urlCallback.getName(); + credentials = new NodeAuthenticationToken(username, + password, url); + } else { + credentials = new NodeAuthenticationToken(username, + password); + } + + Authentication authentication; + try { + authentication = authenticationManager + .authenticate(credentials); + } catch (BadCredentialsException e) { + // wait between failed login attempts + Thread.sleep(waitBetweenFailedLoginAttempts); + throw e; + } + registerAuthentication(authentication); + } + + if (selectedLocale != null) + LocaleUtils.threadLocale.set(selectedLocale); + + return super.login(); + } catch (LoginException e) { + throw e; + } catch (ThreadDeath e) { + LoginException le = new LoginException( + "Spring Security login thread died"); + le.initCause(e); + throw le; + } catch (Exception e) { + LoginException le = new LoginException( + "Spring Security login failed"); + le.initCause(e); + throw le; + } + } + + @Override + public boolean logout() throws LoginException { + subject.getPrincipals().clear(); + return super.logout(); + } + + /** + * Register an {@link Authentication} in the security context. + * + * @param authentication + * has to implement {@link Authentication}. + */ + protected void registerAuthentication(Object authentication) { + SecurityContextHolder.getContext().setAuthentication( + (Authentication) authentication); + } + + public void setAuthenticationManager( + AuthenticationManager authenticationManager) { + this.authenticationManager = authenticationManager; + } + + /** Authenticates on a remote node */ + public void setRemote(Boolean remote) { + this.remote = remote; + } + + /** + * Request anonymous authentication (incompatible with remote) + */ + public void setAnonymous(Boolean anonymous) { + this.anonymous = anonymous; + } + + /** Role identifying an anonymous user */ + public void setAnonymousRole(String anonymousRole) { + this.anonymousRole = anonymousRole; + } + + /** System key */ + public void setKey(String key) { + this.key = key; + } + + public void setAvailableLocales(String locales) { + this.availableLocales = locales; + } + +} diff --git a/org.argeo.security.jackrabbit/.classpath b/org.argeo.security.jackrabbit/.classpath new file mode 100644 index 000000000..5641c7ca3 --- /dev/null +++ b/org.argeo.security.jackrabbit/.classpath @@ -0,0 +1,7 @@ + + + + >> + + + diff --git a/org.argeo.security.jackrabbit/.project b/org.argeo.security.jackrabbit/.project new file mode 100644 index 000000000..35bcca28f --- /dev/null +++ b/org.argeo.security.jackrabbit/.project @@ -0,0 +1,28 @@ + + + org.argeo.security.jackrabbit + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/org.argeo.security.jackrabbit/build.properties b/org.argeo.security.jackrabbit/build.properties new file mode 100644 index 000000000..5fc538bc8 --- /dev/null +++ b/org.argeo.security.jackrabbit/build.properties @@ -0,0 +1,4 @@ +source.. = src/main/java/ +output.. = target/classes/ +bin.includes = META-INF/,\ + . diff --git a/org.argeo.security.jackrabbit/pom.xml b/org.argeo.security.jackrabbit/pom.xml new file mode 100644 index 000000000..a18c453dd --- /dev/null +++ b/org.argeo.security.jackrabbit/pom.xml @@ -0,0 +1,63 @@ + + + 4.0.0 + + org.argeo.commons + argeo-commons + 2.1.12-SNAPSHOT + .. + + org.argeo.security.jackrabbit + Commons Security Jackrabbit + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-source-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + org.apache.felix + maven-bundle-plugin + + + + org.apache.jackrabbit + org.argeo.security.jackrabbit.* + + org.springframework.core, + org.argeo.jcr, + * + + + + + + + + org.argeo.commons + org.argeo.security.core + 2.1.12-SNAPSHOT + + + org.argeo.tp + javax.jcr + + + org.argeo.tp + org.apache.jackrabbit + + + org.argeo.tp + org.springframework.security.core + + + \ No newline at end of file diff --git a/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoAccessManager.java b/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoAccessManager.java new file mode 100644 index 000000000..52ea3c984 --- /dev/null +++ b/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoAccessManager.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.jackrabbit; + +import javax.jcr.PathNotFoundException; +import javax.jcr.RepositoryException; +import javax.jcr.security.Privilege; + +import org.apache.jackrabbit.core.id.ItemId; +import org.apache.jackrabbit.core.security.DefaultAccessManager; +import org.apache.jackrabbit.spi.Path; + +/** + * Intermediary class in order to have a consistent naming in config files. Does + * nothing for the time being, but may in the future. + */ +public class ArgeoAccessManager extends DefaultAccessManager { + + @Override + public boolean canRead(Path itemPath, ItemId itemId) + throws RepositoryException { + return super.canRead(itemPath, itemId); + } + + @Override + public Privilege[] getPrivileges(String absPath) + throws PathNotFoundException, RepositoryException { + return super.getPrivileges(absPath); + } + + @Override + public boolean hasPrivileges(String absPath, Privilege[] privileges) + throws PathNotFoundException, RepositoryException { + return super.hasPrivileges(absPath, privileges); + } + +} diff --git a/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoLoginModule.java b/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoLoginModule.java new file mode 100644 index 000000000..43c544083 --- /dev/null +++ b/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoLoginModule.java @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.jackrabbit; + +import java.security.Principal; +import java.security.acl.Group; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + +import javax.jcr.Credentials; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.SimpleCredentials; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.login.LoginException; + +import org.apache.jackrabbit.core.security.AnonymousPrincipal; +import org.apache.jackrabbit.core.security.authentication.AbstractLoginModule; +import org.apache.jackrabbit.core.security.authentication.Authentication; +import org.apache.jackrabbit.core.security.principal.AdminPrincipal; +import org.argeo.security.SystemAuthentication; +import org.springframework.security.GrantedAuthority; +import org.springframework.security.context.SecurityContextHolder; +import org.springframework.security.providers.anonymous.AnonymousAuthenticationToken; + +/** Jackrabbit login mechanism based on Spring Security */ +public class ArgeoLoginModule extends AbstractLoginModule { + private String adminRole = "ROLE_ADMIN"; + + @SuppressWarnings("unused") + @Override + public boolean login() throws LoginException { + boolean loginOk = super.login(); + if (!loginOk) { + org.springframework.security.Authentication authen = (org.springframework.security.Authentication) SecurityContextHolder + .getContext().getAuthentication(); + } + return loginOk; + } + + @SuppressWarnings("unused") + @Override + public boolean commit() throws LoginException { + boolean commitOk = super.commit(); + if (!commitOk) { + org.springframework.security.Authentication authen = (org.springframework.security.Authentication) SecurityContextHolder + .getContext().getAuthentication(); + } + return commitOk; + } + + /** + * Returns the Spring {@link org.springframework.security.Authentication} + * (which can be null) + */ + @Override + protected Principal getPrincipal(Credentials credentials) { + org.springframework.security.Authentication authen = SecurityContextHolder + .getContext().getAuthentication(); + return authen; + } + + protected Set getPrincipals() { + // clear already registered Jackrabbit principals + // clearPrincipals(AdminPrincipal.class); + // clearPrincipals(AnonymousPrincipal.class); + // clearPrincipals(GrantedAuthorityPrincipal.class); + + return syncPrincipals(); + } + + protected Set syncPrincipals() { + // use linked HashSet instead of HashSet in order to maintain the order + // of principals (as in the Subject). + org.springframework.security.Authentication authen = (org.springframework.security.Authentication) principal; + + Set principals = new LinkedHashSet(); + principals.add(authen); + + if (authen instanceof SystemAuthentication) { + principals.add(new AdminPrincipal(authen.getName())); + principals.add(new ArgeoSystemPrincipal(authen.getName())); + } else if (authen instanceof AnonymousAuthenticationToken) { + principals.add(new AnonymousPrincipal()); + } else { + for (GrantedAuthority ga : authen.getAuthorities()) { + principals.add(new GrantedAuthorityPrincipal(ga)); + // FIXME: make it more generic + if (adminRole.equals(ga.getAuthority())) + principals.add(new AdminPrincipal(authen.getName())); + } + } + + // remove previous credentials + Set thisCredentials = subject + .getPublicCredentials(SimpleCredentials.class); + if (thisCredentials != null) + thisCredentials.clear(); + // override credentials since we did not used the one passed to us + // credentials = new SimpleCredentials(authen.getName(), authen + // .getCredentials().toString().toCharArray()); + + return principals; + } + + /** + * Super implementation removes all {@link Principal}, the Spring + * {@link org.springframework.security.Authentication} as well. Here we + * simply clear Jackrabbit related {@link Principal}s. + */ + @Override + public boolean logout() throws LoginException { + clearPrincipals(AdminPrincipal.class); + clearPrincipals(ArgeoSystemPrincipal.class); + clearPrincipals(AnonymousPrincipal.class); + clearPrincipals(GrantedAuthorityPrincipal.class); + + // we resync with Spring Security since the subject may have been reused + // in beetween + // TODO: check if this is clean + // subject.getPrincipals().addAll(syncPrincipals()); + + return true; + } + + private void clearPrincipals(Class clss) { + Set principals = subject.getPrincipals(clss); + if (principals != null) + principals.clear(); + } + + @SuppressWarnings("rawtypes") + @Override + protected void doInit(CallbackHandler callbackHandler, Session session, + Map options) throws LoginException { + } + + @Override + protected boolean impersonate(Principal principal, Credentials credentials) + throws RepositoryException, LoginException { + throw new UnsupportedOperationException( + "Impersonation is not yet supported"); + } + + @Override + protected Authentication getAuthentication(final Principal principal, + Credentials creds) throws RepositoryException { + if (principal instanceof Group) { + return null; + } + return new Authentication() { + public boolean canHandle(Credentials credentials) { + return principal instanceof org.springframework.security.Authentication; + } + + public boolean authenticate(Credentials credentials) + throws RepositoryException { + return ((org.springframework.security.Authentication) principal) + .isAuthenticated(); + } + }; + } + +} diff --git a/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoSecurityManager.java b/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoSecurityManager.java new file mode 100644 index 000000000..3450c75d8 --- /dev/null +++ b/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoSecurityManager.java @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.jackrabbit; + +import java.security.Principal; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.security.auth.Subject; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.jackrabbit.api.security.user.Group; +import org.apache.jackrabbit.api.security.user.User; +import org.apache.jackrabbit.api.security.user.UserManager; +import org.apache.jackrabbit.core.DefaultSecurityManager; +import org.apache.jackrabbit.core.security.AMContext; +import org.apache.jackrabbit.core.security.AccessManager; +import org.apache.jackrabbit.core.security.AnonymousPrincipal; +import org.apache.jackrabbit.core.security.SecurityConstants; +import org.apache.jackrabbit.core.security.authorization.WorkspaceAccessManager; +import org.springframework.security.Authentication; +import org.springframework.security.GrantedAuthority; +import org.springframework.security.context.SecurityContextHolder; + +/** Integrates Spring Security and Jackrabbit Security users and roles. */ +public class ArgeoSecurityManager extends DefaultSecurityManager { + /** Legacy security sync */ + final static String PROPERTY_JACKRABBIT_SECURITY_SYNC_1_1 = "argeo.jackarabbit.securitySync.1.1"; + + private final static Log log = LogFactory + .getLog(ArgeoSecurityManager.class); + + private static Boolean synchronize = Boolean.parseBoolean(System + .getProperty(PROPERTY_JACKRABBIT_SECURITY_SYNC_1_1, "false")); + + /** TODO? use a bounded buffer */ + private Map userRolesCache = Collections + .synchronizedMap(new HashMap()); + + @Override + public AccessManager getAccessManager(Session session, AMContext amContext) + throws RepositoryException { + synchronized (getSystemSession()) { + return super.getAccessManager(session, amContext); + } + } + + @Override + public UserManager getUserManager(Session session) + throws RepositoryException { + synchronized (getSystemSession()) { + return super.getUserManager(session); + } + } + + /** + * Since this is called once when the session is created, we take the + * opportunity to make sure that Jackrabbit users and groups reflect Spring + * Security name and authorities. + */ + @Override + public String getUserID(Subject subject, String workspaceName) + throws RepositoryException { + if (!synchronize) { + Authentication authentication = SecurityContextHolder.getContext() + .getAuthentication(); + if (authentication != null) + return authentication.getName(); + else + return super.getUserID(subject, workspaceName); + } + + if (log.isTraceEnabled()) + log.trace(subject); + // skip anonymous user (no rights) + if (!subject.getPrincipals(AnonymousPrincipal.class).isEmpty()) + return super.getUserID(subject, workspaceName); + // skip Jackrabbit system user (all rights) + if (!subject.getPrincipals(ArgeoSystemPrincipal.class).isEmpty()) + return super.getUserID(subject, workspaceName); + + // retrieve Spring authentication from JAAS + // TODO? use Spring Security context holder + Authentication authen; + Set authens = subject + .getPrincipals(Authentication.class); + String userId = super.getUserID(subject, workspaceName); + if (authens.size() == 0) { + // make sure that logged-in user has a Principal, useful for testing + // using an admin user + UserManager systemUm = getSystemUserManager(null); + if (systemUm.getAuthorizable(userId) == null) + systemUm.createUser(userId, ""); + } else {// Spring Security + authen = authens.iterator().next(); + + if (!userId.equals(authen.getName())) + log.warn("User ID is '" + userId + "' but authen is " + + authen.getName()); + StringBuffer roles = new StringBuffer(""); + GrantedAuthority[] authorities = authen.getAuthorities(); + for (GrantedAuthority ga : authorities) { + roles.append(ga.toString()); + } + + // do not sync if not changed + if (userRolesCache.containsKey(userId) + && userRolesCache.get(userId).equals(roles.toString())) + return userId; + + // sync Spring and Jackrabbit + // workspace is irrelevant here + UserManager systemUm = getSystemUserManager(null); + syncSpringAndJackrabbitSecurity(systemUm, authen); + userRolesCache.put(userId, roles.toString()); + } + return userId; + } + + /** + * Make sure that the Jackrabbit security model contains this user and its + * granted authorities + */ + static private void syncSpringAndJackrabbitSecurity(UserManager systemUm, + Authentication authen) throws RepositoryException { + long begin = System.currentTimeMillis(); + + String userId = authen.getName(); + User user = (User) systemUm.getAuthorizable(userId); + if (user == null) { + user = systemUm.createUser(userId, authen.getCredentials() + .toString(), authen, null); + log.info(userId + " added as " + user); + } + + // process groups + List userGroupIds = new ArrayList(); + for (GrantedAuthority ga : authen.getAuthorities()) { + Group group = (Group) systemUm.getAuthorizable(ga.getAuthority()); + if (group == null) { + group = systemUm.createGroup(ga.getAuthority()); + log.info(ga.getAuthority() + " added as " + group); + } + if (!group.isMember(user)) + group.addMember(user); + userGroupIds.add(ga.getAuthority()); + } + + // check if user has not been removed from some groups + for (Iterator it = user.declaredMemberOf(); it.hasNext();) { + Group group = it.next(); + if (!userGroupIds.contains(group.getID())) + group.removeMember(user); + } + + if (log.isTraceEnabled()) + log.trace("Spring and Jackrabbit Security synchronized for user " + + userId + " in " + (System.currentTimeMillis() - begin) + + " ms"); + } + + @Override + protected WorkspaceAccessManager createDefaultWorkspaceAccessManager() { + WorkspaceAccessManager wam = super + .createDefaultWorkspaceAccessManager(); + return new ArgeoWorkspaceAccessManagerImpl(wam); + } + + private class ArgeoWorkspaceAccessManagerImpl implements SecurityConstants, + WorkspaceAccessManager { + private final WorkspaceAccessManager wam; + + public ArgeoWorkspaceAccessManagerImpl(WorkspaceAccessManager wam) { + super(); + this.wam = wam; + } + + public void init(Session systemSession) throws RepositoryException { + wam.init(systemSession); + } + + public void close() throws RepositoryException { + } + + public boolean grants(Set principals, String workspaceName) + throws RepositoryException { + // TODO: implements finer access to workspaces + return true; + } + } + +} diff --git a/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoSystemPrincipal.java b/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoSystemPrincipal.java new file mode 100644 index 000000000..e38981ef4 --- /dev/null +++ b/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoSystemPrincipal.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.jackrabbit; + +import java.security.Principal; + +/** Principal for non-interactive system actions. */ +class ArgeoSystemPrincipal implements Principal { + private String name; + + public ArgeoSystemPrincipal(String name) { + super(); + this.name = name; + } + + public String getName() { + return name; + } + + @Override + public int hashCode() { + return getName().hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof ArgeoSystemPrincipal)) + return false; + return getName().equals(((ArgeoSystemPrincipal) obj).getName()); + } + + @Override + public String toString() { + return "Argeo System (non interactive) name=" + getName(); + } + +} diff --git a/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/GrantedAuthorityPrincipal.java b/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/GrantedAuthorityPrincipal.java new file mode 100644 index 000000000..482214e50 --- /dev/null +++ b/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/GrantedAuthorityPrincipal.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.jackrabbit; + +import java.security.Principal; + +import org.springframework.security.GrantedAuthority; + +/** Wraps a {@link GrantedAuthority} as a principal. */ +class GrantedAuthorityPrincipal implements Principal { + private final GrantedAuthority grantedAuthority; + + public GrantedAuthorityPrincipal(GrantedAuthority grantedAuthority) { + this.grantedAuthority = grantedAuthority; + } + + public String getName() { + return grantedAuthority.getAuthority(); + } + + @Override + public int hashCode() { + return getName().hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof GrantedAuthorityPrincipal)) + return false; + return getName().equals(((GrantedAuthorityPrincipal) obj).getName()); + } + + @Override + public String toString() { + return "Granted Authority " + getName(); + } + +} diff --git a/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/JackrabbitSecurityModel.java b/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/JackrabbitSecurityModel.java new file mode 100644 index 000000000..a9985f94f --- /dev/null +++ b/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/JackrabbitSecurityModel.java @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.jackrabbit; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.jackrabbit.api.JackrabbitSession; +import org.apache.jackrabbit.api.security.user.Group; +import org.apache.jackrabbit.api.security.user.User; +import org.apache.jackrabbit.api.security.user.UserManager; +import org.argeo.ArgeoException; +import org.argeo.jcr.ArgeoNames; +import org.argeo.security.jcr.SimpleJcrSecurityModel; + +/** Make sure that user authorizable exists before syncing user directories. */ +public class JackrabbitSecurityModel extends SimpleJcrSecurityModel { + private final static Log log = LogFactory + .getLog(JackrabbitSecurityModel.class); + + @Override + public synchronized Node sync(Session session, String username, + List roles) { + if (!(session instanceof JackrabbitSession)) + return super.sync(session, username, roles); + + try { + UserManager userManager = ((JackrabbitSession) session) + .getUserManager(); + User user = (User) userManager.getAuthorizable(username); + if (user != null) { + String principalName = user.getPrincipal().getName(); + if (!principalName.equals(username)) { + log.warn("Jackrabbit principal is '" + principalName + + "' but username is '" + username + + "'. Recreating..."); + user.remove(); + user = userManager.createUser(username, ""); + } + } else { + // create new principal + user = userManager.createUser(username, ""); + log.info(username + " added as Jackrabbit user " + user); + } + + // generic JCR sync + Node userProfile = super.sync(session, username, roles); + + Boolean enabled = userProfile.getProperty(ArgeoNames.ARGEO_ENABLED) + .getBoolean(); + if (enabled && user.isDisabled()) + user.disable(null); + else if (!enabled && !user.isDisabled()) + user.disable(userProfile.getPath() + " is disabled"); + + // Sync Jackrabbit roles + if (roles != null) + syncRoles(userManager, user, roles); + + return userProfile; + } catch (RepositoryException e) { + throw new ArgeoException( + "Cannot perform Jackrabbit specific operations", e); + } + } + + /** Make sure Jackrabbit roles are in line with authentication */ + void syncRoles(UserManager userManager, User user, List roles) + throws RepositoryException { + List userGroupIds = new ArrayList(); + for (String role : roles) { + Group group = (Group) userManager.getAuthorizable(role); + if (group == null) { + group = userManager.createGroup(role); + log.info(role + " added as " + group); + } + if (!group.isMember(user)) + group.addMember(user); + userGroupIds.add(role); + } + + // check if user has not been removed from some groups + for (Iterator it = user.declaredMemberOf(); it.hasNext();) { + Group group = it.next(); + if (!userGroupIds.contains(group.getID())) + group.removeMember(user); + } + } +} diff --git a/org.argeo.security.ldap/.classpath b/org.argeo.security.ldap/.classpath new file mode 100644 index 000000000..5641c7ca3 --- /dev/null +++ b/org.argeo.security.ldap/.classpath @@ -0,0 +1,7 @@ + + + + >> + + + diff --git a/org.argeo.security.ldap/.project b/org.argeo.security.ldap/.project new file mode 100644 index 000000000..942f1404d --- /dev/null +++ b/org.argeo.security.ldap/.project @@ -0,0 +1,28 @@ + + + org.argeo.security.ldap + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/org.argeo.security.ldap/build.properties b/org.argeo.security.ldap/build.properties new file mode 100644 index 000000000..5fc538bc8 --- /dev/null +++ b/org.argeo.security.ldap/build.properties @@ -0,0 +1,4 @@ +source.. = src/main/java/ +output.. = target/classes/ +bin.includes = META-INF/,\ + . diff --git a/org.argeo.security.ldap/pom.xml b/org.argeo.security.ldap/pom.xml new file mode 100644 index 000000000..5b798b411 --- /dev/null +++ b/org.argeo.security.ldap/pom.xml @@ -0,0 +1,76 @@ + + 4.0.0 + + org.argeo.commons + argeo-commons + 2.1.12-SNAPSHOT + .. + + org.argeo.security.ldap + Commons Security LDAP + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-source-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + org.apache.felix + maven-bundle-plugin + + + + + org.argeo.security.ldap.* + + + org.springframework.core, + org.springframework.dao, + javax.jcr.nodetype, + * + + + + + + + + + org.argeo.commons + org.argeo.util + 2.1.12-SNAPSHOT + + + org.argeo.commons + org.argeo.security.core + 2.1.12-SNAPSHOT + + + + + org.argeo.tp + javax.jcr + + + + + org.argeo.tp + org.springframework.ldap + + + + + org.argeo.tp + slf4j.org.apache.commons.logging + + + + \ No newline at end of file diff --git a/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/ArgeoLdapShaPasswordEncoder.java b/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/ArgeoLdapShaPasswordEncoder.java new file mode 100644 index 000000000..ea22ef350 --- /dev/null +++ b/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/ArgeoLdapShaPasswordEncoder.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ldap; + +import org.springframework.security.providers.ldap.authenticator.LdapShaPasswordEncoder; + +/** + * {@link LdapShaPasswordEncoder} allowing to configure the usage of salt (APache + * Directory Server 1.0 does not support bind with SSHA) + */ +public class ArgeoLdapShaPasswordEncoder extends LdapShaPasswordEncoder { + private Boolean useSalt = true; + + @Override + public String encodePassword(String rawPass, Object salt) { + return super.encodePassword(rawPass, useSalt ? salt : null); + } + + public void setUseSalt(Boolean useSalt) { + this.useSalt = useSalt; + } + +} diff --git a/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/ArgeoLdapUserDetailsManager.java b/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/ArgeoLdapUserDetailsManager.java new file mode 100644 index 000000000..0c7368f1f --- /dev/null +++ b/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/ArgeoLdapUserDetailsManager.java @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ldap; + +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Random; +import java.util.Set; +import java.util.TreeSet; + +import org.argeo.ArgeoException; +import org.argeo.security.UserAdminService; +import org.springframework.ldap.core.ContextSource; +import org.springframework.security.Authentication; +import org.springframework.security.GrantedAuthority; +import org.springframework.security.context.SecurityContextHolder; +import org.springframework.security.providers.encoding.PasswordEncoder; +import org.springframework.security.userdetails.UserDetails; +import org.springframework.security.userdetails.ldap.LdapUserDetailsManager; + +/** Extends {@link LdapUserDetailsManager} by adding password encoding support. */ +public class ArgeoLdapUserDetailsManager extends LdapUserDetailsManager + implements UserAdminService { + private String superUsername = "root"; + private ArgeoUserAdminDaoLdap userAdminDao; + private PasswordEncoder passwordEncoder; + private final Random random; + + public ArgeoLdapUserDetailsManager(ContextSource contextSource) { + super(contextSource); + this.random = createRandom(); + } + + private static Random createRandom() { + try { + return SecureRandom.getInstance("SHA1PRNG"); + } catch (NoSuchAlgorithmException e) { + return new Random(System.currentTimeMillis()); + } + } + + @Override + public void changePassword(String oldPassword, String newPassword) { + Authentication authentication = SecurityContextHolder.getContext() + .getAuthentication(); + if (authentication == null) + throw new ArgeoException( + "Cannot change password without authentication"); + String username = authentication.getName(); + UserDetails userDetails = loadUserByUsername(username); + String currentPassword = userDetails.getPassword(); + if (currentPassword == null) + throw new ArgeoException("Cannot access current password"); + if (!passwordEncoder + .isPasswordValid(currentPassword, oldPassword, null)) + throw new ArgeoException("Old password invalid"); + // Spring Security LDAP 2.0 is buggy when used with OpenLDAP and called + // with oldPassword argument + super.changePassword(null, encodePassword(newPassword)); + } + + public void newRole(String role) { + userAdminDao.createRole(role, superUsername); + } + + public void synchronize() { + for (String username : userAdminDao.listUsers()) + loadUserByUsername(username); + // TODO: find a way to remove from JCR + } + + public void deleteRole(String role) { + userAdminDao.deleteRole(role); + } + + public Set listUsers() { + return userAdminDao.listUsers(); + } + + public Set listUsersInRole(String role) { + Set lst = new TreeSet( + userAdminDao.listUsersInRole(role)); + Iterator it = lst.iterator(); + while (it.hasNext()) { + if (it.next().equals(superUsername)) { + it.remove(); + break; + } + } + return lst; + } + + public List listUserRoles(String username) { + UserDetails userDetails = loadUserByUsername(username); + List roles = new ArrayList(); + for (GrantedAuthority ga : userDetails.getAuthorities()) { + roles.add(ga.getAuthority()); + } + return Collections.unmodifiableList(roles); + } + + public Set listEditableRoles() { + return userAdminDao.listEditableRoles(); + } + + protected String encodePassword(String password) { + if (!password.startsWith("{")) { + byte[] salt = new byte[16]; + random.nextBytes(salt); + return passwordEncoder.encodePassword(password, salt); + } else { + return password; + } + } + + public void setPasswordEncoder(PasswordEncoder passwordEncoder) { + this.passwordEncoder = passwordEncoder; + } + + public void setSuperUsername(String superUsername) { + this.superUsername = superUsername; + } + + public void setUserAdminDao(ArgeoUserAdminDaoLdap userAdminDao) { + this.userAdminDao = userAdminDao; + } + +} diff --git a/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/ArgeoUserAdminDaoLdap.java b/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/ArgeoUserAdminDaoLdap.java new file mode 100644 index 000000000..37d2a06a0 --- /dev/null +++ b/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/ArgeoUserAdminDaoLdap.java @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ldap; + +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +import javax.naming.Name; +import javax.naming.NamingException; +import javax.naming.directory.DirContext; + +import org.springframework.ldap.core.ContextExecutor; +import org.springframework.ldap.core.ContextMapper; +import org.springframework.ldap.core.DirContextAdapter; +import org.springframework.ldap.core.DistinguishedName; +import org.springframework.ldap.core.LdapTemplate; +import org.springframework.ldap.core.support.BaseLdapPathContextSource; +import org.springframework.security.ldap.LdapUsernameToDnMapper; +import org.springframework.security.ldap.LdapUtils; + +/** + * Wraps low-level LDAP operation on user and roles, used by + * {@link ArgeoLdapUserDetailsManager} + */ +public class ArgeoUserAdminDaoLdap { + private String userBase; + private String usernameAttribute; + private String groupBase; + private String[] groupClasses; + + private String groupRoleAttribute; + private String groupMemberAttribute; + private String defaultRole; + private String rolePrefix; + + private final LdapTemplate ldapTemplate; + private LdapUsernameToDnMapper usernameMapper; + + /** + * Standard constructor, using the LDAP context source shared with Spring + * Security components. + */ + public ArgeoUserAdminDaoLdap(BaseLdapPathContextSource contextSource) { + this.ldapTemplate = new LdapTemplate(contextSource); + } + + @SuppressWarnings("unchecked") + public synchronized Set listUsers() { + List usernames = (List) ldapTemplate.listBindings( + new DistinguishedName(userBase), new ContextMapper() { + public Object mapFromContext(Object ctxArg) { + DirContextAdapter ctx = (DirContextAdapter) ctxArg; + return ctx.getStringAttribute(usernameAttribute); + } + }); + + return Collections + .unmodifiableSortedSet(new TreeSet(usernames)); + } + + @SuppressWarnings("unchecked") + public Set listEditableRoles() { + return Collections.unmodifiableSortedSet(new TreeSet( + ldapTemplate.listBindings(groupBase, new ContextMapper() { + public Object mapFromContext(Object ctxArg) { + String groupName = ((DirContextAdapter) ctxArg) + .getStringAttribute(groupRoleAttribute); + String roleName = convertGroupToRole(groupName); + return roleName; + } + }))); + } + + @SuppressWarnings("unchecked") + public Set listUsersInRole(String role) { + return (Set) ldapTemplate.lookup( + buildGroupDn(convertRoleToGroup(role)), new ContextMapper() { + public Object mapFromContext(Object ctxArg) { + DirContextAdapter ctx = (DirContextAdapter) ctxArg; + String[] userDns = ctx + .getStringAttributes(groupMemberAttribute); + TreeSet set = new TreeSet(); + for (String userDn : userDns) { + DistinguishedName dn = new DistinguishedName(userDn); + String username = dn.getValue(usernameAttribute); + set.add(username); + } + return Collections.unmodifiableSortedSet(set); + } + }); + } + + public void createRole(String role, final String superuserName) { + String group = convertRoleToGroup(role); + DistinguishedName superuserDn = (DistinguishedName) ldapTemplate + .executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + return LdapUtils.getFullDn( + usernameMapper.buildDn(superuserName), ctx); + } + }); + + Name groupDn = buildGroupDn(group); + DirContextAdapter context = new DirContextAdapter(); + context.setAttributeValues("objectClass", groupClasses); + context.setAttributeValue("cn", group); + // Add superuser because cannot create empty group + context.setAttributeValue(groupMemberAttribute, superuserDn.toString()); + ldapTemplate.bind(groupDn, context, null); + } + + public void deleteRole(String role) { + String group = convertRoleToGroup(role); + Name dn = buildGroupDn(group); + ldapTemplate.unbind(dn); + } + + /** Maps a role (ROLE_XXX) to the related LDAP group (xxx) */ + protected String convertRoleToGroup(String role) { + String group = role; + if (group.startsWith(rolePrefix)) { + group = group.substring(rolePrefix.length()); + group = group.toLowerCase(); + } + return group; + } + + /** Maps anLDAP group (xxx) to the related role (ROLE_XXX) */ + protected String convertGroupToRole(String groupName) { + groupName = groupName.toUpperCase(); + + return rolePrefix + groupName; + } + + protected Name buildGroupDn(String name) { + return new DistinguishedName(groupRoleAttribute + "=" + name + "," + + groupBase); + } + + public void setUserBase(String userBase) { + this.userBase = userBase; + } + + public void setUsernameAttribute(String usernameAttribute) { + this.usernameAttribute = usernameAttribute; + } + + public void setGroupBase(String groupBase) { + this.groupBase = groupBase; + } + + public void setGroupRoleAttribute(String groupRoleAttributeName) { + this.groupRoleAttribute = groupRoleAttributeName; + } + + public void setGroupMemberAttribute(String groupMemberAttributeName) { + this.groupMemberAttribute = groupMemberAttributeName; + } + + public void setDefaultRole(String defaultRole) { + this.defaultRole = defaultRole; + } + + public void setRolePrefix(String rolePrefix) { + this.rolePrefix = rolePrefix; + } + + public void setUsernameMapper(LdapUsernameToDnMapper usernameMapper) { + this.usernameMapper = usernameMapper; + } + + public String getDefaultRole() { + return defaultRole; + } + + public void setGroupClasses(String[] groupClasses) { + this.groupClasses = groupClasses; + } +} diff --git a/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/jcr/JcrLdapSynchronizer.java b/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/jcr/JcrLdapSynchronizer.java new file mode 100644 index 000000000..3e9e2cbfa --- /dev/null +++ b/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/jcr/JcrLdapSynchronizer.java @@ -0,0 +1,619 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ldap.jcr; + +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.SortedSet; +import java.util.UUID; + +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.query.Query; +import javax.jcr.version.VersionManager; +import javax.naming.Name; +import javax.naming.directory.BasicAttribute; +import javax.naming.directory.DirContext; +import javax.naming.directory.ModificationItem; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; +import org.argeo.jcr.ArgeoNames; +import org.argeo.jcr.ArgeoTypes; +import org.argeo.jcr.JcrUtils; +import org.argeo.security.SecurityUtils; +import org.argeo.security.jcr.JcrSecurityModel; +import org.argeo.security.jcr.JcrUserDetails; +import org.argeo.security.jcr.SimpleJcrSecurityModel; +import org.springframework.ldap.core.ContextMapper; +import org.springframework.ldap.core.DirContextAdapter; +import org.springframework.ldap.core.DirContextOperations; +import org.springframework.ldap.core.DistinguishedName; +import org.springframework.ldap.core.LdapTemplate; +import org.springframework.security.GrantedAuthority; +import org.springframework.security.ldap.LdapUsernameToDnMapper; +import org.springframework.security.providers.encoding.PasswordEncoder; +import org.springframework.security.userdetails.UserDetails; +import org.springframework.security.userdetails.ldap.UserDetailsContextMapper; + +/** Makes sure that LDAP and JCR are in line. */ +public class JcrLdapSynchronizer implements UserDetailsContextMapper, + ArgeoNames { + private final static Log log = LogFactory.getLog(JcrLdapSynchronizer.class); + + // LDAP + private LdapTemplate ldapTemplate; + /** + * LDAP template whose context source has an object factory set to null. see + * this + */ + // private LdapTemplate rawLdapTemplate; + + private String userBase; + private String usernameAttribute; + private String passwordAttribute; + private String[] userClasses; + // private String defaultUserRole ="ROLE_USER"; + + // private NamingListener ldapUserListener; + // private SearchControls subTreeSearchControls; + private LdapUsernameToDnMapper usernameMapper; + + private PasswordEncoder passwordEncoder; + private final Random random; + + // JCR + /** Admin session on the main workspace */ + private Session nodeSession; + private Repository repository; + + // private JcrProfileListener jcrProfileListener; + private JcrSecurityModel jcrSecurityModel = new SimpleJcrSecurityModel(); + + // Mapping + private Map propertyToAttributes = new HashMap(); + + public JcrLdapSynchronizer() { + random = createRandom(); + } + + public void init() { + try { + nodeSession = repository.login(); + + // TODO put this in a different thread, and poll the LDAP server + // until it is up + try { + synchronize(); + + // LDAP + // subTreeSearchControls = new SearchControls(); + // subTreeSearchControls + // .setSearchScope(SearchControls.SUBTREE_SCOPE); + // LDAP listener + // ldapUserListener = new LdapUserListener(); + // rawLdapTemplate.executeReadOnly(new ContextExecutor() { + // public Object executeWithContext(DirContext ctx) + // throws NamingException { + // EventDirContext ectx = (EventDirContext) ctx.lookup(""); + // ectx.addNamingListener(userBase, "(" + // + usernameAttribute + "=*)", + // subTreeSearchControls, ldapUserListener); + // return null; + // } + // }); + } catch (Exception e) { + log.error("Could not synchronize and listen to LDAP," + + " probably because the LDAP server is not available." + + " Restart the system as soon as possible.", e); + } + + // JCR + // String[] nodeTypes = { ArgeoTypes.ARGEO_USER_PROFILE }; + // jcrProfileListener = new JcrProfileListener(); + // noLocal is used so that we are not notified when we modify JCR + // from LDAP + // nodeSession + // .getWorkspace() + // .getObservationManager() + // .addEventListener(jcrProfileListener, + // Event.PROPERTY_CHANGED | Event.NODE_ADDED, "/", + // true, null, nodeTypes, true); + } catch (Exception e) { + JcrUtils.logoutQuietly(nodeSession); + throw new ArgeoException("Cannot initialize LDAP/JCR synchronizer", + e); + } + } + + public void destroy() { + // JcrUtils.removeListenerQuietly(nodeSession, jcrProfileListener); + JcrUtils.logoutQuietly(nodeSession); + // try { + // rawLdapTemplate.executeReadOnly(new ContextExecutor() { + // public Object executeWithContext(DirContext ctx) + // throws NamingException { + // EventDirContext ectx = (EventDirContext) ctx.lookup(""); + // ectx.removeNamingListener(ldapUserListener); + // return null; + // } + // }); + // } catch (Exception e) { + // // silent (LDAP server may have been shutdown already) + // if (log.isTraceEnabled()) + // log.trace("Cannot remove LDAP listener", e); + // } + } + + /* + * LDAP TO JCR + */ + /** Full synchronization between LDAP and JCR. LDAP has priority. */ + protected void synchronize() { + try { + Name userBaseName = new DistinguishedName(userBase); + // TODO subtree search? + @SuppressWarnings("unchecked") + List userPaths = (List) ldapTemplate.listBindings( + userBaseName, new ContextMapper() { + public Object mapFromContext(Object ctxObj) { + try { + return mapLdapToJcr((DirContextAdapter) ctxObj); + } catch (Exception e) { + // do not break process because of error + log.error( + "Could not LDAP->JCR synchronize user " + + ctxObj, e); + return null; + } + } + }); + + // create accounts which are not in LDAP + Query query = nodeSession + .getWorkspace() + .getQueryManager() + .createQuery( + "select * from [" + ArgeoTypes.ARGEO_USER_PROFILE + + "]", Query.JCR_SQL2); + NodeIterator it = query.execute().getNodes(); + while (it.hasNext()) { + Node userProfile = it.nextNode(); + String path = userProfile.getPath(); + try { + if (!userPaths.contains(path)) { + String username = userProfile + .getProperty(ARGEO_USER_ID).getString(); + // GrantedAuthority[] authorities = {new + // GrantedAuthorityImpl(defaultUserRole)}; + GrantedAuthority[] authorities = {}; + JcrUserDetails userDetails = new JcrUserDetails( + userProfile, username, authorities); + String dn = createLdapUser(userDetails); + log.warn("Created ldap entry '" + dn + "' for user '" + + username + "'"); + + // if(!userProfile.getProperty(ARGEO_ENABLED).getBoolean()){ + // continue profiles; + // } + // + // log.warn("Path " + // + path + // + " not found in LDAP, disabling user " + // + userProfile.getProperty(ArgeoNames.ARGEO_USER_ID) + // .getString()); + + // Temporary hack to repair previous behaviour + if (!userProfile.getProperty(ARGEO_ENABLED) + .getBoolean()) { + VersionManager versionManager = nodeSession + .getWorkspace().getVersionManager(); + versionManager.checkout(userProfile.getPath()); + userProfile.setProperty(ArgeoNames.ARGEO_ENABLED, + true); + nodeSession.save(); + versionManager.checkin(userProfile.getPath()); + } + } + } catch (Exception e) { + log.error("Cannot process " + path, e); + } + } + } catch (Exception e) { + JcrUtils.discardQuietly(nodeSession); + log.error("Cannot synchronize LDAP and JCR", e); + // throw new ArgeoException("Cannot synchronize LDAP and JCR", e); + } + } + + private String createLdapUser(UserDetails user) { + DirContextAdapter ctx = new DirContextAdapter(); + mapUserToContext(user, ctx); + DistinguishedName dn = usernameMapper.buildDn(user.getUsername()); + ldapTemplate.bind(dn, ctx, null); + return dn.toString(); + } + + /** Called during authentication in order to retrieve user details */ + public UserDetails mapUserFromContext(final DirContextOperations ctx, + final String username, GrantedAuthority[] authorities) { + if (ctx == null) + throw new ArgeoException("No LDAP information for user " + username); + + String ldapUsername = ctx.getStringAttribute(usernameAttribute); + if (!ldapUsername.equals(username)) + throw new ArgeoException("Logged in with username " + username + + " but LDAP user is " + ldapUsername); + + Node userProfile = jcrSecurityModel.sync(nodeSession, username, + SecurityUtils.authoritiesToStringList(authorities)); + // JcrUserDetails.checkAccountStatus(userProfile); + + // password + SortedSet passwordAttributes = ctx + .getAttributeSortedStringSet(passwordAttribute); + String password; + if (passwordAttributes == null || passwordAttributes.size() == 0) { + //throw new ArgeoException("No password found for user " + username); + password = "NULL"; + } else { + byte[] arr = (byte[]) passwordAttributes.first(); + password = new String(arr); + // erase password + Arrays.fill(arr, (byte) 0); + } + + try { + return new JcrUserDetails(userProfile, password, authorities); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot retrieve user details for " + + username, e); + } + } + + /** + * Writes an LDAP context to the JCR user profile. + * + * @return path to user profile + */ + protected synchronized String mapLdapToJcr(DirContextAdapter ctx) { + Session session = nodeSession; + try { + // process + String username = ctx.getStringAttribute(usernameAttribute); + + Node userProfile = jcrSecurityModel.sync(session, username, null); + Map modifications = new HashMap(); + for (String jcrProperty : propertyToAttributes.keySet()) + ldapToJcr(userProfile, jcrProperty, ctx, modifications); + + int modifCount = modifications.size(); + if (modifCount > 0) { + session.getWorkspace().getVersionManager() + .checkout(userProfile.getPath()); + for (String prop : modifications.keySet()) + userProfile.setProperty(prop, modifications.get(prop)); + JcrUtils.updateLastModified(userProfile); + session.save(); + session.getWorkspace().getVersionManager() + .checkin(userProfile.getPath()); + if (log.isDebugEnabled()) + log.debug("Mapped " + modifCount + " LDAP modification" + + (modifCount == 1 ? "" : "s") + " from " + + ctx.getDn() + " to " + userProfile); + } + return userProfile.getPath(); + } catch (Exception e) { + JcrUtils.discardQuietly(session); + throw new ArgeoException("Cannot synchronize JCR and LDAP", e); + } + } + + /** Maps an LDAP property to a JCR property */ + protected void ldapToJcr(Node userProfile, String jcrProperty, + DirContextOperations ctx, Map modifications) { + // TODO do we really need DirContextOperations? + try { + String ldapAttribute; + if (propertyToAttributes.containsKey(jcrProperty)) + ldapAttribute = propertyToAttributes.get(jcrProperty); + else + throw new ArgeoException( + "No LDAP attribute mapped for JCR proprty " + + jcrProperty); + + String value = ctx.getStringAttribute(ldapAttribute); + String jcrValue = userProfile.hasProperty(jcrProperty) ? userProfile + .getProperty(jcrProperty).getString() : null; + if (value != null && jcrValue != null) { + if (!value.equals(jcrValue)) + modifications.put(jcrProperty, value); + } else if (value != null && jcrValue == null) { + modifications.put(jcrProperty, value); + } else if (value == null && jcrValue != null) { + modifications.put(jcrProperty, value); + } + } catch (Exception e) { + throw new ArgeoException("Cannot map JCR property " + jcrProperty + + " from LDAP", e); + } + } + + /* + * JCR to LDAP + */ + + public void mapUserToContext(UserDetails user, final DirContextAdapter ctx) { + if (!(user instanceof JcrUserDetails)) + throw new ArgeoException("Unsupported user details: " + + user.getClass()); + + ctx.setAttributeValues("objectClass", userClasses); + ctx.setAttributeValue(usernameAttribute, user.getUsername()); + ctx.setAttributeValue(passwordAttribute, + encodePassword(user.getPassword())); + + final JcrUserDetails jcrUserDetails = (JcrUserDetails) user; + try { + Node userProfile = nodeSession + .getNode(jcrUserDetails.getHomePath()).getNode( + ARGEO_PROFILE); + for (String jcrProperty : propertyToAttributes.keySet()) { + if (userProfile.hasProperty(jcrProperty)) { + ModificationItem mi = jcrToLdap(jcrProperty, userProfile + .getProperty(jcrProperty).getString()); + if (mi != null) + ctx.setAttribute(mi.getAttribute()); + } + } + if (log.isTraceEnabled()) + log.trace("Mapped " + userProfile + " to " + ctx.getDn()); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot synchronize JCR and LDAP", e); + } + + } + + /** Maps a JCR property to an LDAP property */ + protected ModificationItem jcrToLdap(String jcrProperty, String value) { + // TODO do we really need DirContextOperations? + try { + String ldapAttribute; + if (propertyToAttributes.containsKey(jcrProperty)) + ldapAttribute = propertyToAttributes.get(jcrProperty); + else + return null; + + // fix issue with empty 'sn' in LDAP + if (ldapAttribute.equals("sn") && (value.trim().equals(""))) + return null; + // fix issue with empty 'description' in LDAP + if (ldapAttribute.equals("description") && value.trim().equals("")) + return null; + BasicAttribute attr = new BasicAttribute( + propertyToAttributes.get(jcrProperty), value); + ModificationItem mi = new ModificationItem( + DirContext.REPLACE_ATTRIBUTE, attr); + return mi; + } catch (Exception e) { + throw new ArgeoException("Cannot map JCR property " + jcrProperty + + " from LDAP", e); + } + } + + /* + * UTILITIES + */ + protected String encodePassword(String password) { + if (!password.startsWith("{")) { + byte[] salt = new byte[16]; + random.nextBytes(salt); + return passwordEncoder.encodePassword(password, salt); + } else { + return password; + } + } + + private static Random createRandom() { + try { + return SecureRandom.getInstance("SHA1PRNG"); + } catch (NoSuchAlgorithmException e) { + return new Random(System.currentTimeMillis()); + } + } + + /* + * DEPENDENCY INJECTION + */ + + public void setLdapTemplate(LdapTemplate ldapTemplate) { + this.ldapTemplate = ldapTemplate; + } + + public void setRawLdapTemplate(LdapTemplate rawLdapTemplate) { + // this.rawLdapTemplate = rawLdapTemplate; + } + + public void setRepository(Repository repository) { + this.repository = repository; + } + + public void setUserBase(String userBase) { + this.userBase = userBase; + } + + public void setUsernameAttribute(String usernameAttribute) { + this.usernameAttribute = usernameAttribute; + } + + public void setPropertyToAttributes(Map propertyToAttributes) { + this.propertyToAttributes = propertyToAttributes; + } + + public void setUsernameMapper(LdapUsernameToDnMapper usernameMapper) { + this.usernameMapper = usernameMapper; + } + + public void setPasswordAttribute(String passwordAttribute) { + this.passwordAttribute = passwordAttribute; + } + + public void setUserClasses(String[] userClasses) { + this.userClasses = userClasses; + } + + public void setPasswordEncoder(PasswordEncoder passwordEncoder) { + this.passwordEncoder = passwordEncoder; + } + + public void setJcrSecurityModel(JcrSecurityModel jcrSecurityModel) { + this.jcrSecurityModel = jcrSecurityModel; + } + + /** Listen to LDAP */ + // class LdapUserListener implements ObjectChangeListener, + // NamespaceChangeListener, UnsolicitedNotificationListener { + // + // public void namingExceptionThrown(NamingExceptionEvent evt) { + // evt.getException().printStackTrace(); + // } + // + // public void objectChanged(NamingEvent evt) { + // Binding user = evt.getNewBinding(); + // // TODO find a way not to be called when JCR is the source of the + // // modification + // DirContextAdapter ctx = (DirContextAdapter) ldapTemplate + // .lookup(user.getName()); + // mapLdapToJcr(ctx); + // } + // + // public void objectAdded(NamingEvent evt) { + // Binding user = evt.getNewBinding(); + // DirContextAdapter ctx = (DirContextAdapter) ldapTemplate + // .lookup(user.getName()); + // mapLdapToJcr(ctx); + // } + // + // public void objectRemoved(NamingEvent evt) { + // if (log.isDebugEnabled()) + // log.debug(evt); + // } + // + // public void objectRenamed(NamingEvent evt) { + // if (log.isDebugEnabled()) + // log.debug(evt); + // } + // + // public void notificationReceived(UnsolicitedNotificationEvent evt) { + // UnsolicitedNotification notification = evt.getNotification(); + // NamingException ne = notification.getException(); + // String msg = "LDAP notification " + "ID=" + notification.getID() + // + ", referrals=" + notification.getReferrals(); + // if (ne != null) { + // if (log.isTraceEnabled()) + // log.trace(msg + ", exception= " + ne, ne); + // else + // log.warn(msg + ", exception= " + ne); + // } else if (log.isDebugEnabled()) { + // log.debug("Unsollicited LDAP notification " + msg); + // } + // } + // + // } + + /** Listen to JCR */ + // class JcrProfileListener implements EventListener { + // + // public void onEvent(EventIterator events) { + // try { + // final Map> modifications = new HashMap>(); + // while (events.hasNext()) { + // Event event = events.nextEvent(); + // try { + // if (Event.PROPERTY_CHANGED == event.getType()) { + // Property property = (Property) nodeSession + // .getItem(event.getPath()); + // String propertyName = property.getName(); + // Node userProfile = property.getParent(); + // String username = userProfile.getProperty( + // ARGEO_USER_ID).getString(); + // if (propertyToAttributes.containsKey(propertyName)) { + // Name name = usernameMapper.buildDn(username); + // if (!modifications.containsKey(name)) + // modifications.put(name, + // new ArrayList()); + // String value = property.getString(); + // ModificationItem mi = jcrToLdap(propertyName, + // value); + // if (mi != null) + // modifications.get(name).add(mi); + // } + // } else if (Event.NODE_ADDED == event.getType()) { + // Node userProfile = nodeSession.getNode(event + // .getPath()); + // String username = userProfile.getProperty( + // ARGEO_USER_ID).getString(); + // Name name = usernameMapper.buildDn(username); + // for (String propertyName : propertyToAttributes + // .keySet()) { + // if (!modifications.containsKey(name)) + // modifications.put(name, + // new ArrayList()); + // String value = userProfile.getProperty( + // propertyName).getString(); + // ModificationItem mi = jcrToLdap(propertyName, + // value); + // if (mi != null) + // modifications.get(name).add(mi); + // } + // } + // } catch (RepositoryException e) { + // throw new ArgeoException("Cannot process event " + // + event, e); + // } + // } + // + // for (Name name : modifications.keySet()) { + // List userModifs = modifications.get(name); + // int modifCount = userModifs.size(); + // ldapTemplate.modifyAttributes(name, userModifs + // .toArray(new ModificationItem[modifCount])); + // if (log.isDebugEnabled()) + // log.debug("Mapped " + modifCount + " JCR modification" + // + (modifCount == 1 ? "" : "s") + " to " + name); + // } + // } catch (Exception e) { + // // if (log.isDebugEnabled()) + // // e.printStackTrace(); + // throw new ArgeoException("Cannot process JCR events (" + // + e.getMessage() + ")", e); + // } + // } + // + // } +} diff --git a/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/jcr/JcrUserDetailsContextMapper.java b/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/jcr/JcrUserDetailsContextMapper.java new file mode 100644 index 000000000..87973d9bd --- /dev/null +++ b/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/jcr/JcrUserDetailsContextMapper.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ldap.jcr; + +import java.util.UUID; + +import javax.jcr.Node; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.argeo.ArgeoException; +import org.argeo.jcr.ArgeoNames; +import org.argeo.jcr.JcrUtils; +import org.argeo.jcr.UserJcrUtils; +import org.argeo.security.jcr.JcrUserDetails; +import org.springframework.ldap.core.DirContextAdapter; +import org.springframework.ldap.core.DirContextOperations; +import org.springframework.security.GrantedAuthority; +import org.springframework.security.userdetails.UserDetails; +import org.springframework.security.userdetails.ldap.UserDetailsContextMapper; + +/** @deprecated Read only mapping from LDAP to user details */ +@Deprecated +public class JcrUserDetailsContextMapper implements UserDetailsContextMapper, + ArgeoNames { + /** Admin session on the security workspace */ + private Session securitySession; + private Repository repository; + private String securityWorkspace = "security"; + + public void init() { + try { + securitySession = repository.login(securityWorkspace); + } catch (RepositoryException e) { + JcrUtils.logoutQuietly(securitySession); + throw new ArgeoException( + "Cannot initialize LDAP/JCR user details context mapper", e); + } + } + + public void destroy() { + JcrUtils.logoutQuietly(securitySession); + } + + /** Called during authentication in order to retrieve user details */ + public UserDetails mapUserFromContext(final DirContextOperations ctx, + final String username, GrantedAuthority[] authorities) { + if (ctx == null) + throw new ArgeoException("No LDAP information for user " + username); + Node userHome = UserJcrUtils.getUserHome(securitySession, username); + if (userHome == null) + throw new ArgeoException("No JCR information for user " + username); + + // password + // SortedSet passwordAttributes = ctx + // .getAttributeSortedStringSet(passwordAttribute); + // String password; + // if (passwordAttributes == null || passwordAttributes.size() == 0) { + // throw new ArgeoException("No password found for user " + username); + // } else { + // byte[] arr = (byte[]) passwordAttributes.first(); + // password = new String(arr); + // // erase password + // Arrays.fill(arr, (byte) 0); + // } + + try { + // we don't have access to password, so let's not pretend + String password = UUID.randomUUID().toString(); + return new JcrUserDetails(userHome.getNode(ARGEO_PROFILE), + password, authorities); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot retrieve user details for " + + username, e); + } + } + + public void mapUserToContext(UserDetails user, final DirContextAdapter ctx) { + throw new UnsupportedOperationException("LDAP access is read-only"); + } + +} diff --git a/org.argeo.security.mvc/.classpath b/org.argeo.security.mvc/.classpath new file mode 100644 index 000000000..ff41fbb4d --- /dev/null +++ b/org.argeo.security.mvc/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/org.argeo.security.mvc/.project b/org.argeo.security.mvc/.project new file mode 100644 index 000000000..b287d0835 --- /dev/null +++ b/org.argeo.security.mvc/.project @@ -0,0 +1,28 @@ + + + org.argeo.security.mvc + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.pde.PluginNature + + diff --git a/org.argeo.security.mvc/.settings/org.eclipse.jdt.core.prefs b/org.argeo.security.mvc/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..d2110d0b1 --- /dev/null +++ b/org.argeo.security.mvc/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,5 @@ +#Tue Sep 15 11:35:07 CEST 2009 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.source=1.5 diff --git a/org.argeo.security.mvc/.settings/org.maven.ide.eclipse.prefs b/org.argeo.security.mvc/.settings/org.maven.ide.eclipse.prefs new file mode 100644 index 000000000..2169c4308 --- /dev/null +++ b/org.argeo.security.mvc/.settings/org.maven.ide.eclipse.prefs @@ -0,0 +1,9 @@ +#Tue Sep 15 11:35:01 CEST 2009 +activeProfiles= +eclipse.preferences.version=1 +fullBuildGoals=process-test-resources +includeModules=false +resolveWorkspaceProjects=true +resourceFilterGoals=process-resources resources\:testResources +skipCompilerPlugin=true +version=1 diff --git a/org.argeo.security.mvc/build.properties b/org.argeo.security.mvc/build.properties new file mode 100644 index 000000000..a740a346d --- /dev/null +++ b/org.argeo.security.mvc/build.properties @@ -0,0 +1,2 @@ +additional.bundles = org.springframework.beans +source.. = src/main/java/ diff --git a/org.argeo.security.mvc/pom.xml b/org.argeo.security.mvc/pom.xml new file mode 100644 index 000000000..dcee8b322 --- /dev/null +++ b/org.argeo.security.mvc/pom.xml @@ -0,0 +1,72 @@ + + 4.0.0 + + org.argeo.commons + argeo-commons + 2.1.12-SNAPSHOT + .. + + org.argeo.security.mvc + Commons Security MVC + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-source-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + org.apache.felix + maven-bundle-plugin + + + + + org.argeo.security.mvc.* + + *,javax.servlet + + + + + + + + + org.argeo.commons + org.argeo.server.core + 2.1.12-SNAPSHOT + + + + + org.argeo.commons + org.argeo.security.core + 2.1.12-SNAPSHOT + + + + + org.argeo.tp + org.springframework.web.servlet + + + org.argeo.tp + org.springframework.aop + + + + + org.argeo.tp + javax.servlet + + + + \ No newline at end of file diff --git a/org.argeo.security.mvc/src/main/java/org/argeo/security/mvc/ArgeoRememberMeServices.java b/org.argeo.security.mvc/src/main/java/org/argeo/security/mvc/ArgeoRememberMeServices.java new file mode 100644 index 000000000..fde9f3034 --- /dev/null +++ b/org.argeo.security.mvc/src/main/java/org/argeo/security/mvc/ArgeoRememberMeServices.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2007-2012 Mathieu Baudier + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.mvc; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.security.ui.rememberme.TokenBasedRememberMeServices; + +public class ArgeoRememberMeServices extends TokenBasedRememberMeServices { + public final static String DEFAULT_COOKIE_NAME = "ARGEO_SECURITY"; + + public ArgeoRememberMeServices() { + setCookieName(DEFAULT_COOKIE_NAME); + } + + /** + * Sets a "cancel cookie" (with maxAge = 0) on the response to disable + * persistent logins. + * + * @param request + * @param response + */ + protected void cancelCookie(HttpServletRequest request, + HttpServletResponse response) { + Cookie cookie = new Cookie(getCookieName(), null); + cookie.setMaxAge(0); + cookie.setPath("/"); + + response.addCookie(cookie); + } + + /** + * Sets the cookie on the response + * + * @param tokens + * the tokens which will be encoded to make the cookie value. + * @param maxAge + * the value passed to {@link Cookie#setMaxAge(int)} + * @param request + * the request + * @param response + * the response to add the cookie to. + */ + protected void setCookie(String[] tokens, int maxAge, + HttpServletRequest request, HttpServletResponse response) { + String cookieValue = encodeCookie(tokens); + Cookie cookie = new Cookie(getCookieName(), cookieValue); + cookie.setMaxAge(maxAge); + cookie.setPath("/"); + response.addCookie(cookie); + } + +} diff --git a/org.argeo.security.mvc/src/main/java/org/argeo/security/mvc/ArgeoUserInterceptor.java b/org.argeo.security.mvc/src/main/java/org/argeo/security/mvc/ArgeoUserInterceptor.java new file mode 100644 index 000000000..fd83e9f73 --- /dev/null +++ b/org.argeo.security.mvc/src/main/java/org/argeo/security/mvc/ArgeoUserInterceptor.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2007-2012 Mathieu Baudier + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.mvc; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.argeo.security.UserAdminService; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; + +/** Add the current argeo user as an attribute to the request. */ +public class ArgeoUserInterceptor extends HandlerInterceptorAdapter { + private UserAdminService securityService; + + @Override + public boolean preHandle(HttpServletRequest request, + HttpServletResponse response, Object handler) throws Exception { + //request.setAttribute("argeoUser", securityService.getCurrentUser()); + return super.preHandle(request, response, handler); + } + + public void setSecurityService(UserAdminService securityService) { + this.securityService = securityService; + } + +} diff --git a/org.argeo.security.mvc/src/main/java/org/argeo/security/mvc/UsersRolesController.java b/org.argeo.security.mvc/src/main/java/org/argeo/security/mvc/UsersRolesController.java new file mode 100644 index 000000000..185d376a6 --- /dev/null +++ b/org.argeo.security.mvc/src/main/java/org/argeo/security/mvc/UsersRolesController.java @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2007-2012 Mathieu Baudier + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.mvc; + +import org.argeo.server.mvc.MvcConstants; +import org.springframework.stereotype.Controller; + +@Controller +public class UsersRolesController implements MvcConstants { +// private ArgeoSecurityService securityService; +// private Deserializer userDeserializer = null; + + /* USER */ + +// @RequestMapping("/getCredentials.*") +// @ModelAttribute("user") +// public ArgeoUser getCredentials() { +// ArgeoUser argeoUser = securityService.getCurrentUser(); +// if (argeoUser == null) +// return new SimpleArgeoUser(); +// else +// return argeoUser; +// } +// +// @RequestMapping("/getUsersList.*") +// @ModelAttribute("users") +// public Set getUsersList() { +// return securityService.listUsers(); +// } +// +// @RequestMapping("/userExists.*") +// public BooleanAnswer userExists(@RequestParam("username") String username) { +// return new BooleanAnswer(securityService.userExists(username)); +// } +// +// @RequestMapping("/createUser.*") +// @ModelAttribute("user") +// public ArgeoUser createUser(Reader reader) { +// ArgeoUser user = userDeserializer.deserialize(reader, +// SimpleArgeoUser.class); +// securityService.newUser(user); +// return securityService.getUser(user.getUsername()); +// } +// +// @RequestMapping("/updateUser.*") +// @ModelAttribute("user") +// public ArgeoUser updateUser(Reader reader) { +// ArgeoUser user = userDeserializer.deserialize(reader, +// SimpleArgeoUser.class); +// securityService.updateUser(user); +// return securityService.getUser(user.getUsername()); +// } +// +// @RequestMapping("/updateUserSelf.*") +// @ModelAttribute("user") +// /** Will only update the user natures.*/ +// public ArgeoUser updateUserSelf(Reader reader) { +// ArgeoUser user = securityService.getCurrentUser(); +// ArgeoUser userForNatures = userDeserializer.deserialize(reader, +// SimpleArgeoUser.class); +// user.updateUserNatures(userForNatures.getUserNatures()); +// securityService.updateUser(user); +// return securityService.getUser(user.getUsername()); +// } +// +// @RequestMapping("/deleteUser.*") +// public ServerAnswer deleteUser(@RequestParam("username") String username) { +// securityService.deleteUser(username); +// return ServerAnswer.ok("User " + username + " deleted"); +// } +// +// @RequestMapping("/getUserDetails.*") +// @ModelAttribute("user") +// public ArgeoUser getUserDetails(@RequestParam("username") String username) { +// return securityService.getUser(username); +// } + + /* ROLE */ +// @RequestMapping("/getRolesList.*") +// @ModelAttribute("roles") +// public Set getEditableRolesList() { +// return securityService.listEditableRoles(); +// } +// +// @RequestMapping("/createRole.*") +// public ServerAnswer createRole(@RequestParam("role") String role) { +// securityService.newRole(role); +// return ServerAnswer.ok("Role " + role + " created"); +// } +// +// @RequestMapping("/deleteRole.*") +// public ServerAnswer deleteRole(@RequestParam("role") String role) { +// securityService.deleteRole(role); +// return ServerAnswer.ok("Role " + role + " deleted"); +// } +// +// @RequestMapping("/updateUserPassword.*") +// public ServerAnswer updateUserPassword( +// @RequestParam("username") String username, +// @RequestParam("password") String password) { +// securityService.updateUserPassword(username, password); +// return ServerAnswer.ok("Password updated for user " + username); +// } +// +// @RequestMapping("/updatePassword.*") +// public ServerAnswer updatePassword( +// @RequestParam("oldPassword") String oldPassword, +// @RequestParam("password") String password) { +// securityService.updateCurrentUserPassword(oldPassword, password); +// return ServerAnswer.ok("Password updated"); +// } +// +// public void setUserDeserializer(Deserializer userDeserializer) { +// this.userDeserializer = userDeserializer; +// } +// +// public void setSecurityService(ArgeoSecurityService securityService) { +// this.securityService = securityService; +// } + +} diff --git a/org.argeo.security.ui.admin/.classpath b/org.argeo.security.ui.admin/.classpath new file mode 100644 index 000000000..848725036 --- /dev/null +++ b/org.argeo.security.ui.admin/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/org.argeo.security.ui.admin/.project b/org.argeo.security.ui.admin/.project new file mode 100644 index 000000000..9821dd947 --- /dev/null +++ b/org.argeo.security.ui.admin/.project @@ -0,0 +1,28 @@ + + + org.argeo.security.ui.admin + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/org.argeo.security.ui.admin/META-INF/spring/commands.xml b/org.argeo.security.ui.admin/META-INF/spring/commands.xml new file mode 100644 index 000000000..e0a435e07 --- /dev/null +++ b/org.argeo.security.ui.admin/META-INF/spring/commands.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.argeo.security.ui.admin/META-INF/spring/common.xml b/org.argeo.security.ui.admin/META-INF/spring/common.xml new file mode 100644 index 000000000..737f30430 --- /dev/null +++ b/org.argeo.security.ui.admin/META-INF/spring/common.xml @@ -0,0 +1,20 @@ + + + + + + + osgibundle:security-admin.properties + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.security.ui.admin/META-INF/spring/editors.xml b/org.argeo.security.ui.admin/META-INF/spring/editors.xml new file mode 100644 index 000000000..740792a61 --- /dev/null +++ b/org.argeo.security.ui.admin/META-INF/spring/editors.xml @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/org.argeo.security.ui.admin/META-INF/spring/osgi.xml b/org.argeo.security.ui.admin/META-INF/spring/osgi.xml new file mode 100644 index 000000000..2fa51446c --- /dev/null +++ b/org.argeo.security.ui.admin/META-INF/spring/osgi.xml @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/org.argeo.security.ui.admin/META-INF/spring/views.xml b/org.argeo.security.ui.admin/META-INF/spring/views.xml new file mode 100644 index 000000000..2ddb05f60 --- /dev/null +++ b/org.argeo.security.ui.admin/META-INF/spring/views.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/org.argeo.security.ui.admin/build.properties b/org.argeo.security.ui.admin/build.properties new file mode 100644 index 000000000..c41623e1f --- /dev/null +++ b/org.argeo.security.ui.admin/build.properties @@ -0,0 +1,5 @@ +bin.includes = plugin.xml,\ + META-INF/,\ + security-admin.properties +source.. = src/main/java/ +output.. = target/classes/ diff --git a/org.argeo.security.ui.admin/icons/add.gif b/org.argeo.security.ui.admin/icons/add.gif new file mode 100644 index 000000000..252d7ebcb Binary files /dev/null and b/org.argeo.security.ui.admin/icons/add.gif differ diff --git a/org.argeo.security.ui.admin/icons/batch.gif b/org.argeo.security.ui.admin/icons/batch.gif new file mode 100644 index 000000000..b8ca14a8b Binary files /dev/null and b/org.argeo.security.ui.admin/icons/batch.gif differ diff --git a/org.argeo.security.ui.admin/icons/clear.gif b/org.argeo.security.ui.admin/icons/clear.gif new file mode 100644 index 000000000..6bc10f9d0 Binary files /dev/null and b/org.argeo.security.ui.admin/icons/clear.gif differ diff --git a/org.argeo.security.ui.admin/icons/refresh.png b/org.argeo.security.ui.admin/icons/refresh.png new file mode 100644 index 000000000..a3884fb48 Binary files /dev/null and b/org.argeo.security.ui.admin/icons/refresh.png differ diff --git a/org.argeo.security.ui.admin/icons/remove.gif b/org.argeo.security.ui.admin/icons/remove.gif new file mode 100644 index 000000000..0ae6decd0 Binary files /dev/null and b/org.argeo.security.ui.admin/icons/remove.gif differ diff --git a/org.argeo.security.ui.admin/icons/role.gif b/org.argeo.security.ui.admin/icons/role.gif new file mode 100644 index 000000000..274a850e4 Binary files /dev/null and b/org.argeo.security.ui.admin/icons/role.gif differ diff --git a/org.argeo.security.ui.admin/icons/save.gif b/org.argeo.security.ui.admin/icons/save.gif new file mode 100644 index 000000000..654ad7b42 Binary files /dev/null and b/org.argeo.security.ui.admin/icons/save.gif differ diff --git a/org.argeo.security.ui.admin/icons/save_security.png b/org.argeo.security.ui.admin/icons/save_security.png new file mode 100644 index 000000000..ca41dc92b Binary files /dev/null and b/org.argeo.security.ui.admin/icons/save_security.png differ diff --git a/org.argeo.security.ui.admin/icons/save_security_disabled.png b/org.argeo.security.ui.admin/icons/save_security_disabled.png new file mode 100644 index 000000000..fb7d08d9a Binary files /dev/null and b/org.argeo.security.ui.admin/icons/save_security_disabled.png differ diff --git a/org.argeo.security.ui.admin/icons/security.gif b/org.argeo.security.ui.admin/icons/security.gif new file mode 100644 index 000000000..57fb95edc Binary files /dev/null and b/org.argeo.security.ui.admin/icons/security.gif differ diff --git a/org.argeo.security.ui.admin/icons/sync.gif b/org.argeo.security.ui.admin/icons/sync.gif new file mode 100644 index 000000000..b4fa052de Binary files /dev/null and b/org.argeo.security.ui.admin/icons/sync.gif differ diff --git a/org.argeo.security.ui.admin/icons/user.gif b/org.argeo.security.ui.admin/icons/user.gif new file mode 100644 index 000000000..90a00147b Binary files /dev/null and b/org.argeo.security.ui.admin/icons/user.gif differ diff --git a/org.argeo.security.ui.admin/icons/users.gif b/org.argeo.security.ui.admin/icons/users.gif new file mode 100644 index 000000000..2de7edd64 Binary files /dev/null and b/org.argeo.security.ui.admin/icons/users.gif differ diff --git a/org.argeo.security.ui.admin/plugin.xml b/org.argeo.security.ui.admin/plugin.xml new file mode 100644 index 000000000..e260bdea4 --- /dev/null +++ b/org.argeo.security.ui.admin/plugin.xml @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.argeo.security.ui.admin/pom.xml b/org.argeo.security.ui.admin/pom.xml new file mode 100644 index 000000000..9aeb51efd --- /dev/null +++ b/org.argeo.security.ui.admin/pom.xml @@ -0,0 +1,113 @@ + + + 4.0.0 + + org.argeo.commons + 2.1.12-SNAPSHOT + argeo-commons + .. + + org.argeo.security.ui.admin + Commons Security Admin UI + jar + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-source-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + org.apache.felix + maven-bundle-plugin + + + ${project.artifactId};singleton:=true + lazy + org.argeo.security.ui.admin.SecurityAdminPlugin + org.eclipse.core.runtime + + *, + org.eclipse.swt, + org.eclipse.ui.services, + org.eclipse.jface.window, + org.argeo.eclipse.spring, + org.springframework.dao, + org.springframework.core, + + org.argeo.security.ui.admin.* + + + + + + + + + org.argeo.commons + org.argeo.security.ui + 2.1.12-SNAPSHOT + + + + org.argeo.commons + org.argeo.security.core + 2.1.12-SNAPSHOT + + + + + org.argeo.commons + org.argeo.eclipse.ui.jcr + 2.1.12-SNAPSHOT + + + + org.argeo.commons + org.argeo.eclipse.ui + 2.1.12-SNAPSHOT + + + + + org.argeo.commons + org.argeo.eclipse.dep.rcp + 2.1.12-SNAPSHOT + provided + + + org.argeo.commons + org.argeo.eclipse.ui.rcp + 2.1.12-SNAPSHOT + provided + + + + + org.argeo.commons + org.argeo.util + 2.1.12-SNAPSHOT + + + + + org.argeo.tp + org.springframework.security.core + + + + + org.argeo.tp + slf4j.org.apache.commons.logging + + + + \ No newline at end of file diff --git a/org.argeo.security.ui.admin/security-admin.properties b/org.argeo.security.ui.admin/security-admin.properties new file mode 100644 index 000000000..e69de29bb diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/SecurityAdminImages.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/SecurityAdminImages.java new file mode 100644 index 000000000..f7ffa9c8d --- /dev/null +++ b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/SecurityAdminImages.java @@ -0,0 +1,33 @@ +/* + * Argeo Connect - Data management and communications + * Copyright (C) 2012 Argeo GmbH + * + * This program 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 3 of the License, or + * (at your option) any later version. + * + * This program 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 this program. If not, see + * + * Additional permission under GNU GPL version 3 section 7 + * + * If you modify this Program, or any covered work, by linking or combining it + * with software covered by the terms of the Eclipse Public License, the + * licensors of this Program grant you additional permission to convey the + * resulting work. Corresponding Source for a non-source form of such a + * combination shall include the source code for the parts of such software + * which are used as well as that of the covered work. + */ +package org.argeo.security.ui.admin; + +/** Shared icons that must be declared programmatically . */ +public class SecurityAdminImages { + @SuppressWarnings("unused") + private final static String PREFIX = "icons/"; +} diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/SecurityAdminPerspective.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/SecurityAdminPerspective.java new file mode 100644 index 000000000..c743f56bd --- /dev/null +++ b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/SecurityAdminPerspective.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.admin; + +import org.argeo.security.ui.admin.views.RolesView; +import org.argeo.security.ui.admin.views.UsersView; +import org.eclipse.ui.IFolderLayout; +import org.eclipse.ui.IPageLayout; +import org.eclipse.ui.IPerspectiveFactory; + +public class SecurityAdminPerspective implements IPerspectiveFactory { + public void createInitialLayout(IPageLayout layout) { + String editorArea = layout.getEditorArea(); + layout.setEditorAreaVisible(true); + layout.setFixed(false); + + IFolderLayout left = layout.createFolder("left", IPageLayout.LEFT, + 0.65f, editorArea); + left.addView(UsersView.ID); + left.addView(RolesView.ID); + } + +} diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/SecurityAdminPlugin.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/SecurityAdminPlugin.java new file mode 100644 index 000000000..06e9bd5b9 --- /dev/null +++ b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/SecurityAdminPlugin.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.admin; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +public class SecurityAdminPlugin extends AbstractUIPlugin { + public static final String PLUGIN_ID = "org.argeo.security.ui.admin"; //$NON-NLS-1$ + private static SecurityAdminPlugin plugin; + + public SecurityAdminPlugin() { + } + + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + } + + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + public static SecurityAdminPlugin getDefault() { + return plugin; + } + + public static ImageDescriptor getImageDescriptor(String path) { + return imageDescriptorFromPlugin(PLUGIN_ID, path); + } + +} diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/UserTableComposite.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/UserTableComposite.java new file mode 100644 index 000000000..720faded4 --- /dev/null +++ b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/UserTableComposite.java @@ -0,0 +1,367 @@ +package org.argeo.security.ui.admin; + +import java.util.ArrayList; +import java.util.List; + +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.Property; +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.query.QueryManager; +import javax.jcr.query.QueryResult; +import javax.jcr.query.qom.Constraint; +import javax.jcr.query.qom.Ordering; +import javax.jcr.query.qom.QueryObjectModel; +import javax.jcr.query.qom.QueryObjectModelFactory; +import javax.jcr.query.qom.Selector; +import javax.jcr.query.qom.StaticOperand; + +import org.argeo.ArgeoException; +import org.argeo.eclipse.ui.EclipseUiUtils; +import org.argeo.eclipse.ui.jcr.JcrUiUtils; +import org.argeo.eclipse.ui.jcr.lists.ColumnDefinition; +import org.argeo.eclipse.ui.jcr.lists.NodeViewerComparator; +import org.argeo.eclipse.ui.jcr.lists.SimpleJcrNodeLabelProvider; +import org.argeo.eclipse.ui.specific.EclipseUiSpecificUtils; +import org.argeo.eclipse.ui.utils.ViewerUtils; +import org.argeo.jcr.ArgeoNames; +import org.argeo.jcr.ArgeoTypes; +import org.argeo.jcr.JcrUtils; +import org.eclipse.jface.viewers.CheckboxTableViewer; +import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TableViewerColumn; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.Text; + +public class UserTableComposite extends Composite implements ArgeoNames { + // private final static Log log = + // LogFactory.getLog(UserTableComposite.class); + + private static final long serialVersionUID = -7385959046279360420L; + + private TableViewer usersViewer; + private Text filterTxt; + private final static String FILTER_HELP_MSG = "Type filter criterion " + + "separated by a space"; + private Session session; + + private Font italic; + private Font bold; + + private boolean hasFilter; + private boolean hasSelectionColumn; + + // private List selectedItems = new ArrayList(); + + /** + * Overwrite to display other columns + */ + public List getColumnsDef() { + List columnDefs = new ArrayList(); + + // User ID + columnDefs.add(new ColumnDefinition(null, ARGEO_USER_ID, + PropertyType.STRING, "User ID", 100)); + // Displayed name + columnDefs.add(new ColumnDefinition(null, Property.JCR_TITLE, + PropertyType.STRING, "Name", 150)); + + // E-mail + columnDefs.add(new ColumnDefinition(null, ARGEO_PRIMARY_EMAIL, + PropertyType.STRING, "E-mail", 150)); + + // Description + columnDefs.add(new ColumnDefinition(null, Property.JCR_DESCRIPTION, + PropertyType.STRING, "Description", 200)); + + return columnDefs; + } + + public UserTableComposite(Composite parent, int style, Session session) { + super(parent, style); + this.session = session; + } + + /** + * + * @param addFilter + * choose to add a field to filter results or not + * @param addSelection + * choose to add a column to select some of the displayed results + * or not + */ + public void populate(boolean addFilter, boolean addSelection) { + // initialization + Composite parent = this; + italic = EclipseUiUtils.getItalicFont(parent); + bold = EclipseUiUtils.getBoldFont(parent); + hasFilter = addFilter; + hasSelectionColumn = addSelection; + + // Main Layout + this.setLayout(new GridLayout(1, false)); + if (hasFilter) + createFilterPart(parent); + usersViewer = createTableViewer(parent); + EclipseUiSpecificUtils.enableToolTipSupport(usersViewer); + usersViewer.setContentProvider(new UsersContentProvider()); + refreshFilteredList(); + } + + public List getSelectedUsers() { + if (hasSelectionColumn) { + Object[] elements = ((CheckboxTableViewer) usersViewer) + .getCheckedElements(); + + List result = new ArrayList(); + for (Object obj : elements) { + result.add((Node) obj); + } + return result; + } else + throw new ArgeoException("Unvalid request: no selection column " + + "has been created for the current table"); + } + + /** Returns the User table viewer, typically to add doubleclick listener */ + public TableViewer getTableViewer() { + return usersViewer; + } + + /** Returns filter String or null*/ + protected String getFilterString() { + return hasFilter ? filterTxt.getText() : null; + } + + + + private TableViewer createTableViewer(final Composite parent) { + int style = SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL; + if (hasSelectionColumn) + style = style | SWT.CHECK; + + Table table = new Table(parent, style); + table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + + TableViewer viewer; + if (hasSelectionColumn) + viewer = new CheckboxTableViewer(table); + else + viewer = new TableViewer(table); + table.setLinesVisible(true); + table.setHeaderVisible(true); + + // pass a mapping between col index and property name to the comparator. + // List propertiesList = new ArrayList(); + + TableViewerColumn column; + int offset = 0; + if (hasSelectionColumn) { + offset = 1; + column = ViewerUtils.createTableViewerColumn(viewer, "", SWT.NONE, + 25); + column.setLabelProvider(new ColumnLabelProvider() { + private static final long serialVersionUID = 1L; + + @Override + public String getText(Object element) { + return null; + } + }); + SelectionAdapter selectionAdapter = new SelectionAdapter() { + private static final long serialVersionUID = 1L; + + boolean allSelected = false; + + @Override + public void widgetSelected(SelectionEvent e) { + allSelected = !allSelected; + ((CheckboxTableViewer) usersViewer) + .setAllChecked(allSelected); + } + }; + column.getColumn().addSelectionListener(selectionAdapter); + } + + // Create other columns + List colDefs = getColumnsDef(); + + NodeViewerComparator comparator = new NodeViewerComparator(); + int i = offset; + for (ColumnDefinition colDef : colDefs) { + column = ViewerUtils.createTableViewerColumn(viewer, + colDef.getHeaderLabel(), SWT.NONE, colDef.getColumnSize()); + column.setLabelProvider(new CLProvider(colDef.getPropertyName())); + column.getColumn().addSelectionListener( + JcrUiUtils.getNodeSelectionAdapter(i, + colDef.getPropertyType(), colDef.getPropertyName(), + comparator, viewer)); + i++; + } + + // IMPORTANT: initialize comparator before setting it + ColumnDefinition firstCol = colDefs.get(0); + comparator.setColumn(firstCol.getPropertyType(), + firstCol.getPropertyName()); + viewer.setComparator(comparator); + + return viewer; + } + + private class CLProvider extends SimpleJcrNodeLabelProvider { + + private static final long serialVersionUID = 1L; + + public CLProvider(String propertyName) { + super(propertyName); + } + + public String getToolTipText(Object element) { + return getText(element); + } + + @Override + public Font getFont(Object elem) { + // self + String username = getProperty(elem, ARGEO_USER_ID); + if (username.equals(session.getUserID())) + return bold; + + // disabled + try { + Node userProfile = (Node) elem; + // Node userProfile = userHome.getNode(ARGEO_PROFILE); + if (!userProfile.getProperty(ARGEO_ENABLED).getBoolean()) + return italic; + else + return null; + } catch (RepositoryException e) { + throw new ArgeoException("Cannot get font for " + username, e); + } + } + } + + @Override + public boolean setFocus() { + usersViewer.getTable().setFocus(); + return true; + } + + @Override + public void dispose() { + super.dispose(); + } + + public void refresh() { + refreshFilteredList(); + } + + private String getProperty(Object element, String name) { + try { + Node userProfile = (Node) element; + return userProfile.hasProperty(name) ? userProfile + .getProperty(name).getString() : ""; + } catch (RepositoryException e) { + throw new ArgeoException("Cannot get property " + name, e); + } + } + + private class UsersContentProvider implements IStructuredContentProvider { + private static final long serialVersionUID = 1L; + + public Object[] getElements(Object inputElement) { + return (Object[]) inputElement; + } + + public void dispose() { + } + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + } + + /* MANAGE FILTER */ + private void createFilterPart(Composite parent) { + // Text Area for the filter + filterTxt = new Text(parent, SWT.BORDER | SWT.SEARCH | SWT.ICON_SEARCH + | SWT.ICON_CANCEL); + filterTxt.setMessage(FILTER_HELP_MSG); + filterTxt.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL + | GridData.HORIZONTAL_ALIGN_FILL)); + filterTxt.addModifyListener(new ModifyListener() { + private static final long serialVersionUID = 1L; + + public void modifyText(ModifyEvent event) { + refreshFilteredList(); + } + }); + } + + /** + * Refresh the user list: caller might overwrite in order to display a + * subset of all users, typically to remove current user from the list + */ + protected void refreshFilteredList() { + List nodes; + try { + nodes = JcrUtils.nodeIteratorToList(listFilteredElements(session, + hasFilter ? filterTxt.getText() : null)); + usersViewer.setInput(nodes.toArray()); + } catch (RepositoryException e) { + throw new ArgeoException("Unable to list users", e); + } + } + + /** + * Build repository request : caller might overwrite in order to display a + * subset of all users + */ + protected NodeIterator listFilteredElements(Session session, String filter) + throws RepositoryException { + QueryManager queryManager = session.getWorkspace().getQueryManager(); + QueryObjectModelFactory factory = queryManager.getQOMFactory(); + + Selector source = factory.selector(ArgeoTypes.ARGEO_USER_PROFILE, + ArgeoTypes.ARGEO_USER_PROFILE); + + // Dynamically build constraint depending on the filter String + Constraint defaultC = null; + if (filter != null && !"".equals(filter.trim())) { + String[] strs = filter.trim().split(" "); + for (String token : strs) { + StaticOperand so = factory.literal(session.getValueFactory() + .createValue("*" + token + "*")); + Constraint currC = factory.fullTextSearch( + source.getSelectorName(), null, so); + if (defaultC == null) + defaultC = currC; + else + defaultC = factory.and(defaultC, currC); + } + } + + Ordering order = factory.ascending(factory.propertyValue( + source.getSelectorName(), ARGEO_USER_ID)); + Ordering[] orderings = { order }; + + QueryObjectModel query = factory.createQuery(source, defaultC, + orderings, null); + + QueryResult result = query.execute(); + return result.getNodes(); + } +} \ No newline at end of file diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/AddRole.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/AddRole.java new file mode 100644 index 000000000..a1008f699 --- /dev/null +++ b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/AddRole.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.admin.commands; + +import org.argeo.ArgeoException; +import org.argeo.security.UserAdminService; +import org.argeo.security.ui.admin.editors.ArgeoUserEditor; +import org.argeo.security.ui.admin.views.RolesView; +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.ui.IEditorReference; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.handlers.HandlerUtil; + +/** Add a new role. */ +public class AddRole extends AbstractHandler { + public final static String COMMAND_ID = "org.argeo.security.ui.admin.addRole"; + private UserAdminService userAdminService; + private String rolePrefix = "ROLE_"; + + public Object execute(ExecutionEvent event) throws ExecutionException { + RolesView rolesView = (RolesView) HandlerUtil + .getActiveWorkbenchWindow(event).getActivePage() + .findView(RolesView.ID); + String role = rolesView.getNewRole(); + if (role.trim().equals("")) + return null; + if (role.equals(rolesView.getAddNewRoleText())) + return null; + role = role.trim().toUpperCase(); + if (!role.startsWith(rolePrefix)) + role = rolePrefix + role; + if (userAdminService.listEditableRoles().contains(role)) + throw new ArgeoException("Role " + role + " already exists"); + userAdminService.newRole(role); + rolesView.refresh(); + + // refresh editors + IEditorReference[] refs = HandlerUtil.getActiveWorkbenchWindow(event) + .getActivePage() + .findEditors(null, ArgeoUserEditor.ID, IWorkbenchPage.MATCH_ID); + for (IEditorReference ref : refs) { + ArgeoUserEditor userEditor = (ArgeoUserEditor) ref.getEditor(false); + if (userEditor != null) { + userEditor.refresh(); + } + } + return null; + } + + public void setUserAdminService(UserAdminService userAdminService) { + this.userAdminService = userAdminService; + } + +} diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/DeleteRole.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/DeleteRole.java new file mode 100644 index 000000000..6cba11eb9 --- /dev/null +++ b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/DeleteRole.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.admin.commands; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.argeo.security.UserAdminService; +import org.argeo.security.ui.admin.views.RolesView; +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.handlers.HandlerUtil; + +/** Deletes the selected roles */ +public class DeleteRole extends AbstractHandler { + private UserAdminService userAdminService; + + @SuppressWarnings("unchecked") + public Object execute(ExecutionEvent event) throws ExecutionException { + ISelection selection = HandlerUtil.getCurrentSelection(event); + if (selection.isEmpty()) + return null; + + List toDelete = new ArrayList(); + Iterator it = ((IStructuredSelection) selection).iterator(); + while (it.hasNext()) { + toDelete.add(it.next()); + } + + if (!MessageDialog + .openQuestion( + HandlerUtil.getActiveShell(event), + "Delete Role", + "Are you sure that you want to delete " + + toDelete + + "?\n" + + "This may lead to inconsistencies in the application.")) + return null; + + for (String role : toDelete) { + userAdminService.deleteRole(role); + } + + RolesView view = (RolesView) HandlerUtil + .getActiveWorkbenchWindow(event).getActivePage() + .findView(RolesView.ID); + view.refresh(); + return null; + } + + public void setUserAdminService(UserAdminService userAdminService) { + this.userAdminService = userAdminService; + } +} \ No newline at end of file diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/DeleteUser.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/DeleteUser.java new file mode 100644 index 000000000..ccf360fd0 --- /dev/null +++ b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/DeleteUser.java @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.admin.commands; + +import java.util.Iterator; +import java.util.Map; +import java.util.TreeMap; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; +import org.argeo.jcr.ArgeoNames; +import org.argeo.jcr.JcrUtils; +import org.argeo.security.UserAdminService; +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.handlers.HandlerUtil; + +/** Deletes the selected user nodes */ +public class DeleteUser extends AbstractHandler { + private final static Log log = LogFactory.getLog(DeleteUser.class); + + private UserAdminService userAdminService; + + @SuppressWarnings("unchecked") + public Object execute(ExecutionEvent event) throws ExecutionException { + ISelection selection = HandlerUtil.getCurrentSelection(event); + if (selection.isEmpty()) + return null; + + Map toDelete = new TreeMap(); + Iterator it = ((IStructuredSelection) selection).iterator(); + nodes: while (it.hasNext()) { + Node profileNode = it.next(); + try { + String userName = profileNode.getProperty( + ArgeoNames.ARGEO_USER_ID).getString(); + if (userName.equals(profileNode.getSession().getUserID())) { + log.warn("Cannot delete its own user: " + userName); + continue nodes; + } + toDelete.put(userName, profileNode); + } catch (RepositoryException e) { + log.warn("Cannot interpred user " + profileNode); + } + } + + if (!MessageDialog + .openQuestion( + HandlerUtil.getActiveShell(event), + "Delete User", + "Are you sure that you want to delete users " + + toDelete.keySet() + + "?\n" + + "This may lead to inconsistencies in the application.")) + return null; + + for (String username : toDelete.keySet()) { + Session session = null; + try { + Node profileNode = toDelete.get(username); + userAdminService.deleteUser(username); + profileNode.getParent().remove(); + session = profileNode.getSession(); + session.save(); + } catch (RepositoryException e) { + JcrUtils.discardQuietly(session); + throw new ArgeoException("Cannot list users", e); + } + } + + userAdminService.synchronize(); + // UsersView view = (UsersView) HandlerUtil + // .getActiveWorkbenchWindow(event).getActivePage() + // .findView(UsersView.ID); + // view.refresh(); + return null; + } + + public void setUserAdminService(UserAdminService userAdminService) { + this.userAdminService = userAdminService; + } +} \ No newline at end of file diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/NewUser.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/NewUser.java new file mode 100644 index 000000000..660896de8 --- /dev/null +++ b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/NewUser.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.admin.commands; + +import javax.jcr.Repository; +import javax.jcr.Session; + +import org.argeo.jcr.JcrUtils; +import org.argeo.security.UserAdminService; +import org.argeo.security.jcr.JcrSecurityModel; +import org.argeo.security.ui.admin.wizards.NewUserWizard; +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.ui.handlers.HandlerUtil; + +/** Launch a wizard that enables creation of a new user. */ +public class NewUser extends AbstractHandler { + private Repository repository; + private UserAdminService userAdminService; + private JcrSecurityModel jcrSecurityModel; + + public Object execute(ExecutionEvent event) throws ExecutionException { + Session session = null; + try { + session = repository.login(); + NewUserWizard newUserWizard = new NewUserWizard(session, + userAdminService, jcrSecurityModel); + WizardDialog dialog = new WizardDialog( + HandlerUtil.getActiveShell(event), newUserWizard); + dialog.open(); + } catch (Exception e) { + throw new ExecutionException("Cannot open wizard", e); + } finally { + JcrUtils.logoutQuietly(session); + } + return null; + } + + public void setRepository(Repository repository) { + this.repository = repository; + } + + public void setUserAdminService(UserAdminService userAdminService) { + this.userAdminService = userAdminService; + } + + public void setJcrSecurityModel(JcrSecurityModel jcrSecurityModel) { + this.jcrSecurityModel = jcrSecurityModel; + } + +} diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/OpenArgeoUserEditor.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/OpenArgeoUserEditor.java new file mode 100644 index 000000000..bae928c22 --- /dev/null +++ b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/OpenArgeoUserEditor.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.admin.commands; + +import org.argeo.security.ui.admin.editors.ArgeoUserEditor; +import org.argeo.security.ui.admin.editors.ArgeoUserEditorInput; +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.handlers.HandlerUtil; + +/** Command handler to set visible or open a Argeo user. */ +public class OpenArgeoUserEditor extends AbstractHandler { + public final static String COMMAND_ID = "org.argeo.security.ui.admin.openArgeoUserEditor"; + public final static String PARAM_USERNAME = "org.argeo.security.ui.admin.username"; + + public Object execute(ExecutionEvent event) throws ExecutionException { + try { + ArgeoUserEditorInput editorInput = new ArgeoUserEditorInput( + event.getParameter(PARAM_USERNAME)); + IWorkbenchPage activePage = HandlerUtil.getActiveWorkbenchWindow( + event).getActivePage(); + activePage.openEditor(editorInput, ArgeoUserEditor.ID); + } catch (Exception e) { + throw new ExecutionException("Cannot open editor", e); + } + return null; + } +} diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/RefreshRoles.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/RefreshRoles.java new file mode 100644 index 000000000..41c78f077 --- /dev/null +++ b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/RefreshRoles.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.admin.commands; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; + +/** + * Refreshes the roles view. + */ +public class RefreshRoles extends AbstractHandler { + public Object execute(ExecutionEvent event) throws ExecutionException { + + return null; + } + +} \ No newline at end of file diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/RefreshUsersList.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/RefreshUsersList.java new file mode 100644 index 000000000..e4c14ab21 --- /dev/null +++ b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/RefreshUsersList.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.admin.commands; + +import java.util.Set; + +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.query.Query; + +import org.argeo.ArgeoException; +import org.argeo.jcr.ArgeoNames; +import org.argeo.jcr.ArgeoTypes; +import org.argeo.jcr.JcrUtils; +import org.argeo.security.UserAdminService; +import org.argeo.security.ui.admin.views.UsersView; +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.handlers.HandlerUtil; + +/** + * Refreshes the main user list, removing nodes which are not referenced by user + * admin service. + */ +public class RefreshUsersList extends AbstractHandler { + private UserAdminService userAdminService; + private Repository repository; + + public Object execute(ExecutionEvent event) throws ExecutionException { + Set users = userAdminService.listUsers(); + Session session = null; + try { + session = repository.login(); + Query query = session + .getWorkspace() + .getQueryManager() + .createQuery( + "select * from [" + ArgeoTypes.ARGEO_USER_HOME + + "]", Query.JCR_SQL2); + NodeIterator nit = query.execute().getNodes(); + while (nit.hasNext()) { + Node node = nit.nextNode(); + String username = node.getProperty(ArgeoNames.ARGEO_USER_ID) + .getString(); + if (!users.contains(username)) + node.remove(); + } + session.save(); + } catch (RepositoryException e) { + JcrUtils.discardQuietly(session); + throw new ArgeoException("Cannot list users", e); + } finally { + JcrUtils.logoutQuietly(session); + } + userAdminService.synchronize(); + + // FIXME try to refresh views that extend the UsersView and have another + // ID + IWorkbenchPart part = HandlerUtil.getActiveWorkbenchWindow(event) + .getActivePage().getActivePart(); + if (part instanceof UsersView) + ((UsersView) part).refresh(); + + // Try to refresh UsersView if opened + UsersView view = (UsersView) HandlerUtil + .getActiveWorkbenchWindow(event).getActivePage() + .findView(UsersView.ID); + if (view != null) + view.refresh(); + + return null; + } + + public void setUserAdminService(UserAdminService userAdminService) { + this.userAdminService = userAdminService; + } + + public void setRepository(Repository repository) { + this.repository = repository; + } + +} \ No newline at end of file diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/SaveArgeoUser.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/SaveArgeoUser.java new file mode 100644 index 000000000..bd16f8bcf --- /dev/null +++ b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/SaveArgeoUser.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.admin.commands; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.handlers.HandlerUtil; + +/** Save the currently edited Argeo user. */ +public class SaveArgeoUser extends AbstractHandler { + public final static String COMMAND_ID = "org.argeo.security.ui.admin.saveArgeoUser"; + + public Object execute(ExecutionEvent event) throws ExecutionException { + try { + IWorkbenchPart iwp = HandlerUtil.getActiveWorkbenchWindow(event) + .getActivePage().getActivePart(); + + if (!(iwp instanceof IEditorPart)) + return null; + IEditorPart editor = (IEditorPart) iwp; + editor.doSave(null); + } catch (Exception e) { + MessageDialog.openError(Display.getDefault().getActiveShell(), + "Error", "Cannot save user: " + e.getMessage()); + } + return null; + } + +} diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/UserBatchUpdate.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/UserBatchUpdate.java new file mode 100644 index 000000000..657dfc70a --- /dev/null +++ b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/UserBatchUpdate.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.admin.commands; + +import javax.jcr.Repository; +import javax.jcr.Session; + +import org.argeo.jcr.JcrUtils; +import org.argeo.security.UserAdminService; +import org.argeo.security.jcr.JcrSecurityModel; +import org.argeo.security.ui.admin.wizards.UserBatchUpdateWizard; +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.ui.handlers.HandlerUtil; + +/** Launch a wizard to update various properties about users in JCR. */ +public class UserBatchUpdate extends AbstractHandler { + private Repository repository; + private UserAdminService userAdminService; + private JcrSecurityModel jcrSecurityModel; + + public Object execute(ExecutionEvent event) throws ExecutionException { + Session session = null; + try { + session = repository.login(); + UserBatchUpdateWizard userBatchUpdateWizard = new UserBatchUpdateWizard(session, + userAdminService, jcrSecurityModel); + WizardDialog dialog = new WizardDialog( + HandlerUtil.getActiveShell(event), userBatchUpdateWizard); + dialog.open(); + } catch (Exception e) { + throw new ExecutionException("Cannot open wizard", e); + } finally { + JcrUtils.logoutQuietly(session); + } + return null; + } + + public void setRepository(Repository repository) { + this.repository = repository; + } + + public void setUserAdminService(UserAdminService userAdminService) { + this.userAdminService = userAdminService; + } + + public void setJcrSecurityModel(JcrSecurityModel jcrSecurityModel) { + this.jcrSecurityModel = jcrSecurityModel; + } + +} diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/ArgeoUserEditor.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/ArgeoUserEditor.java new file mode 100644 index 000000000..ebc08319e --- /dev/null +++ b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/ArgeoUserEditor.java @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.admin.editors; + +import javax.jcr.Node; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.argeo.ArgeoException; +import org.argeo.jcr.JcrUtils; +import org.argeo.jcr.UserJcrUtils; +import org.argeo.security.UserAdminService; +import org.argeo.security.jcr.JcrUserDetails; +import org.argeo.security.ui.admin.SecurityAdminPlugin; +import org.argeo.security.ui.admin.views.UsersView; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorSite; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.forms.editor.FormEditor; +import org.springframework.security.GrantedAuthority; + +/** Editor for an Argeo user. */ +public class ArgeoUserEditor extends FormEditor { + public final static String ID = SecurityAdminPlugin.PLUGIN_ID + + ".adminArgeoUserEditor"; + + /* DEPENDENCY INJECTION */ + private Session session; + private UserAdminService userAdminService; + + // private Node userHome; + private Node userProfile; + private JcrUserDetails userDetails; + + public void init(IEditorSite site, IEditorInput input) + throws PartInitException { + super.init(site, input); + String username = ((ArgeoUserEditorInput) getEditorInput()) + .getUsername(); + userProfile = UserJcrUtils.getUserProfile(session, username); + + if (userAdminService.userExists(username)) { + userDetails = (JcrUserDetails) userAdminService + .loadUserByUsername(username); + } else { + GrantedAuthority[] authorities = {}; + try { + userDetails = new JcrUserDetails(session, username, null, + authorities); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot retrieve disabled JCR profile"); + } + } + + this.setPartProperty("name", username != null ? username : ""); + setPartName(username != null ? username : ""); + } + + protected void addPages() { + try { + addPage(new DefaultUserMainPage(this, userProfile)); + addPage(new UserRolesPage(this, userDetails, userAdminService)); + } catch (Exception e) { + throw new ArgeoException("Cannot add pages", e); + } + } + + @Override + public void doSave(IProgressMonitor monitor) { + // list pages + // TODO: make it more generic + DefaultUserMainPage defaultUserMainPage = (DefaultUserMainPage) findPage(DefaultUserMainPage.ID); + if (defaultUserMainPage.isDirty()) { + defaultUserMainPage.doSave(monitor); + String newPassword = defaultUserMainPage.getNewPassword(); + defaultUserMainPage.resetNewPassword(); + if (newPassword != null) + userDetails = userDetails.cloneWithNewPassword(newPassword); + } + + UserRolesPage userRolesPage = (UserRolesPage) findPage(UserRolesPage.ID); + if (userRolesPage.isDirty()) { + userRolesPage.doSave(monitor); + userDetails = userDetails.cloneWithNewRoles(userRolesPage + .getRoles()); + } + + userAdminService.updateUser(userDetails); + + // if (userAdminService.userExists(user.getUsername())) + // userAdminService.updateUser(user); + // else { + // userAdminService.newUser(user); + // setPartName(user.getUsername()); + // } + firePropertyChange(PROP_DIRTY); + + userRolesPage.setUserDetails(userDetails); + + // FIXME rather use a refresh command. Fails when called by another + // view. + // refresh users view + IWorkbench iw = SecurityAdminPlugin.getDefault().getWorkbench(); + UsersView usersView = (UsersView) iw.getActiveWorkbenchWindow() + .getActivePage().findView(UsersView.ID); + if (usersView != null) + usersView.refresh(); + } + + @Override + public void doSaveAs() { + } + + @Override + public boolean isSaveAsAllowed() { + return false; + } + + public void refresh() { + UserRolesPage userRolesPage = (UserRolesPage) findPage(UserRolesPage.ID); + userRolesPage.refresh(); + } + + @Override + public void dispose() { + JcrUtils.logoutQuietly(session); + super.dispose(); + } + + /* DEPENDENCY INJECTION */ + public void setUserAdminService(UserAdminService userAdminService) { + this.userAdminService = userAdminService; + } + + public void setRepository(Repository repository) { + try { + session = repository.login(); + } catch (RepositoryException re) { + throw new ArgeoException("Unable to initialise local session", re); + } + } +} diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/ArgeoUserEditorInput.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/ArgeoUserEditorInput.java new file mode 100644 index 000000000..9d1d99573 --- /dev/null +++ b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/ArgeoUserEditorInput.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.admin.editors; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IPersistableElement; + +/** Editor input for an Argeo user. */ +public class ArgeoUserEditorInput implements IEditorInput { + private final String username; + + public ArgeoUserEditorInput(String username) { + this.username = username; + } + + public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) { + return null; + } + + public boolean exists() { + return username != null; + } + + public ImageDescriptor getImageDescriptor() { + return null; + } + + public String getName() { + return username != null ? username : ""; + } + + public IPersistableElement getPersistable() { + return null; + } + + public String getToolTipText() { + return username != null ? username : ""; + } + + public boolean equals(Object obj) { + if (!(obj instanceof ArgeoUserEditorInput)) + return false; + if (((ArgeoUserEditorInput) obj).getUsername() == null) + return false; + return ((ArgeoUserEditorInput) obj).getUsername().equals(username); + } + + public String getUsername() { + return username; + } +} diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/DefaultUserMainPage.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/DefaultUserMainPage.java new file mode 100644 index 000000000..5f99e195b --- /dev/null +++ b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/DefaultUserMainPage.java @@ -0,0 +1,245 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.admin.editors; + +import java.util.Arrays; + +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.RepositoryException; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; +import org.argeo.jcr.ArgeoNames; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.forms.AbstractFormPart; +import org.eclipse.ui.forms.IManagedForm; +import org.eclipse.ui.forms.SectionPart; +import org.eclipse.ui.forms.editor.FormEditor; +import org.eclipse.ui.forms.editor.FormPage; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.ScrolledForm; +import org.eclipse.ui.forms.widgets.Section; + +/** + * Display/edit the properties common to all Argeo users + */ +public class DefaultUserMainPage extends FormPage implements ArgeoNames { + final static String ID = "argeoUserEditor.mainPage"; + + private final static Log log = LogFactory.getLog(DefaultUserMainPage.class); + private Node userProfile; + + private char[] newPassword; + + public DefaultUserMainPage(FormEditor editor, Node userProfile) { + super(editor, ID, "Main"); + this.userProfile = userProfile; + } + + protected void createFormContent(final IManagedForm mf) { + try { + ScrolledForm form = mf.getForm(); + refreshFormTitle(form); + GridLayout mainLayout = new GridLayout(1, true); + form.getBody().setLayout(mainLayout); + + createGeneralPart(form.getBody()); + createPassworPart(form.getBody()); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot create form content", e); + } + } + + /** Creates the general section */ + protected void createGeneralPart(Composite parent) + throws RepositoryException { + FormToolkit tk = getManagedForm().getToolkit(); + Section section = tk.createSection(parent, Section.TITLE_BAR); + section.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + section.setText("General"); + Composite body = tk.createComposite(section, SWT.WRAP); + section.setClient(body); + GridLayout layout = new GridLayout(2, false); + body.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + body.setLayout(layout); + + final Text commonName = createLT(body, "Displayed Name", + getProperty(Property.JCR_TITLE)); + final Text firstName = createLT(body, "First name", + getProperty(ARGEO_FIRST_NAME)); + final Text lastName = createLT(body, "Last name", + getProperty(ARGEO_LAST_NAME)); + final Text email = createLT(body, "Email", + getProperty(ARGEO_PRIMARY_EMAIL)); + final Text description = createLMT(body, "Description", + getProperty(Property.JCR_DESCRIPTION)); + + // create form part (controller) + AbstractFormPart part = new SectionPart(section) { + public void commit(boolean onSave) { + try { + userProfile.getSession().getWorkspace().getVersionManager() + .checkout(userProfile.getPath()); + userProfile.setProperty(Property.JCR_TITLE, + commonName.getText()); + userProfile.setProperty(ARGEO_FIRST_NAME, + firstName.getText()); + userProfile + .setProperty(ARGEO_LAST_NAME, lastName.getText()); + userProfile.setProperty(ARGEO_PRIMARY_EMAIL, + email.getText()); + userProfile.setProperty(Property.JCR_DESCRIPTION, + description.getText()); + userProfile.getSession().save(); + userProfile.getSession().getWorkspace().getVersionManager() + .checkin(userProfile.getPath()); + super.commit(onSave); + refreshFormTitle(getManagedForm().getForm()); + if (log.isTraceEnabled()) + log.trace("General part committed"); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot commit", e); + } + } + }; + // if (username != null) + // username.addModifyListener(new FormPartML(part)); + commonName.addModifyListener(new FormPartML(part)); + firstName.addModifyListener(new FormPartML(part)); + lastName.addModifyListener(new FormPartML(part)); + email.addModifyListener(new FormPartML(part)); + description.addModifyListener(new FormPartML(part)); + getManagedForm().addPart(part); + } + + private void refreshFormTitle(ScrolledForm form) throws RepositoryException { + form.setText(getProperty(Property.JCR_TITLE) + + (userProfile.getProperty(ARGEO_ENABLED).getBoolean() ? "" + : " [DISABLED]")); + } + + /** @return the property, or the empty string if not set */ + protected String getProperty(String name) throws RepositoryException { + return userProfile.hasProperty(name) ? userProfile.getProperty(name) + .getString() : ""; + } + + /** Creates the password section */ + protected void createPassworPart(Composite parent) { + FormToolkit tk = getManagedForm().getToolkit(); + Section section = tk.createSection(parent, Section.TITLE_BAR); + section.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + section.setText("Password"); + + Composite body = tk.createComposite(section, SWT.WRAP); + section.setClient(body); + GridLayout layout = new GridLayout(2, false); + body.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + body.setLayout(layout); + + // add widgets (view) + final Text password1 = createLP(body, "New password", ""); + final Text password2 = createLP(body, "Repeat password", ""); + // create form part (controller) + AbstractFormPart part = new SectionPart(section) { + + public void commit(boolean onSave) { + if (!password1.getText().equals("") + || !password2.getText().equals("")) { + if (password1.getText().equals(password2.getText())) { + newPassword = password1.getText().toCharArray(); + password1.setText(""); + password2.setText(""); + super.commit(onSave); + } else { + password1.setText(""); + password2.setText(""); + throw new ArgeoException("Passwords are not equals"); + } + } + } + + }; + password1.addModifyListener(new FormPartML(part)); + password2.addModifyListener(new FormPartML(part)); + getManagedForm().addPart(part); + } + + /** Creates label and text. */ + protected Text createLT(Composite body, String label, String value) { + FormToolkit toolkit = getManagedForm().getToolkit(); + Label lbl = toolkit.createLabel(body, label); + lbl.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false)); + Text text = toolkit.createText(body, value, SWT.BORDER); + text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + return text; + } + + /** Creates label and multiline text. */ + protected Text createLMT(Composite body, String label, String value) { + FormToolkit toolkit = getManagedForm().getToolkit(); + Label lbl = toolkit.createLabel(body, label); + lbl.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false)); + Text text = toolkit.createText(body, value, SWT.BORDER | SWT.MULTI); + text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true)); + return text; + } + + /** Creates label and password. */ + protected Text createLP(Composite body, String label, String value) { + FormToolkit toolkit = getManagedForm().getToolkit(); + Label lbl = toolkit.createLabel(body, label); + lbl.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false)); + Text text = toolkit.createText(body, value, SWT.BORDER | SWT.PASSWORD); + text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + return text; + } + + private class FormPartML implements ModifyListener { + private AbstractFormPart formPart; + + public FormPartML(AbstractFormPart generalPart) { + this.formPart = generalPart; + } + + public void modifyText(ModifyEvent e) { + formPart.markDirty(); + } + + } + + public String getNewPassword() { + if (newPassword != null) + return new String(newPassword); + else + return null; + } + + public void resetNewPassword() { + if (newPassword != null) + Arrays.fill(newPassword, 'x'); + newPassword = null; + } +} diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/UserRolesPage.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/UserRolesPage.java new file mode 100644 index 000000000..08cd457ad --- /dev/null +++ b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/UserRolesPage.java @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.admin.editors; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.jcr.ArgeoNames; +import org.argeo.security.UserAdminService; +import org.argeo.security.ui.admin.SecurityAdminPlugin; +import org.eclipse.jface.viewers.CellEditor; +import org.eclipse.jface.viewers.CheckboxCellEditor; +import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.jface.viewers.EditingSupport; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TableViewerColumn; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.ui.forms.AbstractFormPart; +import org.eclipse.ui.forms.IManagedForm; +import org.eclipse.ui.forms.editor.FormEditor; +import org.eclipse.ui.forms.editor.FormPage; +import org.eclipse.ui.forms.widgets.ScrolledForm; +import org.springframework.security.GrantedAuthority; +import org.springframework.security.userdetails.UserDetails; + +/** + * Display/edit the roles of a user. + */ +public class UserRolesPage extends FormPage implements ArgeoNames { + final static String ID = "argeoUserEditor.rolesPage"; + + private final static Log log = LogFactory.getLog(UserRolesPage.class); + private final static Image ROLE_CHECKED = SecurityAdminPlugin + .getImageDescriptor("icons/security.gif").createImage(); + + private TableViewer rolesViewer; + private UserAdminService userAdminService; + private List roles; + + public UserRolesPage(FormEditor editor, UserDetails userDetails, + UserAdminService userAdminService) { + super(editor, ID, "Roles"); + setUserDetails(userDetails); + this.userAdminService = userAdminService; + } + + public void setUserDetails(UserDetails userDetails) { + this.roles = new ArrayList(); + for (GrantedAuthority ga : userDetails.getAuthorities()) + roles.add(ga.getAuthority()); + if (rolesViewer != null) + rolesViewer.refresh(); + } + + protected void createFormContent(final IManagedForm mf) { + ScrolledForm form = mf.getForm(); + form.setText("Roles"); + FillLayout mainLayout = new FillLayout(); + // ColumnLayout mainLayout = new ColumnLayout(); + // mainLayout.minNumColumns = 1; + // mainLayout.maxNumColumns = 4; + // mainLayout.topMargin = 0; + // mainLayout.bottomMargin = 5; + // mainLayout.leftMargin = mainLayout.rightMargin = + // mainLayout.horizontalSpacing = mainLayout.verticalSpacing = 10; + form.getBody().setLayout(mainLayout); + createRolesPart(form.getBody()); + } + + /** Creates the role section */ + protected void createRolesPart(Composite parent) { + Table table = new Table(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); + + AbstractFormPart part = new AbstractFormPart() { + public void commit(boolean onSave) { + // roles have already been modified in editing + super.commit(onSave); + if (log.isTraceEnabled()) + log.trace("Role part committed"); + } + }; + getManagedForm().addPart(part); + + // GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true); + // gridData.verticalSpan = 20; + // table.setLayoutData(gridData); + table.setLinesVisible(true); + table.setHeaderVisible(false); + rolesViewer = new TableViewer(table); + + // check column + TableViewerColumn column = createTableViewerColumn(rolesViewer, + "checked", 20); + column.setLabelProvider(new ColumnLabelProvider() { + public String getText(Object element) { + return null; + } + + public Image getImage(Object element) { + String role = element.toString(); + if (roles.contains(role)) { + return ROLE_CHECKED; + } else { + return null; + } + } + }); + column.setEditingSupport(new RoleEditingSupport(rolesViewer, part)); + + // role column + column = createTableViewerColumn(rolesViewer, "Role", 200); + column.setLabelProvider(new ColumnLabelProvider() { + public String getText(Object element) { + return element.toString(); + } + + public Image getImage(Object element) { + return null; + } + }); + rolesViewer.setContentProvider(new RolesContentProvider()); + rolesViewer.setInput(getEditorSite()); + } + + protected TableViewerColumn createTableViewerColumn(TableViewer viewer, + String title, int bound) { + final TableViewerColumn viewerColumn = new TableViewerColumn(viewer, + SWT.NONE); + final TableColumn column = viewerColumn.getColumn(); + column.setText(title); + column.setWidth(bound); + column.setResizable(true); + column.setMoveable(true); + return viewerColumn; + + } + + public List getRoles() { + return roles; + } + + public void refresh() { + rolesViewer.refresh(); + } + + private class RolesContentProvider implements IStructuredContentProvider { + public Object[] getElements(Object inputElement) { + return userAdminService.listEditableRoles().toArray(); + } + + public void dispose() { + } + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + } + + /** Select the columns by editing the checkbox in the first column */ + class RoleEditingSupport extends EditingSupport { + + private final TableViewer viewer; + private final AbstractFormPart formPart; + + public RoleEditingSupport(TableViewer viewer, AbstractFormPart formPart) { + super(viewer); + this.viewer = viewer; + this.formPart = formPart; + } + + @Override + protected CellEditor getCellEditor(Object element) { + return new CheckboxCellEditor(null, SWT.CHECK | SWT.READ_ONLY); + + } + + @Override + protected boolean canEdit(Object element) { + return true; + } + + @Override + protected Object getValue(Object element) { + String role = element.toString(); + return roles.contains(role); + + } + + @Override + protected void setValue(Object element, Object value) { + Boolean inRole = (Boolean) value; + String role = element.toString(); + if (inRole && !roles.contains(role)) { + roles.add(role); + formPart.markDirty(); + } else if (!inRole && roles.contains(role)) { + roles.remove(role); + formPart.markDirty(); + } + viewer.refresh(); + } + } + +} diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/views/RolesView.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/views/RolesView.java new file mode 100644 index 000000000..fbe7dd570 --- /dev/null +++ b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/views/RolesView.java @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.admin.views; + +import org.argeo.ArgeoException; +import org.argeo.security.UserAdminService; +import org.argeo.security.ui.admin.SecurityAdminPlugin; +import org.argeo.security.ui.admin.commands.AddRole; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.handlers.IHandlerService; +import org.eclipse.ui.part.ViewPart; + +/** List all roles. */ +public class RolesView extends ViewPart { + public final static String ID = SecurityAdminPlugin.PLUGIN_ID + + ".adminRolesView"; + + private Text newRole; + + private TableViewer viewer; + private UserAdminService userAdminService; + + private String addNewRoleText = ""; + + @Override + public void createPartControl(Composite parent) { + parent.setLayout(new GridLayout(1, false)); + + // new role text field + newRole = new Text(parent, SWT.BORDER); + newRole.setText(addNewRoleText); + newRole.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + // default action is add role + newRole.addListener(SWT.DefaultSelection, new Listener() { + public void handleEvent(Event evt) { + IWorkbench iw = SecurityAdminPlugin.getDefault().getWorkbench(); + IHandlerService handlerService = (IHandlerService) iw + .getService(IHandlerService.class); + try { + handlerService.executeCommand(AddRole.COMMAND_ID, evt); + } catch (Exception e) { + throw new ArgeoException("Cannot execute add role command", + e); + } + } + }); + // select all on focus + newRole.addListener(SWT.FocusIn, new Listener() { + public void handleEvent(Event e) { + newRole.selectAll(); + } + }); + + // roles table + Table table = new Table(parent, SWT.V_SCROLL | SWT.BORDER); + table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + table.setLinesVisible(false); + table.setHeaderVisible(false); + viewer = new TableViewer(table); + viewer.setContentProvider(new RolesContentProvider()); + viewer.setLabelProvider(new UsersLabelProvider()); + getViewSite().setSelectionProvider(viewer); + viewer.setInput(getViewSite()); + } + + @Override + public void setFocus() { + viewer.getTable().setFocus(); + } + + public void setUserAdminService(UserAdminService userAdminService) { + this.userAdminService = userAdminService; + } + + public String getAddNewRoleText() { + return addNewRoleText; + } + + private class RolesContentProvider implements IStructuredContentProvider { + + public Object[] getElements(Object inputElement) { + return userAdminService.listEditableRoles().toArray(); + } + + public void dispose() { + } + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + + } + + private class UsersLabelProvider extends LabelProvider implements + ITableLabelProvider { + public String getColumnText(Object element, int columnIndex) { + return element.toString(); + } + + public Image getColumnImage(Object element, int columnIndex) { + return null; + } + + } + + public String getNewRole() { + return newRole.getText(); + } + + public void refresh() { + viewer.refresh(); + newRole.setText(addNewRoleText); + } +} diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/views/UsersView.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/views/UsersView.java new file mode 100644 index 000000000..a7437156d --- /dev/null +++ b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/views/UsersView.java @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.admin.views; + +import javax.jcr.Node; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.observation.Event; +import javax.jcr.observation.EventIterator; +import javax.jcr.observation.EventListener; + +import org.argeo.ArgeoException; +import org.argeo.eclipse.ui.utils.CommandUtils; +import org.argeo.jcr.ArgeoJcrConstants; +import org.argeo.jcr.ArgeoNames; +import org.argeo.jcr.ArgeoTypes; +import org.argeo.jcr.JcrUtils; +import org.argeo.security.ui.admin.SecurityAdminPlugin; +import org.argeo.security.ui.admin.UserTableComposite; +import org.argeo.security.ui.admin.commands.OpenArgeoUserEditor; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.part.ViewPart; + +/** List all users with filter. */ +public class UsersView extends ViewPart implements ArgeoNames { + public final static String ID = SecurityAdminPlugin.PLUGIN_ID + + ".adminUsersView"; + + /* DEPENDENCY INJECTION */ + private Session session; + + private UserTableComposite userTableCmp; + private JcrUserListener userStructureListener; + private JcrUserListener userPropertiesListener; + + @Override + public void createPartControl(Composite parent) { + parent.setLayout(new FillLayout()); + + // Create the composite that displays the list and a filter + userTableCmp = new UserTableComposite(parent, SWT.NO_FOCUS, session); + userTableCmp.populate(true, false); + + // Configure + userTableCmp.getTableViewer().addDoubleClickListener( + new ViewDoubleClickListener()); + getViewSite().setSelectionProvider(userTableCmp.getTableViewer()); + + // Add listener to refresh the list when something changes + userStructureListener = new JcrUserListener(getSite().getShell() + .getDisplay()); + JcrUtils.addListener(session, userStructureListener, Event.NODE_ADDED + | Event.NODE_REMOVED, ArgeoJcrConstants.PEOPLE_BASE_PATH, null); + userPropertiesListener = new JcrUserListener(getSite().getShell() + .getDisplay()); + JcrUtils.addListener(session, userStructureListener, + Event.PROPERTY_CHANGED | Event.PROPERTY_ADDED + | Event.PROPERTY_REMOVED, + ArgeoJcrConstants.PEOPLE_BASE_PATH, + ArgeoTypes.ARGEO_USER_PROFILE); + } + + @Override + public void setFocus() { + userTableCmp.setFocus(); + } + + @Override + public void dispose() { + JcrUtils.removeListenerQuietly(session, userStructureListener); + JcrUtils.removeListenerQuietly(session, userPropertiesListener); + JcrUtils.logoutQuietly(session); + super.dispose(); + } + + // public void setSession(Session session) { + // this.session = session; + // } + + public void refresh() { + this.getSite().getShell().getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + userTableCmp.refresh(); + } + }); + } + + private class JcrUserListener implements EventListener { + private final Display display; + + public JcrUserListener(Display display) { + super(); + this.display = display; + } + + @Override + public void onEvent(EventIterator events) { + display.asyncExec(new Runnable() { + @Override + public void run() { + userTableCmp.refresh(); + } + }); + } + } + + class ViewDoubleClickListener implements IDoubleClickListener { + public void doubleClick(DoubleClickEvent evt) { + if (evt.getSelection().isEmpty()) + return; + + Object obj = ((IStructuredSelection) evt.getSelection()) + .getFirstElement(); + if (obj instanceof Node) { + try { + String username = ((Node) obj).getProperty(ARGEO_USER_ID) + .getString(); + String commandId = OpenArgeoUserEditor.COMMAND_ID; + String paramName = OpenArgeoUserEditor.PARAM_USERNAME; + CommandUtils.callCommand(commandId, paramName, username); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot open user editor", e); + } + } + } + } + + /* DEPENDENCY INJECTION */ + public void setRepository(Repository repository) { + try { + session = repository.login(); + } catch (RepositoryException re) { + throw new ArgeoException("Unable to initialise local session", re); + } + } + +} \ No newline at end of file diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/wizards/MainUserInfoWizardPage.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/wizards/MainUserInfoWizardPage.java new file mode 100644 index 000000000..ad3662b6f --- /dev/null +++ b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/wizards/MainUserInfoWizardPage.java @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.admin.wizards; + +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.RepositoryException; + +import org.argeo.ArgeoException; +import org.argeo.eclipse.ui.EclipseUiUtils; +import org.argeo.jcr.ArgeoNames; +import org.argeo.security.UserAdminService; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Text; +import org.springframework.security.userdetails.UserDetails; +import org.springframework.security.userdetails.UsernameNotFoundException; + +public class MainUserInfoWizardPage extends WizardPage implements + ModifyListener, ArgeoNames { + private Text username, firstName, lastName, primaryEmail, password1, + password2; + private UserAdminService userAdminService; + + public MainUserInfoWizardPage(UserAdminService userAdminService) { + super("Main"); + this.userAdminService = userAdminService; + setTitle("Required Information"); + } + + @Override + public void createControl(Composite parent) { + Composite composite = new Composite(parent, SWT.NONE); + composite.setLayout(new GridLayout(2, false)); + username = EclipseUiUtils.createGridLT(composite, "Username", this); + primaryEmail = EclipseUiUtils.createGridLT(composite, "Email", this); + firstName = EclipseUiUtils.createGridLT(composite, "First name", this); + lastName = EclipseUiUtils.createGridLT(composite, "Last name", this); + password1 = EclipseUiUtils.createGridLP(composite, "Password", this); + password2 = EclipseUiUtils.createGridLP(composite, "Repeat password", + this); + setControl(composite); + + // Initialize buttons + setPageComplete(false); + getContainer().updateButtons(); + } + + @Override + public void modifyText(ModifyEvent event) { + String message = checkComplete(); + if (message != null) { + setMessage(message, WizardPage.ERROR); + setPageComplete(false); + } else { + setMessage("Complete", WizardPage.INFORMATION); + setPageComplete(true); + } + getContainer().updateButtons(); + } + + /** @return error message or null if complete */ + protected String checkComplete() { + // if (!username.getText().matches(UserAdminService.USERNAME_PATTERN)) + // return + // "Wrong user name format, should be lower case, between 3 and 64 characters with only '_' an '@' as acceptable special character."; + + if (username.getText().trim().equals("")) + return "User name must not be empty"; + + try { + UserDetails userDetails = userAdminService + .loadUserByUsername(username.getText()); + return "User " + userDetails.getUsername() + " already exists"; + } catch (UsernameNotFoundException e) { + // silent + } + if (!primaryEmail.getText().matches(UserAdminService.EMAIL_PATTERN)) + return "Not a valid email address"; + if (firstName.getText().trim().equals("")) + return "Specify a first name"; + if (lastName.getText().trim().equals("")) + return "Specify a last name"; + if (password1.getText().trim().equals("")) + return "Specify a password"; + if (password2.getText().trim().equals("")) + return "Repeat the password"; + if (!password2.getText().equals(password1.getText())) + return "Passwords are different"; + return null; + } + + public String getUsername() { + return username.getText(); + } + + public String getPassword() { + return password1.getText(); + } + + public void mapToProfileNode(Node up) { + try { + up.setProperty(ARGEO_PRIMARY_EMAIL, primaryEmail.getText()); + up.setProperty(ARGEO_FIRST_NAME, firstName.getText()); + up.setProperty(ARGEO_LAST_NAME, lastName.getText()); + + // derived values + // TODO add wizard pages to do it + up.setProperty(Property.JCR_TITLE, firstName.getText() + " " + + lastName.getText()); + up.setProperty(Property.JCR_DESCRIPTION, ""); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot map to " + up, e); + } + } +} diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/wizards/NewUserWizard.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/wizards/NewUserWizard.java new file mode 100644 index 000000000..c2d041f56 --- /dev/null +++ b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/wizards/NewUserWizard.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.admin.wizards; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.eclipse.ui.ErrorFeedback; +import org.argeo.jcr.JcrUtils; +import org.argeo.jcr.UserJcrUtils; +import org.argeo.security.UserAdminService; +import org.argeo.security.jcr.JcrSecurityModel; +import org.argeo.security.jcr.JcrUserDetails; +import org.eclipse.jface.wizard.Wizard; +import org.springframework.security.GrantedAuthority; + +/** Wizard to create a new user */ +public class NewUserWizard extends Wizard { + private final static Log log = LogFactory.getLog(NewUserWizard.class); + private Session session; + private UserAdminService userAdminService; + private JcrSecurityModel jcrSecurityModel; + + // pages + private MainUserInfoWizardPage mainUserInfo; + + public NewUserWizard(Session session, UserAdminService userAdminService, + JcrSecurityModel jcrSecurityModel) { + this.session = session; + this.userAdminService = userAdminService; + this.jcrSecurityModel = jcrSecurityModel; + } + + @Override + public void addPages() { + mainUserInfo = new MainUserInfoWizardPage(userAdminService); + addPage(mainUserInfo); + } + + @Override + public boolean performFinish() { + if (!canFinish()) + return false; + + String username = mainUserInfo.getUsername(); + try { + // Node userProfile = SecurityJcrUtils.createUserProfile(session, + // username); + Node userProfile = jcrSecurityModel.sync(session, username, null); + session.getWorkspace().getVersionManager() + .checkout(userProfile.getPath()); + mainUserInfo.mapToProfileNode(userProfile); + String password = mainUserInfo.getPassword(); + // TODO add roles + JcrUserDetails jcrUserDetails = new JcrUserDetails(userProfile, + password, new GrantedAuthority[0]); + session.save(); + session.getWorkspace().getVersionManager() + .checkin(userProfile.getPath()); + userAdminService.createUser(jcrUserDetails); + return true; + } catch (Exception e) { + JcrUtils.discardQuietly(session); + Node userHome = UserJcrUtils.getUserHome(session, username); + if (userHome != null) { + try { + userHome.remove(); + session.save(); + } catch (RepositoryException e1) { + JcrUtils.discardQuietly(session); + log.warn("Error when trying to clean up failed new user " + + username, e1); + } + } + ErrorFeedback.show("Cannot create new user " + username, e); + return false; + } + } + + public void setSession(Session session) { + this.session = session; + } + +} diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/wizards/UserBatchUpdateWizard.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/wizards/UserBatchUpdateWizard.java new file mode 100644 index 000000000..71e4a1b73 --- /dev/null +++ b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/wizards/UserBatchUpdateWizard.java @@ -0,0 +1,607 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.admin.wizards; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.version.VersionManager; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; +import org.argeo.ArgeoMonitor; +import org.argeo.eclipse.ui.EclipseArgeoMonitor; +import org.argeo.jcr.ArgeoNames; +import org.argeo.jcr.JcrUtils; +import org.argeo.security.UserAdminService; +import org.argeo.security.jcr.JcrSecurityModel; +import org.argeo.security.jcr.JcrUserDetails; +import org.argeo.security.ui.PrivilegedJob; +import org.argeo.security.ui.admin.SecurityAdminPlugin; +import org.argeo.security.ui.admin.UserTableComposite; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.dialogs.IPageChangeProvider; +import org.eclipse.jface.dialogs.IPageChangedListener; +import org.eclipse.jface.dialogs.PageChangedEvent; +import org.eclipse.jface.wizard.IWizardContainer; +import org.eclipse.jface.wizard.Wizard; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; + +/** Wizard to update users */ +public class UserBatchUpdateWizard extends Wizard { + private final static Log log = LogFactory + .getLog(UserBatchUpdateWizard.class); + private Session session; + private UserAdminService userAdminService; + + // pages + private ChooseCommandWizardPage chooseCommandPage; + private ChooseUsersWizardPage userListPage; + private ValidateAndLaunchWizardPage validatePage; + + // ///////////////////////////////////////////////// + // / Definition of the various implemented commands + private final static String CMD_UPDATE_PASSWORD = "resetPassword"; + private final static String CMD_GROUP_MEMBERSHIP = "groupMembership"; + + private final Map commands = new HashMap() { + private static final long serialVersionUID = 1L; + { + put("Enable user(s)", ArgeoNames.ARGEO_ENABLED); + put("Expire credentials", ArgeoNames.ARGEO_CREDENTIALS_NON_EXPIRED); + put("Expire account(s)", ArgeoNames.ARGEO_ACCOUNT_NON_EXPIRED); + put("Lock account(s)", ArgeoNames.ARGEO_ACCOUNT_NON_LOCKED); + put("Reset password(s)", CMD_UPDATE_PASSWORD); + // TODO implement role / group management + // put("Add/Remove from group", CMD_GROUP_MEMBERSHIP); + } + }; + + public UserBatchUpdateWizard(Session session, + UserAdminService userAdminService, JcrSecurityModel jcrSecurityModel) { + this.session = session; + this.userAdminService = userAdminService; + // this.jcrSecurityModel = jcrSecurityModel; + } + + @Override + public void addPages() { + chooseCommandPage = new ChooseCommandWizardPage(); + addPage(chooseCommandPage); + userListPage = new ChooseUsersWizardPage(session); + addPage(userListPage); + validatePage = new ValidateAndLaunchWizardPage(session); + addPage(validatePage); + } + + @Override + public boolean performFinish() { + if (!canFinish()) + return false; + + UpdateJob job = null; + if (ArgeoNames.ARGEO_ENABLED.equals(chooseCommandPage.getCommand())) { + job = new UpdateBoolean(session, userListPage.getSelectedUsers(), + ArgeoNames.ARGEO_ENABLED, + chooseCommandPage.getBoleanValue()); + } else if (ArgeoNames.ARGEO_CREDENTIALS_NON_EXPIRED + .equals(chooseCommandPage.getCommand())) { + job = new UpdateBoolean(session, userListPage.getSelectedUsers(), + ArgeoNames.ARGEO_CREDENTIALS_NON_EXPIRED, + chooseCommandPage.getBoleanValue()); + } else if (ArgeoNames.ARGEO_ACCOUNT_NON_EXPIRED + .equals(chooseCommandPage.getCommand())) { + job = new UpdateBoolean(session, userListPage.getSelectedUsers(), + ArgeoNames.ARGEO_ACCOUNT_NON_EXPIRED, + chooseCommandPage.getBoleanValue()); + } else if (ArgeoNames.ARGEO_ACCOUNT_NON_LOCKED.equals(chooseCommandPage + .getCommand())) { + job = new UpdateBoolean(session, userListPage.getSelectedUsers(), + ArgeoNames.ARGEO_ACCOUNT_NON_LOCKED, + chooseCommandPage.getBoleanValue()); + } else if (CMD_UPDATE_PASSWORD.equals(chooseCommandPage.getCommand())) { + String newValue = chooseCommandPage.getPwdValue(); + if (newValue == null) + throw new ArgeoException( + "Password cannot be null or an empty string"); + job = new ResetPassword(session, userAdminService, + userListPage.getSelectedUsers(), newValue); + } + + if (job != null) + job.schedule(); + return true; + } + + public void setSession(Session session) { + this.session = session; + } + + public boolean canFinish() { + if (this.getContainer().getCurrentPage() == validatePage) + return true; + return false; + } + + // ///////////////////////// + // REEL UPDATE JOB + private class UpdateBoolean extends UpdateJob { + private String propertyName; + private boolean value; + + public UpdateBoolean(Session session, List nodesToUpdate, + String propertyName, boolean value) { + super(session, nodesToUpdate); + this.propertyName = propertyName; + this.value = value; + } + + protected void doUpdate(Node node) { + try { + node.setProperty(propertyName, value); + } catch (RepositoryException re) { + throw new ArgeoException( + "Unable to update boolean value for node " + node, re); + } + } + } + + private class ResetPassword extends UpdateJob { + private String newValue; + private UserAdminService userAdminService; + + public ResetPassword(Session session, + UserAdminService userAdminService, List nodesToUpdate, + String newValue) { + super(session, nodesToUpdate); + this.newValue = newValue; + this.userAdminService = userAdminService; + } + + protected void doUpdate(Node node) { + try { + String userId = node.getProperty(ArgeoNames.ARGEO_USER_ID) + .getString(); + if (userAdminService.userExists(userId)) { + JcrUserDetails userDetails = (JcrUserDetails) userAdminService + .loadUserByUsername(userId); + userAdminService.updateUser(userDetails + .cloneWithNewPassword(newValue)); + } + } catch (RepositoryException re) { + throw new ArgeoException( + "Unable to update boolean value for node " + node, re); + } + } + } + + @SuppressWarnings("unused") + private class AddToGroup extends UpdateJob { + private String groupID; + private Session session; + + public AddToGroup(Session session, List nodesToUpdate, + String groupID) { + super(session, nodesToUpdate); + this.session = session; + this.groupID = groupID; + } + + protected void doUpdate(Node node) { + log.info("Add/Remove to group actions are not yet implemented"); + // TODO implement this + // try { + // throw new ArgeoException("Not yet implemented"); + // } catch (RepositoryException re) { + // throw new ArgeoException( + // "Unable to update boolean value for node " + node, re); + // } + } + } + + /** + * Base privileged job that will be run asynchronously to perform the batch + * update + */ + private abstract class UpdateJob extends PrivilegedJob { + + private final Session currSession; + private final List nodesToUpdate; + + protected abstract void doUpdate(Node node); + + public UpdateJob(Session session, List nodesToUpdate) { + super("Perform update"); + try { + this.currSession = session.getRepository().login(); + // "move" nodes to update in the new session + // the "old" session will be closed by the calling command + // before the job has effectively ran + // TODO there must be a cleaner way to do. + List nodes = new ArrayList(); + for (Node node : nodesToUpdate) { + nodes.add(currSession.getNode(node.getPath())); + } + this.nodesToUpdate = nodes; + } catch (RepositoryException e) { + throw new ArgeoException("Error while dupplicating " + + "session for job", e); + } + } + + @Override + protected IStatus doRun(IProgressMonitor progressMonitor) { + try { + ArgeoMonitor monitor = new EclipseArgeoMonitor(progressMonitor); + VersionManager vm = currSession.getWorkspace() + .getVersionManager(); + int total = nodesToUpdate.size(); + monitor.beginTask("Performing change", total); + for (Node node : nodesToUpdate) { + String path = node.getPath(); + vm.checkout(path); + doUpdate(node); + currSession.save(); + vm.checkin(path); + monitor.worked(1); + } + } catch (Exception e) { + log.error("Cannot perform batch update on users", e); + // e.printStackTrace(); + + // Dig exception to find the root cause that will enable the + // user to understand the problem + Throwable cause = e; + Throwable originalCause = e; + while (cause != null) { + if (log.isTraceEnabled()) + log.trace("Parent Cause message : " + + cause.getMessage()); + originalCause = cause; + cause = cause.getCause(); + } + return new Status(IStatus.ERROR, SecurityAdminPlugin.PLUGIN_ID, + "Cannot perform updates.", originalCause); + } finally { + JcrUtils.logoutQuietly(currSession); + } + return Status.OK_STATUS; + } + } + + // ////////////////////// + // Pages definition + /** Displays a combo box that enables user to choose which action to perform */ + private class ChooseCommandWizardPage extends WizardPage { + private static final long serialVersionUID = 1L; + + private Combo chooseCommandCmb; + private Button trueChk; + private Text valueTxt; + private Text pwdTxt; + private Text pwd2Txt; + + public ChooseCommandWizardPage() { + super("Choose a command to run."); + setTitle("Choose a command to run."); + } + + @Override + public void createControl(Composite parent) { + GridLayout gl = new GridLayout(); + Composite container = new Composite(parent, SWT.NO_FOCUS); + container.setLayout(gl); + + chooseCommandCmb = new Combo(container, SWT.NO_FOCUS); + String[] values = commands.keySet().toArray( + new String[commands.size()]); + chooseCommandCmb.setItems(values); + chooseCommandCmb.setLayoutData(new GridData(SWT.FILL, SWT.TOP, + true, false)); + + final Composite bottomPart = new Composite(container, SWT.NO_FOCUS); + gl = new GridLayout(); + gl.horizontalSpacing = gl.marginWidth = gl.verticalSpacing = 0; + bottomPart.setLayout(gl); + bottomPart.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, + true)); + + chooseCommandCmb.addSelectionListener(new SelectionListener() { + private static final long serialVersionUID = 1L; + + @Override + public void widgetSelected(SelectionEvent e) { + if (getCommand().equals(CMD_UPDATE_PASSWORD)) + populatePasswordCmp(bottomPart); + else if (getCommand().equals(CMD_GROUP_MEMBERSHIP)) + populateGroupCmp(bottomPart); + else + populateBooleanFlagCmp(bottomPart); + bottomPart.pack(true); + bottomPart.layout(); + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + } + }); + + setControl(container); + } + + private void cleanParent(Composite parent) { + if (parent.getChildren().length > 0) { + for (Control control : parent.getChildren()) + control.dispose(); + } + } + + private void populateBooleanFlagCmp(Composite parent) { + cleanParent(parent); + trueChk = new Button(parent, SWT.CHECK); + trueChk.setText("Do it. (It will to the contrary if unchecked)"); + trueChk.setSelection(true); + trueChk.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false)); + } + + private void populatePasswordCmp(Composite parent) { + cleanParent(parent); + Composite body = new Composite(parent, SWT.NO_FOCUS); + body.setLayout(new GridLayout(2, false)); + body.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + pwdTxt = createLP(body, "New password", ""); + pwd2Txt = createLP(body, "Repeat password", ""); + } + + /** Creates label and password. */ + protected Text createLP(Composite body, String label, String value) { + Label lbl = new Label(body, SWT.NONE); + lbl.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false)); + lbl.setText(label); + Text text = new Text(body, SWT.BORDER | SWT.PASSWORD); + text.setText(value); + text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + return text; + } + + private void populateGroupCmp(Composite parent) { + if (parent.getChildren().length > 0) { + for (Control control : parent.getChildren()) + control.dispose(); + } + trueChk = new Button(parent, SWT.CHECK); + trueChk.setText("Add to group. (It will remove user(s) from the " + + "corresponding group if unchecked)"); + trueChk.setSelection(true); + trueChk.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false)); + } + + protected String getCommand() { + return commands.get(chooseCommandCmb.getItem(chooseCommandCmb + .getSelectionIndex())); + } + + protected String getCommandLbl() { + return chooseCommandCmb.getItem(chooseCommandCmb + .getSelectionIndex()); + } + + protected boolean getBoleanValue() { + // FIXME this is not consistent and will lead to errors. + if (ArgeoNames.ARGEO_ENABLED.equals(getCommand())) + return trueChk.getSelection(); + else + return !trueChk.getSelection(); + } + + @SuppressWarnings("unused") + protected String getStringValue() { + String value = null; + if (valueTxt != null) { + value = valueTxt.getText(); + if ("".equals(value.trim())) + value = null; + } + return value; + } + + protected String getPwdValue() { + String newPwd = null; + if (pwdTxt == null || pwd2Txt == null) + return null; + if (!pwdTxt.getText().equals("") || !pwd2Txt.getText().equals("")) { + if (pwdTxt.getText().equals(pwd2Txt.getText())) { + newPwd = pwdTxt.getText(); + pwdTxt.setText(""); + pwd2Txt.setText(""); + } else { + pwdTxt.setText(""); + pwd2Txt.setText(""); + throw new ArgeoException("Passwords are not equals"); + } + } + return newPwd; + } + } + + /** + * Displays a list of users with a check box to be able to choose some of + * them + */ + private class ChooseUsersWizardPage extends WizardPage implements + IPageChangedListener { + private static final long serialVersionUID = 1L; + private UserTableComposite userTableCmp; + private Composite container; + private Session session; + + public ChooseUsersWizardPage(Session session) { + super("Choose Users"); + this.session = session; + setTitle("Select users who will be impacted"); + } + + @Override + public void createControl(Composite parent) { + container = new Composite(parent, SWT.NONE); + container.setLayout(new FillLayout()); + userTableCmp = new MyUserTableCmp(container, SWT.NO_FOCUS, session); + userTableCmp.populate(true, true); + setControl(container); + + // Add listener to update message when shown + final IWizardContainer container = this.getContainer(); + if (container instanceof IPageChangeProvider) { + ((IPageChangeProvider) container).addPageChangedListener(this); + } + + } + + @Override + public void pageChanged(PageChangedEvent event) { + if (event.getSelectedPage() == this) { + String msg = "Chosen batch action: " + + chooseCommandPage.getCommandLbl(); + ((WizardPage) event.getSelectedPage()).setMessage(msg); + } + } + + protected List getSelectedUsers() { + return userTableCmp.getSelectedUsers(); + } + + private class MyUserTableCmp extends UserTableComposite { + + private static final long serialVersionUID = 1L; + + public MyUserTableCmp(Composite parent, int style, Session session) { + super(parent, style, session); + } + + @Override + protected void refreshFilteredList() { + List nodes = new ArrayList(); + try { + NodeIterator ni = listFilteredElements(session, + getFilterString()); + + users: while (ni.hasNext()) { + Node currNode = ni.nextNode(); + String username = currNode.hasProperty(ARGEO_USER_ID) ? currNode + .getProperty(ARGEO_USER_ID).getString() : ""; + if (username.equals(session.getUserID())) + continue users; + else + nodes.add(currNode); + } + getTableViewer().setInput(nodes.toArray()); + } catch (RepositoryException e) { + throw new ArgeoException("Unable to list users", e); + } + } + } + } + + /** + * Recapitulation of input data before running real update + */ + private class ValidateAndLaunchWizardPage extends WizardPage implements + IPageChangedListener { + private static final long serialVersionUID = 1L; + private UserTableComposite userTableCmp; + private Session session; + + public ValidateAndLaunchWizardPage(Session session) { + super("Validate and launch"); + this.session = session; + setTitle("Validate and launch"); + } + + @Override + public void createControl(Composite parent) { + Composite mainCmp = new Composite(parent, SWT.NO_FOCUS); + mainCmp.setLayout(new FillLayout()); + + // Add listener to update user list when shown + final IWizardContainer container = this.getContainer(); + if (container instanceof IPageChangeProvider) { + ((IPageChangeProvider) container).addPageChangedListener(this); + } + + userTableCmp = new UserTableComposite(mainCmp, SWT.NO_FOCUS, + session); + userTableCmp.populate(false, false); + setControl(mainCmp); + } + + @Override + public void pageChanged(PageChangedEvent event) { + if (event.getSelectedPage() == this) { + @SuppressWarnings({ "unchecked", "rawtypes" }) + Object[] values = ((ArrayList) userListPage.getSelectedUsers()) + .toArray(new Object[userListPage.getSelectedUsers() + .size()]); + userTableCmp.getTableViewer().setInput(values); + String msg = "Following batch action: [" + + chooseCommandPage.getCommandLbl() + + "] will be perfomed on the users listed below.\n" + + "Are you sure you want to proceed?"; + ((WizardPage) event.getSelectedPage()).setMessage(msg); + } + } + + // private class MyUserTableCmp extends UserTableComposite { + // public MyUserTableCmp(Composite parent, int style, Session session) { + // super(parent, style, session); + // } + // + // @Override + // protected void refreshFilteredList() { + // @SuppressWarnings({ "unchecked", "rawtypes" }) + // + // setFilteredList(values); + // } + // + // @Override + // public void setVisible(boolean visible) { + // super.setVisible(visible); + // if (visible) + // refreshFilteredList(); + // } + // } + } +} \ No newline at end of file diff --git a/org.argeo.security.ui.rap/.classpath b/org.argeo.security.ui.rap/.classpath new file mode 100644 index 000000000..5641c7ca3 --- /dev/null +++ b/org.argeo.security.ui.rap/.classpath @@ -0,0 +1,7 @@ + + + + >> + + + diff --git a/org.argeo.security.ui.rap/.project b/org.argeo.security.ui.rap/.project new file mode 100644 index 000000000..d20bec7fc --- /dev/null +++ b/org.argeo.security.ui.rap/.project @@ -0,0 +1,28 @@ + + + org.argeo.security.ui.rap + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/org.argeo.security.ui.rap/META-INF/jaas_default.txt b/org.argeo.security.ui.rap/META-INF/jaas_default.txt new file mode 100644 index 000000000..c74797b93 --- /dev/null +++ b/org.argeo.security.ui.rap/META-INF/jaas_default.txt @@ -0,0 +1,23 @@ +UNIX { + org.eclipse.equinox.security.auth.module.ExtensionLoginModule sufficient + extensionId="org.argeo.security.equinox.unixLoginModule"; +}; + +SPRING { + org.eclipse.equinox.security.auth.module.ExtensionLoginModule sufficient + extensionId="org.argeo.security.equinox.springLoginModule"; +}; + +SPRING_ANONYMOUS { + org.eclipse.equinox.security.auth.module.ExtensionLoginModule sufficient + extensionId="org.argeo.security.equinox.anonymousSpringLoginModule"; +}; + +SPRING_SECURITY_CONTEXT { + org.eclipse.equinox.security.auth.module.ExtensionLoginModule sufficient + extensionId="org.argeo.security.equinox.springSecurityContextLoginModule"; +}; + +KEYRING { + org.argeo.security.crypto.KeyringLoginModule required; +}; diff --git a/org.argeo.security.ui.rap/META-INF/spring/commands.xml b/org.argeo.security.ui.rap/META-INF/spring/commands.xml new file mode 100644 index 000000000..3dd037a3c --- /dev/null +++ b/org.argeo.security.ui.rap/META-INF/spring/commands.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + diff --git a/org.argeo.security.ui.rap/META-INF/spring/osgi.xml b/org.argeo.security.ui.rap/META-INF/spring/osgi.xml new file mode 100644 index 000000000..9e357a36d --- /dev/null +++ b/org.argeo.security.ui.rap/META-INF/spring/osgi.xml @@ -0,0 +1,14 @@ + + + + + \ No newline at end of file diff --git a/org.argeo.security.ui.rap/branding/afterLogout.html b/org.argeo.security.ui.rap/branding/afterLogout.html new file mode 100644 index 000000000..ae0901bff --- /dev/null +++ b/org.argeo.security.ui.rap/branding/afterLogout.html @@ -0,0 +1,18 @@ + + + +
+ + + + +
+ Login... +
+
+ + \ No newline at end of file diff --git a/org.argeo.security.ui.rap/branding/empty.html b/org.argeo.security.ui.rap/branding/empty.html new file mode 100644 index 000000000..94fe28ac8 --- /dev/null +++ b/org.argeo.security.ui.rap/branding/empty.html @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/org.argeo.security.ui.rap/branding/favicon.ico b/org.argeo.security.ui.rap/branding/favicon.ico new file mode 100644 index 000000000..213cdf73f Binary files /dev/null and b/org.argeo.security.ui.rap/branding/favicon.ico differ diff --git a/org.argeo.security.ui.rap/branding/login.html b/org.argeo.security.ui.rap/branding/login.html new file mode 100644 index 000000000..6de7eb216 --- /dev/null +++ b/org.argeo.security.ui.rap/branding/login.html @@ -0,0 +1,18 @@ + + + +
+ + + + +
+ Login... +
+
+ + \ No newline at end of file diff --git a/org.argeo.security.ui.rap/branding/public.html b/org.argeo.security.ui.rap/branding/public.html new file mode 100644 index 000000000..e50f6e943 --- /dev/null +++ b/org.argeo.security.ui.rap/branding/public.html @@ -0,0 +1,18 @@ + + + +
+ + + + +
+ Refresh... +
+
+ + \ No newline at end of file diff --git a/org.argeo.security.ui.rap/build.properties b/org.argeo.security.ui.rap/build.properties new file mode 100644 index 000000000..5618fae36 --- /dev/null +++ b/org.argeo.security.ui.rap/build.properties @@ -0,0 +1,6 @@ +bin.includes = plugin.xml,\ + META-INF/,\ + branding/,\ + icons/ +source.. = src/main/java/ +output.. = target/classes/ diff --git a/org.argeo.security.ui.rap/icons/closeAll.gif b/org.argeo.security.ui.rap/icons/closeAll.gif new file mode 100644 index 000000000..28a3785aa Binary files /dev/null and b/org.argeo.security.ui.rap/icons/closeAll.gif differ diff --git a/org.argeo.security.ui.rap/icons/exit.png b/org.argeo.security.ui.rap/icons/exit.png new file mode 100644 index 000000000..cfbf9d15e Binary files /dev/null and b/org.argeo.security.ui.rap/icons/exit.png differ diff --git a/org.argeo.security.ui.rap/icons/home.gif b/org.argeo.security.ui.rap/icons/home.gif new file mode 100644 index 000000000..fd0c66950 Binary files /dev/null and b/org.argeo.security.ui.rap/icons/home.gif differ diff --git a/org.argeo.security.ui.rap/icons/main.gif b/org.argeo.security.ui.rap/icons/main.gif new file mode 100644 index 000000000..90a00147b Binary files /dev/null and b/org.argeo.security.ui.rap/icons/main.gif differ diff --git a/org.argeo.security.ui.rap/icons/password.gif b/org.argeo.security.ui.rap/icons/password.gif new file mode 100644 index 000000000..a6b251fc8 Binary files /dev/null and b/org.argeo.security.ui.rap/icons/password.gif differ diff --git a/org.argeo.security.ui.rap/icons/preferences.png b/org.argeo.security.ui.rap/icons/preferences.png new file mode 100644 index 000000000..aa0dc0be9 Binary files /dev/null and b/org.argeo.security.ui.rap/icons/preferences.png differ diff --git a/org.argeo.security.ui.rap/plugin.xml b/org.argeo.security.ui.rap/plugin.xml new file mode 100644 index 000000000..49506de26 --- /dev/null +++ b/org.argeo.security.ui.rap/plugin.xml @@ -0,0 +1,222 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.argeo.security.ui.rap/pom.xml b/org.argeo.security.ui.rap/pom.xml new file mode 100644 index 000000000..6dd6dceb1 --- /dev/null +++ b/org.argeo.security.ui.rap/pom.xml @@ -0,0 +1,86 @@ + + + 4.0.0 + + org.argeo.commons + 2.1.12-SNAPSHOT + argeo-commons + .. + + org.argeo.security.ui.rap + Commons Security UI RAP + jar + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-source-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + org.apache.felix + maven-bundle-plugin + + + ${project.artifactId};singleton:=true + org.argeo.security.ui.rap.SecureRapActivator + lazy + org.eclipse.rap.ui,org.eclipse.core.runtime + + org.springframework.core, + org.argeo.eclipse.spring, + org.argeo.eclipse.ui.specific, + * + + + + + + + + + + org.argeo.commons + org.argeo.util + 2.1.12-SNAPSHOT + + + + + org.argeo.tp + slf4j.org.apache.commons.logging + + + + + org.argeo.commons + org.argeo.security.ui + 2.1.12-SNAPSHOT + + + org.argeo.commons + org.argeo.security.equinox + 2.1.12-SNAPSHOT + + + + + org.argeo.commons + org.argeo.eclipse.dep.rap + 2.1.12-SNAPSHOT + + + org.argeo.commons + org.argeo.eclipse.ui.rap + 2.1.12-SNAPSHOT + + + \ No newline at end of file diff --git a/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/AnonymousEntryPoint.java b/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/AnonymousEntryPoint.java new file mode 100644 index 000000000..16d24897c --- /dev/null +++ b/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/AnonymousEntryPoint.java @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.rap; + +import java.security.PrivilegedAction; + +import javax.security.auth.Subject; +import javax.security.auth.login.LoginException; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; +import org.eclipse.equinox.security.auth.ILoginContext; +import org.eclipse.rap.rwt.RWT; +import org.eclipse.rap.rwt.application.IEntryPoint; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.PlatformUI; + +/** + * RAP entry point which authenticates the subject as anonymous, for public + * unauthenticated access. + */ +public class AnonymousEntryPoint implements IEntryPoint { + private final static Log log = LogFactory.getLog(AnonymousEntryPoint.class); + + /** + * How many seconds to wait before invalidating the session if the user has + * not yet logged in. + */ + private Integer loginTimeout = 1 * 60; + private Integer sessionTimeout = 15 * 60; + + @Override + public int createUI() { + // Short login timeout so that the modal dialog login doesn't hang + // around too long + RWT.getRequest().getSession().setMaxInactiveInterval(loginTimeout); + + if (log.isDebugEnabled()) + log.debug("Anonymous THREAD=" + Thread.currentThread().getId() + + ", sessionStore=" + RWT.getSessionStore().getId()); + + // create display + final Display display = PlatformUI.createDisplay(); + + // log in + final ILoginContext loginContext = SecureRapActivator + .createLoginContext(SecureRapActivator.CONTEXT_SPRING_ANONYMOUS); + Subject subject = null; + try { + loginContext.login(); + subject = loginContext.getSubject(); + } catch (LoginException e) { + throw new ArgeoException( + "Unexpected exception during authentication", e); + } + + // identify after successful login + if (log.isDebugEnabled()) + log.debug("Authenticated " + subject); + final String username = subject.getPrincipals().iterator().next() + .getName(); + + // Once the user is logged in, she can have a longer session timeout + RWT.getRequest().getSession().setMaxInactiveInterval(sessionTimeout); + + // Logout callback when the display is disposed + display.disposeExec(new Runnable() { + public void run() { + log.debug("Display disposed"); + logout(loginContext, username); + } + }); + + // + // RUN THE WORKBENCH + // + Integer returnCode = null; + try { + returnCode = Subject.doAs(subject, new PrivilegedAction() { + public Integer run() { + RapWorkbenchAdvisor workbenchAdvisor = new RapWorkbenchAdvisor( + null); + int result = PlatformUI.createAndRunWorkbench(display, + workbenchAdvisor); + return new Integer(result); + } + }); + logout(loginContext, username); + } finally { + display.dispose(); + } + return returnCode; + } + + private void logout(ILoginContext secureContext, String username) { + try { + secureContext.logout(); + log.info("Logged out " + (username != null ? username : "") + + " (THREAD=" + Thread.currentThread().getId() + ")"); + } catch (LoginException e) { + log.error("Erorr when logging out", e); + } + } +} diff --git a/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/LogoutEntryPoint.java b/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/LogoutEntryPoint.java new file mode 100644 index 000000000..733754901 --- /dev/null +++ b/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/LogoutEntryPoint.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.rap; + +import javax.security.auth.login.LoginException; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.eclipse.equinox.security.auth.ILoginContext; +import org.eclipse.rap.rwt.RWT; +import org.eclipse.rap.rwt.application.IEntryPoint; +import org.eclipse.ui.PlatformUI; +import org.springframework.security.context.SecurityContextHolder; + +/** + * RAP entry point which logs out the currently authenticated user + */ +public class LogoutEntryPoint implements IEntryPoint { + private final static Log log = LogFactory.getLog(LogoutEntryPoint.class); + + /** + * From org.springframework.security.context. + * HttpSessionContextIntegrationFilter + */ + protected static final String SPRING_SECURITY_CONTEXT_KEY = "SPRING_SECURITY_CONTEXT"; + + @Override + public int createUI() { + // create display + PlatformUI.createDisplay(); + + final ILoginContext loginContext = SecureRapActivator + .createLoginContext(SecureRapActivator.CONTEXT_SPRING); + try { + loginContext.logout(); + } catch (LoginException e) { + e.printStackTrace(); + } + + RWT.getRequest().getSession() + .removeAttribute(SPRING_SECURITY_CONTEXT_KEY); + SecurityContextHolder.clearContext(); + RWT.getRequest().getSession().setMaxInactiveInterval(1); + + if (log.isDebugEnabled()) + log.debug("Logged out session " + RWT.getSessionStore().getId()); + return 0; + } +} diff --git a/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/NullEntryPoint.java b/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/NullEntryPoint.java new file mode 100644 index 000000000..811cc2821 --- /dev/null +++ b/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/NullEntryPoint.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.rap; + +import org.eclipse.rap.rwt.application.IEntryPoint; +import org.eclipse.ui.PlatformUI; + +/** + * RAP entry point which does doesing except creating the display + */ +public class NullEntryPoint implements IEntryPoint { + @Override + public int createUI() { + // create display + PlatformUI.createDisplay(); + return 0; + } +} diff --git a/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/RapActionBarAdvisor.java b/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/RapActionBarAdvisor.java new file mode 100644 index 000000000..074b798c7 --- /dev/null +++ b/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/RapActionBarAdvisor.java @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.rap; + +import org.argeo.security.ui.commands.OpenHomePerspective; +import org.eclipse.core.commands.Category; +import org.eclipse.core.commands.Command; +import org.eclipse.jface.action.ICoolBarManager; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.jface.action.ToolBarManager; +import org.eclipse.swt.SWT; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.actions.ActionFactory; +import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction; +import org.eclipse.ui.application.ActionBarAdvisor; +import org.eclipse.ui.application.IActionBarConfigurer; +import org.eclipse.ui.commands.ICommandService; + +/** Eclipse rap specific action bar advisor */ +public class RapActionBarAdvisor extends ActionBarAdvisor { + private final static String ID_BASE = "org.argeo.security.ui.rap"; + // private final static Log log = LogFactory + // .getLog(SecureActionBarAdvisor.class); + + /** Null means anonymous */ + private String username = null; + + // private IAction logoutAction; + // private IWorkbenchAction openPerspectiveDialogAction; + // private IWorkbenchAction showViewMenuAction; + // private IWorkbenchAction preferences; + private IWorkbenchAction saveAction; + private IWorkbenchAction saveAllAction; + + // private IWorkbenchAction closeAllAction; + + public RapActionBarAdvisor(IActionBarConfigurer configurer, String username) { + super(configurer); + this.username = username; + } + + protected void makeActions(IWorkbenchWindow window) { + // preferences = ActionFactory.PREFERENCES.create(window); + // register(preferences); + // openPerspectiveDialogAction = ActionFactory.OPEN_PERSPECTIVE_DIALOG + // .create(window); + // register(openPerspectiveDialogAction); + // showViewMenuAction = ActionFactory.SHOW_VIEW_MENU.create(window); + // register(showViewMenuAction); + // + // // logout + // logoutAction = ActionFactory.QUIT.create(window); + // // logoutAction = createLogoutAction(); + // register(logoutAction); + // + // Save semantics + saveAction = ActionFactory.SAVE.create(window); + register(saveAction); + saveAllAction = ActionFactory.SAVE_ALL.create(window); + register(saveAllAction); + // closeAllAction = ActionFactory.CLOSE_ALL.create(window); + // register(closeAllAction); + + } + + protected void fillMenuBar(IMenuManager menuBar) { + // MenuManager fileMenu = new MenuManager("&File", + // IWorkbenchActionConstants.M_FILE); + // MenuManager editMenu = new MenuManager("&Edit", + // IWorkbenchActionConstants.M_EDIT); + // MenuManager windowMenu = new MenuManager("&Window", + // IWorkbenchActionConstants.M_WINDOW); + // + // menuBar.add(fileMenu); + // menuBar.add(editMenu); + // menuBar.add(windowMenu); + // // Add a group marker indicating where action set menus will appear. + // menuBar.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS)); + // + // // File + // fileMenu.add(saveAction); + // fileMenu.add(saveAllAction); + // fileMenu.add(closeAllAction); + // fileMenu.add(new + // GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS)); + // fileMenu.add(new Separator()); + // fileMenu.add(logoutAction); + // + // // Edit + // editMenu.add(preferences); + // + // // Window + // windowMenu.add(openPerspectiveDialogAction); + // windowMenu.add(showViewMenuAction); + } + + @Override + protected void fillCoolBar(ICoolBarManager coolBar) { + if (username != null) { + ICommandService cmdService = (ICommandService) getActionBarConfigurer() + .getWindowConfigurer().getWorkbenchConfigurer() + .getWorkbench().getService(ICommandService.class); + Category userMenus = cmdService.getCategory(ID_BASE + ".userMenus"); + if (!userMenus.isDefined()) + userMenus.define("User Menus", "User related menus"); + + Command userMenu = cmdService.getCommand(ID_BASE + + ".userMenuCommand"); + if (userMenu.isDefined()) + userMenu.undefine(); + userMenu.define(username, "User menu actions", userMenus); + userMenu.setHandler(new OpenHomePerspective()); + + // userToolbar.add(new UserMenuAction()); + // coolBar.add(userToolbar); + } else {// anonymous + IToolBarManager userToolbar = new ToolBarManager(SWT.FLAT + | SWT.RIGHT); + // userToolbar.add(logoutAction); + coolBar.add(userToolbar); + } + // IToolBarManager saveToolbar = new ToolBarManager(SWT.FLAT | + // SWT.RIGHT); + // saveToolbar.add(saveAction); + // saveToolbar.add(saveAllAction); + // coolBar.add(saveToolbar); + } + + // class UserMenuAction extends Action implements IWorkbenchAction { + // + // public UserMenuAction() { + // super(username, IAction.AS_DROP_DOWN_MENU); + // // setMenuCreator(new UserMenu()); + // } + // + // @Override + // public String getId() { + // return "org.argeo.security.ui.rap.userMenu"; + // } + // + // @Override + // public void dispose() { + // } + // + // } + + // class UserMenu implements IMenuCreator { + // private Menu menu; + // + // public Menu getMenu(Control parent) { + // Menu menu = new Menu(parent); + // addActionToMenu(menu, logoutAction); + // return menu; + // } + // + // private void addActionToMenu(Menu menu, IAction action) { + // ActionContributionItem item = new ActionContributionItem(action); + // item.fill(menu, -1); + // } + // + // public void dispose() { + // if (menu != null) { + // menu.dispose(); + // } + // } + // + // public Menu getMenu(Menu parent) { + // // Not use + // return null; + // } + // + // } + + // protected IAction createLogoutAction() { + // Subject subject = Subject.getSubject(AccessController.getContext()); + // final String username = subject.getPrincipals().iterator().next() + // .getName(); + // + // IAction logoutAction = new Action() { + // public String getId() { + // return SecureRapActivator.ID + ".logoutAction"; + // } + // + // public String getText() { + // return "Logout " + username; + // } + // + // public void run() { + // // try { + // // Subject subject = SecureRapActivator.getLoginContext() + // // .getSubject(); + // // String subjectStr = subject.toString(); + // // subject.getPrincipals().clear(); + // // SecureRapActivator.getLoginContext().logout(); + // // log.info(subjectStr + " logged out"); + // // } catch (LoginException e) { + // // log.error("Error when logging out", e); + // // } + // // SecureEntryPoint.logout(username); + // // PlatformUI.getWorkbench().close(); + // // try { + // // RWT.getRequest().getSession().setMaxInactiveInterval(1); + // // } catch (Exception e) { + // // if (log.isTraceEnabled()) + // // log.trace("Error when invalidating session", e); + // // } + // } + // + // }; + // return logoutAction; + // } + +} diff --git a/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/RapWindowAdvisor.java b/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/RapWindowAdvisor.java new file mode 100644 index 000000000..480815279 --- /dev/null +++ b/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/RapWindowAdvisor.java @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.rap; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.actions.ActionFactory; +import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction; +import org.eclipse.ui.application.ActionBarAdvisor; +import org.eclipse.ui.application.IActionBarConfigurer; +import org.eclipse.ui.application.IWorkbenchWindowConfigurer; +import org.eclipse.ui.application.WorkbenchWindowAdvisor; +import org.eclipse.ui.internal.UIPlugin; + +/** Eclipse RAP specific window advisor */ +public class RapWindowAdvisor extends WorkbenchWindowAdvisor { + + private String username; + + public RapWindowAdvisor(IWorkbenchWindowConfigurer configurer, + String username) { + super(configurer); + this.username = username; + } + + @Override + public ActionBarAdvisor createActionBarAdvisor( + IActionBarConfigurer configurer) { + return new RapActionBarAdvisor(configurer, username); + } + + public void preWindowOpen() { + IWorkbenchWindowConfigurer configurer = getWindowConfigurer(); + configurer.setShowCoolBar(true); + configurer.setShowMenuBar(false); + configurer.setShowStatusLine(false); + configurer.setShowPerspectiveBar(true); + configurer.setTitle("Argeo Web UI"); //$NON-NLS-1$ + // Full screen, see + // http://wiki.eclipse.org/RAP/FAQ#How_to_create_a_fullscreen_application + configurer.setShellStyle(SWT.NO_TRIM); + Rectangle bounds = Display.getCurrent().getBounds(); + configurer.setInitialSize(new Point(bounds.width, bounds.height)); + + // Handle window resize in Rap 2.1+ see https://bugs.eclipse.org/bugs/show_bug.cgi?id=417254 + Display.getCurrent().addListener(SWT.Resize, new Listener() { + @Override + public void handleEvent(Event event) { + Rectangle bounds = event.display.getBounds(); + IWorkbenchWindow iww = UIPlugin.getDefault().getWorkbench() + .getActiveWorkbenchWindow(); + iww.getShell().setBounds(bounds); + } + }); + } + + @Override + public void postWindowCreate() { + Shell shell = getWindowConfigurer().getWindow().getShell(); + shell.setMaximized(true); + } + + @Override + public void postWindowOpen() { + String defaultPerspective = getWindowConfigurer() + .getWorkbenchConfigurer().getWorkbench() + .getPerspectiveRegistry().getDefaultPerspective(); + if (defaultPerspective == null) { + IWorkbenchWindow window = getWindowConfigurer().getWindow(); + if (window == null) + return; + + IWorkbenchAction openPerspectiveDialogAction = ActionFactory.OPEN_PERSPECTIVE_DIALOG + .create(window); + openPerspectiveDialogAction.run(); + } + } + +} diff --git a/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/RapWorkbenchAdvisor.java b/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/RapWorkbenchAdvisor.java new file mode 100644 index 000000000..edde41f14 --- /dev/null +++ b/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/RapWorkbenchAdvisor.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.rap; + +import org.eclipse.ui.IPerspectiveDescriptor; +import org.eclipse.ui.application.IWorkbenchConfigurer; +import org.eclipse.ui.application.IWorkbenchWindowConfigurer; +import org.eclipse.ui.application.WorkbenchAdvisor; +import org.eclipse.ui.application.WorkbenchWindowAdvisor; + +/** Eclipse RAP specific workbench advisor */ +public class RapWorkbenchAdvisor extends WorkbenchAdvisor { + public final static String INITIAL_PERSPECTIVE_PROPERTY = "org.argeo.security.ui.initialPerspective"; + public final static String SAVE_AND_RESTORE_PROPERTY = "org.argeo.security.ui.saveAndRestore"; + + private String initialPerspective = System.getProperty( + INITIAL_PERSPECTIVE_PROPERTY, null); + + private String username; + + public RapWorkbenchAdvisor(String username) { + this.username = username; + } + + @Override + public void initialize(IWorkbenchConfigurer configurer) { + super.initialize(configurer); + Boolean saveAndRestore = Boolean.parseBoolean(System.getProperty( + SAVE_AND_RESTORE_PROPERTY, "false")); + configurer.setSaveAndRestore(saveAndRestore); + } + + public WorkbenchWindowAdvisor createWorkbenchWindowAdvisor( + IWorkbenchWindowConfigurer configurer) { + return new RapWindowAdvisor(configurer, username); + } + + public String getInitialWindowPerspectiveId() { + if (initialPerspective != null) { + // check whether this user can see the declared perspective + // (typically the perspective won't be listed if this user doesn't + // have the right to see it) + IPerspectiveDescriptor pd = getWorkbenchConfigurer().getWorkbench() + .getPerspectiveRegistry() + .findPerspectiveWithId(initialPerspective); + if (pd == null) + return null; + } + return initialPerspective; + } +} diff --git a/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/SecureEntryPoint.java b/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/SecureEntryPoint.java new file mode 100644 index 000000000..288ca623b --- /dev/null +++ b/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/SecureEntryPoint.java @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.rap; + +import java.security.PrivilegedAction; + +import javax.security.auth.Subject; +import javax.security.auth.login.LoginException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; +import org.argeo.eclipse.ui.ErrorFeedback; +import org.argeo.util.LocaleUtils; +import org.eclipse.equinox.security.auth.ILoginContext; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.rap.rwt.RWT; +import org.eclipse.rap.rwt.application.IEntryPoint; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.PlatformUI; +import org.springframework.security.BadCredentialsException; +import org.springframework.security.context.SecurityContext; +import org.springframework.security.context.SecurityContextHolder; + +/** + * RAP entry point with login capabilities. Once the user has been + * authenticated, the workbench is run as a privileged action by the related + * subject. + */ +public class SecureEntryPoint implements IEntryPoint { + private final static Log log = LogFactory.getLog(SecureEntryPoint.class); + + /** + * From org.springframework.security.context. + * HttpSessionContextIntegrationFilter + */ + protected static final String SPRING_SECURITY_CONTEXT_KEY = "SPRING_SECURITY_CONTEXT"; + + /** + * How many seconds to wait before invalidating the session if the user has + * not yet logged in. + */ + private Integer loginTimeout = 1 * 60; + // TODO make it configurable + /** Default session timeout is 8 hours (European working day length) */ + private Integer sessionTimeout = 8 * 60 * 60; + + /** Override to provide an application specific workbench advisor */ + protected RapWorkbenchAdvisor createRapWorkbenchAdvisor(String username) { + return new RapWorkbenchAdvisor(username); + } + + @Override + public final int createUI() { + // Short login timeout so that the modal dialog login doesn't hang + // around too long + RWT.getRequest().getSession().setMaxInactiveInterval(loginTimeout); + + // Try to load security context thanks to the session processing filter + HttpServletRequest httpRequest = RWT.getRequest(); + HttpSession httpSession = httpRequest.getSession(); + Object contextFromSessionObject = httpSession + .getAttribute(SPRING_SECURITY_CONTEXT_KEY); + if (contextFromSessionObject != null) + SecurityContextHolder + .setContext((SecurityContext) contextFromSessionObject); + +// if (log.isDebugEnabled()) +// log.debug("THREAD=" + Thread.currentThread().getId() +// + ", sessionStore=" + RWT.getSessionStore().getId() +// + ", remote user=" + httpRequest.getRemoteUser()); + + // create display + final Display display = PlatformUI.createDisplay(); + + // log in + final ILoginContext loginContext = SecureRapActivator + .createLoginContext(SecureRapActivator.CONTEXT_SPRING); + Subject subject = null; + tryLogin: while (subject == null && !display.isDisposed()) { + try { + loginContext.login(); + subject = loginContext.getSubject(); + + // add security context to session + if (httpSession.getAttribute(SPRING_SECURITY_CONTEXT_KEY) == null) + httpSession.setAttribute(SPRING_SECURITY_CONTEXT_KEY, + SecurityContextHolder.getContext()); + // add thread locale to RWT session + log.info("Locale "+LocaleUtils.threadLocale.get()); + RWT.setLocale(LocaleUtils.threadLocale.get()); + + // Once the user is logged in, she can have a longer session + // timeout + RWT.getRequest().getSession() + .setMaxInactiveInterval(sessionTimeout); + if (log.isDebugEnabled()) + log.debug("Authenticated " + subject); + } catch (LoginException e) { + BadCredentialsException bce = wasCausedByBadCredentials(e); + if (bce != null) { + MessageDialog.openInformation(display.getActiveShell(), + "Bad Credentials", bce.getMessage()); + // retry login + continue tryLogin; + } + return processLoginDeath(display, e); + } + } + + final String username = subject.getPrincipals().iterator().next() + .getName(); + // Logout callback when the display is disposed + display.disposeExec(new Runnable() { + public void run() { + log.debug("Display disposed"); + logout(loginContext, username); + } + }); + + // + // RUN THE WORKBENCH + // + Integer returnCode = null; + try { + returnCode = Subject.doAs(subject, new PrivilegedAction() { + public Integer run() { + RapWorkbenchAdvisor workbenchAdvisor = createRapWorkbenchAdvisor(username); + int result = PlatformUI.createAndRunWorkbench(display, + workbenchAdvisor); + return new Integer(result); + } + }); + // logout(loginContext, username); + } finally { + display.dispose(); + } + return returnCode; + } + + private Integer processLoginDeath(Display display, LoginException e) { + // check thread death + ThreadDeath td = wasCausedByThreadDeath(e); + if (td != null) { + display.dispose(); + throw td; + } + if (!display.isDisposed()) { + ErrorFeedback.show("Unexpected exception during authentication", e); + // this was not just bad credentials or death thread + RWT.getRequest().getSession().setMaxInactiveInterval(1); + display.dispose(); + return -1; + } else { + throw new ArgeoException( + "Unexpected exception during authentication", e); + } + + } + + /** Recursively look for {@link BadCredentialsException} in the root causes. */ + private BadCredentialsException wasCausedByBadCredentials(Throwable t) { + if (t instanceof BadCredentialsException) + return (BadCredentialsException) t; + + if (t.getCause() != null) + return wasCausedByBadCredentials(t.getCause()); + else + return null; + } + + /** + * If there is a {@link ThreadDeath} in the root causes, rethrow it + * (important for RAP cleaning mechanism) + */ + protected ThreadDeath wasCausedByThreadDeath(Throwable t) { + if (t instanceof ThreadDeath) + return (ThreadDeath) t; + + if (t.getCause() != null) + return wasCausedByThreadDeath(t.getCause()); + else + return null; + } + + protected void logout(ILoginContext secureContext, String username) { + try { + HttpServletRequest httpRequest = RWT.getRequest(); + HttpSession httpSession = httpRequest.getSession(); + httpSession.setAttribute(SPRING_SECURITY_CONTEXT_KEY, null); + RWT.getRequest().getSession().setMaxInactiveInterval(1); + SecurityContextHolder.clearContext(); + secureContext.logout(); + log.info("Logged out " + (username != null ? username : "") + + " (THREAD=" + Thread.currentThread().getId() + ")"); + } catch (LoginException e) { + log.error("Erorr when logging out", e); + } + } +} diff --git a/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/SecureRapActivator.java b/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/SecureRapActivator.java new file mode 100644 index 000000000..4cbb441e7 --- /dev/null +++ b/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/SecureRapActivator.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.rap; + +import java.net.URL; + +import org.eclipse.equinox.security.auth.ILoginContext; +import org.eclipse.equinox.security.auth.LoginContextFactory; +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + +/** Configure Equinox login context from the bundle context. */ +public class SecureRapActivator implements BundleActivator { + + public final static String ID = "org.argeo.security.ui.rap"; + public final static String CONTEXT_SPRING = "SPRING"; + public final static String CONTEXT_SPRING_ANONYMOUS = "SPRING_ANONYMOUS"; + private static final String JAAS_CONFIG_FILE = "/META-INF/jaas_default.txt"; + + private BundleContext bundleContext; + private static SecureRapActivator activator = null; + + public void start(BundleContext bundleContext) throws Exception { + activator = this; + this.bundleContext = bundleContext; + } + + public void stop(BundleContext context) throws Exception { + bundleContext = null; + activator = null; + } + + public BundleContext getBundleContext() { + return bundleContext; + } + + public static SecureRapActivator getActivator() { + return activator; + } + + static ILoginContext createLoginContext(String contextName) { + URL configUrl = getActivator().getBundleContext().getBundle() + .getEntry(JAAS_CONFIG_FILE); + return LoginContextFactory.createContext(contextName, configUrl); + } +} diff --git a/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/commands/UserMenu.java b/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/commands/UserMenu.java new file mode 100644 index 000000000..98674303b --- /dev/null +++ b/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/commands/UserMenu.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.rap.commands; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; + +/** Default action of the user menu */ +public class UserMenu extends AbstractHandler { + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + return null; + } + +} diff --git a/org.argeo.security.ui.rcp/.classpath b/org.argeo.security.ui.rcp/.classpath new file mode 100644 index 000000000..8cf7f48a0 --- /dev/null +++ b/org.argeo.security.ui.rcp/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/org.argeo.security.ui.rcp/.project b/org.argeo.security.ui.rcp/.project new file mode 100644 index 000000000..feeafcf5b --- /dev/null +++ b/org.argeo.security.ui.rcp/.project @@ -0,0 +1,28 @@ + + + org.argeo.security.ui.rcp + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/org.argeo.security.ui.rcp/.settings/org.eclipse.jdt.core.prefs b/org.argeo.security.ui.rcp/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..1f382cb9d --- /dev/null +++ b/org.argeo.security.ui.rcp/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +#Sat Jan 15 17:51:30 CET 2011 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.5 diff --git a/org.argeo.security.ui.rcp/META-INF/jaas_default.txt b/org.argeo.security.ui.rcp/META-INF/jaas_default.txt new file mode 100644 index 000000000..16d476daf --- /dev/null +++ b/org.argeo.security.ui.rcp/META-INF/jaas_default.txt @@ -0,0 +1,27 @@ +OS_SPRING { + org.eclipse.equinox.security.auth.module.ExtensionLoginModule required + extensionId="org.argeo.security.equinox.osSpringLoginModule"; +}; + +NIX { + org.eclipse.equinox.security.auth.module.ExtensionLoginModule requisite + extensionId="org.argeo.security.equinox.unixLoginModule"; + org.eclipse.equinox.security.auth.module.ExtensionLoginModule required + extensionId="org.argeo.security.equinox.osSpringLoginModule"; +}; + +WINDOWS { + org.eclipse.equinox.security.auth.module.ExtensionLoginModule requisite + extensionId="org.argeo.security.equinox.ntLoginModule"; + org.eclipse.equinox.security.auth.module.ExtensionLoginModule required + extensionId="org.argeo.security.equinox.osSpringLoginModule"; +}; + +REMOTE { + org.eclipse.equinox.security.auth.module.ExtensionLoginModule sufficient + extensionId="org.argeo.security.equinox.springLoginModuleRemote"; +}; + +KEYRING { + org.argeo.security.crypto.KeyringLoginModule required; +}; diff --git a/org.argeo.security.ui.rcp/build.properties b/org.argeo.security.ui.rcp/build.properties new file mode 100644 index 000000000..5ac3de985 --- /dev/null +++ b/org.argeo.security.ui.rcp/build.properties @@ -0,0 +1,6 @@ +source.. = src/main/java/ +output.. = target/classes/ +bin.includes = plugin.xml,\ + META-INF/,\ + .,\ + log4j.properties diff --git a/org.argeo.security.ui.rcp/icons/alt_about.gif b/org.argeo.security.ui.rcp/icons/alt_about.gif new file mode 100644 index 000000000..20d9ad2d9 Binary files /dev/null and b/org.argeo.security.ui.rcp/icons/alt_about.gif differ diff --git a/org.argeo.security.ui.rcp/icons/alt_launcher.icns b/org.argeo.security.ui.rcp/icons/alt_launcher.icns new file mode 100644 index 000000000..b77a6a639 Binary files /dev/null and b/org.argeo.security.ui.rcp/icons/alt_launcher.icns differ diff --git a/org.argeo.security.ui.rcp/icons/alt_launcher.ico b/org.argeo.security.ui.rcp/icons/alt_launcher.ico new file mode 100644 index 000000000..d548f7109 Binary files /dev/null and b/org.argeo.security.ui.rcp/icons/alt_launcher.ico differ diff --git a/org.argeo.security.ui.rcp/icons/alt_launcher.xpm b/org.argeo.security.ui.rcp/icons/alt_launcher.xpm new file mode 100644 index 000000000..b0c139e06 --- /dev/null +++ b/org.argeo.security.ui.rcp/icons/alt_launcher.xpm @@ -0,0 +1,307 @@ +/* XPM */ +static char * icon48_xpm[] = { +"48 48 256 2", +" c #4B4B3B3B9090", +". c #0D0D0E0E5454", +"X c #11110E0E5B5B", +"o c #17170F0F6363", +"O c #1D1D13136969", +"+ c #212114146C6C", +"@ c #252514147171", +"# c #282811116C6C", +"$ c #26260D0D6363", +"% c #22220B0B5E5E", +"& c #1C1C0B0B5A5A", +"* c #1C1C0B0B5252", +"= c #1B1B05055353", +"- c #161606064D4D", +"; c #161605054949", +": c #111104044848", +"> c #131304044545", +", c #131305054242", +"< c #141410105E5E", +"1 c #2C2C15157373", +"2 c #2B2B1B1B7575", +"3 c #343416167272", +"4 c #313113136E6E", +"5 c #222209095757", +"6 c #1B1B06064D4D", +"7 c #15150B0B4242", +"8 c #13130C0C5555", +"9 c #2E2E1B1B7878", +"0 c #33331F1F7C7C", +"q c #343418187878", +"w c #3B3B1C1C7575", +"e c #2E2E10106767", +"r c #1B1B07074747", +"t c #18180B0B4646", +"y c #151513136262", +"u c #1A1A15156464", +"i c #34341F1F7777", +"p c #40401E1E8080", +"a c #42421B1B7A7A", +"s c #3B3B15157474", +"d c #2B2B0B0B5B5B", +"f c #222207075252", +"g c #373727277A7A", +"h c #474724248484", +"j c #393915156E6E", +"k c #373711116A6A", +"l c #343413136363", +"z c #232319196E6E", +"x c #292919197070", +"c c #3C3C2C2C8282", +"v c #444431318585", +"b c #494934348A8A", +"n c #505026268A8A", +"m c #3D3D1B1B6E6E", +"M c #31310E0E5C5C", +"N c #2B2B0D0D5353", +"B c #222207074A4A", +"V c #52523C3C9292", +"C c #58583C3C9494", +"Z c #5D5D44449797", +"A c #5C5C2E2E9292", +"S c #676733339595", +"D c #424228287575", +"F c #29290A0A4F4F", +"G c #6C6C4A4A9E9E", +"H c #72725454A7A7", +"J c #8C8C6D6DB2B2", +"K c #343424246E6E", +"L c #3A3A23236A6A", +"P c #3A3A1C1C6767", +"I c #24240A0A4B4B", +"U c #151518186161", +"Y c #76766F6FA5A5", +"T c #ADAD9191CCCC", +"R c #98988989D3D3", +"E c #45453B3B8686", +"W c #3C3C35357979", +"Q c #363631317575", +"! c #32322D2D6B6B", +"~ c #323229296363", +"^ c #30301F1F6262", +"/ c #323218185E5E", +"( c #272707074B4B", +") c #202028286C6C", +"_ c #1E1E1D1D6868", +"` c #9A9A8282BBBB", +"' c #C8C8B3B3D3D3", +"] c #B3B3AFAFE7E7", +"[ c #84847272C6C6", +"{ c #58585757A3A3", +"} c #3F3F3C3C8A8A", +"| c #3B3B3A3A8484", +" . c #414139397D7D", +".. c #3D3D39397A7A", +"X. c #37372E2E6E6E", +"o. c #2C2C21215A5A", +"O. c #2E2E1B1B5B5B", +"+. c #F5F5EFEFF5F5", +"@. c #656566669A9A", +"#. c #47474B4B8E8E", +"$. c #3C3C44447B7B", +"%. c #444442428080", +"&. c #45453E3E8181", +"*. c #40403C3C8181", +"=. c #3D3D33337474", +"-. c #3B3B30306E6E", +";. c #38382D2D6969", +":. c #303026265D5D", +">. c #2C2C15155A5A", +",. c #1F1F1C1C7070", +"<. c #25251E1E7171", +"1. c #59595C5C9191", +"2. c #4D4D53538989", +"3. c #4C4C49498484", +"4. c #484845458585", +"5. c #494941418585", +"6. c #494940408181", +"7. c #2F2F1C1C5353", +"8. c #2B2B28287676", +"9. c #323231317F7F", +"0. c #545452528B8B", +"q. c #51514E4E8989", +"w. c #4E4E4B4B8C8C", +"e. c #4C4C47478686", +"r. c #46463D3D7E7E", +"t. c #434336367A7A", +"y. c #2B2B13135555", +"u. c #47473D3D8D8D", +"i. c #575757578E8E", +"p. c #48483E3E7F7F", +"a. c #46463A3A7D7D", +"s. c #424235357575", +"d. c #404034347171", +"f. c #BFBFCBCBFAFA", +"g. c #B8B8A8A8DDDD", +"h. c #5E5E60609292", +"j. c #565655558C8C", +"k. c #4B4B44448282", +"l. c #454539397B7B", +"z. c #434338387878", +"x. c #3F3F32326D6D", +"c. c #3D3D30306969", +"v. c #3A3A2E2E6363", +"b. c #36362A2A5C5C", +"n. c #343424245555", +"m. c #30301E1E4D4D", +"M. c #49493C3C8282", +"N. c #5E5E4F4F8C8C", +"B. c #56563B3B8B8B", +"V. c #545407078585", +"C. c #424234347272", +"Z. c #9797A4A4F7F7", +"A. c #444436367676", +"S. c #7D7D7979D5D5", +"D. c #464640408A8A", +"F. c #44444B4B8282", +"G. c #414107077777", +"H. c #71716161C1C1", +"J. c #303039397979", +"K. c #8E8E8E8EE6E6", +"L. c #404033338B8B", +"P. c #4A4A45458C8C", +"I. c #46463A3A8080", +"U. c #363629295454", +"Y. c #303022224848", +"T. c #424237377575", +"R. c #2E2E1D1D6363", +"E. c #79798383EAEA", +"W. c #74747B7BE4E4", +"Q. c #6D6D7676D6D6", +"!. c #6A6A7171CECE", +"~. c #66666969C6C6", +"^. c #62626565BCBC", +"/. c #5F5F6060B5B5", +"(. c #5B5B5B5BACAC", +"). c #535353539898", +"_. c #4F4F4F4FA4A4", +"`. c #54544D4DA4A4", +"'. c #323204046B6B", +"]. c #303035357979", +"[. c #313122224343", +"{. c #5A5A5B5BB7B7", +"}. c #484846468080", +"|. c #454541417575", +" X c #4B4B31318282", +".X c #47473C3C8484", +"XX c #3E3E35356E6E", +"oX c #2F2F26264040", +"OX c #2B2B23233A3A", +"+X c #262619195C5C", +"@X c #252515155A5A", +"#X c #55555151B3B3", +"$X c #3C3C2D2D5D5D", +"%X c #39392F2F5656", +"&X c #37372D2D5050", +"*X c #25251F1F3030", +"=X c #24241D1D4343", +"-X c #202013135656", +";X c #41413B3B6C6C", +":X c #444442429696", +">X c #212100005E5E", +",X c #444436367272", +" > , , , ", +" . . X X < < o o O O + @ 1 2 2 1 1 1 1 1 1 1 1 3 4 # # $ $ $ % % % 5 = = 6 6 - ; ; > > , , 7 ", +" . 8 < < < o O O + @ @ 2 9 9 0 0 q q q q q q q w 3 4 4 e e $ $ $ $ % 5 = = 6 6 6 ; ; > > r t ", +" . X < y u O O + @ 1 2 i 0 0 p p p p p p p a a p a s 3 4 4 e e e e d 5 5 f f 6 6 6 ; ; r r t ", +" X < y u O + + @ 2 9 0 g p p h h h h h h h p h h a a s s j k k j l d d 5 5 f f 6 6 r r r r r ", +" X < y O z x x 9 0 g c v b n n n n n n n n n n n h a a s s j j m l M d d N f f B B B B r r r ", +" < y u + z 2 0 c c b V C Z C C A A A A A S S S n h D w w m m m m k l M d d N f F F F B r r r ", +" < y O z z 9 c b V Z G H H H G S G G J J H V v c g g K K K K L P l l l M M N N N N I B B r r ", +" U u + z x i v C H Y J J J J H J T R H V E W W Q Q Q Q ! ! ! ~ ^ ^ / / M M M M M N ( B B r r ", +" ) _ z x 9 g b Z Y ` ' ' ' T T ] [ { } | .........W W Q Q X.! ~ ~ o.O./ / / / N F ( B B B r ", +" ) ) z x i c V G J ' +.+.+.+.] [ @.#.$.%.%.%.&.*. . .....W =.-.X.;.~ :.o.O.^ >.N F ( B B B B ", +" ) ,.<.2 g v C H J ' +.+.+.+.T Y 1.2.3.4.4.4.5.6.&.&. . ...W =.=.-.;.~ :.o.7.>.N F F ( B I I ", +" ) ,.<.8.9.b C H J T +.+.+.' J @.1.0.q.q.w.e.4.5.6.&.r. . .t.W =.=.-.;.~ :.o.7.y.N F ( ( I I ", +" 8.8.8.9.| u.C G J T +.+.' ` Y @.1.i.0.q.q.e.e.5.6.p.r.a. .t.t.s.d.d.-.;.~ :.7.7.y.F F ( I I ", +" 9.c c c v b A S H ' f.g.` Y @.h.1.i.j.0.q.q.e.k.6.p.r.a.l.t.z.s.s.d.x.c.v.b.n.m.7.N F F F I ", +" <.g M.N.B.B.n V.J f.R J @.h.h.1.i.i.j.j.0.q.3.k.6.p.r.a.l.l.z.s.C.d.x.x.c.v.b.n.m.y.N F F F ", +" + x i v B.Z Z G g.Z.[ @.2.i.i.j.j.j.j.j.0.q.3.k.6.p.p.a.l.l.A.s.C.C.d.x.c.v.b.n.m.7.y.N N y. ", +" O # 3 w p n Z ` f.S.H D.F.q.0.0.0.0.j.0.q.q.3.k.6.p.r.a.a.l.A.s.s.C.d.x.x.c.v.b.n.m.y.y.y.y. ", +" O # 4 s a G.V.T Z.H.V J.%.e.w.q.0.0.0.0.q.q.e.k.6.p.r.a.a.l.z.A.s.C.d.d.x.c.v.b.n.m.7.>.y.y. ", +" O # 4 s w G.A f.K.H L...4.P.w.w.w.q.q.q.q.e.e.5.6.M.I.I.a.a.l.z.A.s.d.d.x.c.v.v.U.Y.7.O.>.y. ", +" $ # 4 3 s G.G f.S.Z 9.*.D.P.P.w.w.w.w.w.e.e.5.5.M.M.I.I.a.a.l.z.T.s.d.d.x.x.c.v.U.Y.m.R.>.>. ", +" E.E.W.W.W.W.E.Z.E.W.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.!.!.!.!.!.~.~.~.~.~.~.^.^.^.^.^./././.(.{ { )._.`._. ", +" + # 3 w s '.` f.H.V ].*.D.P.P.P.P.P.P.P.5.5.5.M.M.M.I.I.a.l.z.z.T.T.s.d.d.x.c.v.U.Y.[.^ O.>. ", +" ~.~.~.~.~.~.K.Z.S.~.{.^.^.^.^.^.^.^.^././././././.(.(.(.(.(.(.{ { { { { ).).).w.w.}.|.P.u.} ", +" .I.6. X X XT f.H.b ].*.E D.D.D.D.5.5..X.XM.M.I.I.a.a.l.l.z.z.T.T.T.d.XXx.c.v.b.U.oXOXR.+X@X ", +" E.E.E.W.W.W.K.Z.E.W.Q.Q.Q.Q.Q.Q.Q.Q.!.!.!.!.!.!.~.~.~.~.~.~.^.^.^.^.^./././.(.{ { ).).#X_._. ", +" & % $ e '.= H f.H.b 8.W *.E E E .X.X.XI.I.I.I.a.a.l.l.z.z.T.T.T.C.XXXXc.v.$X%X&XY.*X=X2 @X-X ", +" {.{.{.{.{.#X~.Z.W.~.{.{./././././././././.(.(.(.(.(.(.(.{ { { { { { ).).).w.w.3.}.;X%.:X} } ", +" & & % $ e >XV.f.S.C K X.W t. . .l.l.t.t.t.t.A.A.A.,X,X,X,X,XX7X` Z.Z D ! =.=.s.t.t.t.A.A.s.A.,X,X,X,X > > t t t cX ", +" nXbXbXzXzXlXaXXXY +Xf = f = 7XtXR R mXn.Y.[.[.[.[.OX*X*X8X5X*X=X,.u vXvX; > > MXMX, 7 t t ", +" nXnXnXbXzXvX-.Y +XcX6 6 = = = d L B.G H `.X.:.7.m.=X=X=X=X=X6X,.u cXvXNX: BX> MXVXCXVX7 7 7 ", +" ZXZXnXbXAXgX@.+XvX; - - - - * @XR.>.sX>.R.i 0 x eXeXeXeXO hXaXcXvXNX: BXMXMXMXVXCXCXCXVX7 7 ", +" SXZXZXAXgXN.aXNX: : NXNXNX- * +X+X* 6 6 6 * * * * * * * vXvX- NX: DXBXMXMXFXCXCXCXCXGXVXVX7 ", +" SXSXHXgX0.JXKXLXKXKXDX: : NX* @X-X- - - - - - - - - - - NX: DXDXDXMXMXFXFXCXCXCXCXGXGXGXVXVX ", +" SXHXPX3.JXnXnXnXnXbXLXKXKXNXaX-XvX: : NX: : : : : : : BXDXDXLXMXMXFXFXCXCXCXCXGXGXGXGXGXGXGX ", +" IXUX$.AXZXZXZXZXnXnXnXLXLXNXJXvXBXDXBXBXBXBXDXDXDXDXLXDXLXLXFXFXFXFXCXCXCXCXGXGXGXGXGXGXGXGX ", +" "}; diff --git a/org.argeo.security.ui.rcp/icons/alt_window_16.gif b/org.argeo.security.ui.rcp/icons/alt_window_16.gif new file mode 100644 index 000000000..05626b17d Binary files /dev/null and b/org.argeo.security.ui.rcp/icons/alt_window_16.gif differ diff --git a/org.argeo.security.ui.rcp/icons/alt_window_32.gif b/org.argeo.security.ui.rcp/icons/alt_window_32.gif new file mode 100644 index 000000000..b432f8833 Binary files /dev/null and b/org.argeo.security.ui.rcp/icons/alt_window_32.gif differ diff --git a/org.argeo.security.ui.rcp/plugin.xml b/org.argeo.security.ui.rcp/plugin.xml new file mode 100644 index 000000000..4ddf700d5 --- /dev/null +++ b/org.argeo.security.ui.rcp/plugin.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.argeo.security.ui.rcp/plugin_customization.ini b/org.argeo.security.ui.rcp/plugin_customization.ini new file mode 100644 index 000000000..baf9cefe7 --- /dev/null +++ b/org.argeo.security.ui.rcp/plugin_customization.ini @@ -0,0 +1,5 @@ +org.eclipse.ui/DOCK_PERSPECTIVE_BAR=topRight +org.eclipse.ui/SHOW_TEXT_ON_PERSPECTIVE_BAR=true +org.eclipse.ui/PERSPECTIVE_BAR_SIZE=100 +org.eclipse.ui/SHOW_TRADITIONAL_STYLE_TABS=true +org.eclipse.ui/SHOW_PROGRESS_ON_STARTUP = false diff --git a/org.argeo.security.ui.rcp/pom.xml b/org.argeo.security.ui.rcp/pom.xml new file mode 100644 index 000000000..22cc11400 --- /dev/null +++ b/org.argeo.security.ui.rcp/pom.xml @@ -0,0 +1,85 @@ + + + 4.0.0 + + org.argeo.commons + 2.1.12-SNAPSHOT + argeo-commons + .. + + org.argeo.security.ui.rcp + Commons Security UI RCP + jar + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-source-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + org.apache.felix + maven-bundle-plugin + + + ${project.artifactId};singleton:=true + org.argeo.security.ui.rcp.SecureApplicationActivator + lazy + org.eclipse.ui,org.eclipse.core.runtime + + org.argeo.eclipse.ui.specific, + org.argeo.eclipse.spring, + * + + + + + + + + + + org.argeo.commons + org.argeo.util + 2.1.12-SNAPSHOT + + + + + org.argeo.tp + slf4j.org.apache.commons.logging + + + + + org.argeo.commons + org.argeo.security.ui + 2.1.12-SNAPSHOT + + + org.argeo.commons + org.argeo.security.equinox + 2.1.12-SNAPSHOT + + + + + org.argeo.commons + org.argeo.eclipse.ui.rcp + 2.1.12-SNAPSHOT + + + org.argeo.commons + org.argeo.eclipse.dep.rcp + 2.1.12-SNAPSHOT + + + \ No newline at end of file diff --git a/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/AbstractSecureApplication.java b/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/AbstractSecureApplication.java new file mode 100644 index 000000000..75184cbab --- /dev/null +++ b/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/AbstractSecureApplication.java @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.rcp; + +import java.security.PrivilegedAction; + +import javax.security.auth.Subject; +import javax.security.auth.login.LoginException; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.OperatingSystem; +import org.eclipse.equinox.app.IApplication; +import org.eclipse.equinox.app.IApplicationContext; +import org.eclipse.equinox.security.auth.ILoginContext; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.application.WorkbenchAdvisor; + +/** + * RCP workbench initialization + */ +public abstract class AbstractSecureApplication implements IApplication { + final static String NODE_REPO_URI = "argeo.node.repo.uri"; + + private static final Log log = LogFactory + .getLog(AbstractSecureApplication.class); + + protected WorkbenchAdvisor createWorkbenchAdvisor(String username) { + return new SecureWorkbenchAdvisor(username); + } + + public Object start(IApplicationContext context) throws Exception { + // wait for the system to be initialized + // try { + // Thread.sleep(3000); + // } catch (Exception e2) { + // // silent + // } + + boolean remote = System.getProperty(NODE_REPO_URI) != null; + + // choose login context + final ILoginContext loginContext; + if (remote) { + loginContext = SecureApplicationActivator + .createLoginContext(SecureApplicationActivator.CONTEXT_REMOTE); + } else { + if (OperatingSystem.os == OperatingSystem.WINDOWS) + loginContext = SecureApplicationActivator + .createLoginContext(SecureApplicationActivator.CONTEXT_WINDOWS); + else + loginContext = SecureApplicationActivator + .createLoginContext(SecureApplicationActivator.CONTEXT_NIX); + } + + final Display display = PlatformUI.createDisplay(); + + // login + Subject subject = null; + try { + loginContext.login(); + subject = loginContext.getSubject(); + } catch (LoginException e) { + log.error("Error when logging in.", e); + display.dispose(); + try { + Thread.sleep(2000); + } catch (InterruptedException e1) { + // silent + } + return null; + } + + // identify after successful login + if (log.isDebugEnabled()) + log.debug("subject=" + subject); + final String username = subject.getPrincipals().iterator().next() + .getName(); + if (log.isDebugEnabled()) + log.debug(username + " logged in"); +// display.disposeExec(new Runnable() { +// public void run() { +// log.debug("Display disposed"); +// logout(loginContext, username); +// } +// }); + + try { + PrivilegedAction privilegedAction = new PrivilegedAction() { + public Object run() { + int result = PlatformUI.createAndRunWorkbench(display, + createWorkbenchAdvisor(username)); + return new Integer(result); + } + }; + + Integer returnCode = (Integer) Subject.doAs(subject, + privilegedAction); + logout(loginContext, username); + return processReturnCode(returnCode); + } catch (Exception e) { + if (subject != null) + logout(loginContext, username); + log.error("Unexpected error", e); + } finally { + display.dispose(); + } + return null; + } + + protected Integer processReturnCode(Integer returnCode) { + if (returnCode == PlatformUI.RETURN_RESTART) + return IApplication.EXIT_RESTART; + else + return IApplication.EXIT_OK; + } + + static void logout(ILoginContext secureContext, String username) { + try { + secureContext.logout(); + log.info("Logged out " + (username != null ? username : "") + + " (THREAD=" + Thread.currentThread().getId() + ")"); + } catch (LoginException e) { + log.error("Erorr when logging out", e); + } + } + + public void stop() { + final IWorkbench workbench; + try { + workbench = PlatformUI.getWorkbench(); + } catch (Exception e) { + return; + } + if (workbench == null) + return; + final Display display = workbench.getDisplay(); + if (display != null && !display.isDisposed()) + display.syncExec(new Runnable() { + + public void run() { + if (!display.isDisposed()) + workbench.close(); + } + }); + + if (log.isDebugEnabled()) + log.debug("workbench stopped"); + } + +} diff --git a/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureActionBarAdvisor.java b/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureActionBarAdvisor.java new file mode 100644 index 000000000..481865bfa --- /dev/null +++ b/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureActionBarAdvisor.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.rcp; + +import org.eclipse.jface.action.GroupMarker; +import org.eclipse.jface.action.ICoolBarManager; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.action.Separator; +import org.eclipse.jface.action.ToolBarManager; +import org.eclipse.swt.SWT; +import org.eclipse.ui.IWorkbenchActionConstants; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.actions.ActionFactory; +import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction; +import org.eclipse.ui.application.ActionBarAdvisor; +import org.eclipse.ui.application.IActionBarConfigurer; + +public class SecureActionBarAdvisor extends ActionBarAdvisor { + private IWorkbenchAction exitAction; + private IWorkbenchAction openPerspectiveDialogAction; + private IWorkbenchAction showViewMenuAction; + private IWorkbenchAction preferences; + private IWorkbenchAction saveAction; + private IWorkbenchAction saveAsAction; + private IWorkbenchAction saveAllAction; + private IWorkbenchAction closeAllAction; + + // private final Boolean isRcp; + + public SecureActionBarAdvisor(IActionBarConfigurer configurer, Boolean isRcp) { + super(configurer); + // this.isRcp = isRcp; + } + + protected void makeActions(IWorkbenchWindow window) { + preferences = ActionFactory.PREFERENCES.create(window); + register(preferences); + openPerspectiveDialogAction = ActionFactory.OPEN_PERSPECTIVE_DIALOG + .create(window); + register(openPerspectiveDialogAction); + showViewMenuAction = ActionFactory.SHOW_VIEW_MENU.create(window); + register(showViewMenuAction); + + exitAction = ActionFactory.QUIT.create(window); + register(exitAction); + + // Save semantiocs + saveAction = ActionFactory.SAVE.create(window); + register(saveAction); + saveAsAction = ActionFactory.SAVE_AS.create(window); + register(saveAsAction); + saveAllAction = ActionFactory.SAVE_ALL.create(window); + register(saveAllAction); + closeAllAction = ActionFactory.CLOSE_ALL.create(window); + register(closeAllAction); + + } + + protected void fillMenuBar(IMenuManager menuBar) { + MenuManager fileMenu = new MenuManager("&File", + IWorkbenchActionConstants.M_FILE); + MenuManager editMenu = new MenuManager("&Edit", + IWorkbenchActionConstants.M_EDIT); + MenuManager windowMenu = new MenuManager("&Window", + IWorkbenchActionConstants.M_WINDOW); + + menuBar.add(fileMenu); + menuBar.add(editMenu); + menuBar.add(windowMenu); + // Add a group marker indicating where action set menus will appear. + menuBar.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS)); + + // File + fileMenu.add(saveAction); + fileMenu.add(saveAsAction); + fileMenu.add(saveAllAction); + fileMenu.add(closeAllAction); + fileMenu.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS)); + fileMenu.add(new Separator()); + fileMenu.add(exitAction); + + // Edit + editMenu.add(preferences); + + // Window + windowMenu.add(openPerspectiveDialogAction); + windowMenu.add(showViewMenuAction); + } + + @Override + protected void fillCoolBar(ICoolBarManager coolBar) { + IToolBarManager saveToolbar = new ToolBarManager(SWT.FLAT | SWT.RIGHT); + saveToolbar.add(saveAction); + saveToolbar.add(saveAllAction); + coolBar.add(saveToolbar); + } + +} diff --git a/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureApplicationActivator.java b/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureApplicationActivator.java new file mode 100644 index 000000000..9c0425c5b --- /dev/null +++ b/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureApplicationActivator.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.rcp; + +import java.net.URL; + +import org.eclipse.equinox.security.auth.ILoginContext; +import org.eclipse.equinox.security.auth.LoginContextFactory; +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + +/** Activator able to create {@link ILoginContext} */ +public class SecureApplicationActivator implements BundleActivator { + + public final static String CONTEXT_REMOTE = "REMOTE"; + public final static String CONTEXT_NIX = "NIX"; + public final static String CONTEXT_WINDOWS = "WINDOWS"; + private static final String JAAS_CONFIG_FILE = "/META-INF/jaas_default.txt"; + + private static BundleContext bundleContext; + + public void start(BundleContext bundleContext) throws Exception { + SecureApplicationActivator.bundleContext = bundleContext; + } + + public void stop(BundleContext context) throws Exception { + } + + static ILoginContext createLoginContext(String context) { + URL configUrl = bundleContext.getBundle().getEntry(JAAS_CONFIG_FILE); + return LoginContextFactory.createContext(context, configUrl); + } +} diff --git a/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureRcp.java b/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureRcp.java new file mode 100644 index 000000000..d8125cf6f --- /dev/null +++ b/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureRcp.java @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.rcp; + + +public class SecureRcp extends AbstractSecureApplication { +} diff --git a/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureWorkbenchAdvisor.java b/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureWorkbenchAdvisor.java new file mode 100644 index 000000000..33b781ee5 --- /dev/null +++ b/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureWorkbenchAdvisor.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.rcp; + +import org.eclipse.ui.IPerspectiveDescriptor; +import org.eclipse.ui.application.IWorkbenchConfigurer; +import org.eclipse.ui.application.IWorkbenchWindowConfigurer; +import org.eclipse.ui.application.WorkbenchAdvisor; +import org.eclipse.ui.application.WorkbenchWindowAdvisor; + +/** + * Workbench configuration which is aware of the logged in user and can remember + * workbench state. + */ +public class SecureWorkbenchAdvisor extends WorkbenchAdvisor { + public final static String INITIAL_PERSPECTIVE_PROPERTY = "org.argeo.security.ui.initialPerspective"; + public final static String SAVE_AND_RESTORE_PROPERTY = "org.argeo.security.ui.saveAndRestore"; + + private String initialPerspective = System.getProperty( + INITIAL_PERSPECTIVE_PROPERTY, null); + + private final String username; + + public SecureWorkbenchAdvisor(String username) { + this.username = username; + } + + @Override + public void initialize(final IWorkbenchConfigurer configurer) { + super.initialize(configurer); + Boolean saveAndRestore = Boolean.parseBoolean(System.getProperty( + SAVE_AND_RESTORE_PROPERTY, "true")); + configurer.setSaveAndRestore(saveAndRestore); + } + + public WorkbenchWindowAdvisor createWorkbenchWindowAdvisor( + IWorkbenchWindowConfigurer configurer) { + return new SecureWorkbenchWindowAdvisor(configurer, username); + } + + public String getInitialWindowPerspectiveId() { + if (initialPerspective != null) { + // check whether this user can see the declared perspective + // (typically the perspective won't be listed if this user doesn't + // have the right to see it) + IPerspectiveDescriptor pd = getWorkbenchConfigurer().getWorkbench() + .getPerspectiveRegistry() + .findPerspectiveWithId(initialPerspective); + if (pd == null) + return null; + } + return initialPerspective; + } + + protected String getUsername() { + return username; + } +} diff --git a/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureWorkbenchWindowAdvisor.java b/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureWorkbenchWindowAdvisor.java new file mode 100644 index 000000000..d8aaec443 --- /dev/null +++ b/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureWorkbenchWindowAdvisor.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.rcp; + +import org.eclipse.swt.graphics.Point; +import org.eclipse.ui.application.ActionBarAdvisor; +import org.eclipse.ui.application.IActionBarConfigurer; +import org.eclipse.ui.application.IWorkbenchWindowConfigurer; +import org.eclipse.ui.application.WorkbenchWindowAdvisor; + +public class SecureWorkbenchWindowAdvisor extends WorkbenchWindowAdvisor { + private final String username; + + public SecureWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer, + String username) { + super(configurer); + this.username = username; + } + + public ActionBarAdvisor createActionBarAdvisor( + IActionBarConfigurer configurer) { + return new SecureActionBarAdvisor(configurer, true); + } + + public void preWindowOpen() { + IWorkbenchWindowConfigurer configurer = getWindowConfigurer(); + configurer.setInitialSize(new Point(1200, 900)); + configurer.setShowCoolBar(true); + configurer.setShowMenuBar(true); + configurer.setShowStatusLine(true); + configurer.setShowProgressIndicator(true); + + configurer.setShowPerspectiveBar(true); + String remoteUri = System + .getProperty(AbstractSecureApplication.NODE_REPO_URI); + if (remoteUri != null) + configurer + .setTitle("Argeo UI - " + username + " (" + remoteUri + ")"); //$NON-NLS-1$ + else + configurer.setTitle("Argeo UI - " + username); //$NON-NLS-1$ + + } +} diff --git a/org.argeo.security.ui/.classpath b/org.argeo.security.ui/.classpath new file mode 100644 index 000000000..5641c7ca3 --- /dev/null +++ b/org.argeo.security.ui/.classpath @@ -0,0 +1,7 @@ + + + + >> + + + diff --git a/org.argeo.security.ui/.project b/org.argeo.security.ui/.project new file mode 100644 index 000000000..a052e9a57 --- /dev/null +++ b/org.argeo.security.ui/.project @@ -0,0 +1,28 @@ + + + org.argeo.security.ui + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/org.argeo.security.ui/.settings/org.eclipse.pde.core.prefs b/org.argeo.security.ui/.settings/org.eclipse.pde.core.prefs new file mode 100644 index 000000000..dfa507d81 --- /dev/null +++ b/org.argeo.security.ui/.settings/org.eclipse.pde.core.prefs @@ -0,0 +1,3 @@ +#Sat Jan 15 18:15:48 CET 2011 +eclipse.preferences.version=1 +resolve.requirebundle=false diff --git a/org.argeo.security.ui/META-INF/spring/commands.xml b/org.argeo.security.ui/META-INF/spring/commands.xml new file mode 100644 index 000000000..3b2e6ccb0 --- /dev/null +++ b/org.argeo.security.ui/META-INF/spring/commands.xml @@ -0,0 +1,7 @@ + + + + diff --git a/org.argeo.security.ui/META-INF/spring/keyring.xml b/org.argeo.security.ui/META-INF/spring/keyring.xml new file mode 100644 index 000000000..906c0b731 --- /dev/null +++ b/org.argeo.security.ui/META-INF/spring/keyring.xml @@ -0,0 +1,26 @@ + + + + + + + osgibundle:securityui.properties + + + + + + + + + + + + + + diff --git a/org.argeo.security.ui/META-INF/spring/osgi.xml b/org.argeo.security.ui/META-INF/spring/osgi.xml new file mode 100644 index 000000000..01e21244b --- /dev/null +++ b/org.argeo.security.ui/META-INF/spring/osgi.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.security.ui/META-INF/spring/views.xml b/org.argeo.security.ui/META-INF/spring/views.xml new file mode 100644 index 000000000..e5363dcc0 --- /dev/null +++ b/org.argeo.security.ui/META-INF/spring/views.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/org.argeo.security.ui/build.properties b/org.argeo.security.ui/build.properties new file mode 100644 index 000000000..3868784bf --- /dev/null +++ b/org.argeo.security.ui/build.properties @@ -0,0 +1,6 @@ +source.. = src/main/java/ +output.. = target/classes/ +bin.includes = META-INF/,\ + .,\ + plugin.xml,\ + icons/ diff --git a/org.argeo.security.ui/icons/adminLog.gif b/org.argeo.security.ui/icons/adminLog.gif new file mode 100644 index 000000000..6ef3bca66 Binary files /dev/null and b/org.argeo.security.ui/icons/adminLog.gif differ diff --git a/org.argeo.security.ui/icons/home.gif b/org.argeo.security.ui/icons/home.gif new file mode 100644 index 000000000..fd0c66950 Binary files /dev/null and b/org.argeo.security.ui/icons/home.gif differ diff --git a/org.argeo.security.ui/icons/log.gif b/org.argeo.security.ui/icons/log.gif new file mode 100644 index 000000000..e3ecc5535 Binary files /dev/null and b/org.argeo.security.ui/icons/log.gif differ diff --git a/org.argeo.security.ui/icons/maintenance.gif b/org.argeo.security.ui/icons/maintenance.gif new file mode 100644 index 000000000..e5690ecb1 Binary files /dev/null and b/org.argeo.security.ui/icons/maintenance.gif differ diff --git a/org.argeo.security.ui/icons/password.gif b/org.argeo.security.ui/icons/password.gif new file mode 100644 index 000000000..a6b251fc8 Binary files /dev/null and b/org.argeo.security.ui/icons/password.gif differ diff --git a/org.argeo.security.ui/icons/user.gif b/org.argeo.security.ui/icons/user.gif new file mode 100644 index 000000000..90a00147b Binary files /dev/null and b/org.argeo.security.ui/icons/user.gif differ diff --git a/org.argeo.security.ui/plugin.xml b/org.argeo.security.ui/plugin.xml new file mode 100644 index 000000000..cb139d7b6 --- /dev/null +++ b/org.argeo.security.ui/plugin.xml @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.argeo.security.ui/pom.xml b/org.argeo.security.ui/pom.xml new file mode 100644 index 000000000..bd909d84b --- /dev/null +++ b/org.argeo.security.ui/pom.xml @@ -0,0 +1,94 @@ + + + 4.0.0 + + org.argeo.commons + 2.1.12-SNAPSHOT + argeo-commons + .. + + org.argeo.security.ui + Commons Security UI + jar + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-source-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + org.apache.felix + maven-bundle-plugin + + + ${project.artifactId};singleton:=true + lazy + org.argeo.security.ui.SecurityUiPlugin + org.eclipse.ui;resolution:=optional,org.eclipse.rap.ui;resolution:=optional,org.eclipse.core.runtime + + org.argeo.eclipse.spring, + org.apache.log4j;resolution:=optional, + * + + + !org.argeo.security.ui.internal.*, + org.argeo.security.ui.* + + + + + + + + + + org.argeo.commons + org.argeo.security.core + 2.1.12-SNAPSHOT + + + + + org.argeo.commons + org.argeo.eclipse.ui + 2.1.12-SNAPSHOT + + + + + org.argeo.commons + org.argeo.eclipse.dep.rcp + 2.1.12-SNAPSHOT + provided + + + + + org.argeo.commons + org.argeo.util + 2.1.12-SNAPSHOT + + + + + org.argeo.tp + org.springframework.security.core + + + + + org.argeo.tp + slf4j.org.apache.commons.logging + + + + \ No newline at end of file diff --git a/org.argeo.security.ui/securityui.properties b/org.argeo.security.ui/securityui.properties new file mode 100644 index 000000000..0228d47ee --- /dev/null +++ b/org.argeo.security.ui/securityui.properties @@ -0,0 +1 @@ +argeo.keyring.secreteKeyLength=256 \ No newline at end of file diff --git a/org.argeo.security.ui/src/main/java/org/argeo/security/ui/MaintenancePerspective.java b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/MaintenancePerspective.java new file mode 100644 index 000000000..86307abd2 --- /dev/null +++ b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/MaintenancePerspective.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui; + +import org.argeo.security.ui.views.AdminLogView; +import org.argeo.security.ui.views.UserProfile; +import org.eclipse.ui.IFolderLayout; +import org.eclipse.ui.IPageLayout; +import org.eclipse.ui.IPerspectiveFactory; + +/** Home perspective for the current user */ +public class MaintenancePerspective implements IPerspectiveFactory { + public final static String ID = SecurityUiPlugin.PLUGIN_ID + + ".adminMaintenancePerspective"; + + public void createInitialLayout(IPageLayout layout) { + String editorArea = layout.getEditorArea(); + layout.setEditorAreaVisible(true); + layout.setFixed(false); + + IFolderLayout bottom = layout.createFolder("bottom", + IPageLayout.BOTTOM, 0.50f, editorArea); + bottom.addView(AdminLogView.ID); + + IFolderLayout left = layout.createFolder("left", IPageLayout.LEFT, + 0.30f, editorArea); + left.addView(UserProfile.ID); + // left.addView(RolesView.ID); + + } + +} diff --git a/org.argeo.security.ui/src/main/java/org/argeo/security/ui/PrivilegedJob.java b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/PrivilegedJob.java new file mode 100644 index 000000000..1ded50fdb --- /dev/null +++ b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/PrivilegedJob.java @@ -0,0 +1,46 @@ +package org.argeo.security.ui; + +import java.security.AccessController; +import java.security.PrivilegedAction; + +import javax.security.auth.Subject; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.jobs.Job; +import org.springframework.security.Authentication; +import org.springframework.security.context.SecurityContextHolder; + +/** + * Propagate authentication to an eclipse job. Typically to execute a privileged + * action outside the UI thread + */ +public abstract class PrivilegedJob extends Job { + + private final Authentication authentication; + private Subject subject; + + public PrivilegedJob(String jobName) { + super(jobName); + authentication = SecurityContextHolder.getContext().getAuthentication(); + subject = Subject.getSubject(AccessController.getContext()); + } + + @Override + protected IStatus run(final IProgressMonitor progressMonitor) { + PrivilegedAction privilegedAction = new PrivilegedAction() { + public IStatus run() { + SecurityContextHolder.getContext().setAuthentication( + authentication); + return doRun(progressMonitor); + } + }; + return Subject.doAs(subject, privilegedAction); + } + + /** + * Implement here what should be executed with default context + * authentication + */ + protected abstract IStatus doRun(IProgressMonitor progressMonitor); +} \ No newline at end of file diff --git a/org.argeo.security.ui/src/main/java/org/argeo/security/ui/RolesSourceProvider.java b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/RolesSourceProvider.java new file mode 100644 index 000000000..a81dc200a --- /dev/null +++ b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/RolesSourceProvider.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import org.argeo.security.ui.internal.CurrentUser; +import org.eclipse.ui.AbstractSourceProvider; + +/** + * Provides the roles of the current user as a variable to be used for activity + * binding + */ +public class RolesSourceProvider extends AbstractSourceProvider { + public final static String ROLES_VARIABLE = "roles"; + private final static String[] PROVIDED_SOURCE_NAMES = new String[] { ROLES_VARIABLE }; + + public Map> getCurrentState() { + Map> stateMap = new HashMap>(); + stateMap.put(ROLES_VARIABLE, CurrentUser.roles()); + return stateMap; + } + + public String[] getProvidedSourceNames() { + return PROVIDED_SOURCE_NAMES; + } + + public void updateRoles() { + fireSourceChanged(0, getCurrentState()); + } + + public void dispose() { + } +} \ No newline at end of file diff --git a/org.argeo.security.ui/src/main/java/org/argeo/security/ui/SecurityUiPlugin.java b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/SecurityUiPlugin.java new file mode 100644 index 000000000..03584185b --- /dev/null +++ b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/SecurityUiPlugin.java @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui; + +import java.io.IOException; + +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.UnsupportedCallbackException; + +import org.argeo.ArgeoException; +import org.argeo.security.ui.dialogs.DefaultLoginDialog; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; + +/** + * The activator class controls the plug-in life cycle + */ +public class SecurityUiPlugin extends AbstractUIPlugin { + + // The plug-in ID + public static final String PLUGIN_ID = "org.argeo.security.ui"; //$NON-NLS-1$ + + public final static String CONTEXT_KEYRING = "KEYRING"; + + private CallbackHandler defaultCallbackHandler; + private ServiceRegistration defaultCallbackHandlerReg; + + private static SecurityUiPlugin plugin; + + public static InheritableThreadLocal display = new InheritableThreadLocal() { + + @Override + protected Display initialValue() { + return Display.getCurrent(); + } + }; + + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + + defaultCallbackHandler = new DefaultCallbackHandler(); + defaultCallbackHandlerReg = context.registerService( + CallbackHandler.class.getName(), defaultCallbackHandler, null); + } + + public void stop(BundleContext context) throws Exception { + plugin = null; + defaultCallbackHandlerReg.unregister(); + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static SecurityUiPlugin getDefault() { + return plugin; + } + + public static ImageDescriptor getImageDescriptor(String path) { + return imageDescriptorFromPlugin(PLUGIN_ID, path); + } + + protected class DefaultCallbackHandler implements CallbackHandler { + public void handle(final Callback[] callbacks) throws IOException, + UnsupportedCallbackException { + + // if (display != null) // RCP + Display displayToUse = display.get(); + if (displayToUse == null)// RCP + displayToUse = Display.getDefault(); + displayToUse.syncExec(new Runnable() { + public void run() { + DefaultLoginDialog dialog = new DefaultLoginDialog(display + .get().getActiveShell()); + try { + dialog.handle(callbacks); + } catch (IOException e) { + throw new ArgeoException("Cannot open dialog", e); + } + } + }); + // else {// RAP + // DefaultLoginDialog dialog = new DefaultLoginDialog(); + // dialog.handle(callbacks); + // } + } + + } +} diff --git a/org.argeo.security.ui/src/main/java/org/argeo/security/ui/UserHomePerspective.java b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/UserHomePerspective.java new file mode 100644 index 000000000..119549ffd --- /dev/null +++ b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/UserHomePerspective.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui; + +import org.argeo.security.ui.views.LogView; +import org.argeo.security.ui.views.UserProfile; +import org.eclipse.ui.IFolderLayout; +import org.eclipse.ui.IPageLayout; +import org.eclipse.ui.IPerspectiveFactory; + +/** Home perspective for the current user */ +public class UserHomePerspective implements IPerspectiveFactory { + public final static String ID = SecurityUiPlugin.PLUGIN_ID + + ".userHomePerspective"; + + public void createInitialLayout(IPageLayout layout) { + String editorArea = layout.getEditorArea(); + layout.setEditorAreaVisible(true); + layout.setFixed(false); + + IFolderLayout left = layout.createFolder("left", IPageLayout.LEFT, + 0.30f, editorArea); + left.addView(UserProfile.ID); + left.addView(LogView.ID); + } + +} diff --git a/org.argeo.security.ui/src/main/java/org/argeo/security/ui/commands/OpenChangePasswordDialog.java b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/commands/OpenChangePasswordDialog.java new file mode 100644 index 000000000..3044e2c6c --- /dev/null +++ b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/commands/OpenChangePasswordDialog.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.commands; + +import org.argeo.security.ui.dialogs.ChangePasswordDialog; +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.ui.handlers.HandlerUtil; +import org.springframework.security.userdetails.UserDetailsManager; + +/** Opens the change password dialog. */ +public class OpenChangePasswordDialog extends AbstractHandler { + private UserDetailsManager userDetailsManager; + + public Object execute(ExecutionEvent event) throws ExecutionException { + ChangePasswordDialog dialog = new ChangePasswordDialog( + HandlerUtil.getActiveShell(event), userDetailsManager); + if (dialog.open() == Dialog.OK) { + MessageDialog.openInformation(HandlerUtil.getActiveShell(event), + "Password changed", "Password changed."); + } + return null; + } + + public void setUserDetailsManager(UserDetailsManager userDetailsManager) { + this.userDetailsManager = userDetailsManager; + } + +} diff --git a/org.argeo.security.ui/src/main/java/org/argeo/security/ui/commands/OpenHomePerspective.java b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/commands/OpenHomePerspective.java new file mode 100644 index 000000000..d56498a15 --- /dev/null +++ b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/commands/OpenHomePerspective.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.commands; + +import org.argeo.eclipse.ui.ErrorFeedback; +import org.argeo.security.ui.UserHomePerspective; +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.ui.WorkbenchException; +import org.eclipse.ui.handlers.HandlerUtil; + +/** Default action of the user menu */ +public class OpenHomePerspective extends AbstractHandler { + + public Object execute(ExecutionEvent event) throws ExecutionException { + try { + HandlerUtil.getActiveSite(event).getWorkbenchWindow() + .openPage(UserHomePerspective.ID, null); + } catch (WorkbenchException e) { + ErrorFeedback.show("Cannot open home perspective", e); + } + return null; + } + +} diff --git a/org.argeo.security.ui/src/main/java/org/argeo/security/ui/dialogs/AbstractLoginDialog.java b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/dialogs/AbstractLoginDialog.java new file mode 100644 index 000000000..7c7e0c6b6 --- /dev/null +++ b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/dialogs/AbstractLoginDialog.java @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.dialogs; + +import java.io.IOException; + +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.NameCallback; +import javax.security.auth.callback.PasswordCallback; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.security.ui.SecurityUiPlugin; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.TrayDialog; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.operation.ModalContext; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; + +/** Base for login dialogs */ +public abstract class AbstractLoginDialog extends TrayDialog implements + CallbackHandler { + + private final static Log log = LogFactory.getLog(AbstractLoginDialog.class); + + private Thread modalContextThread = null; + boolean processCallbacks = false; + boolean isCancelled = false; + Callback[] callbackArray; + + protected final Callback[] getCallbacks() { + return this.callbackArray; + } + + public abstract void internalHandle(); + + public boolean isCancelled() { + return isCancelled; + } + + protected AbstractLoginDialog(Shell parentShell) { + super(parentShell); + } + + /* + * (non-Javadoc) + * + * @see + * javax.security.auth.callback.CallbackHandler#handle(javax.security.auth + * .callback.Callback[]) + */ + public void handle(final Callback[] callbacks) throws IOException { + // clean previous usage + if (processCallbacks) { + // this handler was already used + processCallbacks = false; + } + + if (modalContextThread != null) { + try { + modalContextThread.join(1000); + } catch (InterruptedException e) { + // silent + } + modalContextThread = null; + } + + // initialize + this.callbackArray = callbacks; + final Display display = Display.getDefault(); + display.syncExec(new Runnable() { + + public void run() { + isCancelled = false; + setBlockOnOpen(false); + open(); + + final Button okButton = getButton(IDialogConstants.OK_ID); + okButton.setText("Login"); + okButton.addSelectionListener(new SelectionListener() { + + public void widgetSelected(final SelectionEvent event) { + processCallbacks = true; + } + + public void widgetDefaultSelected(final SelectionEvent event) { + // nothing to do + } + }); + final Button cancel = getButton(IDialogConstants.CANCEL_ID); + cancel.addSelectionListener(new SelectionListener() { + + public void widgetSelected(final SelectionEvent event) { + isCancelled = true; + processCallbacks = true; + } + + public void widgetDefaultSelected(final SelectionEvent event) { + // nothing to do + } + }); + } + }); + try { + ModalContext.setAllowReadAndDispatch(true); // Works for now. + ModalContext.run(new IRunnableWithProgress() { + + public void run(final IProgressMonitor monitor) { + modalContextThread = Thread.currentThread(); + // Wait here until OK or cancel is pressed, then let it rip. + // The event + // listener + // is responsible for closing the dialog (in the + // loginSucceeded + // event). + while (!processCallbacks && (modalContextThread != null) + && (modalContextThread == Thread.currentThread()) + && SecurityUiPlugin.getDefault() != null) { + // Note: SecurityUiPlugin.getDefault() != null is false + // when the OSGi runtime is shut down + try { + Thread.sleep(100); + // if (display.isDisposed()) { + // log.warn("Display is disposed, killing login dialog thread"); + // throw new ThreadDeath(); + // } + } catch (final Exception e) { + // do nothing + } + } + processCallbacks = false; + // Call the adapter to handle the callbacks + if (!isCancelled()) + internalHandle(); + else + // clear callbacks are when cancelling + for (Callback callback : callbacks) + if (callback instanceof PasswordCallback) + ((PasswordCallback) callback).setPassword(null); + else if (callback instanceof NameCallback) + ((NameCallback) callback).setName(null); + } + }, true, new NullProgressMonitor(), Display.getDefault()); + } catch (ThreadDeath e) { + isCancelled = true; + log.debug("Thread " + Thread.currentThread().getId() + " died"); + throw e; + } catch (Exception e) { + isCancelled = true; + IOException ioe = new IOException( + "Unexpected issue in login dialog, see root cause for more details"); + ioe.initCause(e); + throw ioe; + } finally { + // so that the modal thread dies + processCallbacks = true; + // try { + // // wait for the modal context thread to gracefully exit + // modalContextThread.join(); + // } catch (InterruptedException ie) { + // // silent + // } + modalContextThread = null; + } + } + + protected void configureShell(Shell shell) { + super.configureShell(shell); + shell.setText("Authentication"); + } +} diff --git a/org.argeo.security.ui/src/main/java/org/argeo/security/ui/dialogs/ChangePasswordDialog.java b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/dialogs/ChangePasswordDialog.java new file mode 100644 index 000000000..fe9b6ae9d --- /dev/null +++ b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/dialogs/ChangePasswordDialog.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.dialogs; + +import org.argeo.ArgeoException; +import org.argeo.eclipse.ui.ErrorFeedback; +import org.eclipse.jface.dialogs.IMessageProvider; +import org.eclipse.jface.dialogs.TitleAreaDialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.springframework.security.userdetails.UserDetailsManager; + +/** Dialog to change the current user password */ +public class ChangePasswordDialog extends TitleAreaDialog { + private Text currentPassword, newPassword1, newPassword2; + private UserDetailsManager userDetailsManager; + + public ChangePasswordDialog(Shell parentShell, + UserDetailsManager securityService) { + super(parentShell); + this.userDetailsManager = securityService; + } + + protected Point getInitialSize() { + return new Point(300, 250); + } + + protected Control createDialogArea(Composite parent) { + Composite dialogarea = (Composite) super.createDialogArea(parent); + dialogarea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + Composite composite = new Composite(dialogarea, SWT.NONE); + composite.setLayout(new GridLayout(2, false)); + composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + currentPassword = createLP(composite, "Current password"); + newPassword1 = createLP(composite, "New password"); + newPassword2 = createLP(composite, "Repeat new password"); + + setMessage("Change password", IMessageProvider.INFORMATION); + parent.pack(); + return composite; + } + + @Override + protected void okPressed() { + if (!newPassword1.getText().equals(newPassword2.getText())) + throw new ArgeoException("Passwords are different"); + try { + userDetailsManager.changePassword(currentPassword.getText(), + newPassword1.getText()); + close(); + } catch (Exception e) { + ErrorFeedback.show("Cannot change password", e); + } + } + + /** Creates label and password. */ + protected Text createLP(Composite parent, String label) { + new Label(parent, SWT.NONE).setText(label); + Text text = new Text(parent, SWT.SINGLE | SWT.LEAD | SWT.PASSWORD + | SWT.BORDER); + text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + return text; + } + + protected void configureShell(Shell shell) { + super.configureShell(shell); + shell.setText("Change password"); + } + +} diff --git a/org.argeo.security.ui/src/main/java/org/argeo/security/ui/dialogs/DefaultLoginDialog.java b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/dialogs/DefaultLoginDialog.java new file mode 100644 index 000000000..57ba01b5b --- /dev/null +++ b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/dialogs/DefaultLoginDialog.java @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.dialogs; + +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.NameCallback; +import javax.security.auth.callback.PasswordCallback; +import javax.security.auth.callback.TextOutputCallback; + +import org.argeo.security.ui.SecurityUiPlugin; +import org.argeo.util.LocaleCallback; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +/** Default authentication dialog, to be used as {@link CallbackHandler}. */ +public class DefaultLoginDialog extends AbstractLoginDialog { + public DefaultLoginDialog() { + this(SecurityUiPlugin.display.get().getActiveShell()); + } + + public DefaultLoginDialog(Shell parentShell) { + super(parentShell); + } + + protected Point getInitialSize() { + return new Point(350, 180); + } + + @Override + protected Control createContents(Composite parent) { + Control control = super.createContents(parent); + parent.pack(); + + // Move the dialog to the center of the top level shell. + Rectangle shellBounds; + if (Display.getCurrent().getActiveShell() != null) // RCP + shellBounds = Display.getCurrent().getActiveShell().getBounds(); + else + shellBounds = Display.getCurrent().getBounds();// RAP + Point dialogSize = parent.getSize(); + int x = shellBounds.x + (shellBounds.width - dialogSize.x) / 2; + int y = shellBounds.y + (shellBounds.height - dialogSize.y) / 2; + parent.setLocation(x, y); + return control; + } + + protected Control createDialogArea(Composite parent) { + Composite dialogarea = (Composite) super.createDialogArea(parent); + Composite composite = new Composite(dialogarea, SWT.NONE); + composite.setLayout(new GridLayout(2, false)); + composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + createCallbackHandlers(composite); + // parent.pack(); + return composite; + } + + private void createCallbackHandlers(Composite composite) { + Callback[] callbacks = getCallbacks(); + for (int i = 0; i < callbacks.length; i++) { + Callback callback = callbacks[i]; + if (callback instanceof TextOutputCallback) { + createLabelTextoutputHandler(composite, + (TextOutputCallback) callback); + } else if (callback instanceof NameCallback) { + createNameHandler(composite, (NameCallback) callback); + } else if (callback instanceof PasswordCallback) { + createPasswordHandler(composite, (PasswordCallback) callback); + } else if (callback instanceof LocaleCallback) { + createLocaleHandler(composite, (LocaleCallback) callback); + } + } + } + + private void createPasswordHandler(Composite composite, + final PasswordCallback callback) { + Label label = new Label(composite, SWT.NONE); + label.setText(callback.getPrompt()); + final Text passwordText = new Text(composite, SWT.SINGLE | SWT.LEAD + | SWT.PASSWORD | SWT.BORDER); + passwordText + .setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + passwordText.addModifyListener(new ModifyListener() { + + public void modifyText(ModifyEvent event) { + // FIXME use getTextChars() in Eclipse 3.7 + callback.setPassword(passwordText.getText().toCharArray()); + } + }); + } + + private void createLocaleHandler(Composite composite, + final LocaleCallback callback) { + String[] labels = callback.getSupportedLocalesLabels(); + if (labels.length == 0) + return; + Label label = new Label(composite, SWT.NONE); + label.setText(callback.getPrompt()); + + final Combo combo = new Combo(composite, SWT.READ_ONLY); + combo.setItems(labels); + combo.select(callback.getDefaultIndex()); + combo.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + combo.addSelectionListener(new SelectionListener() { + @Override + public void widgetSelected(SelectionEvent e) { + callback.setSelectedIndex(combo.getSelectionIndex()); + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + } + }); + } + + private void createNameHandler(Composite composite, + final NameCallback callback) { + Label label = new Label(composite, SWT.NONE); + label.setText(callback.getPrompt()); + final Text text = new Text(composite, SWT.SINGLE | SWT.LEAD + | SWT.BORDER); + if (callback.getDefaultName() != null) { + // set default value, if provided + text.setText(callback.getDefaultName()); + callback.setName(callback.getDefaultName()); + } + text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + text.addModifyListener(new ModifyListener() { + + public void modifyText(ModifyEvent event) { + callback.setName(text.getText()); + } + }); + } + + private void createLabelTextoutputHandler(Composite composite, + final TextOutputCallback callback) { + Label label = new Label(composite, SWT.NONE); + label.setText(callback.getMessage()); + GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); + data.horizontalSpan = 2; + label.setLayoutData(data); + // TODO: find a way to pass this information + // int messageType = callback.getMessageType(); + // int dialogMessageType = IMessageProvider.NONE; + // switch (messageType) { + // case TextOutputCallback.INFORMATION: + // dialogMessageType = IMessageProvider.INFORMATION; + // break; + // case TextOutputCallback.WARNING: + // dialogMessageType = IMessageProvider.WARNING; + // break; + // case TextOutputCallback.ERROR: + // dialogMessageType = IMessageProvider.ERROR; + // break; + // } + // setMessage(callback.getMessage(), dialogMessageType); + } + + public void internalHandle() { + } +} diff --git a/org.argeo.security.ui/src/main/java/org/argeo/security/ui/internal/CurrentUser.java b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/internal/CurrentUser.java new file mode 100644 index 000000000..43ca5884e --- /dev/null +++ b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/internal/CurrentUser.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.internal; + +import java.security.AccessController; +import java.security.Principal; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import javax.security.auth.Subject; + +import org.argeo.ArgeoException; +import org.springframework.security.Authentication; +import org.springframework.security.GrantedAuthority; + +/** + * Retrieves information about the current user. Not an API, can change without + * notice. + */ +public class CurrentUser { + public final static String getUsername() { + Subject subject = getSubject(); + if (subject == null) + return null; + Principal principal = subject.getPrincipals().iterator().next(); + return principal.getName(); + + } + + public final static Set roles() { + Set roles = Collections.synchronizedSet(new HashSet()); + Authentication authentication = getAuthentication(); + for (GrantedAuthority ga : authentication.getAuthorities()) { + roles.add(ga.getAuthority()); + } + return Collections.unmodifiableSet(roles); + } + + public final static Authentication getAuthentication() { + Set authens = getSubject().getPrincipals( + Authentication.class); + if (authens != null && !authens.isEmpty()) { + Principal principal = authens.iterator().next(); + Authentication authentication = (Authentication) principal; + return authentication; + } + throw new ArgeoException("No authentication found"); + } + + public final static Subject getSubject() { + Subject subject = Subject.getSubject(AccessController.getContext()); + if (subject == null) + throw new ArgeoException("Not authenticated."); + return subject; + } +} diff --git a/org.argeo.security.ui/src/main/java/org/argeo/security/ui/views/AdminLogView.java b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/views/AdminLogView.java new file mode 100644 index 000000000..d59edf883 --- /dev/null +++ b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/views/AdminLogView.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.views; + +import java.util.ArrayList; + +import org.argeo.ArgeoLogger; +import org.argeo.security.ui.SecurityUiPlugin; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Table; +import org.eclipse.ui.part.ViewPart; + +/** + * Display log lines for all users with a virtual table. + */ +public class AdminLogView extends ViewPart { + public static String ID = SecurityUiPlugin.PLUGIN_ID + ".adminLogView"; + + private TableViewer viewer; + + private LogContentProvider logContentProvider; + private ArgeoLogger argeoLogger; + + @Override + public void createPartControl(Composite parent) { + // FIXME doesn't return a monospace font in RAP + Font font = JFaceResources.getTextFont(); + Table table = new Table(parent, SWT.VIRTUAL | SWT.MULTI | SWT.H_SCROLL + | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER); + table.setFont(font); + + viewer = new TableViewer(table); + viewer.setLabelProvider(new LabelProvider()); + logContentProvider = new LogContentProvider(viewer) { + + @Override + protected StringBuffer prefix(String username, Long timestamp, + String level, String category, String thread) { + return super + .prefix(username, timestamp, level, category, thread) + .append(norm(level, 5)) + .append(' ') + .append(norm(username != null ? username + : "", 16)).append(' '); + } + }; + viewer.setContentProvider(logContentProvider); + // viewer.setUseHashlookup(true); + viewer.setInput(new ArrayList()); + + if (argeoLogger != null) + argeoLogger.registerForAll(logContentProvider, 1000, true); + } + + @Override + public void setFocus() { + viewer.getTable().setFocus(); + } + + @Override + public void dispose() { + if (argeoLogger != null) + argeoLogger.unregisterForAll(logContentProvider); + } + + public void setArgeoLogger(ArgeoLogger argeoLogger) { + this.argeoLogger = argeoLogger; + } + +} diff --git a/org.argeo.security.ui/src/main/java/org/argeo/security/ui/views/LogContentProvider.java b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/views/LogContentProvider.java new file mode 100644 index 000000000..72f205932 --- /dev/null +++ b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/views/LogContentProvider.java @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.views; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Date; +import java.util.LinkedList; +import java.util.List; + +import org.argeo.ArgeoLogListener; +import org.eclipse.jface.viewers.ILazyContentProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableItem; + +/** A content provider maintaining an array of lines */ +class LogContentProvider implements ILazyContentProvider, ArgeoLogListener { + private DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss"); + + private final Long start; + /** current - start = line number. first line is number '1' */ + private Long current; + + // TODO make it configurable + private final Integer maxLineBufferSize = 10 * 1000; + + private final TableViewer viewer; + private LinkedList lines; + + public LogContentProvider(TableViewer viewer) { + this.viewer = viewer; + start = System.currentTimeMillis(); + lines = new LinkedList(); + current = start; + } + + public synchronized void dispose() { + lines.clear(); + lines = null; + } + + @SuppressWarnings("unchecked") + public synchronized void inputChanged(Viewer viewer, Object oldInput, + Object newInput) { + List lin = (List) newInput; + if (lin == null) + return; + for (String line : lin) { + addLine(line); + } + this.viewer.setItemCount(lines.size()); + } + + public void updateElement(int index) { + viewer.replace(lines.get(index), index); + } + + public synchronized void appendLog(String username, Long timestamp, + String level, String category, String thread, Object msg, + String[] exception) { + // check if valid + if (lines == null) + return; + + String message = msg.toString(); + int count = 0; + String prefix = prefix(username, timestamp, level, category, thread) + .toString(); + // String suffix = suffix(username, timestamp, level, category, thread); + for (String line : message.split("\n")) { + addLine(count == 0 ? prefix + line : line); + count++; + } + + if (exception != null) { + for (String ste : exception) { + addLine(ste); + } + } + + viewer.getTable().getDisplay().asyncExec(new Runnable() { + public void run() { + if (lines == null) + return; + viewer.setItemCount(lines.size()); + // doesn't work with syncExec + scrollToLastLine(); + } + }); + } + + protected StringBuffer prefix(String username, Long timestamp, + String level, String category, String thread) { + StringBuffer buf = new StringBuffer(""); + buf.append(dateFormat.format(new Date(timestamp))).append(" "); + // buf.append(level).append(" "); + return buf; + } + + /** Normalize string to the given size */ + protected String norm(String str, Integer size) { + int length = str.length(); + if (length == size) + return str; + else if (length > size) + return str.substring(0, size); + else { + char[] arr = new char[size - length]; + Arrays.fill(arr, ' '); + return str + new String(arr); + } + } + + // protected String suffix(String username, Long timestamp, String level, + // String category, String thread) { + // return ""; + // } + + /** Scroll to the last line */ + protected synchronized void scrollToLastLine() { + // we try to show last line with two methods + // viewer.reveal(lines.peekLast()); + + Table table = viewer.getTable(); + TableItem ti = table.getItem(table.getItemCount() - 1); + table.showItem(ti); + } + + protected synchronized LogLine addLine(String line) { + // check for maximal size and purge if necessary + while (lines.size() >= maxLineBufferSize) { + for (int i = 0; i < maxLineBufferSize / 10; i++) { + lines.poll(); + } + } + + current++; + LogLine logLine = new LogLine(current, line); + lines.add(logLine); + return logLine; + } + + private class LogLine { + private Long linenumber; + private String message; + + public LogLine(Long linenumber, String message) { + this.linenumber = linenumber; + this.message = message; + } + + @Override + public int hashCode() { + return linenumber.intValue(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof LogLine) + return ((LogLine) obj).linenumber.equals(linenumber); + else + return false; + } + + @Override + public String toString() { + return message; + } + + } +} \ No newline at end of file diff --git a/org.argeo.security.ui/src/main/java/org/argeo/security/ui/views/LogView.java b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/views/LogView.java new file mode 100644 index 000000000..c7c47b352 --- /dev/null +++ b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/views/LogView.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.views; + +import java.util.ArrayList; + +import org.argeo.ArgeoLogListener; +import org.argeo.ArgeoLogger; +import org.argeo.security.ui.SecurityUiPlugin; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Table; +import org.eclipse.ui.part.ViewPart; + +/** + * Display log lines with a virtual table. Register and unregisters a + * {@link ArgeoLogListener} via OSGi services. + */ +public class LogView extends ViewPart { + public static String ID = SecurityUiPlugin.PLUGIN_ID + ".logView"; + + private TableViewer viewer; + + private LogContentProvider logContentProvider; + private ArgeoLogger argeoLogger; + + @Override + public void createPartControl(Composite parent) { + Font font = JFaceResources.getTextFont(); + Table table = new Table(parent, SWT.VIRTUAL | SWT.MULTI | SWT.H_SCROLL + | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER); + table.setFont(font); + + viewer = new TableViewer(table); + viewer.setLabelProvider(new LabelProvider()); + logContentProvider = new LogContentProvider(viewer); + viewer.setContentProvider(logContentProvider); + // viewer.setUseHashlookup(true); + viewer.setInput(new ArrayList()); + + if (argeoLogger != null) + argeoLogger.register(logContentProvider, 1000); + } + + @Override + public void setFocus() { + viewer.getTable().setFocus(); + } + + @Override + public void dispose() { + if (argeoLogger != null) + argeoLogger.unregister(logContentProvider); + } + + public void setArgeoLogger(ArgeoLogger argeoLogger) { + this.argeoLogger = argeoLogger; + } + +} diff --git a/org.argeo.security.ui/src/main/java/org/argeo/security/ui/views/UserProfile.java b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/views/UserProfile.java new file mode 100644 index 000000000..3f1f000bf --- /dev/null +++ b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/views/UserProfile.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.ui.views; + +import java.util.TreeSet; + +import org.argeo.eclipse.ui.EclipseUiUtils; +import org.argeo.security.ui.SecurityUiPlugin; +import org.argeo.security.ui.internal.CurrentUser; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Table; +import org.eclipse.ui.part.ViewPart; +import org.springframework.security.Authentication; + +/** Information about the currently logged in user */ +public class UserProfile extends ViewPart { + public static String ID = SecurityUiPlugin.PLUGIN_ID + ".userProfile"; + + private TableViewer viewer; + + @Override + public void createPartControl(Composite parent) { + parent.setLayout(new GridLayout(2, false)); + + Authentication authentication = CurrentUser.getAuthentication(); + EclipseUiUtils.createGridLL(parent, "Name", authentication + .getPrincipal().toString()); + EclipseUiUtils.createGridLL(parent, "User ID", + CurrentUser.getUsername()); + + // roles table + Table table = new Table(parent, SWT.V_SCROLL | SWT.BORDER); + table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1)); + table.setLinesVisible(false); + table.setHeaderVisible(false); + viewer = new TableViewer(table); + viewer.setContentProvider(new RolesContentProvider()); + viewer.setLabelProvider(new LabelProvider()); + getViewSite().setSelectionProvider(viewer); + viewer.setInput(getViewSite()); + } + + @Override + public void setFocus() { + viewer.getTable(); + } + + private class RolesContentProvider implements IStructuredContentProvider { + public Object[] getElements(Object inputElement) { + return new TreeSet(CurrentUser.roles()).toArray(); + } + + public void dispose() { + } + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + + } + +} diff --git a/org.argeo.server.ads.server/.project b/org.argeo.server.ads.server/.project new file mode 100644 index 000000000..a191480d8 --- /dev/null +++ b/org.argeo.server.ads.server/.project @@ -0,0 +1,22 @@ + + + org.argeo.server.ads.server + + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + + diff --git a/org.argeo.server.ads.server/.settings/org.eclipse.pde.core.prefs b/org.argeo.server.ads.server/.settings/org.eclipse.pde.core.prefs new file mode 100644 index 000000000..5733b3123 --- /dev/null +++ b/org.argeo.server.ads.server/.settings/org.eclipse.pde.core.prefs @@ -0,0 +1,4 @@ +#Sun Jan 16 09:58:38 CET 2011 +eclipse.preferences.version=1 +pluginProject.extensions=false +resolve.requirebundle=false diff --git a/org.argeo.server.ads.server/META-INF/spring/ads.xml b/org.argeo.server.ads.server/META-INF/spring/ads.xml new file mode 100644 index 000000000..6fdf476cc --- /dev/null +++ b/org.argeo.server.ads.server/META-INF/spring/ads.xml @@ -0,0 +1,48 @@ + + + + + + osgibundle:ads.properties + + + + + + + + + + + ${argeo.ads.init.ldif} + + + + + + + + simple + ${argeo.ldap.manager.userdn} + ${argeo.ldap.manager.password} + + + + + + + + + + + + diff --git a/org.argeo.server.ads.server/META-INF/spring/server.xml b/org.argeo.server.ads.server/META-INF/spring/server.xml new file mode 100644 index 000000000..84407be13 --- /dev/null +++ b/org.argeo.server.ads.server/META-INF/spring/server.xml @@ -0,0 +1,363 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.server.ads.server/ads.properties b/org.argeo.server.ads.server/ads.properties new file mode 100644 index 000000000..4aa138d97 --- /dev/null +++ b/org.argeo.server.ads.server/ads.properties @@ -0,0 +1,5 @@ +argeo.ldap.rootdn=dc=demo,dc=example,dc=org +argeo.ldap.port=10389 +argeo.ldap.manager.userdn=uid=admin,ou=system +argeo.ldap.manager.password=secret +argeo.ads.init.ldif=osgibundle:init.ldif \ No newline at end of file diff --git a/org.argeo.server.ads.server/build.properties b/org.argeo.server.ads.server/build.properties new file mode 100644 index 000000000..5f22cdd44 --- /dev/null +++ b/org.argeo.server.ads.server/build.properties @@ -0,0 +1 @@ +bin.includes = META-INF/ diff --git a/org.argeo.server.ads.server/init.ldif b/org.argeo.server.ads.server/init.ldif new file mode 100644 index 000000000..0d2e8ba8f --- /dev/null +++ b/org.argeo.server.ads.server/init.ldif @@ -0,0 +1,47 @@ +dn: dc=demo,dc=example,dc=org +objectClass: domain +objectClass: extensibleObject +objectClass: top +dc: demo + +dn: ou=Roles,dc=demo,dc=example,dc=org +objectClass: organizationalUnit +objectClass: top +ou: Roles + +dn: ou=People,dc=demo,dc=example,dc=org +objectClass: organizationalUnit +objectClass: top +ou: People + +dn: uid=demo,ou=People,dc=demo,dc=example,dc=org +objectClass: organizationalPerson +objectClass: person +objectClass: inetOrgPerson +objectClass: top +cn: demo User +description: Demo user +givenname: Demo +mail: demo@localhost +sn: User +uid: demo +userpassword:: e1NIQX1pZVNWNTVRYytlUU9hWURSU2hhL0Fqek5USkU9 + +dn: uid=root,ou=People,dc=demo,dc=example,dc=org +objectClass: person +objectClass: inetOrgPerson +objectClass: organizationalPerson +objectClass: top +cn: demo User +description: Superuser +givenname: Root +mail: root@localhost +sn: Root +uid: root +userpassword:: e1NIQX1pZVNWNTVRYytlUU9hWURSU2hhL0Fqek5USkU9 + +dn: cn=admin,ou=Roles,dc=demo,dc=example,dc=org +objectClass: groupOfNames +objectClass: top +cn: admin +member: uid=root,ou=People,dc=demo,dc=example,dc=org diff --git a/org.argeo.server.ads.server/pom.xml b/org.argeo.server.ads.server/pom.xml new file mode 100644 index 000000000..4e6c53721 --- /dev/null +++ b/org.argeo.server.ads.server/pom.xml @@ -0,0 +1,50 @@ + + 4.0.0 + + org.argeo.commons + 2.1.12-SNAPSHOT + argeo-commons + .. + + org.argeo.server.ads.server + Commons Server Default ADS LDAP Server + + + + org.apache.felix + maven-bundle-plugin + + + + META-INF/spring/*.xml;create-asynchronously:=false + + *, + javax.naming.directory, + jdbm, + org.apache.directory.server.configuration, + org.apache.directory.server.core.authn, + org.apache.directory.server.core.authz, + org.apache.directory.server.core.collective, + org.apache.directory.server.core.configuration, + org.apache.directory.server.core.event, + org.apache.directory.server.core.exception, + org.apache.directory.server.core.normalization, + org.apache.directory.server.core.operational, + org.apache.directory.server.core.partition.impl.btree, + org.apache.directory.server.core.referral, + org.apache.directory.server.core.schema, + org.apache.directory.server.core.schema.bootstrap, + org.apache.directory.server.core.subtree, + org.apache.directory.server.jndi, + org.apache.directory.server.ldap.support.extended, + org.apache.directory.shared.asn1.codec, + org.argeo.server.ads, + org.springframework.beans.factory.config + + + + + + + \ No newline at end of file diff --git a/org.argeo.server.ads/.classpath b/org.argeo.server.ads/.classpath new file mode 100644 index 000000000..ff41fbb4d --- /dev/null +++ b/org.argeo.server.ads/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/org.argeo.server.ads/.project b/org.argeo.server.ads/.project new file mode 100644 index 000000000..448ef0483 --- /dev/null +++ b/org.argeo.server.ads/.project @@ -0,0 +1,28 @@ + + + org.argeo.server.ads + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.pde.PluginNature + + diff --git a/org.argeo.server.ads/.settings/org.eclipse.jdt.core.prefs b/org.argeo.server.ads/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..34d3d6088 --- /dev/null +++ b/org.argeo.server.ads/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,67 @@ +#Sun Feb 21 11:17:20 CET 2010 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore +org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nullReference=warning +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore +org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.source=1.5 diff --git a/org.argeo.server.ads/.settings/org.maven.ide.eclipse.prefs b/org.argeo.server.ads/.settings/org.maven.ide.eclipse.prefs new file mode 100644 index 000000000..8a80a771a --- /dev/null +++ b/org.argeo.server.ads/.settings/org.maven.ide.eclipse.prefs @@ -0,0 +1,9 @@ +#Mon Nov 23 13:34:22 CET 2009 +activeProfiles= +eclipse.preferences.version=1 +fullBuildGoals=process-test-resources +includeModules=false +resolveWorkspaceProjects=true +resourceFilterGoals=process-resources resources\:testResources +skipCompilerPlugin=true +version=1 diff --git a/org.argeo.server.ads/build.properties b/org.argeo.server.ads/build.properties new file mode 100644 index 000000000..f883dc49f --- /dev/null +++ b/org.argeo.server.ads/build.properties @@ -0,0 +1,2 @@ +additional.bundles = org.apache.directory.server.core +source.. = src/main/java/ diff --git a/org.argeo.server.ads/pom.xml b/org.argeo.server.ads/pom.xml new file mode 100644 index 000000000..51e2a3d83 --- /dev/null +++ b/org.argeo.server.ads/pom.xml @@ -0,0 +1,88 @@ + + 4.0.0 + + org.argeo.commons + argeo-commons + 2.1.12-SNAPSHOT + .. + + org.argeo.server.ads + Commons Server Apache Directory Server + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-source-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + org.apache.felix + maven-bundle-plugin + + + + + org.argeo.server.ads.* + + + + + + + + + org.argeo.commons + org.argeo.util + 2.1.12-SNAPSHOT + + + + + org.argeo.tp + org.apache.directory.server.jndi + + + + org.slf4j + com.springsource.slf4j.api + + + + + + + org.argeo.tp + org.apache.commons.io + + + + + org.argeo.tp + org.springframework.core + + + org.argeo.tp + org.springframework.beans + + + + + org.argeo.tp + slf4j.org.apache.commons.logging + + + org.argeo.tp + slf4j.api + + + \ No newline at end of file diff --git a/org.argeo.server.ads/src/main/java/org/argeo/server/ads/AdsContainer.java b/org.argeo.server.ads/src/main/java/org/argeo/server/ads/AdsContainer.java new file mode 100644 index 000000000..e95cd8f5a --- /dev/null +++ b/org.argeo.server.ads/src/main/java/org/argeo/server/ads/AdsContainer.java @@ -0,0 +1,243 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.server.ads; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Writer; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; +import javax.naming.directory.InitialDirContext; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.directory.server.configuration.MutableServerStartupConfiguration; +import org.apache.directory.server.core.configuration.ShutdownConfiguration; +import org.apache.directory.server.jndi.ServerContextFactory; +import org.argeo.ArgeoException; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.core.io.Resource; +import org.springframework.util.Assert; + +/** Wraps an Apache Directory Server instance. */ +@SuppressWarnings("restriction") +public class AdsContainer implements InitializingBean, DisposableBean { + private final static Log log = LogFactory.getLog(AdsContainer.class); + + private MutableServerStartupConfiguration configuration; + private Properties environment = null; + private File workingDirectory = new File( + System.getProperty("java.io.tmpdir") + File.separator + + "argeo-apacheDirectoryServer"); + private Boolean deleteWorkingDirOnExit = false; + + // LDIF + private List ldifs = new ArrayList(); + private List ignoredLdifAttributes = new ArrayList(); + /** default is 'demo' */ + private String ldifPassword = "e1NIQX1pZVNWNTVRYytlUU9hWURSU2hhL0Fqek5USkU9"; + private String ldifPasswordAttribute = "userPassword"; + private File ldifDirectory; + + @SuppressWarnings("unchecked") + public void afterPropertiesSet() throws Exception { + + log.info("Starting directory server with id '" + + configuration.getInstanceId() + "' in directory " + + workingDirectory.getAbsolutePath()); + + if (deleteWorkingDirOnExit && workingDirectory.exists()) { + log.warn("Found existing directory " + workingDirectory + + " deleting it..."); + FileUtils.deleteDirectory(workingDirectory); + } + configuration.setWorkingDirectory(workingDirectory); + workingDirectory.mkdirs(); + + if (ldifDirectory != null) + configuration.setLdifDirectory(ldifDirectory); + else + configuration.setLdifDirectory(new File(workingDirectory + .getAbsolutePath() + File.separator + "ldif")); + + if (ignoredLdifAttributes.size() == 0) { + ignoredLdifAttributes.add("entryUUID"); + ignoredLdifAttributes.add("structuralObjectClass"); + ignoredLdifAttributes.add("creatorsName"); + ignoredLdifAttributes.add("createTimestamp"); + ignoredLdifAttributes.add("entryCSN"); + ignoredLdifAttributes.add("modifiersName"); + ignoredLdifAttributes.add("modifyTimestamp"); + } + + // Process provided LDIF files + if (ldifs.size() > 0) + configuration.getLdifDirectory().mkdirs(); + for (Resource ldif : ldifs) { + File targetFile = new File(configuration.getLdifDirectory() + .getAbsolutePath() + + File.separator + + ldif.getFilename().replace(':', '_')); + processLdif(ldif, targetFile); + } + + Properties env = new Properties(); + env.setProperty(Context.INITIAL_CONTEXT_FACTORY, + ServerContextFactory.class.getName()); + Assert.notNull(environment); + env.putAll(environment); + env.putAll(configuration.toJndiEnvironment()); + + try { + new InitialDirContext(env); + } catch (NamingException e) { + throw new ArgeoException("Failed to start Apache Directory server", + e); + } + } + + /** + * Processes an LDIF resource, filtering out attributes that cannot be + * imported in ADS and forcing a password. + */ + protected void processLdif(Resource ldif, File targetFile) { + BufferedReader reader = null; + Writer writer = null; + try { + reader = new BufferedReader(new InputStreamReader( + ldif.getInputStream())); + writer = new FileWriter(targetFile); + String line = null; + lines: while ((line = reader.readLine()) != null) { + // comment and empty lines + if (line.trim().equals("") || line.startsWith("#")) { + writer.write(line); + writer.write('\n'); + continue lines; + } + + String[] tokens = line.split(":"); + String attribute = null; + if (tokens != null && tokens.length > 1) { + attribute = tokens[0].trim(); + if (ignoredLdifAttributes.contains(attribute)) + continue lines;// ignore + + if (attribute.equals("bdb_db_open")) { + log.warn("Ignored OpenLDAP output\n" + line); + continue lines; + } + + if (ldifPassword != null + && attribute.equals(ldifPasswordAttribute)) { + line = ldifPasswordAttribute + ":: " + ldifPassword; + } + + writer.write(line); + writer.write('\n'); + } else { + log.warn("Ignored LDIF line\n" + line); + } + } + if (log.isDebugEnabled()) + log.debug("Processed " + ldif + " to LDIF directory " + + configuration.getLdifDirectory()); + } catch (IOException e) { + throw new ArgeoException("Cannot process LDIF " + ldif, e); + } finally { + IOUtils.closeQuietly(reader); + IOUtils.closeQuietly(writer); + } + } + + @SuppressWarnings("unchecked") + public void destroy() throws Exception { + ShutdownConfiguration shutdown = new ShutdownConfiguration( + configuration.getInstanceId()); + + Properties env = new Properties(); + env.setProperty(Context.INITIAL_CONTEXT_FACTORY, + ServerContextFactory.class.getName()); + Assert.notNull(environment); + env.putAll(environment); + env.putAll(shutdown.toJndiEnvironment()); + + log.info("Shutting down directory server with id '" + + configuration.getInstanceId() + "'"); + + try { + new InitialContext(env); + } catch (NamingException e) { + throw new ArgeoException("Failed to stop Apache Directory server", + e); + } + + if (workingDirectory.exists() && deleteWorkingDirOnExit) { + if (log.isDebugEnabled()) + log.debug("Delete Apache DS working dir " + workingDirectory); + FileUtils.deleteDirectory(workingDirectory); + } + + } + + public void setConfiguration(MutableServerStartupConfiguration configuration) { + this.configuration = configuration; + } + + public void setWorkingDirectory(File workingDirectory) { + this.workingDirectory = workingDirectory; + } + + public void setEnvironment(Properties environment) { + this.environment = environment; + } + + public void setLdifs(List ldifs) { + this.ldifs = ldifs; + } + + public void setLdifDirectory(File ldifDirectory) { + this.ldifDirectory = ldifDirectory; + } + + public void setDeleteWorkingDirOnExit(Boolean deleteWorkingDirOnExit) { + this.deleteWorkingDirOnExit = deleteWorkingDirOnExit; + } + + public void setIgnoredLdifAttributes(List ignoredLdifAttributes) { + this.ignoredLdifAttributes = ignoredLdifAttributes; + } + + public void setLdifPassword(String ldifPassword) { + this.ldifPassword = ldifPassword; + } + + public void setLdifPasswordAttribute(String ldifPasswordAttribute) { + this.ldifPasswordAttribute = ldifPasswordAttribute; + } + +} diff --git a/org.argeo.server.core/.classpath b/org.argeo.server.core/.classpath new file mode 100644 index 000000000..3bf3adef5 --- /dev/null +++ b/org.argeo.server.core/.classpath @@ -0,0 +1,7 @@ + + + + >> + + + diff --git a/org.argeo.server.core/.project b/org.argeo.server.core/.project new file mode 100644 index 000000000..b28214ba7 --- /dev/null +++ b/org.argeo.server.core/.project @@ -0,0 +1,28 @@ + + + org.argeo.server.core + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.pde.PluginNature + + diff --git a/org.argeo.server.core/build.properties b/org.argeo.server.core/build.properties new file mode 100644 index 000000000..92847ec08 --- /dev/null +++ b/org.argeo.server.core/build.properties @@ -0,0 +1,7 @@ +source.. = src/main/java/ +additional.bundles = slf4j.api,\ + slf4j.org.apache.commons.logging,\ + slf4j.log4j,\ + org.apache.log4j,\ + com.jcraft.jsch + \ No newline at end of file diff --git a/org.argeo.server.core/pom.xml b/org.argeo.server.core/pom.xml new file mode 100644 index 000000000..f8a23d5a2 --- /dev/null +++ b/org.argeo.server.core/pom.xml @@ -0,0 +1,114 @@ + + + 4.0.0 + + org.argeo.commons + argeo-commons + 2.1.12-SNAPSHOT + .. + + org.argeo.server.core + Commons Server Core + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-source-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + org.apache.felix + maven-bundle-plugin + + + + + org.argeo.server.* + + + javax.servlet, + org.springframework.web.context, + * + + + + + + + + + org.argeo.commons + org.argeo.util + 2.1.12-SNAPSHOT + + + + + org.argeo.tp + org.apache.commons.io + + + org.argeo.tp + org.apache.commons.vfs + + + org.argeo.tp + org.apache.commons.exec + + + org.argeo.tp + com.jcraft.jsch + + + + org.argeo.tp + org.joda.time + + + + + org.argeo.tp + org.springframework.web + + + org.argeo.tp + org.springframework.beans + + + org.argeo.tp + org.springframework.context + + + org.argeo.tp + org.springframework.core + + + org.argeo.tp + org.springframework.web.servlet + + + + + org.argeo.tp + javax.servlet + + + + + org.argeo.tp + slf4j.org.apache.commons.logging + + + + org.argeo.tp + org.apache.commons.fileupload + + + \ No newline at end of file diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/BooleanAnswer.java b/org.argeo.server.core/src/main/java/org/argeo/server/BooleanAnswer.java new file mode 100644 index 000000000..2b7ffb2fc --- /dev/null +++ b/org.argeo.server.core/src/main/java/org/argeo/server/BooleanAnswer.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.server; + + +/** Answer to an execution of a remote service which performed changes. */ +public class BooleanAnswer { + private Boolean value = Boolean.TRUE; + + /** Canonical constructor */ + public BooleanAnswer(Boolean status) { + this.value = status; + } + + /** Empty constructor */ + public BooleanAnswer() { + } + + public Boolean getValue() { + return value; + } + +} diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/Deserializer.java b/org.argeo.server.core/src/main/java/org/argeo/server/Deserializer.java new file mode 100644 index 000000000..4d7faf966 --- /dev/null +++ b/org.argeo.server.core/src/main/java/org/argeo/server/Deserializer.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.server; + +import java.io.Reader; + +public interface Deserializer { + public T deserialize(Reader reader, Class clss); +} diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/DeserializingEditor.java b/org.argeo.server.core/src/main/java/org/argeo/server/DeserializingEditor.java new file mode 100644 index 000000000..915b71cfe --- /dev/null +++ b/org.argeo.server.core/src/main/java/org/argeo/server/DeserializingEditor.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.server; + +import java.beans.PropertyEditorSupport; +import java.io.StringReader; + +import org.apache.commons.io.IOUtils; + +public class DeserializingEditor extends PropertyEditorSupport { + private final Deserializer deserializer; + private final Class targetClass; + + public DeserializingEditor(Deserializer deserializer, Class targetClass) { + super(); + this.deserializer = deserializer; + this.targetClass = targetClass; + } + + @Override + public void setAsText(String text) throws IllegalArgumentException { + StringReader reader = new StringReader(text); + try { + setValue(deserializer.deserialize(reader, targetClass)); + } finally { + IOUtils.closeQuietly(reader); + } + } + +} diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/PrimitiveAnswer.java b/org.argeo.server.core/src/main/java/org/argeo/server/PrimitiveAnswer.java new file mode 100644 index 000000000..c69ffedb8 --- /dev/null +++ b/org.argeo.server.core/src/main/java/org/argeo/server/PrimitiveAnswer.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.server; + +/** + * Answer to a request to a remote service that sends back only one primitive + */ +public class PrimitiveAnswer { + + private Object primitive; + + /** Canonical constructor */ + public PrimitiveAnswer(Object primitive) { + this.primitive = primitive; + } + + public Object getValue() { + return primitive; + } + +} diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/Serializer.java b/org.argeo.server.core/src/main/java/org/argeo/server/Serializer.java new file mode 100644 index 000000000..890b17cd4 --- /dev/null +++ b/org.argeo.server.core/src/main/java/org/argeo/server/Serializer.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.server; + +import java.io.Writer; + +public interface Serializer { + /** Will be removed soon. Use {@link #serialize(Object, Writer)} instead. */ + @Deprecated + public void serialize(Writer writer, Object obj); + + public void serialize(Object obj, Writer writer); +} diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/ServerAnswer.java b/org.argeo.server.core/src/main/java/org/argeo/server/ServerAnswer.java new file mode 100644 index 000000000..2f9cbee1d --- /dev/null +++ b/org.argeo.server.core/src/main/java/org/argeo/server/ServerAnswer.java @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.server; + +import java.io.PrintWriter; +import java.io.StringWriter; + +import org.apache.commons.io.IOUtils; +import org.argeo.ArgeoException; + +/** Answer to an execution of a remote service which performed changes. */ +public class ServerAnswer { + public final static String OK = "OK"; + public final static String ERROR = "ERROR"; + + private String status = OK; + private String message = ""; + + // TODO: add an exception field + + /** Canonical constructor */ + public ServerAnswer(String status, String message) { + setStatus(status); + if (message == null) + throw new ArgeoException("Message cannot be null"); + this.message = message; + } + + /** Empty constructor */ + public ServerAnswer() { + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + if (status == null || (!status.equals(OK) && !status.equals(ERROR))) + throw new ArgeoException("Bad status format: " + status); + this.status = status; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public Boolean isOk() { + return status.equals(OK); + } + + public Boolean isError() { + return status.equals(ERROR); + } + + public static ServerAnswer error(String message) { + return new ServerAnswer(ERROR, message); + } + + public static ServerAnswer error(Throwable e) { + StringWriter writer = new StringWriter(); + try { + e.printStackTrace(new PrintWriter(writer)); + return new ServerAnswer(ERROR, writer.toString()); + } finally { + IOUtils.closeQuietly(writer); + } + } + + public static ServerAnswer ok(String message) { + return new ServerAnswer(OK, message); + } + + @Override + public String toString() { + return "ServerAnswer{status:" + status + ", message:" + message + "}"; + } + +} diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/ServerSerializer.java b/org.argeo.server.core/src/main/java/org/argeo/server/ServerSerializer.java new file mode 100644 index 000000000..cdb163214 --- /dev/null +++ b/org.argeo.server.core/src/main/java/org/argeo/server/ServerSerializer.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.server; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +public interface ServerSerializer { + public void serialize(Object obj, HttpServletRequest request, + HttpServletResponse response); +} diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/backup/AbstractAtomicBackup.java b/org.argeo.server.core/src/main/java/org/argeo/server/backup/AbstractAtomicBackup.java new file mode 100644 index 000000000..53972e503 --- /dev/null +++ b/org.argeo.server.core/src/main/java/org/argeo/server/backup/AbstractAtomicBackup.java @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.server.backup; + +import org.apache.commons.vfs.FileObject; +import org.apache.commons.vfs.FileSystemManager; +import org.apache.commons.vfs.FileSystemOptions; +import org.apache.commons.vfs.provider.sftp.SftpFileSystemConfigBuilder; +import org.argeo.ArgeoException; + +/** + * Simplify atomic backups implementation, especially by managing VFS. + */ +public abstract class AbstractAtomicBackup implements AtomicBackup { + private String name; + private String compression = "bz2"; + + protected abstract void writeBackup(FileObject targetFo); + + public AbstractAtomicBackup() { + } + + public AbstractAtomicBackup(String name) { + this.name = name; + } + + public void init() { + if (name == null) + throw new ArgeoException("Atomic backup name must be set"); + } + + public void destroy() { + + } + + @Override + public String backup(FileSystemManager fileSystemManager, + String backupsBase, BackupContext backupContext, + FileSystemOptions opts) { + if (name == null) + throw new ArgeoException("Atomic backup name must be set"); + + FileObject targetFo = null; + try { + if (backupsBase.startsWith("sftp:")) + SftpFileSystemConfigBuilder.getInstance() + .setStrictHostKeyChecking(opts, "no"); + if (compression == null || compression.equals("none")) + targetFo = fileSystemManager.resolveFile(backupsBase + '/' + + backupContext.getRelativeFolder() + '/' + name, opts); + else if (compression.equals("bz2")) + targetFo = fileSystemManager.resolveFile("bz2:" + backupsBase + + '/' + backupContext.getRelativeFolder() + '/' + name + + ".bz2" + "!" + name, opts); + else if (compression.equals("gz")) + targetFo = fileSystemManager.resolveFile("gz:" + backupsBase + + '/' + backupContext.getRelativeFolder() + '/' + name + + ".gz" + "!" + name, opts); + else + throw new ArgeoException("Unsupported compression " + + compression); + + writeBackup(targetFo); + + return targetFo.toString(); + } catch (Exception e) { + throw new ArgeoException("Cannot backup " + name + " to " + + targetFo, e); + } finally { + BackupUtils.closeFOQuietly(targetFo); + } + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setCompression(String compression) { + this.compression = compression; + } +} diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/backup/AtomicBackup.java b/org.argeo.server.core/src/main/java/org/argeo/server/backup/AtomicBackup.java new file mode 100644 index 000000000..3ebe4b5d2 --- /dev/null +++ b/org.argeo.server.core/src/main/java/org/argeo/server/backup/AtomicBackup.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.server.backup; + +import org.apache.commons.vfs.FileSystemManager; +import org.apache.commons.vfs.FileSystemOptions; + +/** Performs the backup of a single component, typically a database dump */ +public interface AtomicBackup { + /** Name identifiying this backup */ + public String getName(); + + /** + * Retrieves the data of the component in a format that allows to restore + * the component + * + * @param backupContext + * the context of this backup + * @return the VFS URI of the generated file or directory + */ + public String backup(FileSystemManager fileSystemManager, + String backupsBase, BackupContext backupContext, + FileSystemOptions opts); +} diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/backup/BackupContext.java b/org.argeo.server.core/src/main/java/org/argeo/server/backup/BackupContext.java new file mode 100644 index 000000000..5f6442f04 --- /dev/null +++ b/org.argeo.server.core/src/main/java/org/argeo/server/backup/BackupContext.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.server.backup; + +import java.text.DateFormat; +import java.util.Date; + +/** + * Transient information of a given backup, centralizing common information such + * as timestamp and location. + */ +public interface BackupContext { + /** Backup date */ + public Date getTimestamp(); + + /** Formatted backup date */ + public String getTimestampAsString(); + + /** System name */ + public String getSystemName(); + + /** Local base */ + public String getRelativeFolder(); + + /** Date format */ + public DateFormat getDateFormat(); +} diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/backup/BackupFileSystemManager.java b/org.argeo.server.core/src/main/java/org/argeo/server/backup/BackupFileSystemManager.java new file mode 100644 index 000000000..9a0549c5a --- /dev/null +++ b/org.argeo.server.core/src/main/java/org/argeo/server/backup/BackupFileSystemManager.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.server.backup; + +import org.apache.commons.vfs.FileSystemException; +import org.apache.commons.vfs.impl.DefaultFileSystemManager; +import org.apache.commons.vfs.provider.bzip2.Bzip2FileProvider; +import org.apache.commons.vfs.provider.ftp.FtpFileProvider; +import org.apache.commons.vfs.provider.gzip.GzipFileProvider; +import org.apache.commons.vfs.provider.local.DefaultLocalFileProvider; +import org.apache.commons.vfs.provider.ram.RamFileProvider; +import org.apache.commons.vfs.provider.sftp.SftpFileProvider; +import org.apache.commons.vfs.provider.url.UrlFileProvider; +import org.argeo.ArgeoException; + +/** + * Programatically configured VFS file system manager which can be declared as a + * bean and associated with a life cycle (methods + * {@link DefaultFileSystemManager#init()} and + * {@link DefaultFileSystemManager#closet()}). Supports bz2, file, ram, gzip, + * ftp, sftp + */ +public class BackupFileSystemManager extends DefaultFileSystemManager { + + public BackupFileSystemManager() { + super(); + try { + addProvider("file", new DefaultLocalFileProvider()); + addProvider("bz2", new Bzip2FileProvider()); + addProvider("ftp", new FtpFileProvider()); + addProvider("sftp", new SftpFileProvider()); + addProvider("gzip", new GzipFileProvider()); + addProvider("ram", new RamFileProvider()); + setDefaultProvider(new UrlFileProvider()); + } catch (FileSystemException e) { + throw new ArgeoException("Cannot configure backup file provider", e); + } + } +} diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/backup/BackupPurge.java b/org.argeo.server.core/src/main/java/org/argeo/server/backup/BackupPurge.java new file mode 100644 index 000000000..37eecd674 --- /dev/null +++ b/org.argeo.server.core/src/main/java/org/argeo/server/backup/BackupPurge.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.server.backup; + +import java.text.DateFormat; + +import org.apache.commons.vfs.FileSystemManager; +import org.apache.commons.vfs.FileSystemOptions; + +/** Purges previous backups */ +public interface BackupPurge { + /** + * Purge the backups identified by these arguments. Although these are the + * same fields as a {@link BackupContext} we don't pass it as argument since + * we want to use this interface to purge remote backups as well (that is, + * with a different base), or outside the scope of a running backup. + */ + public void purge(FileSystemManager fileSystemManager, String base, + String name, DateFormat dateFormat, FileSystemOptions opts); +} diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/backup/BackupUtils.java b/org.argeo.server.core/src/main/java/org/argeo/server/backup/BackupUtils.java new file mode 100644 index 000000000..e949b0ccf --- /dev/null +++ b/org.argeo.server.core/src/main/java/org/argeo/server/backup/BackupUtils.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.server.backup; + +import org.apache.commons.vfs.FileObject; + +/** Backup utilities */ +public class BackupUtils { + /** Close a file object quietly even if it is null or throws an exception. */ + public static void closeFOQuietly(FileObject fo) { + if (fo != null) { + try { + fo.close(); + } catch (Exception e) { + // silent + } + } + } + + /** Prevents instantiation */ + private BackupUtils() { + } +} diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/backup/MySqlBackup.java b/org.argeo.server.core/src/main/java/org/argeo/server/backup/MySqlBackup.java new file mode 100644 index 000000000..8d3377143 --- /dev/null +++ b/org.argeo.server.core/src/main/java/org/argeo/server/backup/MySqlBackup.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.server.backup; + +import org.apache.commons.vfs.FileObject; + +/** Backups a MySQL database using mysqldump. */ +public class MySqlBackup extends OsCallBackup { + private String mysqldumpLocation = "/usr/bin/mysqldump"; + + private String dbUser; + private String dbPassword; + private String dbName; + + public MySqlBackup() { + } + + public MySqlBackup(String dbUser, String dbPassword, String dbName) { + this.dbUser = dbUser; + this.dbPassword = dbPassword; + this.dbName = dbName; + init(); + } + + @Override + public void init() { + if (getName() == null) + setName(dbName + ".mysql"); + super.init(); + } + + @Override + public void writeBackup(FileObject targetFo) { + if (getCommand() == null) + setCommand(mysqldumpLocation + + " --lock-tables --add-locks --add-drop-table" + + " -u ${dbUser} --password=${dbPassword} --databases ${dbName}"); + getVariables().put("dbUser", dbUser); + getVariables().put("dbPassword", dbPassword); + getVariables().put("dbName", dbName); + + super.writeBackup(targetFo); + } + + public void setDbUser(String dbUser) { + this.dbUser = dbUser; + } + + public void setDbPassword(String dbPassword) { + this.dbPassword = dbPassword; + } + + public void setDbName(String dbName) { + this.dbName = dbName; + } + + public void setMysqldumpLocation(String mysqldumpLocation) { + this.mysqldumpLocation = mysqldumpLocation; + } + +} diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/backup/OpenLdapBackup.java b/org.argeo.server.core/src/main/java/org/argeo/server/backup/OpenLdapBackup.java new file mode 100644 index 000000000..eb5ce2d96 --- /dev/null +++ b/org.argeo.server.core/src/main/java/org/argeo/server/backup/OpenLdapBackup.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.server.backup; + +import org.apache.commons.vfs.FileObject; +import org.argeo.ArgeoException; + +/** Backups an OpenLDAP server using slapcat */ +public class OpenLdapBackup extends OsCallBackup { + private String slapcatLocation = "/usr/sbin/slapcat"; + private String slapdConfLocation = "/etc/openldap/slapd.conf"; + private String baseDn; + + public OpenLdapBackup() { + super(); + } + + public OpenLdapBackup(String baseDn) { + super(); + this.baseDn = baseDn; + } + + @Override + public void writeBackup(FileObject targetFo) { + if (baseDn == null) + throw new ArgeoException("Base DN must be set"); + + if (getCommand() == null) + setCommand(slapcatLocation + + " -f ${slapdConfLocation} -b '${baseDn}'"); + getVariables().put("slapdConfLocation", slapdConfLocation); + getVariables().put("baseDn", baseDn); + + super.writeBackup(targetFo); + } + + public void setSlapcatLocation(String slapcatLocation) { + this.slapcatLocation = slapcatLocation; + } + + public void setSlapdConfLocation(String slapdConfLocation) { + this.slapdConfLocation = slapdConfLocation; + } + + public void setBaseDn(String baseDn) { + this.baseDn = baseDn; + } + +} diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/backup/OsCallBackup.java b/org.argeo.server.core/src/main/java/org/argeo/server/backup/OsCallBackup.java new file mode 100644 index 000000000..816157cfd --- /dev/null +++ b/org.argeo.server.core/src/main/java/org/argeo/server/backup/OsCallBackup.java @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.server.backup; + +import java.io.ByteArrayOutputStream; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.exec.CommandLine; +import org.apache.commons.exec.DefaultExecutor; +import org.apache.commons.exec.ExecuteException; +import org.apache.commons.exec.ExecuteStreamHandler; +import org.apache.commons.exec.Executor; +import org.apache.commons.exec.PumpStreamHandler; +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.commons.vfs.FileContent; +import org.apache.commons.vfs.FileObject; +import org.argeo.ArgeoException; + +/** + * Runs an OS command and save its standard output as a file. Typically used for + * MySQL or OpenLDAP dumps. + */ +public class OsCallBackup extends AbstractAtomicBackup { + private final static Log log = LogFactory.getLog(OsCallBackup.class); + + private String command; + private Map variables = new HashMap(); + private Executor executor = new DefaultExecutor(); + + private Map environment = new HashMap(); + + /** Name of the sudo user, root if "", not sudo if null */ + private String sudo = null; + + public OsCallBackup() { + } + + public OsCallBackup(String name) { + super(name); + } + + public OsCallBackup(String name, String command) { + super(name); + this.command = command; + } + + @Override + public void writeBackup(FileObject targetFo) { + String commandToUse = command; + + // sudo + if (sudo != null) { + if (sudo.equals("")) + commandToUse = "sudo " + commandToUse; + else + commandToUse = "sudo -u " + sudo + " " + commandToUse; + } + + CommandLine commandLine = CommandLine.parse(commandToUse, variables); + ByteArrayOutputStream errBos = new ByteArrayOutputStream(); + if (log.isTraceEnabled()) + log.trace(commandLine.toString()); + + try { + // stdout + FileContent targetContent = targetFo.getContent(); + // stderr + ExecuteStreamHandler streamHandler = new PumpStreamHandler( + targetContent.getOutputStream(), errBos); + executor.setStreamHandler(streamHandler); + executor.execute(commandLine, environment); + } catch (ExecuteException e) { + byte[] err = errBos.toByteArray(); + String errStr = new String(err); + throw new ArgeoException("Process " + commandLine + " failed (" + + e.getExitValue() + "): " + errStr, e); + } catch (Exception e) { + byte[] err = errBos.toByteArray(); + String errStr = new String(err); + throw new ArgeoException("Process " + commandLine + " failed: " + + errStr, e); + } finally { + IOUtils.closeQuietly(errBos); + } + } + + public void setCommand(String command) { + this.command = command; + } + + protected String getCommand() { + return command; + } + + /** + * A reference to the environment variables that will be passed to the + * process. Empty by default. + */ + protected Map getEnvironment() { + return environment; + } + + protected Map getVariables() { + return variables; + } + + public void setVariables(Map variables) { + this.variables = variables; + } + + public void setExecutor(Executor executor) { + this.executor = executor; + } + + public void setSudo(String sudo) { + this.sudo = sudo; + } + +} diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/backup/PostgreSqlBackup.java b/org.argeo.server.core/src/main/java/org/argeo/server/backup/PostgreSqlBackup.java new file mode 100644 index 000000000..37716bb79 --- /dev/null +++ b/org.argeo.server.core/src/main/java/org/argeo/server/backup/PostgreSqlBackup.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.server.backup; + +import org.apache.commons.vfs.FileObject; + +/** Backups a PostgreSQL database using pg_dump. */ +public class PostgreSqlBackup extends OsCallBackup { + /** + * PostgreSQL password environment variable (see + * http://stackoverflow.com/questions + * /2893954/how-to-pass-in-password-to-pg-dump) + */ + protected final static String PGPASSWORD = "PGPASSWORD"; + + private String pgDumpLocation = "/usr/bin/pg_dump"; + + private String dbUser; + private String dbPassword; + private String dbName; + + public PostgreSqlBackup() { + super(); + } + + public PostgreSqlBackup(String dbUser, String dbPassword, String dbName) { + this.dbUser = dbUser; + this.dbPassword = dbPassword; + this.dbName = dbName; + init(); + } + + @Override + public void init() { + // disable compression since pg_dump is used with -Fc option + setCompression(null); + + if (getName() == null) + setName(dbName + ".pgdump"); + super.init(); + } + + @Override + public void writeBackup(FileObject targetFo) { + if (getCommand() == null) { + getEnvironment().put(PGPASSWORD, dbPassword); + setCommand(pgDumpLocation + " -Fc" + " -U ${dbUser} ${dbName}"); + } + getVariables().put("dbUser", dbUser); + getVariables().put("dbPassword", dbPassword); + getVariables().put("dbName", dbName); + + super.writeBackup(targetFo); + } + + public void setDbUser(String dbUser) { + this.dbUser = dbUser; + } + + public void setDbPassword(String dbPassword) { + this.dbPassword = dbPassword; + } + + public void setDbName(String dbName) { + this.dbName = dbName; + } + + public void setPgDumpLocation(String mysqldumpLocation) { + this.pgDumpLocation = mysqldumpLocation; + } + +} diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/backup/SimpleBackupContext.java b/org.argeo.server.core/src/main/java/org/argeo/server/backup/SimpleBackupContext.java new file mode 100644 index 000000000..872f31cf3 --- /dev/null +++ b/org.argeo.server.core/src/main/java/org/argeo/server/backup/SimpleBackupContext.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.server.backup; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.apache.commons.vfs.FileSystemManager; + +/** Simple implementation of a backup context */ +public class SimpleBackupContext implements BackupContext { + private DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmm"); + private final Date timestamp; + private final String name; + + private final FileSystemManager fileSystemManager; + + public SimpleBackupContext(FileSystemManager fileSystemManager, + String backupsBase, String name) { + this.name = name; + this.timestamp = new Date(); + this.fileSystemManager = fileSystemManager; + } + + public Date getTimestamp() { + return timestamp; + } + + public String getTimestampAsString() { + return dateFormat.format(timestamp); + } + + public String getSystemName() { + return name; + } + + public String getRelativeFolder() { + return name + '/' + getTimestampAsString(); + } + + public DateFormat getDateFormat() { + return dateFormat; + } + + public FileSystemManager getFileSystemManager() { + return fileSystemManager; + } + +} diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/backup/SimpleBackupPurge.java b/org.argeo.server.core/src/main/java/org/argeo/server/backup/SimpleBackupPurge.java new file mode 100644 index 000000000..035c49c75 --- /dev/null +++ b/org.argeo.server.core/src/main/java/org/argeo/server/backup/SimpleBackupPurge.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.server.backup; + +import java.text.DateFormat; +import java.util.Date; +import java.util.SortedMap; +import java.util.TreeMap; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.commons.vfs.FileObject; +import org.apache.commons.vfs.FileSystemManager; +import org.apache.commons.vfs.FileSystemOptions; +import org.apache.commons.vfs.Selectors; +import org.argeo.ArgeoException; +import org.joda.time.DateTime; +import org.joda.time.Period; + +/** Simple backup purge which keeps backups only for a given number of days */ +public class SimpleBackupPurge implements BackupPurge { + private final static Log log = LogFactory.getLog(SimpleBackupPurge.class); + + private Integer daysKept = 30; + + @Override + public void purge(FileSystemManager fileSystemManager, String base, + String name, DateFormat dateFormat, FileSystemOptions opts) { + try { + DateTime nowDt = new DateTime(); + FileObject baseFo = fileSystemManager.resolveFile( + base + '/' + name, opts); + + SortedMap toDelete = new TreeMap(); + int backupCount = 0; + + // make sure base dir exists + baseFo.createFolder(); + + // scan backups and list those which should be deleted + for (FileObject backupFo : baseFo.getChildren()) { + String backupName = backupFo.getName().getBaseName(); + Date backupDate = dateFormat.parse(backupName); + backupCount++; + + DateTime backupDt = new DateTime(backupDate.getTime()); + Period sinceThen = new Period(backupDt, nowDt); + int days = sinceThen.getDays(); + // int days = sinceThen.getMinutes(); + if (days > daysKept) { + toDelete.put(backupDt, backupFo); + } + } + + if (toDelete.size() != 0 && toDelete.size() == backupCount) { + // all backups would be deleted + // but we want to keep at least one + DateTime lastBackupDt = toDelete.firstKey(); + FileObject keptFo = toDelete.remove(lastBackupDt); + log.warn("Backup " + keptFo + + " kept although it is older than " + daysKept + + " days."); + } + + // delete old backups + for (FileObject backupFo : toDelete.values()) { + backupFo.delete(Selectors.SELECT_ALL); + if (log.isDebugEnabled()) + log.debug("Deleted backup " + backupFo); + } + } catch (Exception e) { + throw new ArgeoException("Could not purge previous backups", e); + } + + } + +} diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/backup/SvnBackup.java b/org.argeo.server.core/src/main/java/org/argeo/server/backup/SvnBackup.java new file mode 100644 index 000000000..636bbcaaa --- /dev/null +++ b/org.argeo.server.core/src/main/java/org/argeo/server/backup/SvnBackup.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.server.backup; + +import java.io.File; + +import org.apache.commons.vfs.FileObject; + +/** Backups a Subversion repository using svnadmin. */ +public class SvnBackup extends OsCallBackup { + private String svnadminLocation = "/usr/bin/svnadmin"; + + private String repoLocation; + private String repoName; + + public SvnBackup() { + } + + public SvnBackup(String repoLocation) { + this.repoLocation = repoLocation; + init(); + } + + @Override + public void init() { + // use directory as repo name + if (repoName == null) + repoName = new File(repoLocation).getName(); + + if (getName() == null) + setName(repoName + ".svndump"); + super.init(); + } + + @Override + public void writeBackup(FileObject targetFo) { + if (getCommand() == null) { + setCommand(svnadminLocation + " dump " + " ${repoLocation}"); + } + getVariables().put("repoLocation", repoLocation); + + super.writeBackup(targetFo); + } + + public void setRepoLocation(String repoLocation) { + this.repoLocation = repoLocation; + } + + public void setRepoName(String repoName) { + this.repoName = repoName; + } + + public void setSvnadminLocation(String mysqldumpLocation) { + this.svnadminLocation = mysqldumpLocation; + } + +} diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/backup/SystemBackup.java b/org.argeo.server.core/src/main/java/org/argeo/server/backup/SystemBackup.java new file mode 100644 index 000000000..92f73c7a6 --- /dev/null +++ b/org.argeo.server.core/src/main/java/org/argeo/server/backup/SystemBackup.java @@ -0,0 +1,233 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.server.backup; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.commons.vfs.FileObject; +import org.apache.commons.vfs.FileSystemException; +import org.apache.commons.vfs.FileSystemManager; +import org.apache.commons.vfs.FileSystemOptions; +import org.apache.commons.vfs.Selectors; +import org.apache.commons.vfs.UserAuthenticator; +import org.apache.commons.vfs.auth.StaticUserAuthenticator; +import org.apache.commons.vfs.impl.DefaultFileSystemConfigBuilder; +import org.apache.commons.vfs.impl.StandardFileSystemManager; +import org.argeo.ArgeoException; + +/** + * Combines multiple backups and transfer them to a remote location. Purges + * remote and local data based on certain criteria. + */ +public class SystemBackup implements Runnable { + private final static Log log = LogFactory.getLog(SystemBackup.class); + + private FileSystemManager fileSystemManager; + private UserAuthenticator userAuthenticator = null; + + private String backupsBase; + private String systemName; + + private List atomicBackups = new ArrayList(); + private BackupPurge backupPurge = new SimpleBackupPurge(); + + private Map remoteBases = new HashMap(); + + @Override + public void run() { + if (atomicBackups.size() == 0) + throw new ArgeoException("No atomic backup listed"); + List failures = new ArrayList(); + + SimpleBackupContext backupContext = new SimpleBackupContext( + fileSystemManager, backupsBase, systemName); + + // purge older backups + FileSystemOptions opts = new FileSystemOptions(); + try { + DefaultFileSystemConfigBuilder.getInstance().setUserAuthenticator( + opts, userAuthenticator); + } catch (FileSystemException e) { + throw new ArgeoException("Cannot create authentication", e); + } + + try { + + backupPurge.purge(fileSystemManager, backupsBase, systemName, + backupContext.getDateFormat(), opts); + } catch (Exception e) { + failures.add("Purge " + backupsBase + " failed: " + e.getMessage()); + log.error("Purge of " + backupsBase + " failed", e); + } + + // perform backup + for (AtomicBackup atomickBackup : atomicBackups) { + try { + String target = atomickBackup.backup(fileSystemManager, + backupsBase, backupContext, opts); + if (log.isDebugEnabled()) + log.debug("Performed backup " + target); + } catch (Exception e) { + String msg = "Atomic backup " + atomickBackup.getName() + + " failed: " + ArgeoException.chainCausesMessages(e); + failures.add(msg); + log.error(msg); + if (log.isTraceEnabled()) + log.trace( + "Stacktrace of atomic backup " + + atomickBackup.getName() + " failure.", e); + } + } + + // dispatch to remote + for (String remoteBase : remoteBases.keySet()) { + FileObject localBaseFo = null; + FileObject remoteBaseFo = null; + UserAuthenticator auth = remoteBases.get(remoteBase); + + // authentication + FileSystemOptions remoteOpts = new FileSystemOptions(); + try { + DefaultFileSystemConfigBuilder.getInstance() + .setUserAuthenticator(remoteOpts, auth); + backupPurge.purge(fileSystemManager, remoteBase, systemName, + backupContext.getDateFormat(), remoteOpts); + } catch (Exception e) { + failures.add("Purge " + remoteBase + " failed: " + + e.getMessage()); + log.error("Cannot purge " + remoteBase, e); + } + + try { + localBaseFo = fileSystemManager.resolveFile(backupsBase + '/' + + backupContext.getRelativeFolder(), opts); + remoteBaseFo = fileSystemManager.resolveFile(remoteBase + '/' + + backupContext.getRelativeFolder(), remoteOpts); + remoteBaseFo.copyFrom(localBaseFo, Selectors.SELECT_ALL); + if (log.isDebugEnabled()) + log.debug("Copied backup to " + remoteBaseFo + " from " + + localBaseFo); + // } + } catch (Exception e) { + failures.add("Dispatch to " + remoteBase + " failed: " + + e.getMessage()); + log.error( + "Cannot dispatch backups from " + + backupContext.getRelativeFolder() + " to " + + remoteBase, e); + } + BackupUtils.closeFOQuietly(localBaseFo); + BackupUtils.closeFOQuietly(remoteBaseFo); + } + + int failureCount = 0; + if (failures.size() > 0) { + StringBuffer buf = new StringBuffer(); + for (String failure : failures) { + buf.append('\n').append(failureCount).append(" - ") + .append(failure); + failureCount++; + } + throw new ArgeoException(failureCount + + " error(s) when running the backup," + + " check the logs and the backups as soon as possible." + + buf); + } + } + + public void setFileSystemManager(FileSystemManager fileSystemManager) { + this.fileSystemManager = fileSystemManager; + } + + public void setBackupsBase(String backupsBase) { + this.backupsBase = backupsBase; + } + + public void setSystemName(String name) { + this.systemName = name; + } + + public void setAtomicBackups(List atomicBackups) { + this.atomicBackups = atomicBackups; + } + + public void setBackupPurge(BackupPurge backupPurge) { + this.backupPurge = backupPurge; + } + + public void setUserAuthenticator(UserAuthenticator userAuthenticator) { + this.userAuthenticator = userAuthenticator; + } + + public void setRemoteBases(Map remoteBases) { + this.remoteBases = remoteBases; + } + + public static void main(String args[]) { + while (true) { + try { + StandardFileSystemManager fsm = new StandardFileSystemManager(); + fsm.init(); + + SystemBackup systemBackup = new SystemBackup(); + systemBackup.setSystemName("mySystem"); + systemBackup + .setBackupsBase("/home/mbaudier/dev/src/commons/server/runtime/org.argeo.server.core/target"); + systemBackup.setFileSystemManager(fsm); + + List atomicBackups = new ArrayList(); + + MySqlBackup mySqlBackup = new MySqlBackup("root", "", "test"); + atomicBackups.add(mySqlBackup); + PostgreSqlBackup postgreSqlBackup = new PostgreSqlBackup( + "argeo", "argeo", "gis_template"); + atomicBackups.add(postgreSqlBackup); + SvnBackup svnBackup = new SvnBackup( + "/home/mbaudier/tmp/testsvnrepo"); + atomicBackups.add(svnBackup); + + systemBackup.setAtomicBackups(atomicBackups); + + Map remoteBases = new HashMap(); + StaticUserAuthenticator userAuthenticator = new StaticUserAuthenticator( + null, "demo", "demo"); + remoteBases.put("sftp://localhost/home/mbaudier/test", + userAuthenticator); + systemBackup.setRemoteBases(remoteBases); + + systemBackup.run(); + + fsm.close(); + } catch (FileSystemException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + System.exit(1); + } + + // wait + try { + Thread.sleep(120 * 1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } +} diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/dao/AbstractMemoryDaoSupport.java b/org.argeo.server.core/src/main/java/org/argeo/server/dao/AbstractMemoryDaoSupport.java new file mode 100644 index 000000000..f9af51bcf --- /dev/null +++ b/org.argeo.server.core/src/main/java/org/argeo/server/dao/AbstractMemoryDaoSupport.java @@ -0,0 +1,264 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.server.dao; + +import java.beans.PropertyEditor; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; +import org.springframework.beans.BeanWrapper; +import org.springframework.beans.BeanWrapperImpl; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.core.io.Resource; + +public abstract class AbstractMemoryDaoSupport implements LightDaoSupport, + ApplicationContextAware, InitializingBean { + private final static Log log = LogFactory + .getLog(AbstractMemoryDaoSupport.class); + + private ClassLoader classLoader = getClass().getClassLoader(); + private ApplicationContext applicationContext; + private List> additionalClasses = new ArrayList>(); + + private Map, Map> model = new HashMap, Map>(); + + private Map externalRefs = new HashMap(); + + private List scannedPackages = new ArrayList(); + + private List resources = new ArrayList(); + + private Map, PropertyEditor> customEditors = new HashMap, PropertyEditor>();; + + protected abstract void load(InputStream in, List references); + + protected abstract Object findInternalRef(Reference reference); + + public void afterPropertiesSet() throws Exception { + init(); + } + + public void init() { + for (PropertyEditor propertyEditor : customEditors.values()) + if (propertyEditor instanceof LightDaoAware) { + ((LightDaoAware) propertyEditor).setLightDaoSupport(this); + } + + // Load data + List references = new ArrayList(); + + for (Resource res : resources) { + InputStream in = null; + try { + in = res.getInputStream(); + load(in, references); + } catch (Exception e) { + throw new ArgeoException("Cannot load stream", e); + } finally { + IOUtils.closeQuietly(in); + } + } + + // Inject references + for (Reference ref : references) { + injectReference(ref); + } + if (log.isDebugEnabled()) + log.debug(references.size() + " references linked"); + } + + public List> getSupportedClasses() { + List> res = new ArrayList>(); + res.addAll(additionalClasses); + res.addAll(model.keySet()); + return res; + } + + protected void injectReference(Reference reference) { + BeanWrapper bw = new BeanWrapperImpl(reference.object); + Object targetObject; + if (reference.getExternalRef() != null) { + String ref = reference.getExternalRef(); + if (externalRefs.containsKey(ref)) + targetObject = externalRefs.get(ref); + else if (applicationContext != null) + targetObject = applicationContext.getBean(ref); + else { + targetObject = null; + log.warn("Ref " + ref + " not found"); + } + } else { + targetObject = findInternalRef(reference); + } + bw.setPropertyValue(reference.property, targetObject); + + } + + protected BeanWrapper newBeanWrapper(Class targetClass) { + BeanWrapperImpl bw = new BeanWrapperImpl(targetClass); + for (Class clss : customEditors.keySet()) + bw.registerCustomEditor(clss, customEditors.get(clss)); + return bw; + } + + @SuppressWarnings("unchecked") + public T getByKey(Class clss, Object key) { + if (key == null) + throw new ArgeoException("Key is null for " + clss); + return (T) model.get(findClass(clss)).get(key); + } + + /** + * Slow. + * + * @return the first found + */ + public T getByField(Class clss, String field, Object value) { + List all = list(clss, null); + T res = null; + for (T obj : all) { + if (new BeanWrapperImpl(obj).getPropertyValue(field).equals(value)) { + res = obj; + break; + } + } + return res; + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public List list(Class clss, Object filter) { + List res = new ArrayList(); + + Class classToUse = findClass(clss); + if (classToUse != null) + res.addAll((Collection) model.get(classToUse).values()); + + if (applicationContext != null) + res.addAll(applicationContext.getBeansOfType(clss).values()); + + return res; + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + protected Class findClass(Class parent) { + if (model.containsKey(parent)) + return parent; + + for (Class clss : model.keySet()) { + if (parent.isAssignableFrom(clss)) + return clss;// return the first found + } + if (log.isDebugEnabled()) + log.warn("No class found for " + parent.getName()); + return null; + } + + public void setApplicationContext(ApplicationContext applicationContext) + throws BeansException { + this.applicationContext = applicationContext; + } + + /** + * When it should be stored under a different class (e.g. super class or + * interface) + */ + public void saveOrUpdate(Object key, Object value, Class clss) { + if (!model.containsKey(clss)) + model.put(clss, new TreeMap()); + model.get(clss).put(key, value); + } + + protected ClassLoader getClassLoader() { + return classLoader; + } + + public void setExternalRefs(Map externalRefs) { + this.externalRefs = externalRefs; + } + + public Map getExternalRefs() { + return externalRefs; + } + + public void setScannedPackages(List scannedPackages) { + this.scannedPackages = scannedPackages; + } + + public List getScannedPackages() { + return scannedPackages; + } + + public void setResources(List workbooks) { + this.resources = workbooks; + } + + public List getResources() { + return resources; + } + + public void setClassLoader(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + public List> getAdditionalClasses() { + return additionalClasses; + } + + public void setAdditionalClasses(List> additionalClasses) { + this.additionalClasses = additionalClasses; + } + + public void setCustomEditors(Map, PropertyEditor> propertyEditors) { + this.customEditors = propertyEditors; + } + + protected static class Reference { + private Object object; + private String property; + private String externalRef; + + public Reference(Object object, String property, String externalRef) { + this.object = object; + this.property = property; + this.externalRef = externalRef; + } + + public Object getObject() { + return object; + } + + public String getProperty() { + return property; + } + + public String getExternalRef() { + return externalRef; + } + + } +} diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/dao/AbstractTabularDaoSupport.java b/org.argeo.server.core/src/main/java/org/argeo/server/dao/AbstractTabularDaoSupport.java new file mode 100644 index 000000000..1ca5a100c --- /dev/null +++ b/org.argeo.server.core/src/main/java/org/argeo/server/dao/AbstractTabularDaoSupport.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.server.dao; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; + +public abstract class AbstractTabularDaoSupport extends + AbstractMemoryDaoSupport { + private final static Log log = LogFactory + .getLog(AbstractTabularDaoSupport.class); + + private Map> tabularView = new HashMap>(); + + @Override + protected Object findInternalRef(Reference reference) { + TabularInternalReference tabReference = (TabularInternalReference) reference; + return getFromTabularView(tabReference.getTargetTableName(), + tabReference.getTargetRow()); + } + + protected Object getFromTabularView(String tableName, Integer row) { + return tabularView.get(tableName).get(row - 2); + } + + protected void registerInTabularView(String tableName, Object object) { + if (!tabularView.containsKey(tableName)) + tabularView.put(tableName, new ArrayList()); + tabularView.get(tableName).add(object); + } + + protected Class findClassToInstantiate(String tableName) { + // TODO: ability to map sheet names and class names + String className = tableName; + Class clss = null; + try { + clss = getClassLoader().loadClass(className); + return clss; + } catch (ClassNotFoundException e) { + // silent + } + + scannedPkgs: for (String pkg : getScannedPackages()) { + try { + clss = getClassLoader().loadClass(pkg.trim() + "." + className); + break scannedPkgs; + } catch (ClassNotFoundException e) { + // silent + if (log.isTraceEnabled()) + log.trace(e.getMessage()); + } + } + + if (clss == null) + throw new ArgeoException("Cannot find a class for table " + + tableName); + + return clss; + } + + protected static class TabularInternalReference extends Reference { + private String targetTableName; + private Integer targetRow; + + public TabularInternalReference(Object object, String property, + String targetSheet, Integer targetRow) { + super(object, property, null); + this.targetTableName = targetSheet; + this.targetRow = targetRow; + } + + public String getTargetTableName() { + return targetTableName; + } + + public Integer getTargetRow() { + return targetRow; + } + + } +} diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/dao/LightDaoAware.java b/org.argeo.server.core/src/main/java/org/argeo/server/dao/LightDaoAware.java new file mode 100644 index 000000000..5ae7bea1e --- /dev/null +++ b/org.argeo.server.core/src/main/java/org/argeo/server/dao/LightDaoAware.java @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.server.dao; + +public interface LightDaoAware { + public void setLightDaoSupport(LightDaoSupport lightDaoSupport); +} diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/dao/LightDaoPropertyEditor.java b/org.argeo.server.core/src/main/java/org/argeo/server/dao/LightDaoPropertyEditor.java new file mode 100644 index 000000000..de6ba7084 --- /dev/null +++ b/org.argeo.server.core/src/main/java/org/argeo/server/dao/LightDaoPropertyEditor.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.server.dao; + +import java.beans.PropertyEditorSupport; + +import org.argeo.ArgeoException; + +public class LightDaoPropertyEditor extends PropertyEditorSupport implements + LightDaoAware { + private LightDaoSupport lightDaoSupport; + + private Class targetClass; + /** Can be null */ + private String businessIdField; + + @Override + public String getAsText() { + return getValue().toString(); + } + + @Override + public void setAsText(String text) throws IllegalArgumentException { + if (targetClass == null) + throw new ArgeoException("Target class cannot be null"); + + if (businessIdField != null) + setValue(lightDaoSupport.getByField(targetClass, businessIdField, + text)); + else + setValue(lightDaoSupport.getByKey(targetClass, text)); + } + + public void setLightDaoSupport(LightDaoSupport lightDaoSupport) { + this.lightDaoSupport = lightDaoSupport; + } + + public void setTargetClass(Class targetClass) { + this.targetClass = targetClass; + } + + public void setBusinessIdField(String businessIdField) { + this.businessIdField = businessIdField; + } + +} diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/dao/LightDaoSupport.java b/org.argeo.server.core/src/main/java/org/argeo/server/dao/LightDaoSupport.java new file mode 100644 index 000000000..6ea1b754d --- /dev/null +++ b/org.argeo.server.core/src/main/java/org/argeo/server/dao/LightDaoSupport.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.server.dao; + +import java.util.List; + +/** Minimal generic DAO for easy to implements objects <-> storage mapping. */ +public interface LightDaoSupport { + /** Retrieve an object of a given type by its unique key. */ + public T getByKey(Class clss, Object key); + + /** Retrieve an object of a given type by the value of one of its fields. */ + public T getByField(Class clss, String field, Object value); + + /** List all objects, optionally filtering them (implementation dependent) */ + public List list(Class clss, Object filter); + + /** Lis all supported object types. */ + public List> getSupportedClasses(); + + /** Save or update an object */ + public void saveOrUpdate(Object key, Object value, Class clss); +} diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/mvc/DefaultHandlerExceptionResolver.java b/org.argeo.server.core/src/main/java/org/argeo/server/mvc/DefaultHandlerExceptionResolver.java new file mode 100644 index 000000000..6269bd007 --- /dev/null +++ b/org.argeo.server.core/src/main/java/org/argeo/server/mvc/DefaultHandlerExceptionResolver.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.server.mvc; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.server.ServerAnswer; +import org.springframework.web.servlet.HandlerExceptionResolver; +import org.springframework.web.servlet.ModelAndView; + +public class DefaultHandlerExceptionResolver implements + HandlerExceptionResolver { + private final static Log log = LogFactory + .getLog(DefaultHandlerExceptionResolver.class); + + public ModelAndView resolveException(HttpServletRequest request, + HttpServletResponse response, Object handler, Exception ex) { + ModelAndView mv = new ModelAndView(); + ServerAnswer serverAnswer = ServerAnswer.error(ex); + mv.addObject(serverAnswer); + + if (log.isDebugEnabled()) + log.error(serverAnswer); + + mv.setViewName("500"); + // response.setStatus(500); + return mv; + } + +} diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/mvc/EmptyViewController.java b/org.argeo.server.core/src/main/java/org/argeo/server/mvc/EmptyViewController.java new file mode 100644 index 000000000..c83d4aeba --- /dev/null +++ b/org.argeo.server.core/src/main/java/org/argeo/server/mvc/EmptyViewController.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.server.mvc; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.ParameterizableViewController; + +/** Dummy controller which simply redirects to a view (typically a JSP)*/ +public class EmptyViewController extends ParameterizableViewController { + + protected ModelAndView handleRequestInternal(HttpServletRequest request, + HttpServletResponse response) throws Exception { + ModelAndView modelAndView = new ModelAndView(); + modelAndView.setViewName(getViewName()); + return modelAndView; + + } +} diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/mvc/MvcConstants.java b/org.argeo.server.core/src/main/java/org/argeo/server/mvc/MvcConstants.java new file mode 100644 index 000000000..d5c32dc89 --- /dev/null +++ b/org.argeo.server.core/src/main/java/org/argeo/server/mvc/MvcConstants.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.server.mvc; + +public interface MvcConstants { + public final static String ANSWER_MODEL_KEY = "org.argeo.server.mvc.ANSWER"; + public final static String ANSWER_MODEL_KEY_AS_HTML = "org.argeo.server.mvc.ANSWER_AS_HTML"; +} diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/mvc/SerializingView.java b/org.argeo.server.core/src/main/java/org/argeo/server/mvc/SerializingView.java new file mode 100644 index 000000000..b42a9a0d2 --- /dev/null +++ b/org.argeo.server.core/src/main/java/org/argeo/server/mvc/SerializingView.java @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.server.mvc; + +import java.util.Locale; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.argeo.ArgeoException; +import org.argeo.server.ServerAnswer; +import org.argeo.server.ServerSerializer; +import org.springframework.validation.BindingResult; +import org.springframework.web.servlet.View; +import org.springframework.web.servlet.view.AbstractView; + +/** + * Can be used as a standalone {@link View} or using + * {@link SerializingViewResolver} + */ +public class SerializingView extends AbstractView implements MvcConstants { + private final String viewName; + private final Locale locale; + + private ServerSerializer serializer; + + public SerializingView() { + this.viewName = null; + this.locale = Locale.getDefault(); + } + + public SerializingView(String viewName, Locale locale, + ServerSerializer serializer) { + this.viewName = viewName; + this.locale = locale; + this.serializer = serializer; + } + + @SuppressWarnings({ "rawtypes" }) + @Override + protected void renderMergedOutputModel(Map model, + HttpServletRequest request, HttpServletResponse response) + throws Exception { + Boolean serverAnswersAsHtml = model + .containsKey(ANSWER_MODEL_KEY_AS_HTML); + + final Object answer = findAnswerInModel(model); + + if ((answer instanceof ServerAnswer) && serverAnswersAsHtml) { + response.setContentType("text/html"); + ServerAnswer serverAnswer = (ServerAnswer) answer; + response.getWriter().append("
");
+			response.getWriter().append(serverAnswer.getMessage());
+			response.getWriter().append("
"); + } else { + serializer.serialize(answer, request, response); + } + } + + @SuppressWarnings("rawtypes") + protected Object findAnswerInModel(Map model) { + if (model.size() == 1) { + return model.values().iterator().next(); + } else if (model.size() == 2) { + boolean otherIsBindingResult = false; + Object answerValue = null; + for (Object value : model.values()) { + if (value instanceof BindingResult) + otherIsBindingResult = true; + else + answerValue = value; + } + + if (otherIsBindingResult) + return answerValue; + } + + if (model.containsKey(ANSWER_MODEL_KEY)) { + return model.get(ANSWER_MODEL_KEY); + } else if (model.containsKey(ANSWER_MODEL_KEY_AS_HTML)) { + return model.get(ANSWER_MODEL_KEY_AS_HTML); + } else if (viewName != null && model.containsKey(viewName)) { + return model.get(viewName); + } else { + if (model.size() == 0) + throw new ArgeoException("Model is empty."); + else + throw new ArgeoException( + "Model has a size different from 1. Specify a modelKey."); + } + } + + public String getViewName() { + return viewName; + } + + public Locale getLocale() { + return locale; + } + + public void setSerializer(ServerSerializer serializer) { + this.serializer = serializer; + } + +} diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/mvc/SerializingViewResolver.java b/org.argeo.server.core/src/main/java/org/argeo/server/mvc/SerializingViewResolver.java new file mode 100644 index 000000000..93315438f --- /dev/null +++ b/org.argeo.server.core/src/main/java/org/argeo/server/mvc/SerializingViewResolver.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.server.mvc; + +import java.util.Locale; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.server.ServerSerializer; +import org.springframework.web.servlet.View; +import org.springframework.web.servlet.view.AbstractCachingViewResolver; + +/** + * Returns a {@link SerializingView} based on the underlying. + */ +public class SerializingViewResolver extends AbstractCachingViewResolver { + private final static Log log = LogFactory + .getLog(SerializingViewResolver.class); + + private ServerSerializer serializer; + + @Override + protected View loadView(String viewName, Locale locale) throws Exception { + if (log.isTraceEnabled()) + log.trace("viewName=" + viewName); + return new SerializingView(viewName, locale, serializer); + } + + public void setSerializer(ServerSerializer serializer) { + this.serializer = serializer; + } + +} diff --git a/org.argeo.server.jackrabbit/.classpath b/org.argeo.server.jackrabbit/.classpath new file mode 100644 index 000000000..e9c521af6 --- /dev/null +++ b/org.argeo.server.jackrabbit/.classpath @@ -0,0 +1,8 @@ + + + + + >> + + + diff --git a/org.argeo.server.jackrabbit/.project b/org.argeo.server.jackrabbit/.project new file mode 100644 index 000000000..a381d35e0 --- /dev/null +++ b/org.argeo.server.jackrabbit/.project @@ -0,0 +1,28 @@ + + + org.argeo.server.jackrabbit + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.pde.PluginNature + + diff --git a/org.argeo.server.jackrabbit/build.properties b/org.argeo.server.jackrabbit/build.properties new file mode 100644 index 000000000..722c27c73 --- /dev/null +++ b/org.argeo.server.jackrabbit/build.properties @@ -0,0 +1,10 @@ +additional.bundles = slf4j.api,\ + slf4j.log4j,\ + org.apache.log4j,\ + org.apache.commons.collections,\ + edu.oswego.cs.dl.util.concurrent,\ + org.h2,\ + org.apache.lucene,\ + org.springframework.context +source.. = src/main/java/,\ + src/main/resources/ diff --git a/org.argeo.server.jackrabbit/pom.xml b/org.argeo.server.jackrabbit/pom.xml new file mode 100644 index 000000000..41f2a4b82 --- /dev/null +++ b/org.argeo.server.jackrabbit/pom.xml @@ -0,0 +1,106 @@ + + + 4.0.0 + + org.argeo.commons + argeo-commons + 2.1.12-SNAPSHOT + .. + + org.argeo.server.jackrabbit + Commons Server Jackrabbit + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-source-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + org.apache.felix + maven-bundle-plugin + + + + org.argeo.jackrabbit.*, + + + javax.servlet, + org.apache.jackrabbit.webdav.server, + org.springframework.web.context, + org.osgi.framework;version="0.0.0", + org.xml.sax;version="0.0.0", + org.apache.jackrabbit.webdav.jcr, + org.springframework.beans, + * + + + + + + + + + org.argeo.commons + org.argeo.util + 2.1.12-SNAPSHOT + + + org.argeo.commons + org.argeo.server.jcr.mvc + 2.1.12-SNAPSHOT + + + + + org.argeo.commons + org.argeo.dep.jackrabbit + pom + 2.1.12-SNAPSHOT + + + + + org.argeo.tp.rap.platform + org.eclipse.osgi + provided + + + + + org.argeo.tp + org.springframework.beans + + + org.argeo.tp + org.springframework.web.servlet + + + org.argeo.tp + org.springframework.security.core + + + + + org.argeo.commons + org.argeo.support.junit + 2.1.12-SNAPSHOT + test + + + org.argeo.commons + org.argeo.dep.log4j + 2.1.12-SNAPSHOT + pom + test + + + \ No newline at end of file diff --git a/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitAuthorizations.java b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitAuthorizations.java new file mode 100644 index 000000000..e880b6700 --- /dev/null +++ b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitAuthorizations.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jackrabbit; + +import java.security.Principal; +import java.util.Arrays; +import java.util.List; + +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.jackrabbit.api.JackrabbitSession; +import org.apache.jackrabbit.api.security.user.Authorizable; +import org.apache.jackrabbit.api.security.user.UserManager; +import org.argeo.ArgeoException; +import org.argeo.jcr.security.JcrAuthorizations; + +/** Apply authorizations to a Jackrabbit repository. */ +public class JackrabbitAuthorizations extends JcrAuthorizations { + private final static Log log = LogFactory + .getLog(JackrabbitAuthorizations.class); + + private List groupPrefixes = Arrays + .asList(new String[] { "ROLE_" });// new ArrayList(); + + @Override + protected Principal getOrCreatePrincipal(Session session, + String principalName) throws RepositoryException { + UserManager um = ((JackrabbitSession) session).getUserManager(); + synchronized (um) { + Authorizable authorizable = um.getAuthorizable(principalName); + if (authorizable == null) { + groupPrefixes: for (String groupPrefix : groupPrefixes) { + if (principalName.startsWith(groupPrefix)) { + authorizable = um.createGroup(principalName); + log.info("Created group " + principalName); + break groupPrefixes; + } + } + if (authorizable == null) + throw new ArgeoException("Authorizable " + principalName + + " not found"); + } + return authorizable.getPrincipal(); + } + } + + public void setGroupPrefixes(List groupsToCreate) { + this.groupPrefixes = groupsToCreate; + } +} diff --git a/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitContainer.java b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitContainer.java new file mode 100644 index 000000000..9060b585a --- /dev/null +++ b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitContainer.java @@ -0,0 +1,352 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jackrabbit; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashSet; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.TreeSet; +import java.util.UUID; + +import javax.jcr.Node; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.jackrabbit.api.JackrabbitRepository; +import org.apache.jackrabbit.core.RepositoryImpl; +import org.apache.jackrabbit.core.config.RepositoryConfig; +import org.apache.jackrabbit.core.config.RepositoryConfigurationParser; +import org.argeo.ArgeoException; +import org.argeo.jcr.ArgeoNames; +import org.argeo.jcr.JcrUtils; +import org.argeo.jcr.MaintainedRepository; +import org.springframework.core.io.Resource; +import org.springframework.util.SystemPropertyUtils; +import org.xml.sax.InputSource; + +/** + * Wrapper around a Jackrabbit repository which allows to configure it in Spring + * and expose it as a {@link Repository}. + */ +public class JackrabbitContainer extends JackrabbitWrapper implements + MaintainedRepository { + private final static Log log = LogFactory.getLog(JackrabbitContainer.class); + + // local + private Resource configuration; + private Resource variables; + private RepositoryConfig repositoryConfig; + private File homeDirectory; + private Boolean inMemory = false; + + /** Migrations to execute (if not already done) */ + private Set dataModelMigrations = new HashSet(); + + /** + * Empty constructor, {@link #init()} should be called after properties have + * been set + */ + public JackrabbitContainer() { + } + + public void init() { + long begin = System.currentTimeMillis(); + + if (getRepository() != null) + throw new ArgeoException( + "Cannot be used to wrap another repository"); + Repository repository = createJackrabbitRepository(); + super.setRepository(repository); + + // migrate if needed + migrate(); + + // apply new CND files after migration + prepareDataModel(); + + double duration = ((double) (System.currentTimeMillis() - begin)) / 1000; + if (log.isDebugEnabled()) + log.debug("Initialized JCR repository wrapper in " + duration + + " s"); + } + + /** Actually creates the new repository. */ + protected Repository createJackrabbitRepository() { + long begin = System.currentTimeMillis(); + InputStream configurationIn = null; + Repository repository; + try { + // temporary + if (inMemory && getHomeDirectory().exists()) { + FileUtils.deleteDirectory(getHomeDirectory()); + log.warn("Deleted Jackrabbit home directory " + + getHomeDirectory()); + } + + // process configuration file + Properties vars = getConfigurationProperties(); + configurationIn = readConfiguration(); + vars.put(RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE, + getHomeDirectory().getCanonicalPath()); + repositoryConfig = RepositoryConfig.create(new InputSource( + configurationIn), vars); + + // + // Actual repository creation + // + repository = RepositoryImpl.create(repositoryConfig); + + double duration = ((double) (System.currentTimeMillis() - begin)) / 1000; + if (log.isTraceEnabled()) + log.trace("Created Jackrabbit repository in " + duration + + " s, home: " + getHomeDirectory()); + + return repository; + } catch (Exception e) { + throw new ArgeoException("Cannot create Jackrabbit repository " + + getHomeDirectory(), e); + } finally { + IOUtils.closeQuietly(configurationIn); + } + } + + /** Lazy init. */ + protected File getHomeDirectory() { + try { + if (homeDirectory == null) { + if (inMemory) { + homeDirectory = new File( + System.getProperty("java.io.tmpdir") + + File.separator + + System.getProperty("user.name") + + File.separator + "jackrabbit-" + + UUID.randomUUID()); + homeDirectory.mkdirs(); + // will it work if directory is not empty?? + homeDirectory.deleteOnExit(); + } + } + + return homeDirectory.getCanonicalFile(); + } catch (IOException e) { + throw new ArgeoException("Cannot get canonical file for " + + homeDirectory, e); + } + } + + /** Executes migrations, if needed. */ + protected void migrate() { + // No migration to perform + if (dataModelMigrations.size() == 0) + return; + + Boolean restartAndClearCaches = false; + + // migrate data + Session session = null; + try { + session = login(); + for (JackrabbitDataModelMigration dataModelMigration : new TreeSet( + dataModelMigrations)) { + if (dataModelMigration.migrate(session)) { + restartAndClearCaches = true; + } + } + } catch (ArgeoException e) { + throw e; + } catch (Exception e) { + throw new ArgeoException("Cannot migrate", e); + } finally { + JcrUtils.logoutQuietly(session); + } + + // restart repository + if (restartAndClearCaches) { + Repository repository = getRepository(); + if (repository instanceof RepositoryImpl) { + JackrabbitDataModelMigration + .clearRepositoryCaches(((RepositoryImpl) repository) + .getConfig()); + } + ((JackrabbitRepository) repository).shutdown(); + createJackrabbitRepository(); + } + + // set data model version + try { + session = login(); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot login to migrated repository", e); + } + + for (JackrabbitDataModelMigration dataModelMigration : new TreeSet( + dataModelMigrations)) { + try { + if (session.itemExists(dataModelMigration + .getDataModelNodePath())) { + Node dataModelNode = session.getNode(dataModelMigration + .getDataModelNodePath()); + dataModelNode.setProperty( + ArgeoNames.ARGEO_DATA_MODEL_VERSION, + dataModelMigration.getTargetVersion()); + session.save(); + } + } catch (Exception e) { + log.error("Cannot set model version", e); + } + } + JcrUtils.logoutQuietly(session); + + } + + /** Shutdown the repository */ + public void destroy() throws Exception { + Repository repository = getRepository(); + if (repository != null && repository instanceof RepositoryImpl) { + long begin = System.currentTimeMillis(); + ((RepositoryImpl) repository).shutdown(); + if (inMemory) + if (getHomeDirectory().exists()) { + FileUtils.deleteDirectory(getHomeDirectory()); + if (log.isDebugEnabled()) + log.debug("Deleted Jackrabbit home directory " + + getHomeDirectory()); + } + double duration = ((double) (System.currentTimeMillis() - begin)) / 1000; + log.info("Destroyed Jackrabbit repository in " + duration + + " s, home: " + getHomeDirectory()); + } + repository = null; + } + + public void dispose() { + throw new IllegalArgumentException( + "Call destroy() method instead of dispose()"); + } + + /* + * UTILITIES + */ + /** + * Reads the configuration which will initialize a {@link RepositoryConfig}. + */ + protected InputStream readConfiguration() { + try { + return configuration != null ? configuration.getInputStream() + : null; + } catch (IOException e) { + throw new ArgeoException("Cannot read Jackrabbit configuration " + + configuration, e); + } + } + + /** + * Reads the variables which will initialize a {@link Properties}. Returns + * null by default, to be overridden. + * + * @return a new stream or null if no variables available + */ + protected InputStream readVariables() { + try { + return variables != null ? variables.getInputStream() : null; + } catch (IOException e) { + throw new ArgeoException("Cannot read Jackrabbit variables " + + variables, e); + } + } + + /** + * Resolves ${} placeholders in the provided string. Based on system + * properties if no map is provided. + */ + protected String resolvePlaceholders(String string, + Map variables) { + return SystemPropertyUtils.resolvePlaceholders(string); + } + + /** Generates the properties to use in the configuration. */ + protected Properties getConfigurationProperties() { + InputStream propsIn = null; + Properties vars; + try { + vars = new Properties(); + propsIn = readVariables(); + if (propsIn != null) { + vars.load(propsIn); + } + // resolve system properties + for (Object key : vars.keySet()) { + // TODO: implement a smarter mechanism to resolve nested ${} + String newValue = resolvePlaceholders( + vars.getProperty(key.toString()), null); + vars.put(key, newValue); + } + // override with system properties + vars.putAll(System.getProperties()); + + if (log.isTraceEnabled()) { + log.trace("Jackrabbit config variables:"); + for (Object key : new TreeSet(vars.keySet())) + log.trace(key + "=" + vars.getProperty(key.toString())); + } + + } catch (IOException e) { + throw new ArgeoException("Cannot read configuration properties", e); + } finally { + IOUtils.closeQuietly(propsIn); + } + return vars; + } + + /* + * FIELDS ACCESS + */ + + public void setHomeDirectory(File homeDirectory) { + this.homeDirectory = homeDirectory; + } + + public void setInMemory(Boolean inMemory) { + this.inMemory = inMemory; + } + + public void setRepository(Repository repository) { + throw new ArgeoException("Cannot be used to wrap another repository"); + } + + public void setDataModelMigrations( + Set dataModelMigrations) { + this.dataModelMigrations = dataModelMigrations; + } + + public void setVariables(Resource variables) { + this.variables = variables; + } + + public void setConfiguration(Resource configuration) { + this.configuration = configuration; + } + +} diff --git a/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitDataModelMigration.java b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitDataModelMigration.java new file mode 100644 index 000000000..401b34df6 --- /dev/null +++ b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitDataModelMigration.java @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jackrabbit; + +import java.io.InputStreamReader; +import java.io.Reader; + +import javax.jcr.Node; +import javax.jcr.Session; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.jackrabbit.commons.cnd.CndImporter; +import org.apache.jackrabbit.core.config.RepositoryConfig; +import org.argeo.ArgeoException; +import org.argeo.jcr.ArgeoNames; +import org.argeo.jcr.JcrCallback; +import org.argeo.jcr.JcrUtils; +import org.springframework.core.io.Resource; + +/** Migrate the data in a Jackrabbit repository. */ +public class JackrabbitDataModelMigration implements + Comparable { + private final static Log log = LogFactory + .getLog(JackrabbitDataModelMigration.class); + + private String dataModelNodePath; + private String targetVersion; + private Resource migrationCnd; + private JcrCallback dataModification; + + /** + * Expects an already started repository with the old data model to migrate. + * Expects to be run with admin rights (Repository.login() will be used). + * + * @return true if a migration was performed and the repository needs to be + * restarted and its caches cleared. + */ + public Boolean migrate(Session session) { + long begin = System.currentTimeMillis(); + Reader reader = null; + try { + // check if already migrated + if (!session.itemExists(dataModelNodePath)) { + log.warn("Node " + dataModelNodePath + + " does not exist: nothing to migrate."); + return false; + } + Node dataModelNode = session.getNode(dataModelNodePath); + if (dataModelNode.hasProperty(ArgeoNames.ARGEO_DATA_MODEL_VERSION)) { + String currentVersion = dataModelNode.getProperty( + ArgeoNames.ARGEO_DATA_MODEL_VERSION).getString(); + if (compareVersions(currentVersion, targetVersion) >= 0) { + log.info("Data model at version " + currentVersion + + ", no need to migrate."); + return false; + } + } + + // apply transitional CND + if (migrationCnd != null) { + reader = new InputStreamReader(migrationCnd.getInputStream()); + CndImporter.registerNodeTypes(reader, session, true); + session.save(); + log.info("Registered migration node types from " + migrationCnd); + } + + // modify data + dataModification.execute(session); + + // apply changes + session.save(); + + long duration = System.currentTimeMillis() - begin; + log.info("Migration of data model " + dataModelNodePath + " to " + + targetVersion + " performed in " + duration + "ms"); + return true; + } catch (Exception e) { + JcrUtils.discardQuietly(session); + throw new ArgeoException("Migration of data model " + + dataModelNodePath + " to " + targetVersion + " failed.", + e); + } finally { + JcrUtils.logoutQuietly(session); + IOUtils.closeQuietly(reader); + } + } + + protected static int compareVersions(String version1, String version2) { + // TODO do a proper version analysis and comparison + return version1.compareTo(version2); + } + + /** To be called on a stopped repository. */ + public static void clearRepositoryCaches(RepositoryConfig repositoryConfig) { + try { + String customeNodeTypesPath = "/nodetypes/custom_nodetypes.xml"; + repositoryConfig.getFileSystem().deleteFile(customeNodeTypesPath); + if (log.isDebugEnabled()) + log.debug("Cleared " + customeNodeTypesPath); + } catch (Exception e) { + throw new ArgeoException("Cannot clear caches", e); + } + + // File customNodeTypes = new File(home.getPath() + // + "/repository/nodetypes/custom_nodetypes.xml"); + // if (customNodeTypes.exists()) { + // customNodeTypes.delete(); + // if (log.isDebugEnabled()) + // log.debug("Cleared " + customNodeTypes); + // } else { + // log.warn("File " + customNodeTypes + " not found."); + // } + } + + /* + * FOR USE IN (SORTED) SETS + */ + + public int compareTo(JackrabbitDataModelMigration dataModelMigration) { + // TODO make ordering smarter + if (dataModelNodePath.equals(dataModelMigration.dataModelNodePath)) + return compareVersions(targetVersion, + dataModelMigration.targetVersion); + else + return dataModelNodePath + .compareTo(dataModelMigration.dataModelNodePath); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof JackrabbitDataModelMigration)) + return false; + JackrabbitDataModelMigration dataModelMigration = (JackrabbitDataModelMigration) obj; + return dataModelNodePath.equals(dataModelMigration.dataModelNodePath) + && targetVersion.equals(dataModelMigration.targetVersion); + } + + @Override + public int hashCode() { + return targetVersion.hashCode(); + } + + public void setDataModelNodePath(String dataModelNodePath) { + this.dataModelNodePath = dataModelNodePath; + } + + public void setTargetVersion(String targetVersion) { + this.targetVersion = targetVersion; + } + + public void setMigrationCnd(Resource migrationCnd) { + this.migrationCnd = migrationCnd; + } + + public void setDataModification(JcrCallback dataModification) { + this.dataModification = dataModification; + } + + public String getDataModelNodePath() { + return dataModelNodePath; + } + + public String getTargetVersion() { + return targetVersion; + } + +} diff --git a/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitRepositoryFactory.java b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitRepositoryFactory.java new file mode 100644 index 000000000..d64bb5e68 --- /dev/null +++ b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitRepositoryFactory.java @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jackrabbit; + +import java.io.File; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.RepositoryFactory; +import javax.jcr.Session; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.jackrabbit.commons.JcrUtils; +import org.apache.jackrabbit.core.RepositoryImpl; +import org.apache.jackrabbit.core.config.RepositoryConfig; +import org.apache.jackrabbit.core.config.RepositoryConfigurationParser; +import org.apache.jackrabbit.jcr2dav.Jcr2davRepositoryFactory; +import org.argeo.ArgeoException; +import org.argeo.jcr.ArgeoJcrConstants; +import org.argeo.jcr.DefaultRepositoryFactory; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.xml.sax.InputSource; + +/** + * Repository factory which can create new repositories and access remote + * Jackrabbit repositories + */ +public class JackrabbitRepositoryFactory extends DefaultRepositoryFactory + implements RepositoryFactory, ArgeoJcrConstants { + + private final static Log log = LogFactory + .getLog(JackrabbitRepositoryFactory.class); + + private Resource fileRepositoryConfiguration = new ClassPathResource( + "/org/argeo/jackrabbit/repository-h2.xml"); + + @SuppressWarnings({ "rawtypes", "unchecked" }) + public Repository getRepository(Map parameters) throws RepositoryException { + // check if can be found by alias + Repository repository = super.getRepository(parameters); + if (repository != null) + return repository; + + // check if remote + String uri = null; + if (parameters.containsKey(JCR_REPOSITORY_URI)) + uri = parameters.get(JCR_REPOSITORY_URI).toString(); + else if (parameters.containsKey(JcrUtils.REPOSITORY_URI)) + uri = parameters.get(JcrUtils.REPOSITORY_URI).toString(); + + if (uri != null) { + if (uri.startsWith("http"))// http, https + repository = createRemoteRepository(uri); + else if (uri.startsWith("file"))// http, https + repository = createFileRepository(uri, parameters); + else if (uri.startsWith("vm")) { + log.warn("URI " + + uri + + " should have been managed by generic JCR repository factory"); + repository = getRepositoryByAlias(getAliasFromURI(uri)); + } + } + + // publish under alias + if (parameters.containsKey(JCR_REPOSITORY_ALIAS)) { + Properties properties = new Properties(); + properties.putAll(parameters); + String alias = parameters.get(JCR_REPOSITORY_ALIAS).toString(); + publish(alias, repository, properties); + log.info("Registered JCR repository under alias '" + alias + + "' with properties " + properties); + } + + return repository; + } + + protected Repository createRemoteRepository(String uri) + throws RepositoryException { + Map params = new HashMap(); + params.put(JcrUtils.REPOSITORY_URI, uri); + Repository repository = new Jcr2davRepositoryFactory() + .getRepository(params); + if (repository == null) + throw new ArgeoException("Remote Davex repository " + uri + + " not found"); + log.info("Initialized remote Jackrabbit repository from uri " + uri); + return repository; + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + protected Repository createFileRepository(final String uri, Map parameters) + throws RepositoryException { + InputStream configurationIn = null; + try { + Properties vars = new Properties(); + vars.putAll(parameters); + String dirPath = uri.substring("file:".length()); + File homeDir = new File(dirPath); + if (homeDir.exists() && !homeDir.isDirectory()) + throw new ArgeoException("Repository home " + dirPath + + " is not a directory"); + if (!homeDir.exists()) + homeDir.mkdirs(); + configurationIn = fileRepositoryConfiguration.getInputStream(); + vars.put(RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE, + homeDir.getCanonicalPath()); + RepositoryConfig repositoryConfig = RepositoryConfig.create( + new InputSource(configurationIn), vars); + + // TransientRepository repository = new + // TransientRepository(repositoryConfig); + final RepositoryImpl repository = RepositoryImpl + .create(repositoryConfig); + Session session = repository.login(); + // FIXME make it generic + org.argeo.jcr.JcrUtils.addPrivilege(session, "/", "ROLE_ADMIN", + "jcr:all"); + org.argeo.jcr.JcrUtils.logoutQuietly(session); + Runtime.getRuntime().addShutdownHook( + new Thread("Clean JCR repository " + uri) { + public void run() { + repository.shutdown(); + log.info("Destroyed repository " + uri); + } + }); + log.info("Initialized file Jackrabbit repository from uri " + uri); + return repository; + } catch (Exception e) { + throw new ArgeoException("Cannot create repository " + uri, e); + } finally { + IOUtils.closeQuietly(configurationIn); + } + } + + /** + * Called after the repository has been initialised. Does nothing by + * default. + */ + @SuppressWarnings("rawtypes") + protected void postInitialization(Repository repository, Map parameters) { + + } + + public void setFileRepositoryConfiguration( + Resource fileRepositoryConfiguration) { + this.fileRepositoryConfiguration = fileRepositoryConfiguration; + } + +} diff --git a/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitWrapper.java b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitWrapper.java new file mode 100644 index 000000000..f9f04c4cb --- /dev/null +++ b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitWrapper.java @@ -0,0 +1,375 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jackrabbit; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.jcr.Credentials; +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.Repository; +import javax.jcr.Session; +import javax.jcr.nodetype.NodeType; + +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.jackrabbit.commons.NamespaceHelper; +import org.apache.jackrabbit.commons.cnd.CndImporter; +import org.argeo.ArgeoException; +import org.argeo.jcr.ArgeoJcrConstants; +import org.argeo.jcr.ArgeoNames; +import org.argeo.jcr.ArgeoTypes; +import org.argeo.jcr.JcrRepositoryWrapper; +import org.argeo.jcr.JcrUtils; +import org.argeo.util.security.DigestUtils; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.osgi.service.packageadmin.ExportedPackage; +import org.osgi.service.packageadmin.PackageAdmin; +import org.springframework.context.ResourceLoaderAware; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; + +/** + * Wrapper around a Jackrabbit repository which allows to simplify configuration + * and intercept some actions. It exposes itself as a {@link Repository}. + */ +public class JackrabbitWrapper extends JcrRepositoryWrapper implements + ResourceLoaderAware { + private final static Log log = LogFactory.getLog(JackrabbitWrapper.class); + private final static String DIGEST_ALGORITHM = "MD5"; + + // local + private ResourceLoader resourceLoader; + + // data model + /** Node type definitions in CND format */ + private List cndFiles = new ArrayList(); + /** + * Always import CNDs. Useful during development of new data models. In + * production, explicit migration processes should be used. + */ + private Boolean forceCndImport = true; + + /** Namespaces to register: key is prefix, value namespace */ + private Map namespaces = new HashMap(); + + private BundleContext bundleContext; + + /** + * Explicitly set admin credentials used in initialization. Useful for + * testing, in real applications authentication is rather dealt with + * externally + */ + private Credentials adminCredentials = null; + + /** + * Empty constructor, {@link #init()} should be called after properties have + * been set + */ + public JackrabbitWrapper() { + } + + @Override + public void init() { + prepareDataModel(); + } + + /* + * DATA MODEL + */ + + /** + * Import declared node type definitions and register namespaces. Tries to + * update the node definitions if they have changed. In case of failures an + * error will be logged but no exception will be thrown. + */ + protected void prepareDataModel() { + if ((cndFiles == null || cndFiles.size() == 0) + && (namespaces == null || namespaces.size() == 0)) + return; + + Session session = null; + try { + session = login(adminCredentials); + // register namespaces + if (namespaces.size() > 0) { + NamespaceHelper namespaceHelper = new NamespaceHelper(session); + namespaceHelper.registerNamespaces(namespaces); + } + + // load CND files from classpath or as URL + for (String resUrl : cndFiles) { + processCndFile(session, resUrl); + } + } catch (Exception e) { + JcrUtils.discardQuietly(session); + throw new ArgeoException("Cannot import node type definitions " + + cndFiles, e); + } finally { + JcrUtils.logoutQuietly(session); + } + + } + + protected void processCndFile(Session session, String resUrl) { + Reader reader = null; + try { + // check existing data model nodes + new NamespaceHelper(session).registerNamespace(ArgeoNames.ARGEO, + ArgeoNames.ARGEO_NAMESPACE); + if (!session.itemExists(ArgeoJcrConstants.DATA_MODELS_BASE_PATH)) + JcrUtils.mkdirs(session, + ArgeoJcrConstants.DATA_MODELS_BASE_PATH); + Node dataModels = session + .getNode(ArgeoJcrConstants.DATA_MODELS_BASE_PATH); + NodeIterator it = dataModels.getNodes(); + Node dataModel = null; + while (it.hasNext()) { + Node node = it.nextNode(); + if (node.getProperty(ArgeoNames.ARGEO_URI).getString() + .equals(resUrl)) { + dataModel = node; + break; + } + } + + byte[] cndContent = readCndContent(resUrl); + String newDigest = DigestUtils.digest(DIGEST_ALGORITHM, cndContent); + Bundle bundle = findDataModelBundle(resUrl); + + String currentVersion = null; + if (dataModel != null) { + currentVersion = dataModel.getProperty( + ArgeoNames.ARGEO_DATA_MODEL_VERSION).getString(); + if (dataModel.hasNode(Node.JCR_CONTENT)) { + String oldDigest = JcrUtils.checksumFile(dataModel, + DIGEST_ALGORITHM); + if (oldDigest.equals(newDigest)) { + if (log.isDebugEnabled()) + log.debug("Data model " + resUrl + + " hasn't changed, keeping version " + + currentVersion); + return; + } + } + } + + if (dataModel != null && !forceCndImport) { + log.info("Data model " + + resUrl + + " has changed since version " + + currentVersion + + (bundle != null ? ": version " + bundle.getVersion() + + ", bundle " + bundle.getSymbolicName() : "")); + return; + } + + reader = new InputStreamReader(new ByteArrayInputStream(cndContent)); + // actually imports the CND + try { + CndImporter.registerNodeTypes(reader, session, true); + } catch (Exception e) { + log.error("Cannot import data model " + resUrl, e); + return; + } + + if (dataModel != null && !dataModel.isNodeType(NodeType.NT_FILE)) { + dataModel.remove(); + dataModel = null; + } + + // FIXME: what if argeo.cnd would not be the first called on + // a new repo? argeo:dataModel would not be found + String fileName = FilenameUtils.getName(resUrl); + if (dataModel == null) { + dataModel = dataModels.addNode(fileName, NodeType.NT_FILE); + dataModel.addNode(Node.JCR_CONTENT, NodeType.NT_RESOURCE); + dataModel.addMixin(ArgeoTypes.ARGEO_DATA_MODEL); + dataModel.setProperty(ArgeoNames.ARGEO_URI, resUrl); + } else { + session.getWorkspace().getVersionManager() + .checkout(dataModel.getPath()); + } + if (bundle != null) + dataModel.setProperty(ArgeoNames.ARGEO_DATA_MODEL_VERSION, + bundle.getVersion().toString()); + else + dataModel.setProperty(ArgeoNames.ARGEO_DATA_MODEL_VERSION, + "0.0.0"); + JcrUtils.copyBytesAsFile(dataModel.getParent(), fileName, + cndContent); + JcrUtils.updateLastModified(dataModel); + session.save(); + session.getWorkspace().getVersionManager() + .checkin(dataModel.getPath()); + + if (currentVersion == null) + log.info("Data model " + + resUrl + + (bundle != null ? ", version " + bundle.getVersion() + + ", bundle " + bundle.getSymbolicName() : "")); + else + log.info("Data model " + + resUrl + + " updated from version " + + currentVersion + + (bundle != null ? ", version " + bundle.getVersion() + + ", bundle " + bundle.getSymbolicName() : "")); + } catch (Exception e) { + throw new ArgeoException("Cannot process data model " + resUrl, e); + } finally { + IOUtils.closeQuietly(reader); + } + } + + protected byte[] readCndContent(String resUrl) { + InputStream in = null; + try { + boolean classpath; + // normalize URL + if (bundleContext != null && resUrl.startsWith("classpath:")) { + resUrl = resUrl.substring("classpath:".length()); + classpath = true; + } else if (resUrl.indexOf(':') < 0) { + if (!resUrl.startsWith("/")) { + resUrl = "/" + resUrl; + log.warn("Classpath should start with '/'"); + } + classpath = true; + } else { + classpath = false; + } + + URL url = null; + if (classpath) { + if (bundleContext != null) { + Bundle currentBundle = bundleContext.getBundle(); + url = currentBundle.getResource(resUrl); + } else { + resUrl = "classpath:" + resUrl; + url = null; + } + } else if (!resUrl.startsWith("classpath:")) { + url = new URL(resUrl); + } + + if (url != null) { + in = url.openStream(); + } else if (resourceLoader != null) { + Resource res = resourceLoader.getResource(resUrl); + in = res.getInputStream(); + url = res.getURL(); + } else { + throw new ArgeoException("No " + resUrl + " in the classpath," + + " make sure the containing" + " package is visible."); + } + + return IOUtils.toByteArray(in); + } catch (Exception e) { + throw new ArgeoException("Cannot read CND from " + resUrl, e); + } finally { + IOUtils.closeQuietly(in); + } + } + + /* + * REPOSITORY INTERCEPTOR + */ + + /* + * UTILITIES + */ + /** Find which OSGi bundle provided the data model resource */ + protected Bundle findDataModelBundle(String resUrl) { + if (bundleContext == null) + return null; + + if (resUrl.startsWith("/")) + resUrl = resUrl.substring(1); + String pkg = resUrl.substring(0, resUrl.lastIndexOf('/')).replace('/', + '.'); + ServiceReference paSr = bundleContext + .getServiceReference(PackageAdmin.class.getName()); + PackageAdmin packageAdmin = (PackageAdmin) bundleContext + .getService(paSr); + + // find exported package + ExportedPackage exportedPackage = null; + ExportedPackage[] exportedPackages = packageAdmin + .getExportedPackages(pkg); + if (exportedPackages == null) + throw new ArgeoException("No exported package found for " + pkg); + for (ExportedPackage ep : exportedPackages) { + for (Bundle b : ep.getImportingBundles()) { + if (b.getBundleId() == bundleContext.getBundle().getBundleId()) { + exportedPackage = ep; + break; + } + } + } + + Bundle exportingBundle = null; + if (exportedPackage != null) { + exportingBundle = exportedPackage.getExportingBundle(); + } else { + // assume this is in the same bundle + exportingBundle = bundleContext.getBundle(); +// throw new ArgeoException("No OSGi exporting package found for " +// + resUrl); + } + return exportingBundle; + } + + /* + * FIELDS ACCESS + */ + public void setNamespaces(Map namespaces) { + this.namespaces = namespaces; + } + + public void setCndFiles(List cndFiles) { + this.cndFiles = cndFiles; + } + + public void setBundleContext(BundleContext bundleContext) { + this.bundleContext = bundleContext; + } + + public void setForceCndImport(Boolean forceCndUpdate) { + this.forceCndImport = forceCndUpdate; + } + + public void setResourceLoader(ResourceLoader resourceLoader) { + this.resourceLoader = resourceLoader; + } + + public void setAdminCredentials(Credentials adminCredentials) { + this.adminCredentials = adminCredentials; + } + +} diff --git a/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/OsgiJackrabbitRepositoryFactory.java b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/OsgiJackrabbitRepositoryFactory.java new file mode 100644 index 000000000..b28699e60 --- /dev/null +++ b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/OsgiJackrabbitRepositoryFactory.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jackrabbit; + +import java.util.Hashtable; +import java.util.Properties; + +import javax.jcr.Repository; + +import org.osgi.framework.BundleContext; + +/** + * OSGi-aware Jackrabbit repository factory which can retrieve/publish + * {@link Repository} as OSGi services. + */ +public class OsgiJackrabbitRepositoryFactory extends + JackrabbitRepositoryFactory { + private BundleContext bundleContext; + + protected void publish(String alias, Repository repository, + Properties properties) { + if (bundleContext != null) { + // do not modify reference + Hashtable props = new Hashtable(); + props.putAll(props); + props.put(JCR_REPOSITORY_ALIAS, alias); + bundleContext.registerService(Repository.class.getName(), + repository, props); + } + } + + public void setBundleContext(BundleContext bundleContext) { + this.bundleContext = bundleContext; + } + +} diff --git a/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/AbstractJackrabbitHandlerMapping.java b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/AbstractJackrabbitHandlerMapping.java new file mode 100644 index 000000000..99bfab4e8 --- /dev/null +++ b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/AbstractJackrabbitHandlerMapping.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jackrabbit.remote; + +import org.apache.jackrabbit.server.SessionProvider; +import org.argeo.jcr.mvc.MultipleRepositoryHandlerMapping; + +/** Base class for Jackrabbit handler mappings. */ +public abstract class AbstractJackrabbitHandlerMapping extends + MultipleRepositoryHandlerMapping { + private SessionProvider sessionProvider; + + protected SessionProvider getSessionProvider() { + return sessionProvider; + } + + public void setSessionProvider(SessionProvider sessionProvider) { + this.sessionProvider = sessionProvider; + } + +} diff --git a/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/ExtendedDispatcherServlet.java b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/ExtendedDispatcherServlet.java new file mode 100644 index 000000000..14b6e9989 --- /dev/null +++ b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/ExtendedDispatcherServlet.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jackrabbit.remote; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; +import org.springframework.web.servlet.DispatcherServlet; + +/** + * Overrides Spring {@link DispatcherServlet}, see + * http://forum.springsource.org/showthread.php?t=53472. + */ +public class ExtendedDispatcherServlet extends DispatcherServlet { + private static final long serialVersionUID = -5584673209855752009L; + + private final static Log log = LogFactory + .getLog(ExtendedDispatcherServlet.class); + + protected void service(HttpServletRequest request, + HttpServletResponse response) throws ServletException, + java.io.IOException { + try { + if (log.isTraceEnabled()) { + log.trace("SessionID = " + request.getSession().getId()); + log.trace(" ContextPath = " + request.getContextPath()); + log.trace(" ServletPath = " + request.getServletPath()); + log.trace(" PathInfo = " + request.getPathInfo()); + log.trace(" Method = " + request.getMethod()); + log.trace(" User-Agent = " + request.getHeader("User-Agent")); + } + doService(request, response); + } catch (Exception e) { + throw new ArgeoException("Cannot process request", e); + } + } + +} diff --git a/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/IOHandlerWrapper.java b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/IOHandlerWrapper.java new file mode 100644 index 000000000..daf2ecb2b --- /dev/null +++ b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/IOHandlerWrapper.java @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jackrabbit.remote; + +import java.io.IOException; + +import org.apache.jackrabbit.server.io.ExportContext; +import org.apache.jackrabbit.server.io.IOHandler; +import org.apache.jackrabbit.server.io.IOManager; +import org.apache.jackrabbit.server.io.ImportContext; +import org.apache.jackrabbit.webdav.DavResource; +import org.argeo.ArgeoException; + +/** Wraps an IOHandler so that it can be injected a posteriori */ +public class IOHandlerWrapper implements IOHandler { + private IOManager ioManager = null; + private IOHandler ioHandler = null; + + public void setIOHandler(IOHandler ioHandler) { + if ((this.ioHandler != null) && (ioHandler != null)) + throw new ArgeoException( + "There is already an IO Handler registered"); + this.ioHandler = ioHandler; + if (ioManager != null && this.ioHandler != null) + ioHandler.setIOManager(ioManager); + } + + public IOHandler getIOHandler() { + return ioHandler; + } + + public IOManager getIOManager() { + return ioManager; + } + + public void setIOManager(IOManager ioManager) { + this.ioManager = ioManager; + if (ioHandler != null) + ioHandler.setIOManager(ioManager); + } + + public String getName() { + if (ioHandler != null) + return ioHandler.getName(); + else + return "Empty IOHandler Wrapper"; + } + + public boolean canImport(ImportContext context, boolean isCollection) { + if (ioHandler != null) + return ioHandler.canImport(context, isCollection); + return false; + } + + public boolean canImport(ImportContext context, DavResource resource) { + if (ioHandler != null) + return ioHandler.canImport(context, resource); + return false; + } + + public boolean importContent(ImportContext context, boolean isCollection) + throws IOException { + if (ioHandler != null) + ioHandler.importContent(context, isCollection); + return false; + } + + public boolean importContent(ImportContext context, DavResource resource) + throws IOException { + if (ioHandler != null) + ioHandler.importContent(context, resource); + return false; + } + + public boolean canExport(ExportContext context, boolean isCollection) { + if (ioHandler != null) + ioHandler.canExport(context, isCollection); + return false; + } + + public boolean canExport(ExportContext context, DavResource resource) { + if (ioHandler != null) + ioHandler.canExport(context, resource); + return false; + } + + public boolean exportContent(ExportContext context, boolean isCollection) + throws IOException { + if (ioHandler != null) + ioHandler.exportContent(context, isCollection); + return false; + } + + public boolean exportContent(ExportContext context, DavResource resource) + throws IOException { + if (ioHandler != null) + ioHandler.exportContent(context, resource); + return false; + } + +} diff --git a/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/IOManagerBean.java b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/IOManagerBean.java new file mode 100644 index 000000000..82a76738b --- /dev/null +++ b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/IOManagerBean.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jackrabbit.remote; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.jackrabbit.server.io.ExportContext; +import org.apache.jackrabbit.server.io.IOHandler; +import org.apache.jackrabbit.server.io.IOManager; +import org.apache.jackrabbit.server.io.ImportContext; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.tika.detect.Detector; + +/** {@link IOManager} that can easily be configured as a bean. */ +public class IOManagerBean implements IOManager { + private Detector detector = null; + private List ioHandlers = new ArrayList(); + + public boolean importContent(ImportContext context, boolean isCollection) + throws IOException { + // TODO Auto-generated method stub + return false; + } + + public boolean importContent(ImportContext context, DavResource resource) + throws IOException { + // TODO Auto-generated method stub + return false; + } + + public boolean exportContent(ExportContext context, boolean isCollection) + throws IOException { + // TODO Auto-generated method stub + return false; + } + + public boolean exportContent(ExportContext context, DavResource resource) + throws IOException { + // TODO Auto-generated method stub + return false; + } + + public synchronized void addIOHandler(IOHandler ioHandler) { + ioHandlers.add(ioHandler); + } + + public synchronized IOHandler[] getIOHandlers() { + return ioHandlers.toArray(new IOHandler[ioHandlers.size()]); + } + + public Detector getDetector() { + return detector; + } + + public void setDetector(Detector detector) { + this.detector = detector; + } + + public synchronized List getIoHandlers() { + return ioHandlers; + } + + public synchronized void setIoHandlers(List ioHandlers) { + this.ioHandlers = ioHandlers; + } + +} diff --git a/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/JcrRemotingHandlerMapping.java b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/JcrRemotingHandlerMapping.java new file mode 100644 index 000000000..caea5fc8b --- /dev/null +++ b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/JcrRemotingHandlerMapping.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jackrabbit.remote; + +import java.util.Properties; + +import javax.jcr.Repository; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; + +public class JcrRemotingHandlerMapping extends AbstractJackrabbitHandlerMapping { + + protected HttpServlet createServlet(Repository repository, String pathPrefix) + throws ServletException { + JcrRemotingServlet servlet = new JcrRemotingServlet(repository, + getSessionProvider()); + Properties initParameters = new Properties(); + initParameters.setProperty( + JcrRemotingServlet.INIT_PARAM_RESOURCE_PATH_PREFIX, pathPrefix); + servlet.init(new DelegatingServletConfig(pathPrefix.replace('/', '_'), + initParameters)); + return servlet; + } +} diff --git a/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/JcrRemotingServlet.java b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/JcrRemotingServlet.java new file mode 100644 index 000000000..b3f079745 --- /dev/null +++ b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/JcrRemotingServlet.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jackrabbit.remote; + +import javax.jcr.Repository; + +import org.apache.jackrabbit.server.SessionProvider; + +public class JcrRemotingServlet extends + org.apache.jackrabbit.server.remoting.davex.JcrRemotingServlet { + + private static final long serialVersionUID = 3131835511468341309L; + + private final Repository repository; + private final SessionProvider sessionProvider; + + public JcrRemotingServlet(Repository repository, + SessionProvider sessionProvider) { + this.repository = repository; + this.sessionProvider = sessionProvider; + } + + @Override + protected Repository getRepository() { + return repository; + } + + @Override + protected SessionProvider getSessionProvider() { + return sessionProvider; + } + +} diff --git a/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/OpenInViewSessionProvider.java b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/OpenInViewSessionProvider.java new file mode 100644 index 000000000..b4d1d6021 --- /dev/null +++ b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/OpenInViewSessionProvider.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jackrabbit.remote; + +import java.io.Serializable; + +import javax.jcr.LoginException; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.jackrabbit.server.SessionProvider; +import org.argeo.jcr.JcrUtils; + +/** + * Implements an open session in view patter: a new JCR session is created for + * each request + */ +public class OpenInViewSessionProvider implements SessionProvider, Serializable { + private static final long serialVersionUID = 2270957712453841368L; + + private final static Log log = LogFactory + .getLog(OpenInViewSessionProvider.class); + + public Session getSession(HttpServletRequest request, Repository rep, + String workspace) throws LoginException, ServletException, + RepositoryException { + return login(request, rep, workspace); + } + + protected Session login(HttpServletRequest request, Repository repository, + String workspace) throws RepositoryException { + if (log.isTraceEnabled()) + log.trace("Login to workspace " + + (workspace == null ? "" : workspace) + + " in web session " + request.getSession().getId()); + return repository.login(workspace); + } + + public void releaseSession(Session session) { + JcrUtils.logoutQuietly(session); + if (log.isTraceEnabled()) + log.trace("Logged out remote JCR session " + session); + } + + public void init() { + } + + public void destroy() { + } + +} diff --git a/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/ScopedSessionProvider.java b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/ScopedSessionProvider.java new file mode 100644 index 000000000..ffe6df9b1 --- /dev/null +++ b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/ScopedSessionProvider.java @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jackrabbit.remote; + +import java.io.Serializable; + +import javax.jcr.LoginException; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.jackrabbit.server.SessionProvider; +import org.argeo.ArgeoException; +import org.argeo.jcr.ArgeoJcrConstants; +import org.argeo.jcr.JcrUtils; +import org.springframework.security.Authentication; +import org.springframework.security.context.SecurityContextHolder; + +/** + * Session provider assuming a single workspace and a short life cycle, + * typically a Spring bean of scope (web) 'session'. + */ +public class ScopedSessionProvider implements SessionProvider, Serializable { + private static final long serialVersionUID = 6589775984177317058L; + private static final Log log = LogFactory + .getLog(ScopedSessionProvider.class); + private transient HttpSession httpSession = null; + private transient Session jcrSession = null; + + private transient String currentRepositoryName = null; + private transient String currentWorkspaceName = null; + private transient String currentJcrUser = null; + + // private transient String anonymousUserId = "anonymous"; + + public Session getSession(HttpServletRequest request, Repository rep, + String workspace) throws LoginException, ServletException, + RepositoryException { + + Authentication authentication = SecurityContextHolder.getContext() + .getAuthentication(); + if (authentication == null) + throw new ArgeoException( + "Request not authenticated by Spring Security"); + String springUser = authentication.getName(); + + // HTTP + String requestJcrRepository = (String) request + .getAttribute(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS); + + // HTTP session + if (httpSession != null + && !httpSession.getId().equals(request.getSession().getId())) + throw new ArgeoException( + "Only session scope is supported in this mode"); + if (httpSession == null) + httpSession = request.getSession(); + + // Initializes current values + if (currentRepositoryName == null) + currentRepositoryName = requestJcrRepository; + if (currentWorkspaceName == null) + currentWorkspaceName = workspace; + if (currentJcrUser == null) + currentJcrUser = springUser; + + // logout if there was a change in session coordinates + if (jcrSession != null) + if (!currentRepositoryName.equals(requestJcrRepository)) { + if (log.isDebugEnabled()) + log.debug(getHttpSessionId() + " Changed from repository '" + + currentRepositoryName + "' to '" + + requestJcrRepository + + "', logging out cached JCR session."); + logout(); + } else if (!currentWorkspaceName.equals(workspace)) { + if (log.isDebugEnabled()) + log.debug(getHttpSessionId() + " Changed from workspace '" + + currentWorkspaceName + "' to '" + workspace + + "', logging out cached JCR session."); + logout(); + } else if (!currentJcrUser.equals(springUser)) { + if (log.isDebugEnabled()) + log.debug(getHttpSessionId() + " Changed from user '" + + currentJcrUser + "' to '" + springUser + + "', logging out cached JCR session."); + logout(); + } + + // login if needed + if (jcrSession == null) + try { + Session session = login(rep, workspace); + if (!session.getUserID().equals(springUser)) { + JcrUtils.logoutQuietly(session); + throw new ArgeoException("Spring Security user '" + + springUser + "' not in line with JCR user '" + + session.getUserID() + "'"); + } + currentRepositoryName = requestJcrRepository; + // do not use workspace variable which may be null + currentWorkspaceName = session.getWorkspace().getName(); + currentJcrUser = session.getUserID(); + + jcrSession = session; + return jcrSession; + } catch (RepositoryException e) { + throw new ArgeoException("Cannot open session to workspace " + + workspace, e); + } + + // returns cached session + return jcrSession; + } + + protected Session login(Repository repository, String workspace) + throws RepositoryException { + Session session = repository.login(workspace); + if (log.isDebugEnabled()) + log.debug(getHttpSessionId() + " User '" + session.getUserID() + + "' logged in workspace '" + + session.getWorkspace().getName() + "' of repository '" + + currentRepositoryName + "'"); + return session; + } + + public void releaseSession(Session session) { + if (log.isTraceEnabled()) + log.trace(getHttpSessionId() + " Releasing JCR session " + session); + } + + protected void logout() { + JcrUtils.logoutQuietly(jcrSession); + jcrSession = null; + } + + protected final String getHttpSessionId() { + return httpSession != null ? httpSession.getId() : ""; + } + + public void init() { + } + + public void destroy() { + logout(); + if (getHttpSessionId() != null) + if (log.isDebugEnabled()) + log.debug(getHttpSessionId() + + " Cleaned up provider for web session "); + httpSession = null; + } + +} diff --git a/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/SimpleSessionProvider.java b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/SimpleSessionProvider.java new file mode 100644 index 000000000..1d438d504 --- /dev/null +++ b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/SimpleSessionProvider.java @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jackrabbit.remote; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.jcr.LoginException; +import javax.jcr.Node; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.Value; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.jackrabbit.api.JackrabbitSession; +import org.apache.jackrabbit.api.security.user.Group; +import org.apache.jackrabbit.api.security.user.User; +import org.apache.jackrabbit.api.security.user.UserManager; +import org.apache.jackrabbit.server.SessionProvider; +import org.argeo.ArgeoException; +import org.argeo.jcr.ArgeoNames; +import org.argeo.jcr.JcrUtils; +import org.argeo.jcr.UserJcrUtils; + +/** + * Implements an open session in view patter: a new JCR session is created for + * each request + * + * @deprecated use {@link ScopedSessionProvider} or + * {@link OpenInViewSessionProvider} + */ +@Deprecated +public class SimpleSessionProvider implements SessionProvider, Serializable { + private static final long serialVersionUID = 2270957712453841368L; + + private final static Log log = LogFactory + .getLog(SimpleSessionProvider.class); + + private transient Map sessions; + + private Boolean openSessionInView = true; + + private String defaultWorkspace = "default"; + + private String webSessionId = null; + + public Session getSession(HttpServletRequest request, Repository rep, + String workspace) throws LoginException, ServletException, + RepositoryException { + + if (openSessionInView) { + JackrabbitSession session = (JackrabbitSession) login(request, rep, + workspace); + if (session.getWorkspace().getName().equals(defaultWorkspace)) + writeRemoteRoles(session); + return session; + } else { + if (webSessionId != null + && !webSessionId.equals(request.getSession().getId())) + throw new ArgeoException( + "Only session scope is supported in this mode"); + webSessionId = request.getSession().getId(); + + // since sessions is transient it can't be restored from the session + if (sessions == null) + sessions = Collections + .synchronizedMap(new HashMap()); + + if (!sessions.containsKey(workspace)) { + try { + // JackrabbitSession session = (JackrabbitSession) + // rep.login( + // null, workspace); + JackrabbitSession session = (JackrabbitSession) login( + request, rep, workspace); + if (session.getWorkspace().getName() + .equals(defaultWorkspace)) + writeRemoteRoles(session); + if (log.isTraceEnabled()) + log.trace("User " + session.getUserID() + + " logged into " + request.getServletPath()); + sessions.put(workspace, session); + return session; + } catch (Exception e) { + throw new ArgeoException("Cannot open session", e); + } + } else { + Session session = sessions.get(workspace); + if (!session.isLive()) { + sessions.remove(workspace); + session = login(request, rep, workspace); + sessions.put(workspace, session); + } + return session; + } + } + } + + protected Session login(HttpServletRequest request, Repository repository, + String workspace) throws RepositoryException { + if (log.isDebugEnabled()) + log.debug("Login to workspace " + + (workspace == null ? "" : workspace) + + " in web session " + request.getSession().getId()); + return repository.login(workspace); + } + + protected void writeRemoteRoles(JackrabbitSession session) + throws RepositoryException { + // FIXME better deal w/ non node repo + + // retrieve roles + String userId = session.getUserID(); + UserManager userManager = session.getUserManager(); + User user = (User) userManager.getAuthorizable(userId); + if (user == null) { + // anonymous + return; + } + List userGroupIds = new ArrayList(); + if (user != null) + for (Iterator it = user.memberOf(); it.hasNext();) + userGroupIds.add(it.next().getID()); + + // write roles if needed + Node userHome = UserJcrUtils.getUserHome(session); + boolean writeRoles = false; + if (userHome.hasProperty(ArgeoNames.ARGEO_REMOTE_ROLES)) { + Value[] roles = userHome.getProperty(ArgeoNames.ARGEO_REMOTE_ROLES) + .getValues(); + if (roles.length != userGroupIds.size()) + writeRoles = true; + else + for (int i = 0; i < roles.length; i++) + if (!roles[i].getString().equals(userGroupIds.get(i))) + writeRoles = true; + } else + writeRoles = true; + + if (writeRoles) { + session.getWorkspace().getVersionManager() + .checkout(userHome.getPath()); + String[] roleIds = userGroupIds.toArray(new String[userGroupIds + .size()]); + userHome.setProperty(ArgeoNames.ARGEO_REMOTE_ROLES, roleIds); + JcrUtils.updateLastModified(userHome); + session.save(); + session.getWorkspace().getVersionManager() + .checkin(userHome.getPath()); + } + + } + + public void releaseSession(Session session) { + if (log.isTraceEnabled()) + log.trace("Releasing JCR session " + session); + if (openSessionInView) { + JcrUtils.logoutQuietly(session); + if (log.isDebugEnabled()) + log.debug("Logged out remote JCR session " + session); + } + } + + public void init() { + if (log.isDebugEnabled()) + log.debug("Init session provider for web session " + webSessionId); + } + + public void destroy() { + if (log.isDebugEnabled()) + log.debug("Destroy session provider for web session " + + webSessionId); + + if (sessions != null) + for (String workspace : sessions.keySet()) { + Session session = sessions.get(workspace); + JcrUtils.logoutQuietly(session); + } + } + + /** + * If set to true a new session will be created each time (the default), + * otherwise a single session is cached by workspace and the object should + * be of scope session (not supported) + */ + public void setOpenSessionInView(Boolean openSessionInView) { + this.openSessionInView = openSessionInView; + } + + public void setSecurityWorkspace(String securityWorkspace) { + this.defaultWorkspace = securityWorkspace; + } + +} diff --git a/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/SimpleWebdavHandlerMapping.java b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/SimpleWebdavHandlerMapping.java new file mode 100644 index 000000000..bd8d8041a --- /dev/null +++ b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/SimpleWebdavHandlerMapping.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jackrabbit.remote; + +import java.util.Properties; + +import javax.jcr.Repository; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; + +/** Handler mapping for WebDav */ +public class SimpleWebdavHandlerMapping extends + AbstractJackrabbitHandlerMapping { + private String configuration; + + protected HttpServlet createServlet(Repository repository, String pathPrefix) + throws ServletException { + + SimpleWebdavServlet servlet = new SimpleWebdavServlet(repository, + getSessionProvider()); + Properties initParameters = new Properties(); + initParameters.setProperty( + SimpleWebdavServlet.INIT_PARAM_RESOURCE_CONFIG, configuration); + initParameters + .setProperty( + SimpleWebdavServlet.INIT_PARAM_RESOURCE_PATH_PREFIX, + pathPrefix); + servlet.init(new DelegatingServletConfig(pathPrefix.replace('/', '_'), + initParameters)); + return servlet; + } + + public void setConfiguration(String configuration) { + this.configuration = configuration; + } +} diff --git a/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/SimpleWebdavServlet.java b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/SimpleWebdavServlet.java new file mode 100644 index 000000000..f1ca0a9f2 --- /dev/null +++ b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/SimpleWebdavServlet.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jackrabbit.remote; + +import java.io.IOException; + +import javax.jcr.Repository; +import javax.servlet.ServletException; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.jackrabbit.server.SessionProvider; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.WebdavRequest; +import org.apache.jackrabbit.webdav.WebdavResponse; + +/** WebDav servlet whose repository is injected */ +public class SimpleWebdavServlet extends + org.apache.jackrabbit.webdav.simple.SimpleWebdavServlet { + private static final long serialVersionUID = -369787931175177080L; + + private final static Log log = LogFactory.getLog(SimpleWebdavServlet.class); + + private final Repository repository; + + public SimpleWebdavServlet(Repository repository, + SessionProvider sessionProvider) { + this.repository = repository; + setSessionProvider(sessionProvider); + } + + public Repository getRepository() { + return repository; + } + + @Override + protected boolean execute(WebdavRequest request, WebdavResponse response, + int method, DavResource resource) throws ServletException, + IOException, DavException { + if (log.isTraceEnabled()) + log.trace(request.getMethod() + "\t" + request.getPathInfo()); + boolean res = super.execute(request, response, method, resource); + return res; + } + +} diff --git a/org.argeo.server.jackrabbit/src/main/resources/org/argeo/jackrabbit/repository-fs.xml b/org.argeo.server.jackrabbit/src/main/resources/org/argeo/jackrabbit/repository-fs.xml new file mode 100644 index 000000000..609fc8b33 --- /dev/null +++ b/org.argeo.server.jackrabbit/src/main/resources/org/argeo/jackrabbit/repository-fs.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.server.jackrabbit/src/main/resources/org/argeo/jackrabbit/repository-h2.xml b/org.argeo.server.jackrabbit/src/main/resources/org/argeo/jackrabbit/repository-h2.xml new file mode 100644 index 000000000..b6a92528a --- /dev/null +++ b/org.argeo.server.jackrabbit/src/main/resources/org/argeo/jackrabbit/repository-h2.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.server.jackrabbit/src/main/resources/org/argeo/jackrabbit/repository-memory.xml b/org.argeo.server.jackrabbit/src/main/resources/org/argeo/jackrabbit/repository-memory.xml new file mode 100644 index 000000000..e552c33a7 --- /dev/null +++ b/org.argeo.server.jackrabbit/src/main/resources/org/argeo/jackrabbit/repository-memory.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.server.jackrabbit/src/main/wikitext/design.mediawiki b/org.argeo.server.jackrabbit/src/main/wikitext/design.mediawiki new file mode 100644 index 000000000..1a273832c --- /dev/null +++ b/org.argeo.server.jackrabbit/src/main/wikitext/design.mediawiki @@ -0,0 +1,9 @@ += Titre = + + == Sous Titre == + +* point1 +* point2 + + Code (il suffit de mettre un espace en début de ligne + \ No newline at end of file diff --git a/org.argeo.server.jcr.mvc/.classpath b/org.argeo.server.jcr.mvc/.classpath new file mode 100644 index 000000000..c5931a083 --- /dev/null +++ b/org.argeo.server.jcr.mvc/.classpath @@ -0,0 +1,7 @@ + + + >> + + + + diff --git a/org.argeo.server.jcr.mvc/.project b/org.argeo.server.jcr.mvc/.project new file mode 100644 index 000000000..73c19d5d2 --- /dev/null +++ b/org.argeo.server.jcr.mvc/.project @@ -0,0 +1,28 @@ + + + org.argeo.server.jcr.mvc + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/org.argeo.server.jcr.mvc/build.properties b/org.argeo.server.jcr.mvc/build.properties new file mode 100644 index 000000000..5fc538bc8 --- /dev/null +++ b/org.argeo.server.jcr.mvc/build.properties @@ -0,0 +1,4 @@ +source.. = src/main/java/ +output.. = target/classes/ +bin.includes = META-INF/,\ + . diff --git a/org.argeo.server.jcr.mvc/pom.xml b/org.argeo.server.jcr.mvc/pom.xml new file mode 100644 index 000000000..9bc4a42ec --- /dev/null +++ b/org.argeo.server.jcr.mvc/pom.xml @@ -0,0 +1,84 @@ + + + 4.0.0 + + org.argeo.commons + argeo-commons + 2.1.12-SNAPSHOT + .. + + org.argeo.server.jcr.mvc + Commons Server JCR MVC + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-source-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + org.apache.felix + maven-bundle-plugin + + + + + org.argeo.jcr.mvc.* + + + org.springframework.core, + org.springframework.beans.factory, + javax.xml.transform.*;version="0.0.0", + javax.xml.parsers.*;version="0.0.0", + org.w3c.dom.*;version="0.0.0", + org.xml.sax.*;version="0.0.0", + * + + + + + + + + + org.argeo.commons + org.argeo.server.jcr + 2.1.12-SNAPSHOT + + + + + org.argeo.tp + org.springframework.context + + + org.argeo.tp + org.springframework.core + + + org.argeo.tp + org.springframework.beans + + + org.argeo.tp + org.springframework.web + + + org.argeo.tp + org.springframework.web.servlet + + + + + org.argeo.tp + slf4j.org.apache.commons.logging + + + \ No newline at end of file diff --git a/org.argeo.server.jcr.mvc/src/main/java/org/argeo/jcr/mvc/MultipleRepositoryHandlerMapping.java b/org.argeo.server.jcr.mvc/src/main/java/org/argeo/jcr/mvc/MultipleRepositoryHandlerMapping.java new file mode 100644 index 000000000..fb3f1ae65 --- /dev/null +++ b/org.argeo.server.jcr.mvc/src/main/java/org/argeo/jcr/mvc/MultipleRepositoryHandlerMapping.java @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.mvc; + +import java.util.Enumeration; +import java.util.Properties; +import java.util.StringTokenizer; + +import javax.jcr.Repository; +import javax.jcr.RepositoryFactory; +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.jcr.ArgeoJcrConstants; +import org.argeo.jcr.ArgeoJcrUtils; +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.web.context.ServletContextAware; +import org.springframework.web.servlet.HandlerExecutionChain; +import org.springframework.web.servlet.HandlerMapping; + +/** Handles multiple JCR servers with a single servlet. */ +public abstract class MultipleRepositoryHandlerMapping implements + HandlerMapping, ApplicationContextAware, ServletContextAware { + private final static Log log = LogFactory + .getLog(MultipleRepositoryHandlerMapping.class); + + private final static String MKCOL = "MKCOL"; + + private ConfigurableApplicationContext applicationContext; + private ServletContext servletContext; + + // private RepositoryRegister repositoryRegister; + private RepositoryFactory repositoryFactory; + + /** Actually creates the servlet to be registered. */ + protected abstract HttpServlet createServlet(Repository repository, + String pathPrefix) throws ServletException; + + public HandlerExecutionChain getHandler(HttpServletRequest request) + throws Exception { + if (log.isTraceEnabled()) { + log.trace("getContextPath=" + request.getContextPath()); + log.trace("getServletPath=" + request.getServletPath()); + log.trace("getPathInfo=" + request.getPathInfo()); + } + + String pathInfo = request.getPathInfo(); + String repositoryAlias = extractRepositoryAlias(pathInfo); + if (repositoryAlias.equals("")) + return null; + + // MKCOL on repository or root node doesn't make sense + // and causes issues + if (request.getMethod().equals(MKCOL)) { + StringTokenizer st = new StringTokenizer(pathInfo, "/"); + if (!st.hasMoreTokens()) + return null; + st.nextToken();// repository + if (!st.hasMoreTokens()) + return null; + st.nextToken();// workspace + if (!st.hasMoreTokens()) + return null; + } + + request.setAttribute(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS, + repositoryAlias); + String pathPrefix = request.getServletPath() + '/' + repositoryAlias; + String beanName = pathPrefix; + + if (!applicationContext.containsBean(beanName)) { + Repository repository = ArgeoJcrUtils.getRepositoryByAlias( + repositoryFactory, repositoryAlias); + // Repository repository = repositoryRegister.getRepositories().get( + // repositoryAlias); + HttpServlet servlet = createServlet(repository, pathPrefix); + applicationContext.getBeanFactory().registerSingleton(beanName, + servlet); + // TODO: unregister it as well + } + HttpServlet remotingServlet = (HttpServlet) applicationContext + .getBean(beanName); + HandlerExecutionChain hec = new HandlerExecutionChain(remotingServlet); + return hec; + } + + /** Returns the first two token of the path */ + // protected String[] extractPrefix(String pathInfo) { + // String[] res = new String[2]; + // StringTokenizer st = new StringTokenizer(pathInfo, "/"); + // if (st.hasMoreTokens()) + // res[0] = st.nextToken(); + // if (st.hasMoreTokens()) + // res[1] = st.nextToken(); + // return res; + // } + + /** Returns the first token of the path */ + protected String extractRepositoryAlias(String pathInfo) { + StringBuffer buf = new StringBuffer(); + for (int i = 1; i < pathInfo.length(); i++) { + char c = pathInfo.charAt(i); + if (c == '/') + break; + buf.append(c); + } + return buf.toString(); + } + + /** The repository name is the first part of the path info */ + // protected String extractRepositoryName(List pathTokens) { + // StringBuffer currName = new StringBuffer(""); + // for (String token : pathTokens) { + // currName.append(token); + // if (repositoryRegister.getRepositories().containsKey( + // currName.toString())) + // return currName.toString(); + // currName.append('/'); + // } + // throw new ArgeoException("No repository can be found for request " + // + pathTokens); + // } + + public void setApplicationContext(ApplicationContext applicationContext) + throws BeansException { + this.applicationContext = (ConfigurableApplicationContext) applicationContext; + } + + public void setServletContext(ServletContext servletContext) { + this.servletContext = servletContext; + } + + // public void setRepositoryRegister(RepositoryRegister repositoryRegister) + // { + // this.repositoryRegister = repositoryRegister; + // } + + public void setRepositoryFactory(RepositoryFactory repositoryFactory) { + this.repositoryFactory = repositoryFactory; + } + + protected class DelegatingServletConfig implements ServletConfig { + private String name; + private Properties initParameters; + + public DelegatingServletConfig(String name, Properties initParameters) { + super(); + this.name = name; + this.initParameters = initParameters; + } + + public String getServletName() { + return name; + } + + public ServletContext getServletContext() { + return servletContext; + } + + public String getInitParameter(String paramName) { + return initParameters.getProperty(paramName); + } + + @SuppressWarnings("rawtypes") + public Enumeration getInitParameterNames() { + return initParameters.keys(); + } + } +} diff --git a/org.argeo.server.jcr.mvc/src/main/java/org/argeo/jcr/mvc/ResourceProxyServlet.java b/org.argeo.server.jcr.mvc/src/main/java/org/argeo/jcr/mvc/ResourceProxyServlet.java new file mode 100644 index 000000000..c821be054 --- /dev/null +++ b/org.argeo.server.jcr.mvc/src/main/java/org/argeo/jcr/mvc/ResourceProxyServlet.java @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.mvc; + +import java.io.IOException; +import java.io.InputStream; + +import javax.jcr.Binary; +import javax.jcr.Node; +import javax.jcr.PathNotFoundException; +import javax.jcr.Property; +import javax.jcr.RepositoryException; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; +import org.argeo.jcr.JcrUtils; +import org.argeo.jcr.proxy.ResourceProxy; + +/** Wraps a proxy via HTTP */ +public class ResourceProxyServlet extends HttpServlet { + private static final long serialVersionUID = -8886549549223155801L; + + private final static Log log = LogFactory + .getLog(ResourceProxyServlet.class); + + private ResourceProxy proxy; + + private String contentTypeCharset = "UTF-8"; + + @Override + protected void doGet(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + String path = request.getPathInfo(); + + if (log.isTraceEnabled()) { + log.trace("path=" + path); + log.trace("UserPrincipal = " + request.getUserPrincipal().getName()); + log.trace("SessionID = " + request.getSession().getId()); + log.trace("ContextPath = " + request.getContextPath()); + log.trace("ServletPath = " + request.getServletPath()); + log.trace("PathInfo = " + request.getPathInfo()); + log.trace("Method = " + request.getMethod()); + log.trace("User-Agent = " + request.getHeader("User-Agent")); + } + + Node node = null; + try { + node = proxy.proxy(path); + if (node == null) + response.sendError(404); + else + processResponse(node, response); + } finally { + if (node != null) + try { + JcrUtils.logoutQuietly(node.getSession()); + } catch (RepositoryException e) { + // silent + } + } + + } + + /** Retrieve the content of the node. */ + protected void processResponse(Node node, HttpServletResponse response) { + Binary binary = null; + InputStream in = null; + try { + String fileName = node.getName(); + String ext = FilenameUtils.getExtension(fileName); + + // TODO use a more generic / standard approach + // see http://svn.apache.org/viewvc/tomcat/trunk/conf/web.xml + String contentType; + if ("xml".equals(ext)) + contentType = "text/xml;charset=" + contentTypeCharset; + else if ("jar".equals(ext)) + contentType = "application/java-archive"; + else if ("zip".equals(ext)) + contentType = "application/zip"; + else if ("gz".equals(ext)) + contentType = "application/x-gzip"; + else if ("bz2".equals(ext)) + contentType = "application/x-bzip2"; + else if ("tar".equals(ext)) + contentType = "application/x-tar"; + else if ("rpm".equals(ext)) + contentType = "application/x-redhat-package-manager"; + else + contentType = "application/octet-stream"; + contentType = contentType + ";name=\"" + fileName + "\""; + response.setHeader("Content-Disposition", "attachment; filename=\"" + + fileName + "\""); + response.setHeader("Expires", "0"); + response.setHeader("Cache-Control", "no-cache, must-revalidate"); + response.setHeader("Pragma", "no-cache"); + + response.setContentType(contentType); + + try { + binary = node.getNode(Property.JCR_CONTENT) + .getProperty(Property.JCR_DATA).getBinary(); + } catch (PathNotFoundException e) { + log.error("Node " + node + " as no data under content"); + throw e; + } + in = binary.getStream(); + IOUtils.copy(in, response.getOutputStream()); + } catch (Exception e) { + throw new ArgeoException("Cannot download " + node, e); + } finally { + IOUtils.closeQuietly(in); + JcrUtils.closeQuietly(binary); + } + } + + public void setProxy(ResourceProxy resourceProxy) { + this.proxy = resourceProxy; + } + +} diff --git a/org.argeo.server.jcr/.classpath b/org.argeo.server.jcr/.classpath new file mode 100644 index 000000000..d40e15cbf --- /dev/null +++ b/org.argeo.server.jcr/.classpath @@ -0,0 +1,10 @@ + + + + + + + >> + + + diff --git a/org.argeo.server.jcr/.project b/org.argeo.server.jcr/.project new file mode 100644 index 000000000..977218c59 --- /dev/null +++ b/org.argeo.server.jcr/.project @@ -0,0 +1,28 @@ + + + org.argeo.server.jcr + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/org.argeo.server.jcr/build.properties b/org.argeo.server.jcr/build.properties new file mode 100644 index 000000000..d564e5792 --- /dev/null +++ b/org.argeo.server.jcr/build.properties @@ -0,0 +1,22 @@ +source.. = src/main/java/,\ + src/test/java/,\ + src/test/resources/,\ + src/main/resources/ +output.. = target/classes/,\ + target/test-classes/ +bin.includes = META-INF/,\ + . +additional.bundles = slf4j.api,\ + slf4j.log4j,\ + org.apache.log4j,\ + org.apache.commons.collections,\ + edu.oswego.cs.dl.util.concurrent,\ + org.apache.lucene,\ + junit,\ + org.apache.xml.serializer,\ + org.apache.commons.dbcp,\ + org.apache.commons.pool,\ + org.apache.jackrabbit,\ + org.h2,\ + org.apache.tika + diff --git a/org.argeo.server.jcr/pom.xml b/org.argeo.server.jcr/pom.xml new file mode 100644 index 000000000..4d8c2ea38 --- /dev/null +++ b/org.argeo.server.jcr/pom.xml @@ -0,0 +1,136 @@ + + 4.0.0 + + org.argeo.commons + argeo-commons + 2.1.12-SNAPSHOT + .. + + org.argeo.server.jcr + Commons Server JCR + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-source-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + org.apache.felix + maven-bundle-plugin + + + + org.argeo.jcr.* + + junit.framework;resolution:=optional, + org.xml.sax;version="0.0.0", + org.springframework.core;resolution:=optional, + org.springframework.core.io;resolution:=optional, + org.springframework.*;resolution:=optional, + * + + + + + org.argeo.maven.plugins + maven-argeo-osgi-plugin + + true + true + + -clean + + + + XXX + + + + + + + + org.argeo.commons + org.argeo.util + 2.1.12-SNAPSHOT + + + + + org.argeo.tp + javax.jcr + + + + org.argeo.tp + org.apache.commons.io + + + + + org.argeo.tp + org.springframework.core + provided + + + org.argeo.tp + org.springframework.beans + provided + + + + + org.argeo.tp + org.eclipse.osgi + provided + + + + + org.argeo.tp + slf4j.org.apache.commons.logging + + + + + + org.argeo.tp + junit + true + + + org.argeo.commons + org.argeo.dep.jackrabbit + 2.1.12-SNAPSHOT + pom + test + + + org.argeo.commons + org.argeo.support.junit + 2.1.12-SNAPSHOT + test + + + org.argeo.commons + org.argeo.dep.log4j + 2.1.12-SNAPSHOT + pom + test + + + org.argeo.commons + org.argeo.osgi.boot + 2.1.12-SNAPSHOT + test + + + \ No newline at end of file diff --git a/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoJcrConstants.java b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoJcrConstants.java new file mode 100644 index 000000000..b9b513a30 --- /dev/null +++ b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoJcrConstants.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr; + +/** Argeo model specific constants */ +public interface ArgeoJcrConstants { + public final static String ARGEO_BASE_PATH = "/argeo:system"; + public final static String DATA_MODELS_BASE_PATH = ARGEO_BASE_PATH + + "/argeo:dataModels"; + public final static String PEOPLE_BASE_PATH = ARGEO_BASE_PATH + + "/argeo:people"; + + // parameters (typically for call to a RepositoryFactory) + public final static String JCR_REPOSITORY_ALIAS = "argeo.jcr.repository.alias"; + public final static String JCR_REPOSITORY_URI = "argeo.jcr.repository.uri"; + + // standard aliases + public final static String ALIAS_NODE = "node"; + +} diff --git a/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoJcrUtils.java b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoJcrUtils.java new file mode 100644 index 000000000..dccb06cf4 --- /dev/null +++ b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoJcrUtils.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr; + +import java.util.HashMap; +import java.util.Map; + +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.RepositoryFactory; + +import org.argeo.ArgeoException; + +/** Utilities related to Argeo model in JCR */ +public class ArgeoJcrUtils implements ArgeoJcrConstants { + /** + * Wraps the call to the repository factory based on parameter + * {@link ArgeoJcrConstants#JCR_REPOSITORY_ALIAS} in order to simplify it + * and protect against future API changes. + */ + public static Repository getRepositoryByAlias( + RepositoryFactory repositoryFactory, String alias) { + try { + Map parameters = new HashMap(); + parameters.put(JCR_REPOSITORY_ALIAS, alias); + return repositoryFactory.getRepository(parameters); + } catch (RepositoryException e) { + throw new ArgeoException( + "Unexpected exception when trying to retrieve repository with alias " + + alias, e); + } + } + + /** + * Wraps the call to the repository factory based on parameter + * {@link ArgeoJcrConstants#JCR_REPOSITORY_URI} in order to simplify it and + * protect against future API changes. + */ + public static Repository getRepositoryByUri( + RepositoryFactory repositoryFactory, String uri) { + return getRepositoryByUri(repositoryFactory, uri, null); + } + + /** + * Wraps the call to the repository factory based on parameter + * {@link ArgeoJcrConstants#JCR_REPOSITORY_URI} in order to simplify it and + * protect against future API changes. + */ + public static Repository getRepositoryByUri( + RepositoryFactory repositoryFactory, String uri, String alias) { + try { + Map parameters = new HashMap(); + parameters.put(JCR_REPOSITORY_URI, uri); + if (alias != null) + parameters.put(JCR_REPOSITORY_ALIAS, alias); + return repositoryFactory.getRepository(parameters); + } catch (RepositoryException e) { + throw new ArgeoException( + "Unexpected exception when trying to retrieve repository with uri " + + uri, e); + } + } + + private ArgeoJcrUtils() { + } + +} diff --git a/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoNames.java b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoNames.java new file mode 100644 index 000000000..6e3eca999 --- /dev/null +++ b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoNames.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr; + +/** JCR names in the http://www.argeo.org/argeo namespace */ +public interface ArgeoNames { + public final static String ARGEO_NAMESPACE = "http://www.argeo.org/ns/argeo"; + public final static String ARGEO = "argeo"; + + public final static String ARGEO_URI = "argeo:uri"; + public final static String ARGEO_USER_ID = "argeo:userID"; + public final static String ARGEO_PREFERENCES = "argeo:preferences"; + public final static String ARGEO_DATA_MODEL_VERSION = "argeo:dataModelVersion"; + + public final static String ARGEO_REMOTE = "argeo:remote"; + public final static String ARGEO_PASSWORD = "argeo:password"; + public final static String ARGEO_REMOTE_ROLES = "argeo:remoteRoles"; + + // user profile + public final static String ARGEO_PROFILE = "argeo:profile"; + + // spring security + public final static String ARGEO_ENABLED = "argeo:enabled"; + public final static String ARGEO_ACCOUNT_NON_EXPIRED = "argeo:accountNonExpired"; + public final static String ARGEO_ACCOUNT_NON_LOCKED = "argeo:accountNonLocked"; + public final static String ARGEO_CREDENTIALS_NON_EXPIRED = "argeo:credentialsNonExpired"; + + // personal details + public final static String ARGEO_FIRST_NAME = "argeo:firstName"; + public final static String ARGEO_LAST_NAME = "argeo:lastName"; + public final static String ARGEO_PRIMARY_EMAIL = "argeo:primaryEmail"; + public final static String ARGEO_PRIMARY_ORGANIZATION = "argeo:primaryOrganization"; + + // tabular + public final static String ARGEO_IS_KEY = "argeo:isKey"; + + // crypto + public final static String ARGEO_IV = "argeo:iv"; + public final static String ARGEO_SECRET_KEY_FACTORY = "argeo:secretKeyFactory"; + public final static String ARGEO_SALT = "argeo:salt"; + public final static String ARGEO_ITERATION_COUNT = "argeo:iterationCount"; + public final static String ARGEO_KEY_LENGTH = "argeo:keyLength"; + public final static String ARGEO_SECRET_KEY_ENCRYPTION = "argeo:secretKeyEncryption"; + public final static String ARGEO_CIPHER = "argeo:cipher"; + public final static String ARGEO_KEYRING = "argeo:keyring"; +} diff --git a/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoTypes.java b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoTypes.java new file mode 100644 index 000000000..a11ead53f --- /dev/null +++ b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoTypes.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr; + +/** JCR types in the http://www.argeo.org/argeo namespace */ +public interface ArgeoTypes { + public final static String ARGEO_LINK = "argeo:link"; + public final static String ARGEO_USER_HOME = "argeo:userHome"; + public final static String ARGEO_USER_PROFILE = "argeo:userProfile"; + public final static String ARGEO_REMOTE_REPOSITORY = "argeo:remoteRepository"; + public final static String ARGEO_PREFERENCE_NODE = "argeo:preferenceNode"; + + // data model + public final static String ARGEO_DATA_MODEL = "argeo:dataModel"; + + // tabular + public final static String ARGEO_TABLE = "argeo:table"; + public final static String ARGEO_COLUMN = "argeo:column"; + public final static String ARGEO_CSV = "argeo:csv"; + + // crypto + public final static String ARGEO_ENCRYPTED = "argeo:encrypted"; + public final static String ARGEO_PBE_SPEC = "argeo:pbeSpec"; + +} diff --git a/org.argeo.server.jcr/src/main/java/org/argeo/jcr/CollectionNodeIterator.java b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/CollectionNodeIterator.java new file mode 100644 index 000000000..a65907a7a --- /dev/null +++ b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/CollectionNodeIterator.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr; + +import java.util.Collection; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import javax.jcr.Node; +import javax.jcr.NodeIterator; + +/** Wraps a collection of nodes in order to read it as a {@link NodeIterator} */ +public class CollectionNodeIterator implements NodeIterator { + private final Long collectionSize; + private final Iterator iterator; + private Integer position = 0; + + public CollectionNodeIterator(Collection nodes) { + super(); + this.collectionSize = (long) nodes.size(); + this.iterator = nodes.iterator(); + } + + public void skip(long skipNum) { + if (skipNum < 0) + throw new IllegalArgumentException( + "Skip count has to be positive: " + skipNum); + + for (long i = 0; i < skipNum; i++) { + if (!hasNext()) + throw new NoSuchElementException("Last element past (position=" + + getPosition() + ")"); + nextNode(); + } + } + + public long getSize() { + return collectionSize; + } + + public long getPosition() { + return position; + } + + public boolean hasNext() { + return iterator.hasNext(); + } + + public Object next() { + return nextNode(); + } + + public void remove() { + iterator.remove(); + } + + public Node nextNode() { + Node node = iterator.next(); + position++; + return node; + } + +} diff --git a/org.argeo.server.jcr/src/main/java/org/argeo/jcr/DefaultJcrListener.java b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/DefaultJcrListener.java new file mode 100644 index 000000000..253b3055d --- /dev/null +++ b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/DefaultJcrListener.java @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr; + +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.observation.Event; +import javax.jcr.observation.EventIterator; +import javax.jcr.observation.EventListener; +import javax.jcr.observation.ObservationManager; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; + +/** To be overridden */ +public class DefaultJcrListener implements EventListener { + private final static Log log = LogFactory.getLog(DefaultJcrListener.class); + private Session session; + private String path = "/"; + private Boolean deep = true; + + public void start() { + try { + addEventListener(session().getWorkspace().getObservationManager()); + if (log.isDebugEnabled()) + log.debug("Registered JCR event listener on " + path); + } catch (Exception e) { + throw new ArgeoException("Cannot register event listener", e); + } + } + + public void stop() { + try { + session().getWorkspace().getObservationManager() + .removeEventListener(this); + if (log.isDebugEnabled()) + log.debug("Unregistered JCR event listener on " + path); + } catch (Exception e) { + throw new ArgeoException("Cannot unregister event listener", e); + } + } + + /** Default is listen to all events */ + protected Integer getEvents() { + return Event.NODE_ADDED | Event.NODE_REMOVED | Event.PROPERTY_ADDED + | Event.PROPERTY_CHANGED | Event.PROPERTY_REMOVED; + } + + /** To be overidden */ + public void onEvent(EventIterator events) { + while (events.hasNext()) { + Event event = events.nextEvent(); + log.debug(event); + } + } + + /** To be overidden */ + protected void addEventListener(ObservationManager observationManager) + throws RepositoryException { + observationManager.addEventListener(this, getEvents(), path, deep, + null, null, false); + } + + private Session session() { + return session; + } + + public void setPath(String path) { + this.path = path; + } + + public void setDeep(Boolean deep) { + this.deep = deep; + } + + public void setSession(Session session) { + this.session = session; + } + +} diff --git a/org.argeo.server.jcr/src/main/java/org/argeo/jcr/DefaultRepositoryFactory.java b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/DefaultRepositoryFactory.java new file mode 100644 index 000000000..a7b30e7be --- /dev/null +++ b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/DefaultRepositoryFactory.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Map; +import java.util.Properties; + +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.RepositoryFactory; + +import org.argeo.ArgeoException; + +/** + * Simple implementation of {@link RepositoryFactory}, supporting OSGi aliases. + */ +public class DefaultRepositoryFactory extends DefaultRepositoryRegister + implements RepositoryFactory, ArgeoJcrConstants { + @SuppressWarnings("rawtypes") + public Repository getRepository(Map parameters) throws RepositoryException { + if (parameters.containsKey(JCR_REPOSITORY_ALIAS)) { + String alias = parameters.get(JCR_REPOSITORY_ALIAS).toString(); + return getRepositoryByAlias(alias); + } else if (parameters.containsKey(JCR_REPOSITORY_URI)) { + String uri = parameters.get(JCR_REPOSITORY_URI).toString(); + return getRepositoryByAlias(getAliasFromURI(uri)); + } + return null; + } + + protected String getAliasFromURI(String uri) { + try { + URI uriObj = new URI(uri); + String alias = uriObj.getPath(); + if (alias.charAt(0) == '/') + alias = alias.substring(1); + if (alias.charAt(alias.length() - 1) == '/') + alias = alias.substring(0, alias.length() - 1); + return alias; + } catch (URISyntaxException e) { + throw new ArgeoException("Cannot interpret URI " + uri, e); + } + } + + /** + * Retrieve a repository by alias + * + * @return the repository registered with alias or null if none + */ + protected Repository getRepositoryByAlias(String alias) { + if (getRepositories().containsKey(alias)) + return getRepositories().get(alias); + else + return null; + } + + protected void publish(String alias, Repository repository, + Properties properties) { + register(repository, properties); + } + +} diff --git a/org.argeo.server.jcr/src/main/java/org/argeo/jcr/DefaultRepositoryRegister.java b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/DefaultRepositoryRegister.java new file mode 100644 index 000000000..f13c84e3b --- /dev/null +++ b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/DefaultRepositoryRegister.java @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr; + +import java.util.Collections; +import java.util.Map; +import java.util.Observable; +import java.util.TreeMap; + +import javax.jcr.Repository; +import javax.jcr.RepositoryException; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +public class DefaultRepositoryRegister extends Observable implements + RepositoryRegister, ArgeoJcrConstants { + private final static Log log = LogFactory + .getLog(DefaultRepositoryRegister.class); + + /** Read only map which will be directly exposed. */ + private Map repositories = Collections + .unmodifiableMap(new TreeMap()); + + @SuppressWarnings("rawtypes") + public synchronized Repository getRepository(Map parameters) + throws RepositoryException { + if (!parameters.containsKey(JCR_REPOSITORY_ALIAS)) + throw new RepositoryException("Parameter " + JCR_REPOSITORY_ALIAS + + " has to be defined."); + String alias = parameters.get(JCR_REPOSITORY_ALIAS).toString(); + if (!repositories.containsKey(alias)) + throw new RepositoryException( + "No repository registered with alias " + alias); + + return repositories.get(alias); + } + + /** Access to the read-only map */ + public synchronized Map getRepositories() { + return repositories; + } + + /** Registers a service, typically called when OSGi services are bound. */ + @SuppressWarnings("rawtypes") + public synchronized void register(Repository repository, Map properties) { + // TODO: also check bean name? + String alias; + if (properties == null || !properties.containsKey(JCR_REPOSITORY_ALIAS)) { + log.warn("Cannot register a repository if no " + + JCR_REPOSITORY_ALIAS + " property is speecified."); + return; + } + alias = properties.get(JCR_REPOSITORY_ALIAS).toString(); + Map map = new TreeMap( + repositories); + map.put(alias, repository); + repositories = Collections.unmodifiableMap(map); + setChanged(); + notifyObservers(alias); + } + + /** Unregisters a service, typically called when OSGi services are unbound. */ + @SuppressWarnings("rawtypes") + public synchronized void unregister(Repository repository, Map properties) { + // TODO: also check bean name? + if (properties == null || !properties.containsKey(JCR_REPOSITORY_ALIAS)) { + log.warn("Cannot unregister a repository without property " + + JCR_REPOSITORY_ALIAS); + return; + } + + String alias = properties.get(JCR_REPOSITORY_ALIAS).toString(); + Map map = new TreeMap( + repositories); + map.put(alias, repository); + repositories = Collections.unmodifiableMap(map); + setChanged(); + notifyObservers(alias); + } +} diff --git a/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrCallback.java b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrCallback.java new file mode 100644 index 000000000..0c4706f84 --- /dev/null +++ b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrCallback.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr; + +import javax.jcr.Session; + +/** An arbitrary execution on a JCR session, optionally returning a result. */ +public interface JcrCallback { + public Object execute(Session session); +} diff --git a/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrRepositoryWrapper.java b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrRepositoryWrapper.java new file mode 100644 index 000000000..f993c2f58 --- /dev/null +++ b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrRepositoryWrapper.java @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr; + +import javax.jcr.Credentials; +import javax.jcr.LoginException; +import javax.jcr.NoSuchWorkspaceException; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.Value; + +import org.argeo.ArgeoException; + +/** + * Wrapper around a JCR repository which allows to simplify configuration and + * intercept some actions. It exposes itself as a {@link Repository}. + */ +public abstract class JcrRepositoryWrapper implements Repository { + // private final static Log log = LogFactory + // .getLog(JcrRepositoryWrapper.class); + + // wrapped repository + private Repository repository; + + private Boolean autocreateWorkspaces = false; + + /** + * Empty constructor, {@link #init()} should be called after properties have + * been set + */ + public JcrRepositoryWrapper() { + } + + /** Initializes */ + public void init() { + } + + /** Shutdown the repository */ + public void destroy() throws Exception { + } + + /* + * DELEGATED JCR REPOSITORY METHODS + */ + + public String getDescriptor(String key) { + return getRepository().getDescriptor(key); + } + + public String[] getDescriptorKeys() { + return getRepository().getDescriptorKeys(); + } + + /** Central login method */ + public Session login(Credentials credentials, String workspaceName) + throws LoginException, NoSuchWorkspaceException, + RepositoryException { + Session session; + try { + session = getRepository().login(credentials, workspaceName); + } catch (NoSuchWorkspaceException e) { + if (autocreateWorkspaces && workspaceName != null) + session = createWorkspaceAndLogsIn(credentials, workspaceName); + else + throw e; + } + processNewSession(session); + return session; + } + + public Session login() throws LoginException, RepositoryException { + return login(null, null); + } + + public Session login(Credentials credentials) throws LoginException, + RepositoryException { + return login(credentials, null); + } + + public Session login(String workspaceName) throws LoginException, + NoSuchWorkspaceException, RepositoryException { + return login(null, workspaceName); + } + + /** Called after a session has been created, does nothing by default. */ + protected void processNewSession(Session session) { + } + + /** Wraps access to the repository, making sure it is available. */ + protected synchronized Repository getRepository() { +// if (repository == null) { +// throw new ArgeoException("No repository initialized." +// + " Was the init() method called?" +// + " The destroy() method should also" +// + " be called on shutdown."); +// } + return repository; + } + + /** + * Logs in to the default workspace, creates the required workspace, logs + * out, logs in to the required workspace. + */ + protected Session createWorkspaceAndLogsIn(Credentials credentials, + String workspaceName) throws RepositoryException { + if (workspaceName == null) + throw new ArgeoException("No workspace specified."); + Session session = getRepository().login(credentials); + session.getWorkspace().createWorkspace(workspaceName); + session.logout(); + return getRepository().login(credentials, workspaceName); + } + + public boolean isStandardDescriptor(String key) { + return getRepository().isStandardDescriptor(key); + } + + public boolean isSingleValueDescriptor(String key) { + return getRepository().isSingleValueDescriptor(key); + } + + public Value getDescriptorValue(String key) { + return getRepository().getDescriptorValue(key); + } + + public Value[] getDescriptorValues(String key) { + return getRepository().getDescriptorValues(key); + } + + public synchronized void setRepository(Repository repository) { + this.repository = repository; + } + + public void setAutocreateWorkspaces(Boolean autocreateWorkspaces) { + this.autocreateWorkspaces = autocreateWorkspaces; + } + +} diff --git a/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrResourceAdapter.java b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrResourceAdapter.java new file mode 100644 index 000000000..0b1a98cf0 --- /dev/null +++ b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrResourceAdapter.java @@ -0,0 +1,245 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +import javax.jcr.Binary; +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.nodetype.NodeType; +import javax.jcr.version.Version; +import javax.jcr.version.VersionHistory; +import javax.jcr.version.VersionIterator; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; + +/** + * Bridge Spring resources and JCR folder / files semantics (nt:folder / + * nt:file), supporting versioning as well. + */ +public class JcrResourceAdapter { + private final static Log log = LogFactory.getLog(JcrResourceAdapter.class); + + private Session session; + + private Boolean versioning = true; + private String defaultEncoding = "UTF-8"; + + // private String restoreBase = "/.restore"; + + public JcrResourceAdapter() { + } + + public JcrResourceAdapter(Session session) { + this.session = session; + } + + public void mkdirs(String path) { + JcrUtils.mkdirs(session(), path, NodeType.NT_FOLDER, + NodeType.NT_FOLDER, versioning); + } + + public void create(String path, InputStream in, String mimeType) { + try { + if (session().itemExists(path)) { + throw new ArgeoException("Node " + path + " already exists."); + } + + int index = path.lastIndexOf('/'); + String parentPath = path.substring(0, index); + if (parentPath.equals("")) + parentPath = "/"; + String fileName = path.substring(index + 1); + if (!session().itemExists(parentPath)) + throw new ArgeoException("Parent folder of node " + path + + " does not exist: " + parentPath); + + Node folderNode = (Node) session().getItem(parentPath); + Node fileNode = folderNode.addNode(fileName, "nt:file"); + + Node contentNode = fileNode.addNode(Property.JCR_CONTENT, + "nt:resource"); + if (mimeType != null) + contentNode.setProperty(Property.JCR_MIMETYPE, mimeType); + contentNode.setProperty(Property.JCR_ENCODING, defaultEncoding); + Binary binary = session().getValueFactory().createBinary(in); + contentNode.setProperty(Property.JCR_DATA, binary); + JcrUtils.closeQuietly(binary); + Calendar lastModified = Calendar.getInstance(); + // lastModified.setTimeInMillis(file.lastModified()); + contentNode.setProperty(Property.JCR_LAST_MODIFIED, lastModified); + // resNode.addMixin("mix:referenceable"); + + if (versioning) + fileNode.addMixin("mix:versionable"); + + session().save(); + + if (versioning) + session().getWorkspace().getVersionManager() + .checkin(fileNode.getPath()); + + if (log.isDebugEnabled()) + log.debug("Created " + path); + } catch (Exception e) { + throw new ArgeoException("Cannot create node for " + path, e); + } + + } + + public void update(String path, InputStream in) { + try { + + if (!session().itemExists(path)) { + String type = null; + // FIXME: using javax.activation leads to conflict between Java + // 1.5 and 1.6 (since javax.activation was included in Java 1.6) + // String type = new MimetypesFileTypeMap() + // .getContentType(FilenameUtils.getName(path)); + create(path, in, type); + return; + } + + Node fileNode = (Node) session().getItem(path); + Node contentNode = fileNode.getNode(Property.JCR_CONTENT); + if (versioning) + session().getWorkspace().getVersionManager() + .checkout(fileNode.getPath()); + Binary binary = session().getValueFactory().createBinary(in); + contentNode.setProperty(Property.JCR_DATA, binary); + JcrUtils.closeQuietly(binary); + Calendar lastModified = Calendar.getInstance(); + // lastModified.setTimeInMillis(file.lastModified()); + contentNode.setProperty(Property.JCR_LAST_MODIFIED, lastModified); + + session().save(); + if (versioning) + session().getWorkspace().getVersionManager() + .checkin(fileNode.getPath()); + + if (log.isDebugEnabled()) + log.debug("Updated " + path); + } catch (Exception e) { + throw new ArgeoException("Cannot update node " + path, e); + } + } + + public List listVersions(String path) { + if (!versioning) + throw new ArgeoException("Versioning is not activated"); + + try { + List versions = new ArrayList(); + Node fileNode = (Node) session().getItem(path); + VersionHistory history = session().getWorkspace() + .getVersionManager().getVersionHistory(fileNode.getPath()); + for (VersionIterator it = history.getAllVersions(); it.hasNext();) { + Version version = (Version) it.next(); + versions.add(version.getCreated()); + if (log.isTraceEnabled()) { + log.debug(version); + // debug(version); + } + } + return versions; + } catch (Exception e) { + throw new ArgeoException("Cannot list version of node " + path, e); + } + } + + public InputStream retrieve(String path) { + try { + Node node = (Node) session().getItem( + path + "/" + Property.JCR_CONTENT); + Property property = node.getProperty(Property.JCR_DATA); + return property.getBinary().getStream(); + } catch (Exception e) { + throw new ArgeoException("Cannot retrieve " + path, e); + } + } + + public synchronized InputStream retrieve(String path, Integer revision) { + if (!versioning) + throw new ArgeoException("Versioning is not activated"); + + try { + Node fileNode = (Node) session().getItem(path); + VersionHistory history = session().getWorkspace() + .getVersionManager().getVersionHistory(fileNode.getPath()); + int count = 0; + Version version = null; + for (VersionIterator it = history.getAllVersions(); it.hasNext();) { + version = (Version) it.next(); + if (count == revision + 1) { + InputStream in = fromVersion(version); + if (log.isDebugEnabled()) + log.debug("Retrieved " + path + " at revision " + + revision); + return in; + } + count++; + } + } catch (Exception e) { + throw new ArgeoException("Cannot retrieve version " + revision + + " of " + path, e); + } + + throw new ArgeoException("Version " + revision + + " does not exist for node " + path); + } + + protected InputStream fromVersion(Version version) + throws RepositoryException { + Node frozenNode = version.getNode("jcr:frozenNode"); + InputStream in = frozenNode.getNode(Property.JCR_CONTENT) + .getProperty(Property.JCR_DATA).getBinary().getStream(); + return in; + } + + protected Session session() { + return session; + } + + public void setVersioning(Boolean versioning) { + this.versioning = versioning; + } + + public void setDefaultEncoding(String defaultEncoding) { + this.defaultEncoding = defaultEncoding; + } + + protected String fill(Integer number) { + int size = 4; + String str = number.toString(); + for (int i = str.length(); i < size; i++) { + str = "0" + str; + } + return str; + } + + public void setSession(Session session) { + this.session = session; + } + +} diff --git a/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrUrlStreamHandler.java b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrUrlStreamHandler.java new file mode 100644 index 000000000..a77763937 --- /dev/null +++ b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrUrlStreamHandler.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLStreamHandler; + +import javax.jcr.Item; +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.nodetype.NodeType; + +/** URL stream handler able to deal with nt:file node and properties. NOT FINISHED */ +public class JcrUrlStreamHandler extends URLStreamHandler { + private final Session session; + + public JcrUrlStreamHandler(Session session) { + this.session = session; + } + + @Override + protected URLConnection openConnection(final URL u) throws IOException { + // TODO Auto-generated method stub + return new URLConnection(u) { + + @Override + public void connect() throws IOException { + String itemPath = u.getPath(); + try { + if (!session.itemExists(itemPath)) + throw new IOException("No item under " + itemPath); + + Item item = session.getItem(u.getPath()); + if (item.isNode()) { + // this should be a nt:file node + Node node = (Node) item; + if (!node.getPrimaryNodeType().isNodeType( + NodeType.NT_FILE)) + throw new IOException("Node " + node + " is not a " + + NodeType.NT_FILE); + + } else { + Property property = (Property) item; + if(property.getType()==PropertyType.BINARY){ + //Binary binary = property.getBinary(); + + } + } + } catch (RepositoryException e) { + IOException ioe = new IOException( + "Unexpected JCR exception"); + ioe.initCause(e); + throw ioe; + } + } + + @Override + public InputStream getInputStream() throws IOException { + // TODO Auto-generated method stub + return super.getInputStream(); + } + + }; + } + +} diff --git a/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrUtils.java b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrUtils.java new file mode 100644 index 000000000..2176e757c --- /dev/null +++ b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrUtils.java @@ -0,0 +1,1590 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.security.Principal; +import java.text.DateFormat; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collections; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import javax.jcr.Binary; +import javax.jcr.NamespaceRegistry; +import javax.jcr.NoSuchWorkspaceException; +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.Property; +import javax.jcr.PropertyIterator; +import javax.jcr.PropertyType; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.Value; +import javax.jcr.Workspace; +import javax.jcr.nodetype.NodeType; +import javax.jcr.observation.EventListener; +import javax.jcr.query.Query; +import javax.jcr.query.QueryResult; +import javax.jcr.security.AccessControlEntry; +import javax.jcr.security.AccessControlList; +import javax.jcr.security.AccessControlManager; +import javax.jcr.security.AccessControlPolicy; +import javax.jcr.security.AccessControlPolicyIterator; +import javax.jcr.security.Privilege; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; +import org.argeo.ArgeoMonitor; +import org.argeo.util.security.DigestUtils; +import org.argeo.util.security.SimplePrincipal; + +/** Utility methods to simplify common JCR operations. */ +public class JcrUtils implements ArgeoJcrConstants { + + final private static Log log = LogFactory.getLog(JcrUtils.class); + + /** + * Not complete yet. See + * http://www.day.com/specs/jcr/2.0/3_Repository_Model.html#3.2.2%20Local + * %20Names + */ + public final static char[] INVALID_NAME_CHARACTERS = { '/', ':', '[', ']', + '|', '*', /* + * invalid XML chars : + */ + '<', '>', '&' }; + + /** Prevents instantiation */ + private JcrUtils() { + } + + /** + * Queries one single node. + * + * @return one single node or null if none was found + * @throws ArgeoException + * if more than one node was found + */ + public static Node querySingleNode(Query query) { + NodeIterator nodeIterator; + try { + QueryResult queryResult = query.execute(); + nodeIterator = queryResult.getNodes(); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot execute query " + query, e); + } + Node node; + if (nodeIterator.hasNext()) + node = nodeIterator.nextNode(); + else + return null; + + if (nodeIterator.hasNext()) + throw new ArgeoException("Query returned more than one node."); + return node; + } + + /** Retrieves the node name from the provided path */ + public static String nodeNameFromPath(String path) { + if (path.equals("/")) + return ""; + if (path.charAt(0) != '/') + throw new ArgeoException("Path " + path + " must start with a '/'"); + String pathT = path; + if (pathT.charAt(pathT.length() - 1) == '/') + pathT = pathT.substring(0, pathT.length() - 2); + + int index = pathT.lastIndexOf('/'); + return pathT.substring(index + 1); + } + + /** Retrieves the parent path of the provided path */ + public static String parentPath(String path) { + if (path.equals("/")) + throw new ArgeoException("Root path '/' has no parent path"); + if (path.charAt(0) != '/') + throw new ArgeoException("Path " + path + " must start with a '/'"); + String pathT = path; + if (pathT.charAt(pathT.length() - 1) == '/') + pathT = pathT.substring(0, pathT.length() - 2); + + int index = pathT.lastIndexOf('/'); + return pathT.substring(0, index); + } + + /** The provided data as a path ('/' at the end, not the beginning) */ + public static String dateAsPath(Calendar cal) { + return dateAsPath(cal, false); + } + + /** + * Creates a deep path based on a URL: + * http://subdomain.example.com/to/content?args => + * com/example/subdomain/to/content + */ + public static String urlAsPath(String url) { + try { + URL u = new URL(url); + StringBuffer path = new StringBuffer(url.length()); + // invert host + path.append(hostAsPath(u.getHost())); + // we don't put port since it may not always be there and may change + path.append(u.getPath()); + return path.toString(); + } catch (MalformedURLException e) { + throw new ArgeoException("Cannot generate URL path for " + url, e); + } + } + + /** Set the {@link NodeType#NT_ADDRESS} properties based on this URL. */ + public static void urlToAddressProperties(Node node, String url) { + try { + URL u = new URL(url); + node.setProperty(Property.JCR_PROTOCOL, u.getProtocol()); + node.setProperty(Property.JCR_HOST, u.getHost()); + node.setProperty(Property.JCR_PORT, Integer.toString(u.getPort())); + node.setProperty(Property.JCR_PATH, normalizePath(u.getPath())); + } catch (Exception e) { + throw new ArgeoException("Cannot set URL " + url + + " as nt:address properties", e); + } + } + + /** Build URL based on the {@link NodeType#NT_ADDRESS} properties. */ + public static String urlFromAddressProperties(Node node) { + try { + URL u = new URL( + node.getProperty(Property.JCR_PROTOCOL).getString(), node + .getProperty(Property.JCR_HOST).getString(), + (int) node.getProperty(Property.JCR_PORT).getLong(), node + .getProperty(Property.JCR_PATH).getString()); + return u.toString(); + } catch (Exception e) { + throw new ArgeoException( + "Cannot get URL from nt:address properties of " + node, e); + } + } + + /* + * PATH UTILITIES + */ + + /** Make sure that: starts with '/', do not end with '/', do not have '//' */ + public static String normalizePath(String path) { + List tokens = tokenize(path); + StringBuffer buf = new StringBuffer(path.length()); + for (String token : tokens) { + buf.append('/'); + buf.append(token); + } + return buf.toString(); + } + + /** + * Creates a path from a FQDN, inverting the order of the component: + * www.argeo.org => org.argeo.www + */ + public static String hostAsPath(String host) { + StringBuffer path = new StringBuffer(host.length()); + String[] hostTokens = host.split("\\."); + for (int i = hostTokens.length - 1; i >= 0; i--) { + path.append(hostTokens[i]); + if (i != 0) + path.append('/'); + } + return path.toString(); + } + + /** + * Creates a path from a UUID (e.g. 6ebda899-217d-4bf1-abe4-2839085c8f3c => + * 6ebda899-217d/4bf1/abe4/2839085c8f3c/). '/' at the end, not the beginning + */ + public static String uuidAsPath(String uuid) { + StringBuffer path = new StringBuffer(uuid.length()); + String[] tokens = uuid.split("-"); + for (int i = 0; i < tokens.length; i++) { + path.append(tokens[i]); + if (i != 0) + path.append('/'); + } + return path.toString(); + } + + /** + * The provided data as a path ('/' at the end, not the beginning) + * + * @param cal + * the date + * @param addHour + * whether to add hour as well + */ + public static String dateAsPath(Calendar cal, Boolean addHour) { + StringBuffer buf = new StringBuffer(14); + buf.append('Y'); + buf.append(cal.get(Calendar.YEAR)); + buf.append('/'); + + int month = cal.get(Calendar.MONTH) + 1; + buf.append('M'); + if (month < 10) + buf.append(0); + buf.append(month); + buf.append('/'); + + int day = cal.get(Calendar.DAY_OF_MONTH); + buf.append('D'); + if (day < 10) + buf.append(0); + buf.append(day); + buf.append('/'); + + if (addHour) { + int hour = cal.get(Calendar.HOUR_OF_DAY); + buf.append('H'); + if (hour < 10) + buf.append(0); + buf.append(hour); + buf.append('/'); + } + return buf.toString(); + + } + + /** Converts in one call a string into a gregorian calendar. */ + public static Calendar parseCalendar(DateFormat dateFormat, String value) { + try { + Date date = dateFormat.parse(value); + Calendar calendar = new GregorianCalendar(); + calendar.setTime(date); + return calendar; + } catch (ParseException e) { + throw new ArgeoException("Cannot parse " + value + + " with date format " + dateFormat, e); + } + + } + + /** The last element of a path. */ + public static String lastPathElement(String path) { + if (path.charAt(path.length() - 1) == '/') + throw new ArgeoException("Path " + path + " cannot end with '/'"); + int index = path.lastIndexOf('/'); + if (index < 0) + return path; + return path.substring(index + 1); + } + + /** + * Call {@link Node#getName()} without exceptions (useful in super + * constructors). + */ + public static String getNameQuietly(Node node) { + try { + return node.getName(); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot get name from " + node, e); + } + } + + /** + * Call {@link Node#getProperty(String)} without exceptions (useful in super + * constructors). + */ + public static String getStringPropertyQuietly(Node node, String propertyName) { + try { + return node.getProperty(propertyName).getString(); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot get name from " + node, e); + } + } + + /** + * Routine that get the child with this name, adding id it does not already + * exist + */ + public static Node getOrAdd(Node parent, String childName, + String childPrimaryNodeType) throws RepositoryException { + return parent.hasNode(childName) ? parent.getNode(childName) : parent + .addNode(childName, childPrimaryNodeType); + } + + /** + * Routine that get the child with this name, adding id it does not already + * exist + */ + public static Node getOrAdd(Node parent, String childName) + throws RepositoryException { + return parent.hasNode(childName) ? parent.getNode(childName) : parent + .addNode(childName); + } + + /** Convert a {@link NodeIterator} to a list of {@link Node} */ + public static List nodeIteratorToList(NodeIterator nodeIterator) { + List nodes = new ArrayList(); + while (nodeIterator.hasNext()) { + nodes.add(nodeIterator.nextNode()); + } + return nodes; + } + + /* + * PROPERTIES + */ + + /** + * Concisely get the string value of a property or null if this node doesn't + * have this property + */ + public static String get(Node node, String propertyName) { + try { + if (!node.hasProperty(propertyName)) + return null; + return node.getProperty(propertyName).getString(); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot get property " + propertyName + + " of " + node, e); + } + } + + /** Concisely get the boolean value of a property */ + public static Boolean check(Node node, String propertyName) { + try { + return node.getProperty(propertyName).getBoolean(); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot get property " + propertyName + + " of " + node, e); + } + } + + /** Concisely get the bytes array value of a property */ + public static byte[] getBytes(Node node, String propertyName) { + try { + return getBinaryAsBytes(node.getProperty(propertyName)); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot get property " + propertyName + + " of " + node, e); + } + } + + /** Creates the nodes making path, if they don't exist. */ + public static Node mkdirs(Session session, String path) { + return mkdirs(session, path, null, null, false); + } + + /** + * use {@link #mkdirs(Session, String, String, String, Boolean)} instead. + * + * @deprecated + */ + @Deprecated + public static Node mkdirs(Session session, String path, String type, + Boolean versioning) { + return mkdirs(session, path, type, type, false); + } + + /** + * @param type + * the type of the leaf node + */ + public static Node mkdirs(Session session, String path, String type) { + return mkdirs(session, path, type, null, false); + } + + /** + * Create sub nodes relative to a parent node + * + * @param nodeType + * the type of the leaf node + */ + public static Node mkdirs(Node parentNode, String relativePath, + String nodeType) { + return mkdirs(parentNode, relativePath, nodeType, null); + } + + /** + * Create sub nodes relative to a parent node + * + * @param nodeType + * the type of the leaf node + */ + public static Node mkdirs(Node parentNode, String relativePath, + String nodeType, String intermediaryNodeType) { + List tokens = tokenize(relativePath); + Node currParent = parentNode; + try { + for (int i = 0; i < tokens.size(); i++) { + String name = tokens.get(i); + if (currParent.hasNode(name)) { + currParent = currParent.getNode(name); + } else { + if (i != (tokens.size() - 1)) {// intermediary + currParent = currParent.addNode(name, + intermediaryNodeType); + } else {// leaf + currParent = currParent.addNode(name, nodeType); + } + } + } + return currParent; + } catch (RepositoryException e) { + throw new ArgeoException("Cannot mkdirs relative path " + + relativePath + " from " + parentNode, e); + } + } + + /** + * Synchronized and save is performed, to avoid race conditions in + * initializers leading to duplicate nodes. + */ + public synchronized static Node mkdirsSafe(Session session, String path, + String type) { + try { + if (session.hasPendingChanges()) + throw new ArgeoException( + "Session has pending changes, save them first."); + Node node = mkdirs(session, path, type); + session.save(); + return node; + } catch (RepositoryException e) { + discardQuietly(session); + throw new ArgeoException("Cannot safely make directories", e); + } + } + + public synchronized static Node mkdirsSafe(Session session, String path) { + return mkdirsSafe(session, path, null); + } + + /** + * Creates the nodes making path, if they don't exist. This is up to the + * caller to save the session. Use with caution since it can create + * duplicate nodes if used concurrently. + */ + public static Node mkdirs(Session session, String path, String type, + String intermediaryNodeType, Boolean versioning) { + try { + if (path.equals('/')) + return session.getRootNode(); + + if (session.itemExists(path)) { + Node node = session.getNode(path); + // check type + if (type != null && !node.isNodeType(type) + && !node.getPath().equals("/")) + throw new ArgeoException("Node " + node + + " exists but is of type " + + node.getPrimaryNodeType().getName() + + " not of type " + type); + // TODO: check versioning + return node; + } + + StringBuffer current = new StringBuffer("/"); + Node currentNode = session.getRootNode(); + Iterator it = tokenize(path).iterator(); + while (it.hasNext()) { + String part = it.next(); + current.append(part).append('/'); + if (!session.itemExists(current.toString())) { + if (!it.hasNext() && type != null) + currentNode = currentNode.addNode(part, type); + else if (it.hasNext() && intermediaryNodeType != null) + currentNode = currentNode.addNode(part, + intermediaryNodeType); + else + currentNode = currentNode.addNode(part); + if (versioning) + currentNode.addMixin(NodeType.MIX_VERSIONABLE); + if (log.isTraceEnabled()) + log.debug("Added folder " + part + " as " + current); + } else { + currentNode = (Node) session.getItem(current.toString()); + } + } + return currentNode; + } catch (RepositoryException e) { + discardQuietly(session); + throw new ArgeoException("Cannot mkdirs " + path, e); + } finally { + } + } + + /** Convert a path to the list of its tokens */ + public static List tokenize(String path) { + List tokens = new ArrayList(); + boolean optimized = false; + if (!optimized) { + String[] rawTokens = path.split("/"); + for (String token : rawTokens) { + if (!token.equals("")) + tokens.add(token); + } + } else { + StringBuffer curr = new StringBuffer(); + char[] arr = path.toCharArray(); + chars: for (int i = 0; i < arr.length; i++) { + char c = arr[i]; + if (c == '/') { + if (i == 0 || (i == arr.length - 1)) + continue chars; + if (curr.length() > 0) { + tokens.add(curr.toString()); + curr = new StringBuffer(); + } + } else + curr.append(c); + } + if (curr.length() > 0) { + tokens.add(curr.toString()); + curr = new StringBuffer(); + } + } + return Collections.unmodifiableList(tokens); + } + + /** + * Safe and repository implementation independent registration of a + * namespace. + */ + public static void registerNamespaceSafely(Session session, String prefix, + String uri) { + try { + registerNamespaceSafely(session.getWorkspace() + .getNamespaceRegistry(), prefix, uri); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot find namespace registry", e); + } + } + + /** + * Safe and repository implementation independent registration of a + * namespace. + */ + public static void registerNamespaceSafely(NamespaceRegistry nr, + String prefix, String uri) { + try { + String[] prefixes = nr.getPrefixes(); + for (String pref : prefixes) + if (pref.equals(prefix)) { + String registeredUri = nr.getURI(pref); + if (!registeredUri.equals(uri)) + throw new ArgeoException("Prefix " + pref + + " already registered for URI " + + registeredUri + + " which is different from provided URI " + + uri); + else + return;// skip + } + nr.registerNamespace(prefix, uri); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot register namespace " + uri + + " under prefix " + prefix, e); + } + } + + /** Recursively outputs the contents of the given node. */ + public static void debug(Node node) { + debug(node, log); + } + + /** Recursively outputs the contents of the given node. */ + public static void debug(Node node, Log log) { + try { + // First output the node path + log.debug(node.getPath()); + // Skip the virtual (and large!) jcr:system subtree + if (node.getName().equals("jcr:system")) { + return; + } + + // Then the children nodes (recursive) + NodeIterator it = node.getNodes(); + while (it.hasNext()) { + Node childNode = it.nextNode(); + debug(childNode, log); + } + + // Then output the properties + PropertyIterator properties = node.getProperties(); + // log.debug("Property are : "); + + properties: while (properties.hasNext()) { + Property property = properties.nextProperty(); + if (property.getType() == PropertyType.BINARY) + continue properties;// skip + if (property.getDefinition().isMultiple()) { + // A multi-valued property, print all values + Value[] values = property.getValues(); + for (int i = 0; i < values.length; i++) { + log.debug(property.getPath() + "=" + + values[i].getString()); + } + } else { + // A single-valued property + log.debug(property.getPath() + "=" + property.getString()); + } + } + } catch (Exception e) { + log.error("Could not debug " + node, e); + } + + } + + /** Logs the effective access control policies */ + public static void logEffectiveAccessPolicies(Node node) { + try { + logEffectiveAccessPolicies(node.getSession(), node.getPath()); + } catch (RepositoryException e) { + log.error("Cannot log effective access policies of " + node, e); + } + } + + /** Logs the effective access control policies */ + public static void logEffectiveAccessPolicies(Session session, String path) { + if (!log.isDebugEnabled()) + return; + + try { + AccessControlPolicy[] effectivePolicies = session + .getAccessControlManager().getEffectivePolicies(path); + if (effectivePolicies.length > 0) { + for (AccessControlPolicy policy : effectivePolicies) { + if (policy instanceof AccessControlList) { + AccessControlList acl = (AccessControlList) policy; + log.debug("Access control list for " + path + "\n" + + accessControlListSummary(acl)); + } + } + } else { + log.debug("No effective access control policy for " + path); + } + } catch (RepositoryException e) { + log.error("Cannot log effective access policies of " + path, e); + } + } + + /** Returns a human-readable summary of this access control list. */ + public static String accessControlListSummary(AccessControlList acl) { + StringBuffer buf = new StringBuffer(""); + try { + for (AccessControlEntry ace : acl.getAccessControlEntries()) { + buf.append('\t').append(ace.getPrincipal().getName()) + .append('\n'); + for (Privilege priv : ace.getPrivileges()) + buf.append("\t\t").append(priv.getName()).append('\n'); + } + return buf.toString(); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot write summary of " + acl, e); + } + } + + /** + * Copies recursively the content of a node to another one. Do NOT copy the + * property values of {@link NodeType#MIX_CREATED} and + * {@link NodeType#MIX_LAST_MODIFIED}, but update the + * {@link Property#JCR_LAST_MODIFIED} and + * {@link Property#JCR_LAST_MODIFIED_BY} properties if the target node has + * the {@link NodeType#MIX_LAST_MODIFIED} mixin. + */ + public static void copy(Node fromNode, Node toNode) { + try { + if (toNode.getDefinition().isProtected()) + return; + + // process properties + PropertyIterator pit = fromNode.getProperties(); + properties: while (pit.hasNext()) { + Property fromProperty = pit.nextProperty(); + String propertyName = fromProperty.getName(); + if (toNode.hasProperty(propertyName) + && toNode.getProperty(propertyName).getDefinition() + .isProtected()) + continue properties; + + if (fromProperty.getDefinition().isProtected()) + continue properties; + + if (propertyName.equals("jcr:created") + || propertyName.equals("jcr:createdBy") + || propertyName.equals("jcr:lastModified") + || propertyName.equals("jcr:lastModifiedBy")) + continue properties; + + if (fromProperty.isMultiple()) { + toNode.setProperty(propertyName, fromProperty.getValues()); + } else { + toNode.setProperty(propertyName, fromProperty.getValue()); + } + } + + // update jcr:lastModified and jcr:lastModifiedBy in toNode in case + // they existed, before adding the mixins + updateLastModified(toNode); + + // add mixins + for (NodeType mixinType : fromNode.getMixinNodeTypes()) { + toNode.addMixin(mixinType.getName()); + } + + // process children nodes + NodeIterator nit = fromNode.getNodes(); + while (nit.hasNext()) { + Node fromChild = nit.nextNode(); + Integer index = fromChild.getIndex(); + String nodeRelPath = fromChild.getName() + "[" + index + "]"; + Node toChild; + if (toNode.hasNode(nodeRelPath)) + toChild = toNode.getNode(nodeRelPath); + else + toChild = toNode.addNode(fromChild.getName(), fromChild + .getPrimaryNodeType().getName()); + copy(fromChild, toChild); + } + } catch (RepositoryException e) { + throw new ArgeoException("Cannot copy " + fromNode + " to " + + toNode, e); + } + } + + /** + * Check whether all first-level properties (except jcr:* properties) are + * equal. Skip jcr:* properties + */ + public static Boolean allPropertiesEquals(Node reference, Node observed, + Boolean onlyCommonProperties) { + try { + PropertyIterator pit = reference.getProperties(); + props: while (pit.hasNext()) { + Property propReference = pit.nextProperty(); + String propName = propReference.getName(); + if (propName.startsWith("jcr:")) + continue props; + + if (!observed.hasProperty(propName)) + if (onlyCommonProperties) + continue props; + else + return false; + // TODO: deal with multiple property values? + if (!observed.getProperty(propName).getValue() + .equals(propReference.getValue())) + return false; + } + return true; + } catch (RepositoryException e) { + throw new ArgeoException("Cannot check all properties equals of " + + reference + " and " + observed, e); + } + } + + public static Map diffProperties(Node reference, + Node observed) { + Map diffs = new TreeMap(); + diffPropertiesLevel(diffs, null, reference, observed); + return diffs; + } + + /** + * Compare the properties of two nodes. Recursivity to child nodes is not + * yet supported. Skip jcr:* properties. + */ + static void diffPropertiesLevel(Map diffs, + String baseRelPath, Node reference, Node observed) { + try { + // check removed and modified + PropertyIterator pit = reference.getProperties(); + props: while (pit.hasNext()) { + Property p = pit.nextProperty(); + String name = p.getName(); + if (name.startsWith("jcr:")) + continue props; + + if (!observed.hasProperty(name)) { + String relPath = propertyRelPath(baseRelPath, name); + PropertyDiff pDiff = new PropertyDiff(PropertyDiff.REMOVED, + relPath, p.getValue(), null); + diffs.put(relPath, pDiff); + } else { + if (p.isMultiple()) { + // FIXME implement multiple + } else { + Value referenceValue = p.getValue(); + Value newValue = observed.getProperty(name).getValue(); + if (!referenceValue.equals(newValue)) { + String relPath = propertyRelPath(baseRelPath, name); + PropertyDiff pDiff = new PropertyDiff( + PropertyDiff.MODIFIED, relPath, + referenceValue, newValue); + diffs.put(relPath, pDiff); + } + } + } + } + // check added + pit = observed.getProperties(); + props: while (pit.hasNext()) { + Property p = pit.nextProperty(); + String name = p.getName(); + if (name.startsWith("jcr:")) + continue props; + if (!reference.hasProperty(name)) { + if (p.isMultiple()) { + // FIXME implement multiple + } else { + String relPath = propertyRelPath(baseRelPath, name); + PropertyDiff pDiff = new PropertyDiff( + PropertyDiff.ADDED, relPath, null, p.getValue()); + diffs.put(relPath, pDiff); + } + } + } + } catch (RepositoryException e) { + throw new ArgeoException("Cannot diff " + reference + " and " + + observed, e); + } + } + + /** + * Compare only a restricted list of properties of two nodes. No + * recursivity. + * + */ + public static Map diffProperties(Node reference, + Node observed, List properties) { + Map diffs = new TreeMap(); + try { + Iterator pit = properties.iterator(); + + props: while (pit.hasNext()) { + String name = pit.next(); + if (!reference.hasProperty(name)) { + if (!observed.hasProperty(name)) + continue props; + Value val = observed.getProperty(name).getValue(); + try { + // empty String but not null + if ("".equals(val.getString())) + continue props; + } catch (Exception e) { + // not parseable as String, silent + } + PropertyDiff pDiff = new PropertyDiff(PropertyDiff.ADDED, + name, null, val); + diffs.put(name, pDiff); + } else if (!observed.hasProperty(name)) { + PropertyDiff pDiff = new PropertyDiff(PropertyDiff.REMOVED, + name, reference.getProperty(name).getValue(), null); + diffs.put(name, pDiff); + } else { + Value referenceValue = reference.getProperty(name) + .getValue(); + Value newValue = observed.getProperty(name).getValue(); + if (!referenceValue.equals(newValue)) { + PropertyDiff pDiff = new PropertyDiff( + PropertyDiff.MODIFIED, name, referenceValue, + newValue); + diffs.put(name, pDiff); + } + } + } + } catch (RepositoryException e) { + throw new ArgeoException("Cannot diff " + reference + " and " + + observed, e); + } + return diffs; + } + + /** Builds a property relPath to be used in the diff. */ + private static String propertyRelPath(String baseRelPath, + String propertyName) { + if (baseRelPath == null) + return propertyName; + else + return baseRelPath + '/' + propertyName; + } + + /** + * Normalizes a name so that it can be stored in contexts not supporting + * names with ':' (typically databases). Replaces ':' by '_'. + */ + public static String normalize(String name) { + return name.replace(':', '_'); + } + + /** + * Replaces characters which are invalid in a JCR name by '_'. Currently not + * exhaustive. + * + * @see JcrUtils#INVALID_NAME_CHARACTERS + */ + public static String replaceInvalidChars(String name) { + return replaceInvalidChars(name, '_'); + } + + /** + * Replaces characters which are invalid in a JCR name. Currently not + * exhaustive. + * + * @see JcrUtils#INVALID_NAME_CHARACTERS + */ + public static String replaceInvalidChars(String name, char replacement) { + boolean modified = false; + char[] arr = name.toCharArray(); + for (int i = 0; i < arr.length; i++) { + char c = arr[i]; + invalid: for (char invalid : INVALID_NAME_CHARACTERS) { + if (c == invalid) { + arr[i] = replacement; + modified = true; + break invalid; + } + } + } + if (modified) + return new String(arr); + else + // do not create new object if unnecessary + return name; + } + + /** + * Removes forbidden characters from a path, replacing them with '_' + * + * @deprecated use {@link #replaceInvalidChars(String)} instead + */ + public static String removeForbiddenCharacters(String str) { + return str.replace('[', '_').replace(']', '_').replace('/', '_') + .replace('*', '_'); + + } + + /** Cleanly disposes a {@link Binary} even if it is null. */ + public static void closeQuietly(Binary binary) { + if (binary == null) + return; + binary.dispose(); + } + + /** Retrieve a {@link Binary} as a byte array */ + public static byte[] getBinaryAsBytes(Property property) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + InputStream in = null; + Binary binary = null; + try { + binary = property.getBinary(); + in = binary.getStream(); + IOUtils.copy(in, out); + return out.toByteArray(); + } catch (Exception e) { + throw new ArgeoException("Cannot read binary " + property + + " as bytes", e); + } finally { + IOUtils.closeQuietly(out); + IOUtils.closeQuietly(in); + closeQuietly(binary); + } + } + + /** Writes a {@link Binary} from a byte array */ + public static void setBinaryAsBytes(Node node, String property, byte[] bytes) { + InputStream in = null; + Binary binary = null; + try { + in = new ByteArrayInputStream(bytes); + binary = node.getSession().getValueFactory().createBinary(in); + node.setProperty(property, binary); + } catch (Exception e) { + throw new ArgeoException("Cannot read binary " + property + + " as bytes", e); + } finally { + IOUtils.closeQuietly(in); + closeQuietly(binary); + } + } + + /** + * Creates depth from a string (typically a username) by adding levels based + * on its first characters: "aBcD",2 => a/aB + */ + public static String firstCharsToPath(String str, Integer nbrOfChars) { + if (str.length() < nbrOfChars) + throw new ArgeoException("String " + str + + " length must be greater or equal than " + nbrOfChars); + StringBuffer path = new StringBuffer(""); + StringBuffer curr = new StringBuffer(""); + for (int i = 0; i < nbrOfChars; i++) { + curr.append(str.charAt(i)); + path.append(curr); + if (i < nbrOfChars - 1) + path.append('/'); + } + return path.toString(); + } + + /** + * Discards the current changes in the session attached to this node. To be + * used typically in a catch block. + * + * @see #discardQuietly(Session) + */ + public static void discardUnderlyingSessionQuietly(Node node) { + try { + discardQuietly(node.getSession()); + } catch (RepositoryException e) { + log.warn("Cannot quietly discard session of node " + node + ": " + + e.getMessage()); + } + } + + /** + * Discards the current changes in a session by calling + * {@link Session#refresh(boolean)} with false, only logging + * potential errors when doing so. To be used typically in a catch block. + */ + public static void discardQuietly(Session session) { + try { + if (session != null) + session.refresh(false); + } catch (RepositoryException e) { + log.warn("Cannot quietly discard session " + session + ": " + + e.getMessage()); + } + } + + /** + * Login to a workspace with implicit credentials, creates the workspace + * with these credentials if it does not already exist. + */ + public static Session loginOrCreateWorkspace(Repository repository, + String workspaceName) throws RepositoryException { + Session workspaceSession = null; + Session defaultSession = null; + try { + try { + workspaceSession = repository.login(workspaceName); + } catch (NoSuchWorkspaceException e) { + // try to create workspace + defaultSession = repository.login(); + defaultSession.getWorkspace().createWorkspace(workspaceName); + workspaceSession = repository.login(workspaceName); + } + return workspaceSession; + } finally { + logoutQuietly(defaultSession); + } + } + + /** Logs out the session, not throwing any exception, even if it is null. */ + public static void logoutQuietly(Session session) { + try { + if (session != null) + if (session.isLive()) + session.logout(); + } catch (Exception e) { + // silent + } + } + + /** + * Convenient method to add a listener. uuids passed as null, deep=true, + * local=true, only one node type + */ + public static void addListener(Session session, EventListener listener, + int eventTypes, String basePath, String nodeType) { + try { + session.getWorkspace() + .getObservationManager() + .addEventListener( + listener, + eventTypes, + basePath, + true, + null, + nodeType == null ? null : new String[] { nodeType }, + true); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot add JCR listener " + listener + + " to session " + session, e); + } + } + + /** Removes a listener without throwing exception */ + public static void removeListenerQuietly(Session session, + EventListener listener) { + if (session == null || !session.isLive()) + return; + try { + session.getWorkspace().getObservationManager() + .removeEventListener(listener); + } catch (RepositoryException e) { + // silent + } + } + + /** + * Quietly unregisters an {@link EventListener} from the udnerlying + * workspace of this node. + */ + public static void unregisterQuietly(Node node, EventListener eventListener) { + try { + unregisterQuietly(node.getSession().getWorkspace(), eventListener); + } catch (RepositoryException e) { + // silent + if (log.isTraceEnabled()) + log.trace("Could not unregister event listener " + + eventListener); + } + } + + /** Quietly unregisters an {@link EventListener} from this workspace */ + public static void unregisterQuietly(Workspace workspace, + EventListener eventListener) { + if (eventListener == null) + return; + try { + workspace.getObservationManager() + .removeEventListener(eventListener); + } catch (RepositoryException e) { + // silent + if (log.isTraceEnabled()) + log.trace("Could not unregister event listener " + + eventListener); + } + } + + /** + * If this node is has the {@link NodeType#MIX_LAST_MODIFIED} mixin, it + * updates the {@link Property#JCR_LAST_MODIFIED} property with the current + * time and the {@link Property#JCR_LAST_MODIFIED_BY} property with the + * underlying session user id. In Jackrabbit 2.x, these properties + * are not automatically updated, hence the need for manual update. The + * session is not saved. + */ + public static void updateLastModified(Node node) { + try { + if (!node.isNodeType(NodeType.MIX_LAST_MODIFIED)) + node.addMixin(NodeType.MIX_LAST_MODIFIED); + node.setProperty(Property.JCR_LAST_MODIFIED, + new GregorianCalendar()); + node.setProperty(Property.JCR_LAST_MODIFIED_BY, node.getSession() + .getUserID()); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot update last modified on " + node, + e); + } + } + + /** + * Update lastModified recursively until this parent. + * + * @param node + * the node + * @param untilPath + * the base path, null is equivalent to "/" + */ + public static void updateLastModifiedAndParents(Node node, String untilPath) { + try { + if (untilPath != null && !node.getPath().startsWith(untilPath)) + throw new ArgeoException(node + " is not under " + untilPath); + updateLastModified(node); + if (untilPath == null) { + if (!node.getPath().equals("/")) + updateLastModifiedAndParents(node.getParent(), untilPath); + } else { + if (!node.getPath().equals(untilPath)) + updateLastModifiedAndParents(node.getParent(), untilPath); + } + } catch (RepositoryException e) { + throw new ArgeoException("Cannot update lastModified from " + node + + " until " + untilPath, e); + } + } + + /** + * Returns a String representing the short version (see Node type + * Notation attributes grammar) of the main business attributes of this + * property definition + * + * @param prop + */ + public static String getPropertyDefinitionAsString(Property prop) { + StringBuffer sbuf = new StringBuffer(); + try { + if (prop.getDefinition().isAutoCreated()) + sbuf.append("a"); + if (prop.getDefinition().isMandatory()) + sbuf.append("m"); + if (prop.getDefinition().isProtected()) + sbuf.append("p"); + if (prop.getDefinition().isMultiple()) + sbuf.append("*"); + } catch (RepositoryException re) { + throw new ArgeoException( + "unexpected error while getting property definition as String", + re); + } + return sbuf.toString(); + } + + /** + * Estimate the sub tree size from current node. Computation is based on the + * Jcr {@link Property.getLength()} method. Note : it is not the exact size + * used on the disk by the current part of the JCR Tree. + */ + + public static long getNodeApproxSize(Node node) { + long curNodeSize = 0; + try { + PropertyIterator pi = node.getProperties(); + while (pi.hasNext()) { + Property prop = pi.nextProperty(); + if (prop.isMultiple()) { + int nb = prop.getLengths().length; + for (int i = 0; i < nb; i++) { + curNodeSize += (prop.getLengths()[i] > 0 ? prop + .getLengths()[i] : 0); + } + } else + curNodeSize += (prop.getLength() > 0 ? prop.getLength() : 0); + } + + NodeIterator ni = node.getNodes(); + while (ni.hasNext()) + curNodeSize += getNodeApproxSize(ni.nextNode()); + return curNodeSize; + } catch (RepositoryException re) { + throw new ArgeoException( + "Unexpected error while recursively determining node size.", + re); + } + } + + /* + * SECURITY + */ + + /** + * Convenience method for adding a single privilege to a principal (user or + * role), typically jcr:all + */ + public synchronized static void addPrivilege(Session session, String path, + String principal, String privilege) throws RepositoryException { + List privileges = new ArrayList(); + privileges.add(session.getAccessControlManager().privilegeFromName( + privilege)); + addPrivileges(session, path, new SimplePrincipal(principal), privileges); + } + + /** + * Add privileges on a path to a {@link Principal}. The path must already + * exist. Session is saved. Synchronized to prevent concurrent modifications + * of the same node. + */ + public synchronized static Boolean addPrivileges(Session session, + String path, Principal principal, List privs) + throws RepositoryException { + // make sure the session is in line with the persisted state + session.refresh(false); + AccessControlManager acm = session.getAccessControlManager(); + AccessControlList acl = getAccessControlList(acm, path); + + accessControlEntries: for (AccessControlEntry ace : acl + .getAccessControlEntries()) { + Principal currentPrincipal = ace.getPrincipal(); + if (currentPrincipal.getName().equals(principal.getName())) { + Privilege[] currentPrivileges = ace.getPrivileges(); + if (currentPrivileges.length != privs.size()) + break accessControlEntries; + for (int i = 0; i < currentPrivileges.length; i++) { + Privilege currP = currentPrivileges[i]; + Privilege p = privs.get(i); + if (!currP.getName().equals(p.getName())) { + break accessControlEntries; + } + } + return false; + } + } + + Privilege[] privileges = privs.toArray(new Privilege[privs.size()]); + acl.addAccessControlEntry(principal, privileges); + acm.setPolicy(path, acl); + if (log.isDebugEnabled()) { + StringBuffer privBuf = new StringBuffer(); + for (Privilege priv : privs) + privBuf.append(priv.getName()); + log.debug("Added privileges " + privBuf + " to " + + principal.getName() + " on " + path + " in '" + + session.getWorkspace().getName() + "'"); + } + session.refresh(true); + session.save(); + return true; + } + + /** Gets access control list for this path, throws exception if not found */ + public synchronized static AccessControlList getAccessControlList( + AccessControlManager acm, String path) throws RepositoryException { + // search for an access control list + AccessControlList acl = null; + AccessControlPolicyIterator policyIterator = acm + .getApplicablePolicies(path); + if (policyIterator.hasNext()) { + while (policyIterator.hasNext()) { + AccessControlPolicy acp = policyIterator + .nextAccessControlPolicy(); + if (acp instanceof AccessControlList) + acl = ((AccessControlList) acp); + } + } else { + AccessControlPolicy[] existingPolicies = acm.getPolicies(path); + for (AccessControlPolicy acp : existingPolicies) { + if (acp instanceof AccessControlList) + acl = ((AccessControlList) acp); + } + } + if (acl != null) + return acl; + else + throw new ArgeoException("ACL not found at " + path); + } + + /** Clear authorizations for a user at this path */ + public synchronized static void clearAccessControList(Session session, + String path, String username) throws RepositoryException { + AccessControlManager acm = session.getAccessControlManager(); + AccessControlList acl = getAccessControlList(acm, path); + for (AccessControlEntry ace : acl.getAccessControlEntries()) { + if (ace.getPrincipal().getName().equals(username)) { + acl.removeAccessControlEntry(ace); + } + } + } + + /* + * FILES UTILITIES + */ + /** + * Creates the nodes making the path as {@link NodeType#NT_FOLDER} + */ + public static Node mkfolders(Session session, String path) { + return mkdirs(session, path, NodeType.NT_FOLDER, NodeType.NT_FOLDER, + false); + } + + /** + * Copy only nt:folder and nt:file, without their additional types and + * properties. + * + * @param recursive + * if true copies folders as well, otherwise only first level + * files + * @return how many files were copied + */ + @SuppressWarnings("resource") + public static Long copyFiles(Node fromNode, Node toNode, Boolean recursive, + ArgeoMonitor monitor) { + long count = 0l; + + Binary binary = null; + InputStream in = null; + try { + NodeIterator fromChildren = fromNode.getNodes(); + while (fromChildren.hasNext()) { + if (monitor != null && monitor.isCanceled()) + throw new ArgeoException( + "Copy cancelled before it was completed"); + + Node fromChild = fromChildren.nextNode(); + String fileName = fromChild.getName(); + if (fromChild.isNodeType(NodeType.NT_FILE)) { + if (monitor != null) + monitor.subTask("Copy " + fileName); + binary = fromChild.getNode(Node.JCR_CONTENT) + .getProperty(Property.JCR_DATA).getBinary(); + in = binary.getStream(); + copyStreamAsFile(toNode, fileName, in); + IOUtils.closeQuietly(in); + closeQuietly(binary); + + // save session + toNode.getSession().save(); + count++; + + if (log.isDebugEnabled()) + log.debug("Copied file " + fromChild.getPath()); + if (monitor != null) + monitor.worked(1); + } else if (fromChild.isNodeType(NodeType.NT_FOLDER) + && recursive) { + Node toChildFolder; + if (toNode.hasNode(fileName)) { + toChildFolder = toNode.getNode(fileName); + if (!toChildFolder.isNodeType(NodeType.NT_FOLDER)) + throw new ArgeoException(toChildFolder + + " is not of type nt:folder"); + } else { + toChildFolder = toNode.addNode(fileName, + NodeType.NT_FOLDER); + + // save session + toNode.getSession().save(); + } + count = count + + copyFiles(fromChild, toChildFolder, recursive, + monitor); + } + } + return count; + } catch (RepositoryException e) { + throw new ArgeoException("Cannot copy files between " + fromNode + + " and " + toNode); + } finally { + // in case there was an exception + IOUtils.closeQuietly(in); + closeQuietly(binary); + } + } + + /** + * Iteratively count all file nodes in subtree, inefficient but can be + * useful when query are poorly supported, such as in remoting. + */ + public static Long countFiles(Node node) { + Long localCount = 0l; + try { + for (NodeIterator nit = node.getNodes(); nit.hasNext();) { + Node child = nit.nextNode(); + if (child.isNodeType(NodeType.NT_FOLDER)) + localCount = localCount + countFiles(child); + else if (child.isNodeType(NodeType.NT_FILE)) + localCount = localCount + 1; + } + } catch (RepositoryException e) { + throw new ArgeoException("Cannot count all children of " + node); + } + return localCount; + } + + /** + * Copy a file as an nt:file, assuming an nt:folder hierarchy. The session + * is NOT saved. + * + * @return the created file node + */ + public static Node copyFile(Node folderNode, File file) { + InputStream in = null; + try { + in = new FileInputStream(file); + return copyStreamAsFile(folderNode, file.getName(), in); + } catch (IOException e) { + throw new ArgeoException("Cannot copy file " + file + " under " + + folderNode, e); + } finally { + IOUtils.closeQuietly(in); + } + } + + /** Copy bytes as an nt:file */ + public static Node copyBytesAsFile(Node folderNode, String fileName, + byte[] bytes) { + InputStream in = null; + try { + in = new ByteArrayInputStream(bytes); + return copyStreamAsFile(folderNode, fileName, in); + } catch (Exception e) { + throw new ArgeoException("Cannot copy file " + fileName + " under " + + folderNode, e); + } finally { + IOUtils.closeQuietly(in); + } + } + + /** + * Copy a stream as an nt:file, assuming an nt:folder hierarchy. The session + * is NOT saved. + * + * @return the created file node + */ + public static Node copyStreamAsFile(Node folderNode, String fileName, + InputStream in) { + Binary binary = null; + try { + Node fileNode; + Node contentNode; + if (folderNode.hasNode(fileName)) { + fileNode = folderNode.getNode(fileName); + if (!fileNode.isNodeType(NodeType.NT_FILE)) + throw new ArgeoException(fileNode + + " is not of type nt:file"); + // we assume that the content node is already there + contentNode = fileNode.getNode(Node.JCR_CONTENT); + } else { + fileNode = folderNode.addNode(fileName, NodeType.NT_FILE); + contentNode = fileNode.addNode(Node.JCR_CONTENT, + NodeType.NT_RESOURCE); + } + binary = contentNode.getSession().getValueFactory() + .createBinary(in); + contentNode.setProperty(Property.JCR_DATA, binary); + return fileNode; + } catch (Exception e) { + throw new ArgeoException("Cannot create file node " + fileName + + " under " + folderNode, e); + } finally { + closeQuietly(binary); + } + } + + /** Computes the checksum of an nt:file */ + public static String checksumFile(Node fileNode, String algorithm) { + Binary data = null; + InputStream in = null; + try { + data = fileNode.getNode(Node.JCR_CONTENT) + .getProperty(Property.JCR_DATA).getBinary(); + in = data.getStream(); + return DigestUtils.digest(algorithm, in); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot checksum file " + fileNode, e); + } finally { + IOUtils.closeQuietly(in); + closeQuietly(data); + } + } + +} diff --git a/org.argeo.server.jcr/src/main/java/org/argeo/jcr/MaintainedRepository.java b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/MaintainedRepository.java new file mode 100644 index 000000000..702d47a5c --- /dev/null +++ b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/MaintainedRepository.java @@ -0,0 +1,8 @@ +package org.argeo.jcr; + +import javax.jcr.Repository; + +/** Abstracts maintenance operations on a {@link Repository} */ +public interface MaintainedRepository extends Repository { + +} diff --git a/org.argeo.server.jcr/src/main/java/org/argeo/jcr/NodeMapper.java b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/NodeMapper.java new file mode 100644 index 000000000..af792c3ca --- /dev/null +++ b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/NodeMapper.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr; + +import javax.jcr.Node; +import javax.jcr.Session; + +public interface NodeMapper { + public Object load(Node node); + + public void update(Node node, Object obj); + + public Node save(Session session, String path, Object obj); + + public void setNodeMapperProvider(NodeMapperProvider nmp); +} diff --git a/org.argeo.server.jcr/src/main/java/org/argeo/jcr/NodeMapperProvider.java b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/NodeMapperProvider.java new file mode 100644 index 000000000..07e623bfd --- /dev/null +++ b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/NodeMapperProvider.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr; + +import javax.jcr.Node; + +/** Provides a node mapper relevant for this node. */ +public interface NodeMapperProvider { + + /** + * Node Mapper is chosen regarding the Jcr path of the node parameter + * @param Node node + * @return the node mapper or null if no relevant node mapper can be found. */ + public NodeMapper findNodeMapper(Node node); +} diff --git a/org.argeo.server.jcr/src/main/java/org/argeo/jcr/PropertyDiff.java b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/PropertyDiff.java new file mode 100644 index 000000000..bdd316f31 --- /dev/null +++ b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/PropertyDiff.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr; + +import javax.jcr.Value; + +import org.argeo.ArgeoException; + +/** The result of the comparison of two JCR properties. */ +public class PropertyDiff { + public final static Integer MODIFIED = 0; + public final static Integer ADDED = 1; + public final static Integer REMOVED = 2; + + private final Integer type; + private final String relPath; + private final Value referenceValue; + private final Value newValue; + + public PropertyDiff(Integer type, String relPath, Value referenceValue, + Value newValue) { + super(); + + if (type == MODIFIED) { + if (referenceValue == null || newValue == null) + throw new ArgeoException( + "Reference and new values must be specified."); + } else if (type == ADDED) { + if (referenceValue != null || newValue == null) + throw new ArgeoException( + "New value and only it must be specified."); + } else if (type == REMOVED) { + if (referenceValue == null || newValue != null) + throw new ArgeoException( + "Reference value and only it must be specified."); + } else { + throw new ArgeoException("Unkown diff type " + type); + } + + if (relPath == null) + throw new ArgeoException("Relative path must be specified"); + + this.type = type; + this.relPath = relPath; + this.referenceValue = referenceValue; + this.newValue = newValue; + } + + public Integer getType() { + return type; + } + + public String getRelPath() { + return relPath; + } + + public Value getReferenceValue() { + return referenceValue; + } + + public Value getNewValue() { + return newValue; + } + +} diff --git a/org.argeo.server.jcr/src/main/java/org/argeo/jcr/RepositoryRegister.java b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/RepositoryRegister.java new file mode 100644 index 000000000..2e3d4550d --- /dev/null +++ b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/RepositoryRegister.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr; + +import java.util.Map; + +import javax.jcr.Repository; +import javax.jcr.RepositoryFactory; + +/** Allows to register repositories by name. */ +public interface RepositoryRegister extends RepositoryFactory { + /** + * The registered {@link Repository} as a read-only map. Note that this + * method should be called for each access in order to be sure to be up to + * date in case repositories have registered/unregistered + */ + public Map getRepositories(); +} diff --git a/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ThreadBoundJcrSessionFactory.java b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ThreadBoundJcrSessionFactory.java new file mode 100644 index 000000000..193f22c48 --- /dev/null +++ b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ThreadBoundJcrSessionFactory.java @@ -0,0 +1,304 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.jcr.LoginException; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.SimpleCredentials; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; + +/** Proxy JCR sessions and attach them to calling threads. */ +public abstract class ThreadBoundJcrSessionFactory { + private final static Log log = LogFactory + .getLog(ThreadBoundJcrSessionFactory.class); + + private Repository repository; + /** can be injected as list, only used if repository is null */ + private List repositories; + + private ThreadLocal session = new ThreadLocal(); + private final Session proxiedSession; + /** If workspace is null, default will be used. */ + private String workspace = null; + + private String defaultUsername = "demo"; + private String defaultPassword = "demo"; + private Boolean forceDefaultCredentials = false; + + private boolean active = true; + + // monitoring + private final List threads = Collections + .synchronizedList(new ArrayList()); + private final Map activeSessions = Collections + .synchronizedMap(new HashMap()); + private MonitoringThread monitoringThread; + + public ThreadBoundJcrSessionFactory() { + Class[] interfaces = { Session.class }; + proxiedSession = (Session) Proxy.newProxyInstance( + ThreadBoundJcrSessionFactory.class.getClassLoader(), + interfaces, new JcrSessionInvocationHandler()); + } + + /** Logs in to the repository using various strategies. */ + protected synchronized Session login() { + if (!isActive()) + throw new ArgeoException("Thread bound session factory inactive"); + + // discard session previously attached to this thread + Thread thread = Thread.currentThread(); + if (activeSessions.containsKey(thread.getId())) { + Session oldSession = activeSessions.remove(thread.getId()); + oldSession.logout(); + session.remove(); + } + + Session newSession = null; + // first try to login without credentials, assuming the underlying login + // module will have dealt with authentication (typically using Spring + // Security) + if (!forceDefaultCredentials) + try { + newSession = repository().login(workspace); + } catch (LoginException e1) { + log.warn("Cannot login without credentials: " + e1.getMessage()); + // invalid credentials, go to the next step + } catch (RepositoryException e1) { + // other kind of exception, fail + throw new ArgeoException("Cannot log in to repository", e1); + } + + // log using default username / password (useful for testing purposes) + if (newSession == null) + try { + SimpleCredentials sc = new SimpleCredentials(defaultUsername, + defaultPassword.toCharArray()); + newSession = repository().login(sc, workspace); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot log in to repository", e); + } + + session.set(newSession); + // Log and monitor new session + if (log.isTraceEnabled()) + log.trace("Logged in to JCR session " + newSession + "; userId=" + + newSession.getUserID()); + + // monitoring + activeSessions.put(thread.getId(), newSession); + threads.add(thread); + return newSession; + } + + public Object getObject() { + return proxiedSession; + } + + public void init() throws Exception { + monitoringThread = new MonitoringThread(); + monitoringThread.start(); + } + + public synchronized void dispose() throws Exception { + if (activeSessions.size() == 0) + return; + + if (log.isTraceEnabled()) + log.trace("Cleaning up " + activeSessions.size() + + " active JCR sessions..."); + + deactivate(); + for (Session sess : activeSessions.values()) { + JcrUtils.logoutQuietly(sess); + } + activeSessions.clear(); + } + + protected Boolean isActive() { + return active; + } + + protected synchronized void deactivate() { + active = false; + notifyAll(); + } + + protected synchronized void removeSession(Thread thread) { + if (!isActive()) + return; + activeSessions.remove(thread.getId()); + threads.remove(thread); + } + + protected synchronized void cleanDeadThreads() { + if (!isActive()) + return; + Iterator it = threads.iterator(); + while (it.hasNext()) { + Thread thread = it.next(); + if (!thread.isAlive() && isActive()) { + if (activeSessions.containsKey(thread.getId())) { + Session session = activeSessions.get(thread.getId()); + activeSessions.remove(thread.getId()); + session.logout(); + if (log.isTraceEnabled()) + log.trace("Cleaned up JCR session (userID=" + + session.getUserID() + ") from dead thread " + + thread.getId()); + } + it.remove(); + } + } + try { + wait(1000); + } catch (InterruptedException e) { + // silent + } + } + + public Class getObjectType() { + return Session.class; + } + + public boolean isSingleton() { + return true; + } + + /** + * Called before a method is actually called, allowing to check the session + * or re-login it (e.g. if authentication has changed). The default + * implementation returns the session. + */ + protected Session preCall(Session session) { + return session; + } + + protected Repository repository() { + if (repository != null) + return repository; + if (repositories != null) { + // hardened for OSGi dynamic services + Iterator it = repositories.iterator(); + if (it.hasNext()) + return it.next(); + } + throw new ArgeoException("No repository injected"); + } + + // /** Useful for declarative registration of OSGi services (blueprint) */ + // public void register(Repository repository, Map params) { + // this.repository = repository; + // } + // + // /** Useful for declarative registration of OSGi services (blueprint) */ + // public void unregister(Repository repository, Map params) { + // this.repository = null; + // } + + public void setRepository(Repository repository) { + this.repository = repository; + } + + public void setRepositories(List repositories) { + this.repositories = repositories; + } + + public void setDefaultUsername(String defaultUsername) { + this.defaultUsername = defaultUsername; + } + + public void setDefaultPassword(String defaultPassword) { + this.defaultPassword = defaultPassword; + } + + public void setForceDefaultCredentials(Boolean forceDefaultCredentials) { + this.forceDefaultCredentials = forceDefaultCredentials; + } + + public void setWorkspace(String workspace) { + this.workspace = workspace; + } + + protected class JcrSessionInvocationHandler implements InvocationHandler { + + public Object invoke(Object proxy, Method method, Object[] args) + throws Throwable, RepositoryException { + Session threadSession = session.get(); + if (threadSession == null) { + if ("logout".equals(method.getName()))// no need to login + return Void.TYPE; + else if ("toString".equals(method.getName()))// maybe logging + return "Uninitialized Argeo thread bound JCR session"; + threadSession = login(); + } + + preCall(threadSession); + Object ret; + try { + ret = method.invoke(threadSession, args); + } catch (InvocationTargetException e) { + Throwable cause = e.getCause(); + if (cause instanceof RepositoryException) + throw (RepositoryException) cause; + else + throw cause; + } + if ("logout".equals(method.getName())) { + session.remove(); + Thread thread = Thread.currentThread(); + removeSession(thread); + if (log.isTraceEnabled()) + log.trace("Logged out JCR session (userId=" + + threadSession.getUserID() + ") on thread " + + thread.getId()); + } + return ret; + } + } + + /** Monitors registered thread in order to clean up dead ones. */ + private class MonitoringThread extends Thread { + + public MonitoringThread() { + super("ThreadBound JCR Session Monitor"); + } + + @Override + public void run() { + while (isActive()) { + cleanDeadThreads(); + } + } + + } +} diff --git a/org.argeo.server.jcr/src/main/java/org/argeo/jcr/UserJcrUtils.java b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/UserJcrUtils.java new file mode 100644 index 000000000..1758802f8 --- /dev/null +++ b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/UserJcrUtils.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.query.Query; +import javax.jcr.query.qom.Constraint; +import javax.jcr.query.qom.DynamicOperand; +import javax.jcr.query.qom.QueryObjectModelFactory; +import javax.jcr.query.qom.Selector; +import javax.jcr.query.qom.StaticOperand; + +import org.argeo.ArgeoException; + +/** Utilities related to the user home and properties based on Argeo JCR model. */ +public class UserJcrUtils { + /** The home base path. Not yet configurable */ + public final static String DEFAULT_HOME_BASE_PATH = "/home"; + + /** + * Returns the home node of the user or null if none was found. + * + * @param session + * the session to use in order to perform the search, this can be + * a session with a different user ID than the one searched, + * typically when a system or admin session is used. + * @param username + * the username of the user + */ + public static Node getUserHome(Session session, String username) { + try { + // String homePath = UserJcrUtils.getUserHomePath(username); + // return session.itemExists(homePath) ? session.getNode(homePath) + // : null; + // kept for example of QOM queries + QueryObjectModelFactory qomf = session.getWorkspace() + .getQueryManager().getQOMFactory(); + Selector userHomeSel = qomf.selector(ArgeoTypes.ARGEO_USER_HOME, + "userHome"); + DynamicOperand userIdDop = qomf.propertyValue( + userHomeSel.getSelectorName(), ArgeoNames.ARGEO_USER_ID); + StaticOperand userIdSop = qomf.literal(session.getValueFactory() + .createValue(username)); + Constraint constraint = qomf.comparison(userIdDop, + QueryObjectModelFactory.JCR_OPERATOR_EQUAL_TO, userIdSop); + Query query = qomf.createQuery(userHomeSel, constraint, null, null); + return JcrUtils.querySingleNode(query); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot find home for user " + username, e); + } + } + + public static Node getUserProfile(Session session, String username) { + try { + QueryObjectModelFactory qomf = session.getWorkspace() + .getQueryManager().getQOMFactory(); + Selector userHomeSel = qomf.selector(ArgeoTypes.ARGEO_USER_PROFILE, + "userProfile"); + DynamicOperand userIdDop = qomf.propertyValue( + userHomeSel.getSelectorName(), ArgeoNames.ARGEO_USER_ID); + StaticOperand userIdSop = qomf.literal(session.getValueFactory() + .createValue(username)); + Constraint constraint = qomf.comparison(userIdDop, + QueryObjectModelFactory.JCR_OPERATOR_EQUAL_TO, userIdSop); + Query query = qomf.createQuery(userHomeSel, constraint, null, null); + return JcrUtils.querySingleNode(query); + } catch (RepositoryException e) { + throw new ArgeoException( + "Cannot find profile for user " + username, e); + } + } + + /** Returns the home node of the session user or null if none was found. */ + public static Node getUserHome(Session session) { + String userID = session.getUserID(); + return getUserHome(session, userID); + } + + private UserJcrUtils() { + } +} diff --git a/org.argeo.server.jcr/src/main/java/org/argeo/jcr/VersionDiff.java b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/VersionDiff.java new file mode 100644 index 000000000..e6ae9130b --- /dev/null +++ b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/VersionDiff.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr; + +import java.util.Calendar; +import java.util.Map; + +/** + * Generic Object that enables the creation of history reports based on a JCR + * versionable node. userId and creation date are added to the map of + * PropertyDiff. + * + * These two fields might be null + * + */ +public class VersionDiff { + + private String userId; + private Map diffs; + private Calendar updateTime; + + public VersionDiff(String userId, Calendar updateTime, + Map diffs) { + this.userId = userId; + this.updateTime = updateTime; + this.diffs = diffs; + } + + public String getUserId() { + return userId; + } + + public Map getDiffs() { + return diffs; + } + + public Calendar getUpdateTime() { + return updateTime; + } +} diff --git a/org.argeo.server.jcr/src/main/java/org/argeo/jcr/proxy/AbstractUrlProxy.java b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/proxy/AbstractUrlProxy.java new file mode 100644 index 000000000..8a66f3102 --- /dev/null +++ b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/proxy/AbstractUrlProxy.java @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.proxy; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +import javax.jcr.Binary; +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.nodetype.NodeType; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; +import org.argeo.jcr.JcrUtils; + +/** Base class for URL based proxys. */ +public abstract class AbstractUrlProxy implements ResourceProxy { + private final static Log log = LogFactory.getLog(AbstractUrlProxy.class); + + private Repository jcrRepository; + private Session jcrAdminSession; + private String proxyWorkspace = "proxy"; + + protected abstract Node retrieve(Session session, String path); + + void init() { + try { + jcrAdminSession = JcrUtils.loginOrCreateWorkspace(jcrRepository, + proxyWorkspace); + beforeInitSessionSave(jcrAdminSession); + if (jcrAdminSession.hasPendingChanges()) + jcrAdminSession.save(); + } catch (Exception e) { + JcrUtils.discardQuietly(jcrAdminSession); + throw new ArgeoException("Cannot initialize Maven proxy", e); + } + } + + /** + * Called before the (admin) session is saved at the end of the + * initialization. Does nothing by default, to be overridden. + */ + protected void beforeInitSessionSave(Session session) + throws RepositoryException { + } + + void destroy() { + JcrUtils.logoutQuietly(jcrAdminSession); + } + + /** + * Called before the (admin) session is logged out when resources are + * released. Does nothing by default, to be overridden. + */ + protected void beforeDestroySessionLogout() throws RepositoryException { + } + + public Node proxy(String path) { + // we open a JCR session with client credentials in order not to use the + // admin session in multiple thread or make it a bottleneck. + Node nodeAdmin = null; + Node nodeClient = null; + Session clientSession = null; + try { + clientSession = jcrRepository.login(proxyWorkspace); + if (!clientSession.itemExists(path) + || shouldUpdate(clientSession, path)) { + nodeAdmin = retrieveAndSave(path); + if (nodeAdmin != null) + nodeClient = clientSession.getNode(path); + } else + nodeClient = clientSession.getNode(path); + return nodeClient; + } catch (RepositoryException e) { + throw new ArgeoException("Cannot proxy " + path, e); + } finally { + if (nodeClient == null) + JcrUtils.logoutQuietly(clientSession); + } + } + + protected synchronized Node retrieveAndSave(String path) { + try { + Node node = retrieve(jcrAdminSession, path); + if (node == null) + return null; + jcrAdminSession.save(); + return node; + } catch (RepositoryException e) { + JcrUtils.discardQuietly(jcrAdminSession); + throw new ArgeoException("Cannot retrieve and save " + path, e); + } finally { + notifyAll(); + } + } + + /** Session is not saved */ + protected synchronized Node proxyUrl(Session session, String remoteUrl, + String path) throws RepositoryException { + Node node = null; + if (session.itemExists(path)) { + // throw new ArgeoException("Node " + path + " already exists"); + } + InputStream in = null; + try { + URL u = new URL(remoteUrl); + in = u.openStream(); + node = importFile(session, path, in); + } catch (IOException e) { + if (log.isDebugEnabled()) { + log.debug("Cannot read " + remoteUrl + ", skipping... " + + e.getMessage()); + // log.trace("Cannot read because of ", e); + } + JcrUtils.discardQuietly(session); + } finally { + IOUtils.closeQuietly(in); + } + return node; + } + + protected synchronized Node importFile(Session session, String path, + InputStream in) throws RepositoryException { + Binary binary = null; + try { + Node content = null; + Node node = null; + if (!session.itemExists(path)) { + node = JcrUtils.mkdirs(session, path, NodeType.NT_FILE, + NodeType.NT_FOLDER, false); + content = node.addNode(Node.JCR_CONTENT, NodeType.NT_RESOURCE); + } else { + node = session.getNode(path); + content = node.getNode(Node.JCR_CONTENT); + } + binary = session.getValueFactory().createBinary(in); + content.setProperty(Property.JCR_DATA, binary); + JcrUtils.updateLastModifiedAndParents(node, null); + return node; + } finally { + JcrUtils.closeQuietly(binary); + } + } + + /** Whether the file should be updated. */ + protected Boolean shouldUpdate(Session clientSession, String nodePath) { + return false; + } + + public void setJcrRepository(Repository jcrRepository) { + this.jcrRepository = jcrRepository; + } + + public void setProxyWorkspace(String localWorkspace) { + this.proxyWorkspace = localWorkspace; + } + +} diff --git a/org.argeo.server.jcr/src/main/java/org/argeo/jcr/proxy/ResourceProxy.java b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/proxy/ResourceProxy.java new file mode 100644 index 000000000..b4fb33286 --- /dev/null +++ b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/proxy/ResourceProxy.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.proxy; + +import javax.jcr.Node; + +/** A proxy which nows how to resolve and synchronize relative URLs */ +public interface ResourceProxy { + /** + * Proxy the file referenced by this relative path in the underlying + * repository. A new session is created by each call, so the underlying + * session of the returned node must be closed by the caller. + * + * @return the proxied Node, null if the resource was not found + * (e.g. HTTP 404) + */ + public Node proxy(String relativePath); +} diff --git a/org.argeo.server.jcr/src/main/java/org/argeo/jcr/security/JcrAuthorizations.java b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/security/JcrAuthorizations.java new file mode 100644 index 000000000..491f8a6fe --- /dev/null +++ b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/security/JcrAuthorizations.java @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.security; + +import java.security.Principal; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.security.AccessControlManager; +import javax.jcr.security.Privilege; + +import org.argeo.ArgeoException; +import org.argeo.jcr.JcrUtils; +import org.argeo.util.security.SimplePrincipal; + +/** Apply authorizations to a JCR repository. */ +public class JcrAuthorizations implements Runnable { + // private final static Log log = + // LogFactory.getLog(JcrAuthorizations.class); + + private Repository repository; + private String workspace = null; + + private String securityWorkspace = "security"; + + /** + * key := privilege1,privilege2/path/to/node
+ * value := group1,group2,user1 + */ + private Map principalPrivileges = new HashMap(); + + public void run() { + String currentWorkspace = workspace; + Session session = null; + try { + if (workspace != null && workspace.equals("*")) { + session = repository.login(); + String[] workspaces = session.getWorkspace() + .getAccessibleWorkspaceNames(); + JcrUtils.logoutQuietly(session); + for (String wksp : workspaces) { + currentWorkspace = wksp; + if (currentWorkspace.equals(securityWorkspace)) + continue; + session = repository.login(currentWorkspace); + initAuthorizations(session); + JcrUtils.logoutQuietly(session); + } + } else { + session = repository.login(workspace); + initAuthorizations(session); + } + } catch (Exception e) { + JcrUtils.discardQuietly(session); + throw new ArgeoException( + "Cannot set authorizations " + principalPrivileges + + " on workspace " + currentWorkspace, e); + } finally { + JcrUtils.logoutQuietly(session); + } + } + + protected void processWorkspace(String workspace) { + Session session = null; + try { + session = repository.login(workspace); + initAuthorizations(session); + } catch (Exception e) { + JcrUtils.discardQuietly(session); + throw new ArgeoException("Cannot set authorizations " + + principalPrivileges + " on repository " + repository, e); + } finally { + JcrUtils.logoutQuietly(session); + } + } + + /** @deprecated call {@link #run()} instead. */ + @Deprecated + public void init() { + run(); + } + + protected void initAuthorizations(Session session) + throws RepositoryException { + AccessControlManager acm = session.getAccessControlManager(); + + for (String privileges : principalPrivileges.keySet()) { + String path = null; + int slashIndex = privileges.indexOf('/'); + if (slashIndex == 0) { + throw new ArgeoException("Privilege " + privileges + + " badly formatted it starts with /"); + } else if (slashIndex > 0) { + path = privileges.substring(slashIndex); + privileges = privileges.substring(0, slashIndex); + } + + if (path == null) + path = "/"; + + List privs = new ArrayList(); + for (String priv : privileges.split(",")) { + privs.add(acm.privilegeFromName(priv)); + } + + String principalNames = principalPrivileges.get(privileges); + for (String principalName : principalNames.split(",")) { + Principal principal = getOrCreatePrincipal(session, + principalName); + JcrUtils.addPrivileges(session, path, principal, privs); + // if (log.isDebugEnabled()) { + // StringBuffer privBuf = new StringBuffer(); + // for (Privilege priv : privs) + // privBuf.append(priv.getName()); + // log.debug("Added privileges " + privBuf + " to " + // + principal.getName() + " on " + path + " in '" + // + session.getWorkspace().getName() + "'"); + // } + } + } + + // if (log.isDebugEnabled()) + // log.debug("JCR authorizations applied on '" + // + session.getWorkspace().getName() + "'"); + } + + /** + * Returns a {@link SimplePrincipal}, does not check whether it exists since + * such capabilities is not provided by the standard JCR API. Can be + * overridden to provide smarter handling + */ + protected Principal getOrCreatePrincipal(Session session, + String principalName) throws RepositoryException { + return new SimplePrincipal(principalName); + } + + // public static void addPrivileges(Session session, Principal principal, + // String path, List privs) throws RepositoryException { + // AccessControlManager acm = session.getAccessControlManager(); + // // search for an access control list + // AccessControlList acl = null; + // AccessControlPolicyIterator policyIterator = acm + // .getApplicablePolicies(path); + // if (policyIterator.hasNext()) { + // while (policyIterator.hasNext()) { + // AccessControlPolicy acp = policyIterator + // .nextAccessControlPolicy(); + // if (acp instanceof AccessControlList) + // acl = ((AccessControlList) acp); + // } + // } else { + // AccessControlPolicy[] existingPolicies = acm.getPolicies(path); + // for (AccessControlPolicy acp : existingPolicies) { + // if (acp instanceof AccessControlList) + // acl = ((AccessControlList) acp); + // } + // } + // + // if (acl != null) { + // acl.addAccessControlEntry(principal, + // privs.toArray(new Privilege[privs.size()])); + // acm.setPolicy(path, acl); + // session.save(); + // if (log.isDebugEnabled()) { + // StringBuffer buf = new StringBuffer(""); + // for (int i = 0; i < privs.size(); i++) { + // if (i != 0) + // buf.append(','); + // buf.append(privs.get(i).getName()); + // } + // log.debug("Added privilege(s) '" + buf + "' to '" + // + principal.getName() + "' on " + path + // + " from workspace '" + // + session.getWorkspace().getName() + "'"); + // } + // } else { + // throw new ArgeoException("Don't know how to apply privileges " + // + privs + " to " + principal + " on " + path + // + " from workspace '" + session.getWorkspace().getName() + // + "'"); + // } + // } + + @Deprecated + public void setGroupPrivileges(Map groupPrivileges) { + this.principalPrivileges = groupPrivileges; + } + + public void setPrincipalPrivileges(Map principalPrivileges) { + this.principalPrivileges = principalPrivileges; + } + + public void setRepository(Repository repository) { + this.repository = repository; + } + + public void setWorkspace(String workspace) { + this.workspace = workspace; + } + + public void setSecurityWorkspace(String securityWorkspace) { + this.securityWorkspace = securityWorkspace; + } + +} diff --git a/org.argeo.server.jcr/src/main/java/org/argeo/jcr/spring/BeanNodeMapper.java b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/spring/BeanNodeMapper.java new file mode 100644 index 000000000..9f70f5c58 --- /dev/null +++ b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/spring/BeanNodeMapper.java @@ -0,0 +1,649 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.spring; + +import java.beans.PropertyDescriptor; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; + +import javax.jcr.Binary; +import javax.jcr.ItemNotFoundException; +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.Property; +import javax.jcr.PropertyIterator; +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.Value; +import javax.jcr.ValueFactory; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; +import org.argeo.jcr.JcrUtils; +import org.argeo.jcr.NodeMapper; +import org.argeo.jcr.NodeMapperProvider; +import org.springframework.beans.BeanWrapper; +import org.springframework.beans.BeanWrapperImpl; + +public class BeanNodeMapper implements NodeMapper { + private final static Log log = LogFactory.getLog(BeanNodeMapper.class); + + private final static String NODE_VALUE = "value"; + + // private String keyNode = "bean:key"; + private String uuidProperty = "uuid"; + private String classProperty = "class"; + + private Boolean versioning = false; + private Boolean strictUuidReference = false; + + // TODO define a primaryNodeType Strategy + private String primaryNodeType = null; + + private ClassLoader classLoader = getClass().getClassLoader(); + + private NodeMapperProvider nodeMapperProvider; + + /** + * exposed method to retrieve a bean from a node + */ + public Object load(Node node) { + try { + if (nodeMapperProvider != null) { + NodeMapper nodeMapper = nodeMapperProvider.findNodeMapper(node); + if (nodeMapper != this) { + return nodeMapper.load(node); + } + } + return nodeToBean(node); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot load object from node " + node, e); + } + } + + /** Update an existing node with an object */ + public void update(Node node, Object obj) { + try { + if (nodeMapperProvider != null) { + + NodeMapper nodeMapper = nodeMapperProvider.findNodeMapper(node); + if (nodeMapper != this) { + nodeMapper.update(node, obj); + } else + beanToNode(createBeanWrapper(obj), node); + } else + beanToNode(createBeanWrapper(obj), node); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot update node " + node + " with " + + obj, e); + } + } + + /** + * if no storage path is given; we use canonical path + * + * @see this.storagePath() + */ + public Node save(Session session, Object obj) { + return save(session, storagePath(obj), obj); + } + + /** + * Create a new node to store an object. If the parentNode doesn't exist, it + * is created + * + * the primaryNodeType may be initialized before + */ + public Node save(Session session, String path, Object obj) { + try { + final Node node; + String parentPath = JcrUtils.parentPath(path); + // find or create parent node + Node parentNode; + if (session.itemExists(path)) + parentNode = (Node) session.getItem(parentPath); + else { + parentNode = JcrUtils.mkdirs(session, parentPath, null, null, + versioning); + } + // create node + + if (primaryNodeType != null) + node = parentNode.addNode(JcrUtils.lastPathElement(path), + primaryNodeType); + else + node = parentNode.addNode(JcrUtils.lastPathElement(path)); + + // Check specific cases + if (nodeMapperProvider != null) { + NodeMapper nodeMapper = nodeMapperProvider.findNodeMapper(node); + if (nodeMapper != this) { + nodeMapper.update(node, obj); + return node; + } + } + update(node, obj); + return node; + } catch (ArgeoException e) { + throw e; + } catch (Exception e) { + throw new ArgeoException("Cannot save or update " + obj + " under " + + path, e); + } + } + + /** + * Parse the FQN of a class to string with '/' delimiters Prefix the + * returned string with "/objects/" + */ + public String storagePath(Object obj) { + String clss = obj.getClass().getName(); + StringBuffer buf = new StringBuffer("/objects/"); + StringTokenizer st = new StringTokenizer(clss, "."); + while (st.hasMoreTokens()) { + buf.append(st.nextToken()).append('/'); + } + buf.append(obj.toString()); + return buf.toString(); + } + + @SuppressWarnings("unchecked") + /** + * Transforms a node into an object of the class defined by classProperty Property + */ + protected Object nodeToBean(Node node) throws RepositoryException { + if (log.isTraceEnabled()) + log.trace("Load " + node); + + try { + String clssName = node.getProperty(classProperty).getValue() + .getString(); + + BeanWrapper beanWrapper = createBeanWrapper(loadClass(clssName)); + + // process properties + PropertyIterator propIt = node.getProperties(); + props: while (propIt.hasNext()) { + Property prop = propIt.nextProperty(); + if (!beanWrapper.isWritableProperty(prop.getName())) + continue props; + + PropertyDescriptor pd = beanWrapper.getPropertyDescriptor(prop + .getName()); + Class propClass = pd.getPropertyType(); + + if (log.isTraceEnabled()) + log.trace("Load " + prop + ", propClass=" + propClass + + ", property descriptor=" + pd); + + // primitive list + if (propClass != null && List.class.isAssignableFrom(propClass)) { + List lst = new ArrayList(); + Class valuesClass = classFromProperty(prop); + if (valuesClass != null) + for (Value value : prop.getValues()) { + lst.add(asObject(value, valuesClass)); + } + continue props; + } + + // Case of other type of property accepted by jcr + // Long, Double, String, Binary, Date, Boolean, Name + Object value = asObject(prop.getValue(), pd.getPropertyType()); + if (value != null) + beanWrapper.setPropertyValue(prop.getName(), value); + } + + // process children nodes + NodeIterator nodeIt = node.getNodes(); + nodes: while (nodeIt.hasNext()) { + Node childNode = nodeIt.nextNode(); + String name = childNode.getName(); + if (!beanWrapper.isWritableProperty(name)) + continue nodes; + + PropertyDescriptor pd = beanWrapper.getPropertyDescriptor(name); + Class propClass = pd.getPropertyType(); + + // objects list + if (propClass != null && List.class.isAssignableFrom(propClass)) { + String lstClass = childNode.getProperty(classProperty) + .getString(); + List lst; + try { + lst = (List) loadClass(lstClass).newInstance(); + } catch (Exception e) { + lst = new ArrayList(); + } + + if (childNode.hasNodes()) { + // Look for children nodes + NodeIterator valuesIt = childNode.getNodes(); + while (valuesIt.hasNext()) { + Node lstValueNode = valuesIt.nextNode(); + Object lstValue = nodeToBean(lstValueNode); + lst.add(lstValue); + } + } else { + // look for a property with the same name which will + // provide + // primitives + Property childProp = childNode.getProperty(childNode + .getName()); + Class valuesClass = classFromProperty(childProp); + if (valuesClass != null) + if (childProp.getDefinition().isMultiple()) + for (Value value : childProp.getValues()) { + lst.add(asObject(value, valuesClass)); + } + else + lst.add(asObject(childProp.getValue(), + valuesClass)); + } + beanWrapper.setPropertyValue(name, lst); + continue nodes; + } + + // objects map + if (propClass != null && Map.class.isAssignableFrom(propClass)) { + String mapClass = childNode.getProperty(classProperty) + .getString(); + Map map; + try { + map = (Map) loadClass(mapClass) + .newInstance(); + } catch (Exception e) { + map = new HashMap(); + } + + // properties + PropertyIterator keysPropIt = childNode.getProperties(); + keyProps: while (keysPropIt.hasNext()) { + Property keyProp = keysPropIt.nextProperty(); + // FIXME: use property editor + String key = keyProp.getName(); + if (classProperty.equals(key)) + continue keyProps; + + Class keyPropClass = classFromProperty(keyProp); + if (keyPropClass != null) { + Object mapValue = asObject(keyProp.getValue(), + keyPropClass); + map.put(key, mapValue); + } + } + + // node + NodeIterator keysIt = childNode.getNodes(); + while (keysIt.hasNext()) { + Node mapValueNode = keysIt.nextNode(); + // FIXME: use property editor + Object key = mapValueNode.getName(); + + Object mapValue = nodeToBean(mapValueNode); + + map.put(key, mapValue); + } + beanWrapper.setPropertyValue(name, map); + continue nodes; + } + + // default + Object value = nodeToBean(childNode); + beanWrapper.setPropertyValue(name, value); + + } + return beanWrapper.getWrappedInstance(); + } catch (Exception e) { + throw new ArgeoException("Cannot map node " + node, e); + } + } + + /** + * Transforms an object to the specified jcr Node in order to persist it. + * + * @param beanWrapper + * @param node + * @throws RepositoryException + */ + protected void beanToNode(BeanWrapper beanWrapper, Node node) + throws RepositoryException { + properties: for (PropertyDescriptor pd : beanWrapper + .getPropertyDescriptors()) { + String name = pd.getName(); + if (!beanWrapper.isReadableProperty(name)) + continue properties;// skip + + Object value = beanWrapper.getPropertyValue(name); + if (value == null) { + // remove values when updating + if (node.hasProperty(name)) + node.setProperty(name, (Value) null); + if (node.hasNode(name)) + node.getNode(name).remove(); + + continue properties; + } + + // if (uuidProperty != null && uuidProperty.equals(name)) { + // // node.addMixin(ArgeoJcrConstants.MIX_REFERENCEABLE); + // node.setProperty(ArgeoJcrConstants.JCR_UUID, value.toString()); + // continue properties; + // } + + if ("class".equals(name)) { + if (classProperty != null) { + node.setProperty(classProperty, + ((Class) value).getName()); + // TODO: store a class hierarchy? + } + continue properties; + } + + // Some bean reference other classes. We must deal with this case + if (value instanceof Class) { + node.setProperty(name, ((Class) value).getName()); + continue properties; + } + + Value val = asValue(node.getSession(), value); + if (val != null) { + node.setProperty(name, val); + continue properties; + } + + if (value instanceof List) { + List lst = (List) value; + addList(node, name, lst); + continue properties; + } + + if (value instanceof Map) { + Map map = (Map) value; + addMap(node, name, map); + continue properties; + } + + BeanWrapper child = createBeanWrapper(value); + // TODO: delegate to another mapper + + // TODO: deal with references + // Node childNode = findChildReference(session, child); + // if (childNode != null) { + // node.setProperty(name, childNode); + // continue properties; + // } + + // default case (recursive) + if (node.hasNode(name)) {// update + // TODO: optimize + node.getNode(name).remove(); + } + Node childNode = node.addNode(name); + beanToNode(child, childNode); + } + } + + /** + * Process specific case of list + * + * @param node + * @param name + * @param lst + * @throws RepositoryException + */ + protected void addList(Node node, String name, List lst) + throws RepositoryException { + if (node.hasNode(name)) {// update + // TODO: optimize + node.getNode(name).remove(); + } + + Node listNode = node.addNode(name); + listNode.setProperty(classProperty, lst.getClass().getName()); + Value[] values = new Value[lst.size()]; + boolean atLeastOneSet = false; + for (int i = 0; i < lst.size(); i++) { + Object lstValue = lst.get(i); + values[i] = asValue(node.getSession(), lstValue); + if (values[i] != null) { + atLeastOneSet = true; + } else { + Node childNode = findChildReference(node.getSession(), + createBeanWrapper(lstValue)); + if (childNode != null) { + values[i] = node.getSession().getValueFactory() + .createValue(childNode); + atLeastOneSet = true; + } + } + } + + // will be either properties or nodes, not both + if (!atLeastOneSet && lst.size() != 0) { + for (Object lstValue : lst) { + Node childNode = listNode.addNode(NODE_VALUE); + beanToNode(createBeanWrapper(lstValue), childNode); + } + } else { + listNode.setProperty(name, values); + } + } + + /** + * Process specific case of maps. + * + * @param node + * @param name + * @param map + * @throws RepositoryException + */ + protected void addMap(Node node, String name, Map map) + throws RepositoryException { + if (node.hasNode(name)) {// update + // TODO: optimize + node.getNode(name).remove(); + } + + Node mapNode = node.addNode(name); + mapNode.setProperty(classProperty, map.getClass().getName()); + for (Object key : map.keySet()) { + Object mapValue = map.get(key); + // PropertyEditor pe = beanWrapper.findCustomEditor(key.getClass(), + // null); + String keyStr; + // if (pe == null) { + if (key instanceof CharSequence) + keyStr = key.toString(); + else + throw new ArgeoException( + "Cannot find property editor for class " + + key.getClass()); + // } else { + // pe.setValue(key); + // keyStr = pe.getAsText(); + // } + // TODO: check string format + + Value mapVal = asValue(node.getSession(), mapValue); + if (mapVal != null) + mapNode.setProperty(keyStr, mapVal); + else { + Node entryNode = mapNode.addNode(keyStr); + beanToNode(createBeanWrapper(mapValue), entryNode); + } + + } + + } + + protected BeanWrapper createBeanWrapper(Object obj) { + return new BeanWrapperImpl(obj); + } + + protected BeanWrapper createBeanWrapper(Class clss) { + return new BeanWrapperImpl(clss); + } + + /** Returns null if value cannot be found */ + protected Value asValue(Session session, Object value) + throws RepositoryException { + ValueFactory valueFactory = session.getValueFactory(); + if (value instanceof Integer) + return valueFactory.createValue((Integer) value); + else if (value instanceof Long) + return valueFactory.createValue((Long) value); + else if (value instanceof Float) + return valueFactory.createValue((Float) value); + else if (value instanceof Double) + return valueFactory.createValue((Double) value); + else if (value instanceof Boolean) + return valueFactory.createValue((Boolean) value); + else if (value instanceof Calendar) + return valueFactory.createValue((Calendar) value); + else if (value instanceof Date) { + Calendar cal = new GregorianCalendar(); + cal.setTime((Date) value); + return valueFactory.createValue(cal); + } else if (value instanceof CharSequence) + return valueFactory.createValue(value.toString()); + else if (value instanceof InputStream) { + Binary binary = session.getValueFactory().createBinary( + (InputStream) value); + return valueFactory.createValue(binary); + } else + return null; + } + + protected Class classFromProperty(Property property) + throws RepositoryException { + switch (property.getType()) { + case PropertyType.LONG: + return Long.class; + case PropertyType.DOUBLE: + return Double.class; + case PropertyType.STRING: + return String.class; + case PropertyType.BOOLEAN: + return Boolean.class; + case PropertyType.DATE: + return Calendar.class; + case PropertyType.NAME: + return null; + default: + throw new ArgeoException("Cannot find class for property " + + property + ", type=" + + PropertyType.nameFromValue(property.getType())); + } + } + + protected Object asObject(Value value, Class propClass) + throws RepositoryException { + if (propClass.equals(Integer.class)) + return (int) value.getLong(); + else if (propClass.equals(Long.class)) + return value.getLong(); + else if (propClass.equals(Float.class)) + return (float) value.getDouble(); + else if (propClass.equals(Double.class)) + return value.getDouble(); + else if (propClass.equals(Boolean.class)) + return value.getBoolean(); + else if (CharSequence.class.isAssignableFrom(propClass)) + return value.getString(); + else if (InputStream.class.isAssignableFrom(propClass)) + return value.getBinary().getStream(); + else if (Calendar.class.isAssignableFrom(propClass)) + return value.getDate(); + else if (Date.class.isAssignableFrom(propClass)) + return value.getDate().getTime(); + else + return null; + } + + protected Node findChildReference(Session session, BeanWrapper child) + throws RepositoryException { + if (child.isReadableProperty(uuidProperty)) { + String childUuid = child.getPropertyValue(uuidProperty).toString(); + try { + return session.getNodeByIdentifier(childUuid); + } catch (ItemNotFoundException e) { + if (strictUuidReference) + throw new ArgeoException("No node found with uuid " + + childUuid, e); + } + } + return null; + } + + protected Class loadClass(String name) { + // log.debug("Class loader: " + classLoader); + try { + return classLoader.loadClass(name); + } catch (ClassNotFoundException e) { + throw new ArgeoException("Cannot load class " + name, e); + } + } + + protected String propertyName(String name) { + return name; + } + + public void setVersioning(Boolean versioning) { + this.versioning = versioning; + } + + public void setUuidProperty(String uuidProperty) { + this.uuidProperty = uuidProperty; + } + + public void setClassProperty(String classProperty) { + this.classProperty = classProperty; + } + + public void setStrictUuidReference(Boolean strictUuidReference) { + this.strictUuidReference = strictUuidReference; + } + + public void setPrimaryNodeType(String primaryNodeType) { + this.primaryNodeType = primaryNodeType; + } + + public void setClassLoader(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + public void setNodeMapperProvider(NodeMapperProvider nodeMapperProvider) { + this.nodeMapperProvider = nodeMapperProvider; + } + + public String getPrimaryNodeType() { + return this.primaryNodeType; + } + + public String getClassProperty() { + return this.classProperty; + } +} diff --git a/org.argeo.server.jcr/src/main/java/org/argeo/jcr/spring/ThreadBoundSession.java b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/spring/ThreadBoundSession.java new file mode 100644 index 000000000..a46bef1fe --- /dev/null +++ b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/spring/ThreadBoundSession.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.spring; + +import org.argeo.jcr.ThreadBoundJcrSessionFactory; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.InitializingBean; + +public class ThreadBoundSession extends ThreadBoundJcrSessionFactory implements FactoryBean, InitializingBean, DisposableBean{ + public void afterPropertiesSet() throws Exception { + init(); + } + + public void destroy() throws Exception { + dispose(); + } + +} diff --git a/org.argeo.server.jcr/src/main/java/org/argeo/jcr/tabular/JcrTabularRowIterator.java b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/tabular/JcrTabularRowIterator.java new file mode 100644 index 000000000..ca0635c95 --- /dev/null +++ b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/tabular/JcrTabularRowIterator.java @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.tabular; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ArrayBlockingQueue; + +import javax.jcr.Binary; +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.Property; +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; + +import org.apache.commons.io.IOUtils; +import org.argeo.ArgeoException; +import org.argeo.jcr.ArgeoTypes; +import org.argeo.util.CsvParser; +import org.argeo.util.tabular.ArrayTabularRow; +import org.argeo.util.tabular.TabularColumn; +import org.argeo.util.tabular.TabularRow; +import org.argeo.util.tabular.TabularRowIterator; + +/** Iterates over the rows of a {@link ArgeoTypes#ARGEO_TABLE} node. */ +public class JcrTabularRowIterator implements TabularRowIterator { + private Boolean hasNext = null; + private Boolean parsingCompleted = false; + + private Long currentRowNumber = 0l; + + private List header = new ArrayList(); + + /** referenced so that we can close it */ + private Binary binary; + private InputStream in; + + private CsvParser csvParser; + private ArrayBlockingQueue> textLines; + + public JcrTabularRowIterator(Node tableNode) { + try { + for (NodeIterator it = tableNode.getNodes(); it.hasNext();) { + Node node = it.nextNode(); + if (node.isNodeType(ArgeoTypes.ARGEO_COLUMN)) { + Integer type = PropertyType.valueFromName(node.getProperty( + Property.JCR_REQUIRED_TYPE).getString()); + TabularColumn tc = new TabularColumn(node.getProperty( + Property.JCR_TITLE).getString(), type); + header.add(tc); + } + } + Node contentNode = tableNode.getNode(Property.JCR_CONTENT); + if (contentNode.isNodeType(ArgeoTypes.ARGEO_CSV)) { + textLines = new ArrayBlockingQueue>(1000); + csvParser = new CsvParser() { + protected void processLine(Integer lineNumber, + List header, List tokens) { + try { + textLines.put(tokens); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + // textLines.add(tokens); + if (hasNext == null) { + hasNext = true; + synchronized (JcrTabularRowIterator.this) { + JcrTabularRowIterator.this.notifyAll(); + } + } + } + }; + csvParser.setNoHeader(true); + binary = contentNode.getProperty(Property.JCR_DATA).getBinary(); + in = binary.getStream(); + Thread thread = new Thread(contentNode.getPath() + " reader") { + public void run() { + try { + csvParser.parse(in); + } finally { + parsingCompleted = true; + IOUtils.closeQuietly(in); + } + } + }; + thread.start(); + } + } catch (RepositoryException e) { + throw new ArgeoException("Cannot read table " + tableNode, e); + } + } + + public synchronized boolean hasNext() { + // we don't know if there is anything available + // while (hasNext == null) + // try { + // wait(); + // } catch (InterruptedException e) { + // // silent + // // FIXME better deal with interruption + // Thread.currentThread().interrupt(); + // break; + // } + + // buffer not empty + if (!textLines.isEmpty()) + return true; + + // maybe the parsing is finished but the flag has not been set + while (!parsingCompleted && textLines.isEmpty()) + try { + wait(100); + } catch (InterruptedException e) { + // silent + // FIXME better deal with interruption + Thread.currentThread().interrupt(); + break; + } + + // buffer not empty + if (!textLines.isEmpty()) + return true; + + // (parsingCompleted && textLines.isEmpty()) + return false; + + // if (!hasNext && textLines.isEmpty()) { + // if (in != null) { + // IOUtils.closeQuietly(in); + // in = null; + // } + // if (binary != null) { + // JcrUtils.closeQuietly(binary); + // binary = null; + // } + // return false; + // } else + // return true; + } + + public synchronized TabularRow next() { + try { + List tokens = textLines.take(); + List objs = new ArrayList(tokens.size()); + for (String token : tokens) { + // TODO convert to other formats using header + objs.add(token); + } + currentRowNumber++; + return new ArrayTabularRow(objs); + } catch (InterruptedException e) { + // silent + // FIXME better deal with interruption + } + return null; + } + + public void remove() { + throw new UnsupportedOperationException(); + } + + public Long getCurrentRowNumber() { + return currentRowNumber; + } + + public List getHeader() { + return header; + } + +} diff --git a/org.argeo.server.jcr/src/main/java/org/argeo/jcr/tabular/JcrTabularWriter.java b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/tabular/JcrTabularWriter.java new file mode 100644 index 000000000..718ff2374 --- /dev/null +++ b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/tabular/JcrTabularWriter.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.tabular; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.util.List; + +import javax.jcr.Binary; +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; + +import org.apache.commons.io.IOUtils; +import org.argeo.ArgeoException; +import org.argeo.jcr.ArgeoTypes; +import org.argeo.jcr.JcrUtils; +import org.argeo.util.CsvWriter; +import org.argeo.util.tabular.TabularColumn; +import org.argeo.util.tabular.TabularWriter; + +/** Write / reference tabular content in a JCR repository. */ +public class JcrTabularWriter implements TabularWriter { + private Node contentNode; + private ByteArrayOutputStream out; + private CsvWriter csvWriter; + + @SuppressWarnings("unused") + private final List columns; + + /** Creates a table node */ + public JcrTabularWriter(Node tableNode, List columns, + String contentNodeType) { + try { + this.columns = columns; + for (TabularColumn column : columns) { + String normalized = JcrUtils.replaceInvalidChars(column + .getName()); + Node columnNode = tableNode.addNode(normalized, + ArgeoTypes.ARGEO_COLUMN); + columnNode.setProperty(Property.JCR_TITLE, column.getName()); + if (column.getType() != null) + columnNode.setProperty(Property.JCR_REQUIRED_TYPE, + PropertyType.nameFromValue(column.getType())); + else + columnNode.setProperty(Property.JCR_REQUIRED_TYPE, + PropertyType.TYPENAME_STRING); + } + contentNode = tableNode.addNode(Property.JCR_CONTENT, + contentNodeType); + if (contentNodeType.equals(ArgeoTypes.ARGEO_CSV)) { + contentNode.setProperty(Property.JCR_MIMETYPE, "text/csv"); + contentNode.setProperty(Property.JCR_ENCODING, "UTF-8"); + out = new ByteArrayOutputStream(); + csvWriter = new CsvWriter(out); + } + } catch (RepositoryException e) { + throw new ArgeoException("Cannot create table node " + tableNode, e); + } + } + + public void appendRow(Object[] row) { + csvWriter.writeLine(row); + } + + public void close() { + Binary binary = null; + InputStream in = null; + try { + // TODO parallelize with pipes and writing from another thread + in = new ByteArrayInputStream(out.toByteArray()); + binary = contentNode.getSession().getValueFactory() + .createBinary(in); + contentNode.setProperty(Property.JCR_DATA, binary); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot store data in " + contentNode, e); + } finally { + IOUtils.closeQuietly(in); + JcrUtils.closeQuietly(binary); + } + } +} diff --git a/org.argeo.server.jcr/src/main/java/org/argeo/jcr/unit/AbstractJcrTestCase.java b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/unit/AbstractJcrTestCase.java new file mode 100644 index 000000000..530605eac --- /dev/null +++ b/org.argeo.server.jcr/src/main/java/org/argeo/jcr/unit/AbstractJcrTestCase.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.unit; + +import java.io.File; + +import javax.jcr.Repository; +import javax.jcr.Session; +import javax.jcr.SimpleCredentials; + +import junit.framework.TestCase; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; + +public abstract class AbstractJcrTestCase extends TestCase { + private final static Log log = LogFactory.getLog(AbstractJcrTestCase.class); + + private Repository repository; + private Session session = null; + + protected abstract File getRepositoryFile() throws Exception; + + protected abstract Repository createRepository() throws Exception; + + @Override + protected void setUp() throws Exception { + File homeDir = getHomeDir(); + FileUtils.deleteDirectory(homeDir); + repository = createRepository(); + } + + protected File getHomeDir() { + File homeDir = new File(System.getProperty("java.io.tmpdir"), + AbstractJcrTestCase.class.getSimpleName() + "-" + + System.getProperty("user.name")); + return homeDir; + } + + @Override + protected void tearDown() throws Exception { + if (session != null) { + session.logout(); + if (log.isDebugEnabled()) + log.debug("Logout session"); + } + } + + protected Session session() { + if (session == null) { + try { + if (log.isDebugEnabled()) + log.debug("Login session"); + session = getRepository().login( + new SimpleCredentials("demo", "demo".toCharArray())); + } catch (Exception e) { + throw new ArgeoException("Cannot login to repository", e); + } + } + return session; + } + + protected Repository getRepository() { + return repository; + } + + /** + * enables children class to set an existing repository in case it is not + * deleted on startup, to test migration by instance + */ + protected void setRepository(Repository repository) { + this.repository = repository; + } +} diff --git a/org.argeo.server.jcr/src/main/resources/org/argeo/jcr/argeo.cnd b/org.argeo.server.jcr/src/main/resources/org/argeo/jcr/argeo.cnd new file mode 100644 index 000000000..fbfea9dd9 --- /dev/null +++ b/org.argeo.server.jcr/src/main/resources/org/argeo/jcr/argeo.cnd @@ -0,0 +1,72 @@ + + +// GENERIC TYPES NOT AVAILABLE IN JCR +[argeo:link] > mix:created, mix:lastModified +mixin +// URI(s) +- argeo:uri (STRING) m + +[argeo:references] > nt:unstructured +- * (REFERENCE) * + +// DATA MODEL +[argeo:dataModel] > mix:created, mix:lastModified, mix:versionable +mixin +- argeo:uri (STRING) m +- argeo:dataModelVersion (STRING) m + +// USER NODES +// user should be lower case, between 3 and 15 characters long +[argeo:userHome] > mix:created, mix:lastModified +mixin +- argeo:userID (STRING) m +- argeo:remoteRoles (STRING) * +// deprecated. for backward compatibility: ++ argeo:profile (argeo:userProfile) ++ argeo:keyring (argeo:pbeSpec) ++ argeo:preferences (argeo:preferenceNode) + +[argeo:userProfile] > mix:created, mix:lastModified, mix:title, mix:versionable +mixin +- argeo:userID (STRING) m +- argeo:enabled (BOOLEAN) +- argeo:accountNonExpired (BOOLEAN) +- argeo:accountNonLocked (BOOLEAN) +- argeo:credentialsNonExpired (BOOLEAN) + +[argeo:preferenceNode] > mix:lastModified, mix:versionable +mixin ++ * (argeo:preferenceNode) * version + +[argeo:remoteRepository] > nt:unstructured +- argeo:uri (STRING) +- argeo:userID (STRING) ++ argeo:password (argeo:encrypted) + +// TABULAR CONTENT +[argeo:table] > nt:file ++ * (argeo:column) * + +[argeo:column] > mix:title +- jcr:requiredType (STRING) = 'STRING' + +[argeo:csv] > nt:resource + +// CRYPTO +[argeo:encrypted] > nt:base +mixin +// initialization vector used by some algorithms +- argeo:iv (BINARY) + +[argeo:pbeKeySpec] > nt:base +mixin +- argeo:secretKeyFactory (STRING) +- argeo:salt (BINARY) +- argeo:iterationCount (LONG) +- argeo:keyLength (LONG) +- argeo:secretKeyEncryption (STRING) + +[argeo:pbeSpec] > argeo:pbeKeySpec +mixin +- argeo:cipher (STRING) + diff --git a/org.argeo.server.jcr/src/test/java/org/argeo/jcr/AbstractInternalJackrabbitTestCase.java b/org.argeo.server.jcr/src/test/java/org/argeo/jcr/AbstractInternalJackrabbitTestCase.java new file mode 100644 index 000000000..23281d075 --- /dev/null +++ b/org.argeo.server.jcr/src/test/java/org/argeo/jcr/AbstractInternalJackrabbitTestCase.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr; + +import java.io.File; + +import javax.jcr.Repository; + +import org.apache.jackrabbit.core.TransientRepository; +import org.argeo.jcr.unit.AbstractJcrTestCase; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; + +/** Factorizes configuration of an in memory transient repository */ +public abstract class AbstractInternalJackrabbitTestCase extends + AbstractJcrTestCase { + protected File getRepositoryFile() throws Exception { + Resource res = new ClassPathResource( + "org/argeo/server/jcr/repository-memory.xml"); + return res.getFile(); + } + + protected Repository createRepository() throws Exception { + Repository repository = new TransientRepository(getRepositoryFile(), + getHomeDir()); + return repository; + } + +} diff --git a/org.argeo.server.jcr/src/test/java/org/argeo/jcr/CollectionsObject.java b/org.argeo.server.jcr/src/test/java/org/argeo/jcr/CollectionsObject.java new file mode 100644 index 000000000..1cbb931a7 --- /dev/null +++ b/org.argeo.server.jcr/src/test/java/org/argeo/jcr/CollectionsObject.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class CollectionsObject { + private String id; + private String label; + private SimpleObject simpleObject; + private List stringList = new ArrayList(); + private Map floatMap = new HashMap(); + private Map objectMap = new HashMap(); + private Map> mapOfMaps = new HashMap>(); + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + + public SimpleObject getSimpleObject() { + return simpleObject; + } + + public void setSimpleObject(SimpleObject simpleObject) { + this.simpleObject = simpleObject; + } + + public List getStringList() { + return stringList; + } + + public void setStringList(List stringList) { + this.stringList = stringList; + } + + public Map getFloatMap() { + return floatMap; + } + + public void setFloatMap(Map floatMap) { + this.floatMap = floatMap; + } + + public Map getObjectMap() { + return objectMap; + } + + public void setObjectMap(Map objectMap) { + this.objectMap = objectMap; + } + + public Map> getMapOfMaps() { + return mapOfMaps; + } + + public void setMapOfMaps(Map> mapOfMaps) { + this.mapOfMaps = mapOfMaps; + } +} diff --git a/org.argeo.server.jcr/src/test/java/org/argeo/jcr/MapperTest.java b/org.argeo.server.jcr/src/test/java/org/argeo/jcr/MapperTest.java new file mode 100644 index 000000000..5486ff458 --- /dev/null +++ b/org.argeo.server.jcr/src/test/java/org/argeo/jcr/MapperTest.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr; + +import javax.jcr.Node; + +import org.argeo.jcr.spring.BeanNodeMapper; + +public class MapperTest extends AbstractInternalJackrabbitTestCase { + public void testSimpleObject() throws Exception { + SimpleObject mySo = new SimpleObject(); + mySo.setInteger(100); + mySo.setString("hello world"); + + OtherObject oo1 = new OtherObject(); + oo1.setKey("someKey"); + oo1.setValue("stringValue"); + mySo.setOtherObject(oo1); + + OtherObject oo2 = new OtherObject(); + oo2.setKey("anotherSimpleObject"); + oo2.setValue(new SimpleObject()); + mySo.setAnotherObject(oo2); + + BeanNodeMapper bnm = new BeanNodeMapper(); + + Node node = bnm.save(session(), mySo); + session().save(); + JcrUtils.debug(node); + } +} diff --git a/org.argeo.server.jcr/src/test/java/org/argeo/jcr/OtherObject.java b/org.argeo.server.jcr/src/test/java/org/argeo/jcr/OtherObject.java new file mode 100644 index 000000000..5cce8ffaa --- /dev/null +++ b/org.argeo.server.jcr/src/test/java/org/argeo/jcr/OtherObject.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr; + +public class OtherObject { + private String key; + private Object value; + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public Object getValue() { + return value; + } + + public void setValue(Object value) { + this.value = value; + } +} diff --git a/org.argeo.server.jcr/src/test/java/org/argeo/jcr/SimpleObject.java b/org.argeo.server.jcr/src/test/java/org/argeo/jcr/SimpleObject.java new file mode 100644 index 000000000..cdc32fc99 --- /dev/null +++ b/org.argeo.server.jcr/src/test/java/org/argeo/jcr/SimpleObject.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr; + +import java.util.UUID; + +public class SimpleObject { + private String string; + private String uuid = UUID.randomUUID().toString(); + private Integer integer; + private OtherObject otherObject; + private OtherObject anotherObject; + + public String getString() { + return string; + } + + public void setString(String sting) { + this.string = sting; + } + + public Integer getInteger() { + return integer; + } + + public void setInteger(Integer integer) { + this.integer = integer; + } + + public OtherObject getOtherObject() { + return otherObject; + } + + public void setOtherObject(OtherObject otherObject) { + this.otherObject = otherObject; + } + + public OtherObject getAnotherObject() { + return anotherObject; + } + + public void setAnotherObject(OtherObject anotherObject) { + this.anotherObject = anotherObject; + } + + @Override + public boolean equals(Object obj) { + return string.equals(((SimpleObject) obj).string); + } + + @Override + public int hashCode() { + return string.hashCode(); + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public String getUuid() { + return uuid; + } + +} diff --git a/org.argeo.server.jcr/src/test/java/org/argeo/jcr/tabular/JcrTabularTest.java b/org.argeo.server.jcr/src/test/java/org/argeo/jcr/tabular/JcrTabularTest.java new file mode 100644 index 000000000..2045f9ae5 --- /dev/null +++ b/org.argeo.server.jcr/src/test/java/org/argeo/jcr/tabular/JcrTabularTest.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jcr.tabular; + +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; + +import javax.jcr.Node; +import javax.jcr.PropertyType; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.jackrabbit.commons.cnd.CndImporter; +import org.argeo.jcr.AbstractInternalJackrabbitTestCase; +import org.argeo.jcr.ArgeoNames; +import org.argeo.jcr.ArgeoTypes; +import org.argeo.util.tabular.TabularColumn; +import org.argeo.util.tabular.TabularRow; +import org.argeo.util.tabular.TabularRowIterator; +import org.argeo.util.tabular.TabularWriter; + +public class JcrTabularTest extends AbstractInternalJackrabbitTestCase { + private final static Log log = LogFactory.getLog(JcrTabularTest.class); + + public void testWriteReadCsv() throws Exception { + session().setNamespacePrefix("argeo", ArgeoNames.ARGEO_NAMESPACE); + InputStreamReader reader = new InputStreamReader(getClass() + .getResourceAsStream("/org/argeo/jcr/argeo.cnd")); + CndImporter.registerNodeTypes(reader, session()); + reader.close(); + + // write + Integer columnCount = 15; + Long rowCount = 1000l; + String stringValue = "test, \ntest"; + + List header = new ArrayList(); + for (int i = 0; i < columnCount; i++) { + header.add(new TabularColumn("col" + i, PropertyType.STRING)); + } + Node tableNode = session().getRootNode().addNode("table", + ArgeoTypes.ARGEO_TABLE); + TabularWriter writer = new JcrTabularWriter(tableNode, header, + ArgeoTypes.ARGEO_CSV); + for (int i = 0; i < rowCount; i++) { + List objs = new ArrayList(); + for (int j = 0; j < columnCount; j++) { + objs.add(stringValue); + } + writer.appendRow(objs.toArray()); + } + writer.close(); + session().save(); + + if (log.isDebugEnabled()) + log.debug("Wrote tabular content " + rowCount + " rows, " + + columnCount + " columns"); + // read + TabularRowIterator rowIt = new JcrTabularRowIterator(tableNode); + Long count = 0l; + while (rowIt.hasNext()) { + TabularRow tr = rowIt.next(); + assertEquals(header.size(), tr.size()); + count++; + } + assertEquals(rowCount, count); + if (log.isDebugEnabled()) + log.debug("Read tabular content " + rowCount + " rows, " + + columnCount + " columns"); + } +} diff --git a/org.argeo.server.jcr/src/test/java/org/argeo/server/jcr/JcrResourceAdapterTest.java b/org.argeo.server.jcr/src/test/java/org/argeo/server/jcr/JcrResourceAdapterTest.java new file mode 100644 index 000000000..b691572e9 --- /dev/null +++ b/org.argeo.server.jcr/src/test/java/org/argeo/server/jcr/JcrResourceAdapterTest.java @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.server.jcr; + +import java.io.InputStream; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.List; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.jcr.AbstractInternalJackrabbitTestCase; +import org.argeo.jcr.JcrResourceAdapter; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; + +public class JcrResourceAdapterTest extends AbstractInternalJackrabbitTestCase { + private static SimpleDateFormat sdf = new SimpleDateFormat( + "yyyyMMdd:hhmmss.SSS"); + + private final static Log log = LogFactory + .getLog(JcrResourceAdapterTest.class); + + private JcrResourceAdapter jra; + + public void testCreate() throws Exception { + String basePath = "/test/subdir"; + jra.mkdirs(basePath); + Resource res = new ClassPathResource("org/argeo/server/jcr/dummy00.xls"); + String filePath = basePath + "/dummy.xml"; + jra.create(filePath, res.getInputStream(), "application/vnd.ms-excel"); + InputStream in = jra.retrieve(filePath); + assertTrue(IOUtils.contentEquals(res.getInputStream(), in)); + } + + public void testVersioning() throws Exception { + String basePath = "/test/versions"; + jra.mkdirs(basePath); + String filePath = basePath + "/dummy.xml"; + Resource res00 = new ClassPathResource( + "org/argeo/server/jcr/dummy00.xls"); + jra.create(filePath, res00.getInputStream(), "application/vnd.ms-excel"); + Resource res01 = new ClassPathResource( + "org/argeo/server/jcr/dummy01.xls"); + jra.update(filePath, res01.getInputStream()); + Resource res02 = new ClassPathResource( + "org/argeo/server/jcr/dummy02.xls"); + jra.update(filePath, res02.getInputStream()); + + List versions = jra.listVersions(filePath); + log.debug("Versions of " + filePath); + int count = 0; + for (Calendar version : versions) { + log.debug(" " + (count == 0 ? "base" : count - 1) + "\t" + + sdf.format(version.getTime())); + count++; + } + + assertEquals(4, versions.size()); + + InputStream in = jra.retrieve(filePath, 1); + assertTrue(IOUtils.contentEquals(res01.getInputStream(), in)); + in = jra.retrieve(filePath, 0); + assertTrue(IOUtils.contentEquals(res00.getInputStream(), in)); + in = jra.retrieve(filePath, 2); + assertTrue(IOUtils.contentEquals(res02.getInputStream(), in)); + Resource res03 = new ClassPathResource( + "org/argeo/server/jcr/dummy03.xls"); + jra.update(filePath, res03.getInputStream()); + in = jra.retrieve(filePath, 1); + assertTrue(IOUtils.contentEquals(res01.getInputStream(), in)); + } + + @Override + protected void setUp() throws Exception { + log.debug("SET UP"); + super.setUp(); + jra = new JcrResourceAdapter(); + jra.setSession(session()); + } + + @Override + protected void tearDown() throws Exception { + log.debug("TEAR DOWN"); + super.tearDown(); + } +} diff --git a/org.argeo.server.jcr/src/test/resources/log4j.properties b/org.argeo.server.jcr/src/test/resources/log4j.properties new file mode 100644 index 000000000..ca995af8e --- /dev/null +++ b/org.argeo.server.jcr/src/test/resources/log4j.properties @@ -0,0 +1,13 @@ +log4j.rootLogger=WARN, console + +## Levels +log4j.logger.org.argeo=DEBUG +log4j.logger.org.apache.jackrabbit=OFF + +## Appenders +# console is set to be a ConsoleAppender. +log4j.appender.console=org.apache.log4j.ConsoleAppender + +# console uses PatternLayout. +log4j.appender.console.layout=org.apache.log4j.PatternLayout +log4j.appender.console.layout.ConversionPattern= %-5p %d{ISO8601} %m - %c%n diff --git a/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/dummy00.xls b/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/dummy00.xls new file mode 100644 index 000000000..e5846fef7 Binary files /dev/null and b/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/dummy00.xls differ diff --git a/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/dummy01.xls b/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/dummy01.xls new file mode 100644 index 000000000..b5c6b5539 Binary files /dev/null and b/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/dummy01.xls differ diff --git a/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/dummy02.xls b/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/dummy02.xls new file mode 100644 index 000000000..d73bc6605 Binary files /dev/null and b/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/dummy02.xls differ diff --git a/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/dummy03.xls b/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/dummy03.xls new file mode 100644 index 000000000..0759cb927 Binary files /dev/null and b/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/dummy03.xls differ diff --git a/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/repository-h2.xml b/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/repository-h2.xml new file mode 100644 index 000000000..ef3f0c426 --- /dev/null +++ b/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/repository-h2.xml @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/repository-memory.xml b/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/repository-memory.xml new file mode 100644 index 000000000..839542417 --- /dev/null +++ b/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/repository-memory.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.server.rap.webapp/.project b/org.argeo.server.rap.webapp/.project new file mode 100644 index 000000000..3ffaae189 --- /dev/null +++ b/org.argeo.server.rap.webapp/.project @@ -0,0 +1,22 @@ + + + org.argeo.server.rap.webapp + + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + + diff --git a/org.argeo.server.rap.webapp/.settings/org.eclipse.pde.core.prefs b/org.argeo.server.rap.webapp/.settings/org.eclipse.pde.core.prefs new file mode 100644 index 000000000..fd884c249 --- /dev/null +++ b/org.argeo.server.rap.webapp/.settings/org.eclipse.pde.core.prefs @@ -0,0 +1,4 @@ +#Tue Mar 01 15:09:47 CET 2011 +eclipse.preferences.version=1 +pluginProject.extensions=false +resolve.requirebundle=false diff --git a/org.argeo.server.rap.webapp/META-INF/context-template.xml b/org.argeo.server.rap.webapp/META-INF/context-template.xml new file mode 100644 index 000000000..eaf6e86cc --- /dev/null +++ b/org.argeo.server.rap.webapp/META-INF/context-template.xml @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/org.argeo.server.rap.webapp/WEB-INF/applicationContext.xml b/org.argeo.server.rap.webapp/WEB-INF/applicationContext.xml new file mode 100644 index 000000000..336862453 --- /dev/null +++ b/org.argeo.server.rap.webapp/WEB-INF/applicationContext.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + osgibundle:rap-webapp.properties + + + + \ No newline at end of file diff --git a/org.argeo.server.rap.webapp/WEB-INF/osgi.xml b/org.argeo.server.rap.webapp/WEB-INF/osgi.xml new file mode 100644 index 000000000..fec44339b --- /dev/null +++ b/org.argeo.server.rap.webapp/WEB-INF/osgi.xml @@ -0,0 +1,16 @@ + + + + + + \ No newline at end of file diff --git a/org.argeo.server.rap.webapp/WEB-INF/security-filters.xml b/org.argeo.server.rap.webapp/WEB-INF/security-filters.xml new file mode 100644 index 000000000..4c7df6b06 --- /dev/null +++ b/org.argeo.server.rap.webapp/WEB-INF/security-filters.xml @@ -0,0 +1,144 @@ + + + + + + + + + + + + + + + + + + + PATTERN_TYPE_APACHE_ANT + /**=ROLE_USER,ROLE_ADMIN + + + + + + + PATTERN_TYPE_APACHE_ANT + /**=IS_AUTHENTICATED_ANONYMOUSLY + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${argeo.server.realmName} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.server.rap.webapp/WEB-INF/service-servlet.xml b/org.argeo.server.rap.webapp/WEB-INF/service-servlet.xml new file mode 100644 index 000000000..7a052199e --- /dev/null +++ b/org.argeo.server.rap.webapp/WEB-INF/service-servlet.xml @@ -0,0 +1,28 @@ + + + + + + + + osgiServiceController + + + + + + + org.eclipse.equinox.http.servlet.HttpServiceServlet + + + osgiService + + + \ No newline at end of file diff --git a/org.argeo.server.rap.webapp/WEB-INF/web.xml b/org.argeo.server.rap.webapp/WEB-INF/web.xml new file mode 100644 index 000000000..1b6e766e5 --- /dev/null +++ b/org.argeo.server.rap.webapp/WEB-INF/web.xml @@ -0,0 +1,66 @@ + + + + Argeo OSGi Webapp + + + + contextConfigLocation + /WEB-INF/applicationContext.xml + + + + Spring Context + org.springframework.web.context.ContextLoaderListener + + + contextClass + org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext + + + + + service + org.springframework.web.servlet.DispatcherServlet + + contextClass + org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext + + 1 + + + + service + /* + + + + + springSecurityFilterChain + org.springframework.web.filter.DelegatingFilterProxy + + + + springSecurityFilterChain + /private + + + springSecurityFilterChain + /basicauth + + + springSecurityFilterChain + /clientauth + + + springSecurityFilterChain + /none + + + springSecurityFilterChain + /public + + + diff --git a/org.argeo.server.rap.webapp/build.properties b/org.argeo.server.rap.webapp/build.properties new file mode 100644 index 000000000..29dea25a4 --- /dev/null +++ b/org.argeo.server.rap.webapp/build.properties @@ -0,0 +1,2 @@ +bin.includes = META-INF/,\ + WEB-INF/ diff --git a/org.argeo.server.rap.webapp/pom.xml b/org.argeo.server.rap.webapp/pom.xml new file mode 100644 index 000000000..abf636f5e --- /dev/null +++ b/org.argeo.server.rap.webapp/pom.xml @@ -0,0 +1,54 @@ + + 4.0.0 + + org.argeo.commons + 2.1.12-SNAPSHOT + argeo-commons + .. + + org.argeo.server.rap.webapp + Commons Server RAP Webapp + Integrates into OSGi HTTP registry + + + + org.apache.felix + maven-bundle-plugin + + + ui + + *, + + org.springframework.beans.factory.config, + + org.eclipse.equinox.http.servlet, + org.springframework.osgi.web.context.support, + org.springframework.security, + org.springframework.security.context, + org.springframework.security.intercept.web, + org.springframework.security.providers.anonymous, + org.springframework.security.ui, + org.springframework.security.ui.basicauth, + org.springframework.security.ui.logout, + org.springframework.security.ui.rememberme, + org.springframework.security.ui.webapp, + org.springframework.security.ui.preauth.x509, + org.springframework.security.userdetails, + org.springframework.security.util, + org.springframework.security.vote, + org.springframework.security.wrapper, + org.springframework.web.context, + org.springframework.web.filter, + org.springframework.web.servlet, + org.springframework.web.servlet.handler, + org.springframework.web.servlet.mvc, + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.server.rap.webapp/rap-webapp.properties b/org.argeo.server.rap.webapp/rap-webapp.properties new file mode 100644 index 000000000..012255a15 --- /dev/null +++ b/org.argeo.server.rap.webapp/rap-webapp.properties @@ -0,0 +1,2 @@ +argeo.security.systemKey=argeo +argeo.server.realmName=Argeo \ No newline at end of file diff --git a/org.argeo.support.junit/.classpath b/org.argeo.support.junit/.classpath new file mode 100644 index 000000000..3bf3adef5 --- /dev/null +++ b/org.argeo.support.junit/.classpath @@ -0,0 +1,7 @@ + + + + >> + + + diff --git a/org.argeo.support.junit/.project b/org.argeo.support.junit/.project new file mode 100644 index 000000000..cc37598f2 --- /dev/null +++ b/org.argeo.support.junit/.project @@ -0,0 +1,28 @@ + + + org.argeo.support.junit + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/org.argeo.support.junit/.settings/org.eclipse.jdt.core.prefs b/org.argeo.support.junit/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..383a4ec69 --- /dev/null +++ b/org.argeo.support.junit/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,5 @@ +#Tue Oct 13 10:02:09 CEST 2009 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.source=1.5 diff --git a/org.argeo.support.junit/.settings/org.maven.ide.eclipse.prefs b/org.argeo.support.junit/.settings/org.maven.ide.eclipse.prefs new file mode 100644 index 000000000..721e27ec2 --- /dev/null +++ b/org.argeo.support.junit/.settings/org.maven.ide.eclipse.prefs @@ -0,0 +1,9 @@ +#Tue Oct 13 10:01:59 CEST 2009 +activeProfiles= +eclipse.preferences.version=1 +fullBuildGoals=process-test-resources +includeModules=false +resolveWorkspaceProjects=true +resourceFilterGoals=process-resources resources\:testResources +skipCompilerPlugin=true +version=1 diff --git a/org.argeo.support.junit/pom.xml b/org.argeo.support.junit/pom.xml new file mode 100644 index 000000000..e836ca52c --- /dev/null +++ b/org.argeo.support.junit/pom.xml @@ -0,0 +1,64 @@ + + 4.0.0 + + org.argeo.commons + argeo-commons + 2.1.12-SNAPSHOT + .. + + org.argeo.support.junit + Commons Support JUnit + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-source-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + org.apache.felix + maven-bundle-plugin + + + + + org.argeo.support.junit.* + + org.springframework.core.io,* + + + + + + + + org.argeo.tp + junit + + + org.argeo.tp + org.springframework.core + + + org.argeo.tp + org.springframework.context + + + org.argeo.tp + org.springframework.beans + + + + + org.argeo.tp + slf4j.org.apache.commons.logging + + + \ No newline at end of file diff --git a/org.argeo.support.junit/src/main/java/org/argeo/support/junit/AbstractSpringTestCase.java b/org.argeo.support.junit/src/main/java/org/argeo/support/junit/AbstractSpringTestCase.java new file mode 100644 index 000000000..11a93e9cd --- /dev/null +++ b/org.argeo.support.junit/src/main/java/org/argeo/support/junit/AbstractSpringTestCase.java @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.support.junit; + +import java.util.Map; + +import junit.framework.TestCase; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.BeanFactoryUtils; +import org.springframework.beans.factory.ListableBeanFactory; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + + +/** Helper for tests using a Spring application context. */ +public abstract class AbstractSpringTestCase extends TestCase { + protected final Log log = LogFactory.getLog(getClass()); + private ConfigurableApplicationContext context; + + /** + * Gets (and creates if necessary) the application context to use. Default + * implementation uses a class path xml application context and calls + * {@link #getApplicationContextLocation()}. + */ + protected ConfigurableApplicationContext getContext() { + if (context == null) { + context = new ClassPathXmlApplicationContext( + getApplicationContextLocation()); + if (getIsStartContext()) + context.start(); + } + return context; + } + + /** Whether the context should be started after being created. */ + protected Boolean getIsStartContext() { + return false; + } + + /** Returns a bean from the underlying context */ + @SuppressWarnings(value = { "unchecked" }) + protected T getBean(String beanId) { + return (T) getContext().getBean(beanId); + } + + protected T getBean(Class clss) { + T bean = loadSingleFromContext(getContext(), clss); + if (bean == null) { + throw new RuntimeException("Cannot retrieve a unique bean of type " + + clss); + } else { + return bean; + } + } + + /** + * The location of the application to load. The default implementation + * returns applicationContext.xml found in the same package as the + * test. + */ + protected String getApplicationContextLocation() { + return inPackage("applicationContext.xml"); + } + + /** + * Prefixes the package of the class after converting the '.' to '/' in + * order to have a resource path. + */ + protected String inPackage(String suffix) { + String prefix = getClass().getPackage().getName().replace('.', '/'); + return prefix + '/' + suffix; + } + + @SuppressWarnings(value = { "unchecked" }) + protected T loadSingleFromContext(ListableBeanFactory context, + Class clss) { + Map beans = BeanFactoryUtils.beansOfTypeIncludingAncestors( + context, clss, false, false); + if (beans.size() == 1) { + return beans.values().iterator().next(); + } else if (beans.size() > 1) { + if (log.isDebugEnabled()) { + log + .debug(("Found more that one bean for type " + clss + + ": " + beans.keySet())); + } + return null; + } else { + return null; + } + } + +} diff --git a/org.argeo.util/.classpath b/org.argeo.util/.classpath new file mode 100644 index 000000000..8499fd0fa --- /dev/null +++ b/org.argeo.util/.classpath @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/org.argeo.util/.project b/org.argeo.util/.project new file mode 100644 index 000000000..171ff88dc --- /dev/null +++ b/org.argeo.util/.project @@ -0,0 +1,28 @@ + + + org.argeo.util + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.pde.PluginNature + + diff --git a/org.argeo.util/build.properties b/org.argeo.util/build.properties new file mode 100644 index 000000000..fcffb0f5e --- /dev/null +++ b/org.argeo.util/build.properties @@ -0,0 +1,6 @@ +source.. = src/main/java/,\ + src/test/resources/,\ + src/test/java/ +bin.includes = META-INF/,\ + . +additional.bundles = junit diff --git a/org.argeo.util/pom.xml b/org.argeo.util/pom.xml new file mode 100644 index 000000000..9077e7fc5 --- /dev/null +++ b/org.argeo.util/pom.xml @@ -0,0 +1,33 @@ + + 4.0.0 + + org.argeo.commons + argeo-commons + 2.1.12-SNAPSHOT + .. + + org.argeo.util + Commons Util (no third party dependencies) + + + + org.apache.felix + maven-bundle-plugin + + + + org.argeo.* + + + + + + + + + org.argeo.tp + junit + test + + + \ No newline at end of file diff --git a/org.argeo.util/src/main/java/org/argeo/ArgeoException.java b/org.argeo.util/src/main/java/org/argeo/ArgeoException.java new file mode 100644 index 000000000..9cf918667 --- /dev/null +++ b/org.argeo.util/src/main/java/org/argeo/ArgeoException.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo; + +/** Argeo Commons specific exception. */ +public class ArgeoException extends RuntimeException { + private static final long serialVersionUID = 1L; + + /** Creates an exception with a message. */ + public ArgeoException(String message) { + super(message); + } + + /** Creates an exception with a message and a root cause. */ + public ArgeoException(String message, Throwable e) { + super(message, e); + } + + /** + * Chain the messages of all causes (one per line, starts with a line + * return) without all the stack + */ + public static String chainCausesMessages(Throwable t) { + StringBuffer buf = new StringBuffer(); + chainCauseMessage(buf, t); + return buf.toString(); + } + + /** Recursive chaining of messages */ + private static void chainCauseMessage(StringBuffer buf, Throwable t) { + buf.append('\n').append(' ').append(t.getClass().getCanonicalName()) + .append(": ").append(t.getMessage()); + if (t.getCause() != null) + chainCauseMessage(buf, t.getCause()); + } +} diff --git a/org.argeo.util/src/main/java/org/argeo/ArgeoLogListener.java b/org.argeo.util/src/main/java/org/argeo/ArgeoLogListener.java new file mode 100644 index 000000000..bac8a9820 --- /dev/null +++ b/org.argeo.util/src/main/java/org/argeo/ArgeoLogListener.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo; + +/** Framework agnostic interface for log notifications */ +public interface ArgeoLogListener { + /** + * Appends a log + * + * @param username + * authentified user, null for anonymous + * @param level + * INFO, DEBUG, WARN, etc. (logging framework specific) + * @param category + * hierarchy (logging framework specific) + * @param thread + * name of the thread which logged this message + * @param msg + * any object as long as its toString() method returns the + * message + * @param the + * exception in log4j ThrowableStrRep format + */ + public void appendLog(String username, Long timestamp, String level, + String category, String thread, Object msg, String[] exception); +} diff --git a/org.argeo.util/src/main/java/org/argeo/ArgeoLogger.java b/org.argeo.util/src/main/java/org/argeo/ArgeoLogger.java new file mode 100644 index 000000000..0657c29dd --- /dev/null +++ b/org.argeo.util/src/main/java/org/argeo/ArgeoLogger.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo; + +/** + * Logging framework agnostic identifying a logging service, to which one can + * register + */ +public interface ArgeoLogger { + /** + * Register for events by threads with the same authentication (or all + * threads if admin) + */ + public void register(ArgeoLogListener listener, + Integer numberOfPreviousEvents); + + /** + * For admin use only: register for all users + * + * @param listener + * the log listener + * @param numberOfPreviousEvents + * the number of previous events to notify + * @param everything + * if true even anonymous is logged + */ + public void registerForAll(ArgeoLogListener listener, + Integer numberOfPreviousEvents, boolean everything); + + public void unregister(ArgeoLogListener listener); + + public void unregisterForAll(ArgeoLogListener listener); +} diff --git a/org.argeo.util/src/main/java/org/argeo/ArgeoMonitor.java b/org.argeo.util/src/main/java/org/argeo/ArgeoMonitor.java new file mode 100644 index 000000000..9ef23cc8b --- /dev/null +++ b/org.argeo.util/src/main/java/org/argeo/ArgeoMonitor.java @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo; + +/** + * Simple monitor abstraction. Inspired by Eclipse IProgressMOnitor, but without + * dependency to it. + */ +public interface ArgeoMonitor { + /** + * Constant indicating an unknown amount of work. + */ + public final static int UNKNOWN = -1; + + /** + * Notifies that the main task is beginning. This must only be called once + * on a given progress monitor instance. + * + * @param name + * the name (or description) of the main task + * @param totalWork + * the total number of work units into which the main task is + * been subdivided. If the value is UNKNOWN the + * implementation is free to indicate progress in a way which + * doesn't require the total number of work units in advance. + */ + public void beginTask(String name, int totalWork); + + /** + * Notifies that the work is done; that is, either the main task is + * completed or the user canceled it. This method may be called more than + * once (implementations should be prepared to handle this case). + */ + public void done(); + + /** + * Returns whether cancelation of current operation has been requested. + * Long-running operations should poll to see if cancelation has been + * requested. + * + * @return true if cancellation has been requested, and + * false otherwise + * @see #setCanceled(boolean) + */ + public boolean isCanceled(); + + /** + * Sets the cancel state to the given value. + * + * @param value + * true indicates that cancelation has been + * requested (but not necessarily acknowledged); + * false clears this flag + * @see #isCanceled() + */ + public void setCanceled(boolean value); + + /** + * Sets the task name to the given value. This method is used to restore the + * task label after a nested operation was executed. Normally there is no + * need for clients to call this method. + * + * @param name + * the name (or description) of the main task + * @see #beginTask(java.lang.String, int) + */ + public void setTaskName(String name); + + /** + * Notifies that a subtask of the main task is beginning. Subtasks are + * optional; the main task might not have subtasks. + * + * @param name + * the name (or description) of the subtask + */ + public void subTask(String name); + + /** + * Notifies that a given number of work unit of the main task has been + * completed. Note that this amount represents an installment, as opposed to + * a cumulative amount of work done to date. + * + * @param work + * a non-negative number of work units just completed + */ + public void worked(int work); + +} diff --git a/org.argeo.util/src/main/java/org/argeo/OperatingSystem.java b/org.argeo.util/src/main/java/org/argeo/OperatingSystem.java new file mode 100644 index 000000000..697c86c51 --- /dev/null +++ b/org.argeo.util/src/main/java/org/argeo/OperatingSystem.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo; + +/** The current operating system. */ +public class OperatingSystem { + public final static int NIX = 1; + public final static int WINDOWS = 2; + public final static int SOLARIS = 3; + + public final static int os; + static { + String osName = System.getProperty("os.name"); + if (osName.startsWith("Win")) + os = WINDOWS; + else if (osName.startsWith("Solaris")) + os = SOLARIS; + else + os = NIX; + } + +} diff --git a/org.argeo.util/src/main/java/org/argeo/StreamUtils.java b/org.argeo.util/src/main/java/org/argeo/StreamUtils.java new file mode 100644 index 000000000..39caaddda --- /dev/null +++ b/org.argeo.util/src/main/java/org/argeo/StreamUtils.java @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; + +/** Utilities to be used when APache COmmons IO is not available. */ +public class StreamUtils { + private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; + + /* + * APACHE COMMONS IO (inspired) + */ + + /** @return the number of bytes */ + public static Long copy(InputStream in, OutputStream out) + throws IOException { + Long count = 0l; + byte[] buf = new byte[DEFAULT_BUFFER_SIZE]; + while (true) { + int length = in.read(buf); + if (length < 0) + break; + out.write(buf, 0, length); + count = count + length; + } + return count; + } + + /** @return the number of chars */ + public static Long copy(Reader in, Writer out) throws IOException { + Long count = 0l; + char[] buf = new char[DEFAULT_BUFFER_SIZE]; + while (true) { + int length = in.read(buf); + if (length < 0) + break; + out.write(buf, 0, length); + count = count + length; + } + return count; + } + + public static void closeQuietly(InputStream in) { + if (in != null) + try { + in.close(); + } catch (Exception e) { + // + } + } + + public static void closeQuietly(OutputStream out) { + if (out != null) + try { + out.close(); + } catch (Exception e) { + // + } + } + + public static void closeQuietly(Reader in) { + if (in != null) + try { + in.close(); + } catch (Exception e) { + // + } + } + + public static void closeQuietly(Writer out) { + if (out != null) + try { + out.close(); + } catch (Exception e) { + // + } + } + + /* + * APACHE COMMONS CODEC (forked) + */ + /** + * Used to build output as Hex + */ + private static final char[] DIGITS_LOWER = { '0', '1', '2', '3', '4', '5', + '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + + /** + * Used to build output as Hex + */ + private static final char[] DIGITS_UPPER = { '0', '1', '2', '3', '4', '5', + '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + + /** + * Converts an array of bytes into a String representing the hexadecimal + * values of each byte in order. The returned String will be double the + * length of the passed array, as it takes two characters to represent any + * given byte. + * + * @param data + * a byte[] to convert to Hex characters + * @return A String containing hexadecimal characters + * @since 1.4 + */ + public static String encodeHexString(byte[] data) { + return new String(encodeHex(data)); + } + + /** + * Converts an array of bytes into an array of characters representing the + * hexadecimal values of each byte in order. The returned array will be + * double the length of the passed array, as it takes two characters to + * represent any given byte. + * + * @param data + * a byte[] to convert to Hex characters + * @return A char[] containing hexadecimal characters + */ + public static char[] encodeHex(byte[] data) { + return encodeHex(data, true); + } + + /** + * Converts an array of bytes into an array of characters representing the + * hexadecimal values of each byte in order. The returned array will be + * double the length of the passed array, as it takes two characters to + * represent any given byte. + * + * @param data + * a byte[] to convert to Hex characters + * @param toLowerCase + * true converts to lowercase, false to + * uppercase + * @return A char[] containing hexadecimal characters + * @since 1.4 + */ + public static char[] encodeHex(byte[] data, boolean toLowerCase) { + return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER); + } + + /** + * Converts an array of bytes into an array of characters representing the + * hexadecimal values of each byte in order. The returned array will be + * double the length of the passed array, as it takes two characters to + * represent any given byte. + * + * @param data + * a byte[] to convert to Hex characters + * @param toDigits + * the output alphabet + * @return A char[] containing hexadecimal characters + * @since 1.4 + */ + protected static char[] encodeHex(byte[] data, char[] toDigits) { + int l = data.length; + char[] out = new char[l << 1]; + // two characters form the hex value. + for (int i = 0, j = 0; i < l; i++) { + out[j++] = toDigits[(0xF0 & data[i]) >>> 4]; + out[j++] = toDigits[0x0F & data[i]]; + } + return out; + } + +} diff --git a/org.argeo.util/src/main/java/org/argeo/util/CsvParser.java b/org.argeo.util/src/main/java/org/argeo/util/CsvParser.java new file mode 100644 index 000000000..7680b3267 --- /dev/null +++ b/org.argeo.util/src/main/java/org/argeo/util/CsvParser.java @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.util; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.argeo.ArgeoException; +import org.argeo.StreamUtils; + +/** + * Parses a CSV file interpreting the first line as a header. The + * {@link #parse(InputStream)} method and the setters are synchronized so that + * the object cannot be modified when parsing. + */ +public abstract class CsvParser { + private char separator = ','; + private char quote = '\"'; + + private Boolean noHeader = false; + private Boolean strictLineAsLongAsHeader = true; + + /** + * Actually process a parsed line. If + * {@link #setStrictLineAsLongAsHeader(Boolean)} is true (default) the + * header and the tokens are guaranteed to have the same size. + * + * @param lineNumber + * the current line number, starts at 1 (the header, if header + * processing is enabled, the first line otherwise) + * @param header + * the read-only header or null if {@link #setNoHeader(Boolean)} + * is true (default is false) + * @param tokens + * the parsed tokens + */ + protected abstract void processLine(Integer lineNumber, + List header, List tokens); + + /** + * Parses the CSV file (stream is closed at the end) + */ + public synchronized void parse(InputStream in) { + parse(in, null); + } + + /** + * Parses the CSV file (stream is closed at the end) + */ + public synchronized void parse(InputStream in, String encoding) { + BufferedReader reader = null; + Integer lineCount = 0; + try { + if (encoding == null) + reader = new BufferedReader(new InputStreamReader(in)); + else + reader = new BufferedReader(new InputStreamReader(in, encoding)); + List header = null; + if (!noHeader) { + String headerStr = reader.readLine(); + if (headerStr == null)// empty file + return; + lineCount++; + header = new ArrayList(); + StringBuffer currStr = new StringBuffer(""); + Boolean wasInquote = false; + while (parseLine(headerStr, header, currStr, wasInquote)) { + headerStr = reader.readLine(); + if (headerStr == null) + break; + wasInquote = true; + } + header = Collections.unmodifiableList(header); + } + + String line = null; + lines: while ((line = reader.readLine()) != null) { + line = preProcessLine(line); + if (line == null) { + // skip line + continue lines; + } + lineCount++; + List tokens = new ArrayList(); + StringBuffer currStr = new StringBuffer(""); + Boolean wasInquote = false; + sublines: while (parseLine(line, tokens, currStr, wasInquote)) { + line = reader.readLine(); + if (line == null) + break sublines; + wasInquote = true; + } + if (!noHeader && strictLineAsLongAsHeader) { + int headerSize = header.size(); + int tokenSize = tokens.size(); + if (tokenSize == 1 && line.trim().equals("")) + continue lines;// empty line + if (headerSize != tokenSize) { + throw new ArgeoException("Token size " + tokenSize + + " is different from header size " + + headerSize + " at line " + lineCount + + ", line: " + line + ", header: " + header + + ", tokens: " + tokens); + } + } + processLine(lineCount, header, tokens); + } + } catch (ArgeoException e) { + throw e; + } catch (IOException e) { + throw new ArgeoException("Cannot parse CSV file (line: " + + lineCount + ")", e); + } finally { + StreamUtils.closeQuietly(reader); + } + } + + /** + * Called before each (logical) line is processed, giving a change to modify + * it (typically for cleaning dirty files). To be overridden, return the + * line unchanged by default. Skip the line if 'null' is returned. + */ + protected String preProcessLine(String line) { + return line; + } + + /** + * Parses a line character by character for performance purpose + * + * @return whether to continue parsing this line + */ + protected Boolean parseLine(String str, List tokens, + StringBuffer currStr, Boolean wasInquote) { + // List tokens = new ArrayList(); + + // System.out.println("#LINE: " + str); + + if (wasInquote) + currStr.append('\n'); + + char[] arr = str.toCharArray(); + boolean inQuote = wasInquote; + // StringBuffer currStr = new StringBuffer(""); + for (int i = 0; i < arr.length; i++) { + char c = arr[i]; + if (c == separator) { + if (!inQuote) { + tokens.add(currStr.toString()); + // System.out.println("# TOKEN: " + currStr); + currStr.delete(0, currStr.length()); + } else { + // we don't remove separator that are in a quoted substring + // System.out + // .println("IN QUOTE, got a separator: [" + c + "]"); + currStr.append(c); + } + } else if (c == quote) { + if (inQuote && (i + 1) < arr.length && arr[i + 1] == quote) { + // case of double quote + currStr.append(quote); + i++; + } else {// standard + inQuote = inQuote ? false : true; + } + } else { + currStr.append(c); + } + } + + if (!inQuote) { + tokens.add(currStr.toString()); + // System.out.println("# TOKEN: " + currStr); + } + // if (inQuote) + // throw new ArgeoException("Missing quote at the end of the line " + // + str + " (parsed: " + tokens + ")"); + if (inQuote) + return true; + else + return false; + // return tokens; + } + + public char getSeparator() { + return separator; + } + + public synchronized void setSeparator(char separator) { + this.separator = separator; + } + + public char getQuote() { + return quote; + } + + public synchronized void setQuote(char quote) { + this.quote = quote; + } + + public Boolean getNoHeader() { + return noHeader; + } + + public synchronized void setNoHeader(Boolean noHeader) { + this.noHeader = noHeader; + } + + public Boolean getStrictLineAsLongAsHeader() { + return strictLineAsLongAsHeader; + } + + public synchronized void setStrictLineAsLongAsHeader( + Boolean strictLineAsLongAsHeader) { + this.strictLineAsLongAsHeader = strictLineAsLongAsHeader; + } + +} diff --git a/org.argeo.util/src/main/java/org/argeo/util/CsvParserWithLinesAsMap.java b/org.argeo.util/src/main/java/org/argeo/util/CsvParserWithLinesAsMap.java new file mode 100644 index 000000000..e7baabbf0 --- /dev/null +++ b/org.argeo.util/src/main/java/org/argeo/util/CsvParserWithLinesAsMap.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.util; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.argeo.ArgeoException; + +/** + * CSV parser allowing to process lines as maps whose keys are the header + * fields. + */ +public abstract class CsvParserWithLinesAsMap extends CsvParser { + + /** + * Actually processes a line. + * + * @param lineNumber + * the current line number, starts at 1 (the header, if header + * processing is enabled, the first lien otherwise) + * @param line + * the parsed tokens as a map whose keys are the header fields + */ + protected abstract void processLine(Integer lineNumber, + Map line); + + protected final void processLine(Integer lineNumber, List header, + List tokens) { + if (header == null) + throw new ArgeoException("Only CSV with header is supported"); + Map line = new HashMap(); + for (int i = 0; i < header.size(); i++) { + String key = header.get(i); + String value = null; + if (i < tokens.size()) + value = tokens.get(i); + line.put(key, value); + } + processLine(lineNumber, line); + } + +} diff --git a/org.argeo.util/src/main/java/org/argeo/util/CsvWriter.java b/org.argeo.util/src/main/java/org/argeo/util/CsvWriter.java new file mode 100644 index 000000000..d90f47412 --- /dev/null +++ b/org.argeo.util/src/main/java/org/argeo/util/CsvWriter.java @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.util; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.UnsupportedEncodingException; +import java.io.Writer; +import java.util.Iterator; +import java.util.List; + +import org.argeo.ArgeoException; + +/** Write in CSV format. */ +public class CsvWriter { + private final Writer out; + + private char separator = ','; + private char quote = '\"'; + + /** + * Creates a CSV writer. + * + * @param out + * the stream to write to. Caller is responsible for closing it. + */ + public CsvWriter(OutputStream out) { + this.out = new OutputStreamWriter(out); + } + + /** + * Creates a CSV writer. + * + * @param out + * the stream to write to. Caller is responsible for closing it. + */ + public CsvWriter(OutputStream out, String encoding) { + try { + this.out = new OutputStreamWriter(out, encoding); + } catch (UnsupportedEncodingException e) { + throw new ArgeoException("Cannot initialize CSV writer", e); + } + } + + /** + * Write a CSV line. Also used to write a header if needed (this is + * transparent for the CSV writer): simply call it first, before writing the + * lines. + */ + public void writeLine(List tokens) { + try { + Iterator it = tokens.iterator(); + while (it.hasNext()) { + writeToken(it.next().toString()); + if (it.hasNext()) + out.write(separator); + } + out.write('\n'); + out.flush(); + } catch (IOException e) { + throw new ArgeoException("Could not write " + tokens, e); + } + } + + /** + * Write a CSV line. Also used to write a header if needed (this is + * transparent for the CSV writer): simply call it first, before writing the + * lines. + */ + public void writeLine(Object[] tokens) { + try { + for (int i = 0; i < tokens.length; i++) { + if (tokens[i] == null) { + // TODO configure how to deal with null + writeToken(""); + } else { + writeToken(tokens[i].toString()); + } + if (i != (tokens.length - 1)) + out.write(separator); + } + out.write('\n'); + out.flush(); + } catch (IOException e) { + throw new ArgeoException("Could not write " + tokens, e); + } + } + + protected void writeToken(String token) throws IOException { + // +2 for possible quotes, another +2 assuming there would be an already + // quoted string where quotes needs to be duplicated + // another +2 for safety + // we don't want to increase buffer size while writing + StringBuffer buf = new StringBuffer(token.length() + 6); + char[] arr = token.toCharArray(); + boolean shouldQuote = false; + for (char c : arr) { + if (!shouldQuote) { + if (c == separator) + shouldQuote = true; + if (c == '\n') + shouldQuote = true; + } + + if (c == quote) { + shouldQuote = true; + // duplicate quote + buf.append(quote); + } + + // generic case + buf.append(c); + } + + if (shouldQuote == true) + out.write(quote); + out.write(buf.toString()); + if (shouldQuote == true) + out.write(quote); + } + + public void setSeparator(char separator) { + this.separator = separator; + } + + public void setQuote(char quote) { + this.quote = quote; + } + +} diff --git a/org.argeo.util/src/main/java/org/argeo/util/LocaleCallback.java b/org.argeo.util/src/main/java/org/argeo/util/LocaleCallback.java new file mode 100644 index 000000000..60bf4c40f --- /dev/null +++ b/org.argeo.util/src/main/java/org/argeo/util/LocaleCallback.java @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.util; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Locale; + +import javax.security.auth.callback.Callback; + +/** Choose in a list of locales */ +public class LocaleCallback implements Callback { + private List availableLocales = new ArrayList(); + + private Integer selectedIndex = null; + private Integer defaultIndex = null; + private String prompt = "Language"; + + public LocaleCallback(Integer defaultIndex, List availableLocales) { + this.availableLocales = Collections + .unmodifiableList(new ArrayList(availableLocales)); + this.defaultIndex = defaultIndex; + this.selectedIndex = defaultIndex; + } + + /** + * Convenience constructor based on a comma separated list of iso codes (en, + * en_US, fr_CA, etc.). Default selection is default locale. + */ + public LocaleCallback(String locales) { + if (locales == null || locales.trim().equals("")) + return; + String[] codes = locales.split(","); + for (int i = 0; i < codes.length; i++) { + String code = codes[i]; + // variant not supported + int indexUnd = code.indexOf("_"); + Locale locale; + if (indexUnd > 0) { + String language = code.substring(0, indexUnd); + String country = code.substring(indexUnd + 1); + locale = new Locale(language, country); + } else { + locale = new Locale(code); + } + availableLocales.add(locale); + if (locale.equals(Locale.getDefault())) + defaultIndex = i; + } + + if (defaultIndex == null) + defaultIndex = 0; + + this.selectedIndex = defaultIndex; + } + + public String[] getSupportedLocalesLabels() { + String[] labels = new String[availableLocales.size()]; + for (int i = 0; i < availableLocales.size(); i++) { + Locale locale = availableLocales.get(i); + if (locale.getCountry().equals("")) + labels[i] = locale.getDisplayLanguage(locale) + " [" + + locale.getLanguage() + "]"; + else + labels[i] = locale.getDisplayLanguage(locale) + " (" + + locale.getDisplayCountry(locale) + ") [" + + locale.getLanguage() + "_" + locale.getCountry() + + "]"; + + } + return labels; + } + + public Locale getSelectedLocale() { + if (selectedIndex == null) + return null; + return availableLocales.get(selectedIndex); + } + + public void setSelectedIndex(Integer selectedIndex) { + this.selectedIndex = selectedIndex; + } + + public Integer getDefaultIndex() { + return defaultIndex; + } + + public String getPrompt() { + // TODO localize it? + return prompt; + } + + public void setPrompt(String prompt) { + this.prompt = prompt; + } + + public List getAvailableLocales() { + return availableLocales; + } + + public static void main(String[] args) { + for (String isoL : Locale.getISOLanguages()) { + Locale locale = new Locale(isoL); + System.out.println(isoL + "\t" + locale.getDisplayLanguage() + "\t" + + locale.getDisplayLanguage(locale)); + } + } + +} diff --git a/org.argeo.util/src/main/java/org/argeo/util/LocaleUtils.java b/org.argeo.util/src/main/java/org/argeo/util/LocaleUtils.java new file mode 100644 index 000000000..bc04afa75 --- /dev/null +++ b/org.argeo.util/src/main/java/org/argeo/util/LocaleUtils.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.util; + +import java.util.Locale; + +import org.argeo.ArgeoException; + +/** Utilities around internationalization. */ +public class LocaleUtils { + /** + * The locale of the current thread and its children. Allows to deal with + * internationalisation as a cross cutting aspect. Never null. + */ + public final static InheritableThreadLocal threadLocale = new InheritableThreadLocal() { + @Override + protected Locale initialValue() { + return Locale.getDefault(); + } + + @Override + public void set(Locale value) { + if (value == null) + throw new ArgeoException("Thread local cannot be null."); + super.set(value); + } + + }; +} diff --git a/org.argeo.util/src/main/java/org/argeo/util/Throughput.java b/org.argeo.util/src/main/java/org/argeo/util/Throughput.java new file mode 100644 index 000000000..d081189e2 --- /dev/null +++ b/org.argeo.util/src/main/java/org/argeo/util/Throughput.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.util; + +import java.text.NumberFormat; +import java.text.ParseException; +import java.util.Locale; + +import org.argeo.ArgeoException; + +public class Throughput { + private final static NumberFormat usNumberFormat = NumberFormat + .getInstance(Locale.US); + + public enum Unit { + s, m, h, d + } + + private final Double value; + private final Unit unit; + + public Throughput(Double value, Unit unit) { + this.value = value; + this.unit = unit; + } + + public Throughput(Long periodMs, Long count, Unit unit) { + if (unit.equals(Unit.s)) + value = ((double) count * 1000d) / periodMs; + else if (unit.equals(Unit.m)) + value = ((double) count * 60d * 1000d) / periodMs; + else if (unit.equals(Unit.h)) + value = ((double) count * 60d * 60d * 1000d) / periodMs; + else if (unit.equals(Unit.d)) + value = ((double) count * 24d * 60d * 60d * 1000d) / periodMs; + else + throw new ArgeoException("Unsupported unit " + unit); + this.unit = unit; + } + + public Throughput(Double value, String unitStr) { + this(value, Unit.valueOf(unitStr)); + } + + public Throughput(String def) { + int index = def.indexOf('/'); + if (def.length() < 3 || index <= 0 || index != def.length() - 2) + throw new ArgeoException(def + " no a proper throughput definition" + + " (should be /, e.g. 3.54/s or 1500/h"); + String valueStr = def.substring(0, index); + String unitStr = def.substring(index + 1); + try { + this.value = usNumberFormat.parse(valueStr).doubleValue(); + } catch (ParseException e) { + throw new ArgeoException("Cannot parse " + valueStr + + " as a number.", e); + } + this.unit = Unit.valueOf(unitStr); + } + + public Long asMsPeriod() { + if (unit.equals(Unit.s)) + return Math.round(1000d / value); + else if (unit.equals(Unit.m)) + return Math.round((60d * 1000d) / value); + else if (unit.equals(Unit.h)) + return Math.round((60d * 60d * 1000d) / value); + else if (unit.equals(Unit.d)) + return Math.round((24d * 60d * 60d * 1000d) / value); + else + throw new ArgeoException("Unsupported unit " + unit); + } + + @Override + public String toString() { + return usNumberFormat.format(value) + '/' + unit; + } + + public Double getValue() { + return value; + } + + public Unit getUnit() { + return unit; + } + +} diff --git a/org.argeo.util/src/main/java/org/argeo/util/ThroughputEditor.java b/org.argeo.util/src/main/java/org/argeo/util/ThroughputEditor.java new file mode 100644 index 000000000..4ebf26b81 --- /dev/null +++ b/org.argeo.util/src/main/java/org/argeo/util/ThroughputEditor.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.util; + +import java.beans.PropertyEditorSupport; + +public class ThroughputEditor extends PropertyEditorSupport { + + @Override + public String getAsText() { + return getValue().toString(); + } + + @Override + public void setAsText(String text) throws IllegalArgumentException { + setValue(new Throughput(text)); + } + +} diff --git a/org.argeo.util/src/main/java/org/argeo/util/security/DigestUtils.java b/org.argeo.util/src/main/java/org/argeo/util/security/DigestUtils.java new file mode 100644 index 000000000..b6aae6fd4 --- /dev/null +++ b/org.argeo.util/src/main/java/org/argeo/util/security/DigestUtils.java @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.util.security; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +import org.argeo.ArgeoException; +import org.argeo.StreamUtils; + +/** Utilities around cryptographic digests */ +public class DigestUtils { + private static Boolean debug = true; + // TODO: make it writable + private final static Integer byteBufferCapacity = 100 * 1024;// 100 KB + + public static String digest(String algorithm, byte[] bytes) { + try { + MessageDigest digest = MessageDigest.getInstance(algorithm); + digest.update(bytes); + byte[] checksum = digest.digest(); + String res = StreamUtils.encodeHexString(checksum); + return res; + } catch (Exception e) { + throw new ArgeoException("Cannot digest with algorithm " + + algorithm, e); + } + } + + public static String digest(String algorithm, InputStream in) { + try { + MessageDigest digest = MessageDigest.getInstance(algorithm); + // ReadableByteChannel channel = Channels.newChannel(in); + // ByteBuffer bb = ByteBuffer.allocateDirect(byteBufferCapacity); + // while (channel.read(bb) > 0) + // digest.update(bb); + byte[] buffer = new byte[byteBufferCapacity]; + int read = 0; + while ((read = in.read(buffer)) > 0) { + digest.update(buffer, 0, read); + } + + byte[] checksum = digest.digest(); + String res = StreamUtils.encodeHexString(checksum); + return res; + } catch (Exception e) { + throw new ArgeoException("Cannot digest with algorithm " + + algorithm, e); + } finally { + StreamUtils.closeQuietly(in); + } + } + + public static String digest(String algorithm, File file) { + FileInputStream fis = null; + FileChannel fc = null; + try { + fis = new FileInputStream(file); + fc = fis.getChannel(); + + // Get the file's size and then map it into memory + int sz = (int) fc.size(); + ByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, sz); + return digest(algorithm, bb); + } catch (IOException e) { + throw new ArgeoException("Cannot digest " + file + + " with algorithm " + algorithm, e); + } finally { + StreamUtils.closeQuietly(fis); + if (fc.isOpen()) + try { + fc.close(); + } catch (IOException e) { + // silent + } + } + } + + protected static String digest(String algorithm, ByteBuffer bb) { + long begin = System.currentTimeMillis(); + try { + MessageDigest digest = MessageDigest.getInstance(algorithm); + digest.update(bb); + byte[] checksum = digest.digest(); + String res = StreamUtils.encodeHexString(checksum); + long end = System.currentTimeMillis(); + if (debug) + System.out.println((end - begin) + " ms / " + + ((end - begin) / 1000) + " s"); + return res; + } catch (NoSuchAlgorithmException e) { + throw new ArgeoException("Cannot digest with algorithm " + + algorithm, e); + } + } + + public static void main(String[] args) { + File file; + if (args.length > 0) + file = new File(args[0]); + else { + System.err.println("Usage: []" + + " (see http://java.sun.com/j2se/1.5.0/" + + "docs/guide/security/CryptoSpec.html#AppA)"); + return; + } + + if (args.length > 1) { + String algorithm = args[1]; + System.out.println(digest(algorithm, file)); + } else { + String algorithm = "MD5"; + System.out.println(algorithm + ": " + digest(algorithm, file)); + algorithm = "SHA"; + System.out.println(algorithm + ": " + digest(algorithm, file)); + algorithm = "SHA-256"; + System.out.println(algorithm + ": " + digest(algorithm, file)); + algorithm = "SHA-512"; + System.out.println(algorithm + ": " + digest(algorithm, file)); + } + } + +} diff --git a/org.argeo.util/src/main/java/org/argeo/util/security/Keyring.java b/org.argeo.util/src/main/java/org/argeo/util/security/Keyring.java new file mode 100644 index 000000000..10dbabd49 --- /dev/null +++ b/org.argeo.util/src/main/java/org/argeo/util/security/Keyring.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.util.security; + +import java.io.InputStream; + +/** + * Access to private (typically encrypted) data. The keyring is responsible for + * retrieving the necessary credentials. Experimental. This API may + * change. + */ +public interface Keyring { + public void changePassword(char[] oldPassword, char[] newPassword); + + /** + * Returns the confidential information as chars. Must ask for it if it is + * not stored. + */ + public char[] getAsChars(String path); + + /** + * Returns the confidential information as a stream. Must ask for it if it + * is not stored. + */ + public InputStream getAsStream(String path); + + public void set(String path, char[] arr); + + public void set(String path, InputStream in); +} diff --git a/org.argeo.util/src/main/java/org/argeo/util/security/SimplePrincipal.java b/org.argeo.util/src/main/java/org/argeo/util/security/SimplePrincipal.java new file mode 100644 index 000000000..c7a4daf12 --- /dev/null +++ b/org.argeo.util/src/main/java/org/argeo/util/security/SimplePrincipal.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.util.security; + +import java.security.Principal; + +import org.argeo.ArgeoException; + +/** Canonical implementation of a {@link Principal} */ +public class SimplePrincipal implements Principal { + private final String name; + + public SimplePrincipal(String name) { + if (name == null) + throw new ArgeoException("Principal name cannot be null"); + this.name = name; + } + + public String getName() { + return name; + } + + @Override + public int hashCode() { + return name.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == null) + return false; + return name.equals(obj.toString()); + } + + @Override + protected Object clone() throws CloneNotSupportedException { + return new SimplePrincipal(name); + } + + @Override + public String toString() { + return name; + } + +} diff --git a/org.argeo.util/src/main/java/org/argeo/util/tabular/ArrayTabularRow.java b/org.argeo.util/src/main/java/org/argeo/util/tabular/ArrayTabularRow.java new file mode 100644 index 000000000..b1672e94c --- /dev/null +++ b/org.argeo.util/src/main/java/org/argeo/util/tabular/ArrayTabularRow.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.util.tabular; + +import java.util.List; + +/** Minimal tabular row wrapping an {@link Object} array */ +public class ArrayTabularRow implements TabularRow { + private final Object[] arr; + + public ArrayTabularRow(List objs) { + this.arr = objs.toArray(); + } + + public Object get(Integer col) { + return arr[col]; + } + + public int size() { + return arr.length; + } + + public Object[] toArray() { + return arr; + } + +} diff --git a/org.argeo.util/src/main/java/org/argeo/util/tabular/CsvTabularWriter.java b/org.argeo.util/src/main/java/org/argeo/util/tabular/CsvTabularWriter.java new file mode 100644 index 000000000..8f5c52dca --- /dev/null +++ b/org.argeo.util/src/main/java/org/argeo/util/tabular/CsvTabularWriter.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.util.tabular; + +import java.io.OutputStream; + +import org.argeo.util.CsvWriter; + +/** Write tabular content in a stream as CSV. Wraps a {@link CsvWriter}. */ +public class CsvTabularWriter implements TabularWriter { + private CsvWriter csvWriter; + + public CsvTabularWriter(OutputStream out) { + this.csvWriter = new CsvWriter(out); + } + + public void appendRow(Object[] row) { + csvWriter.writeLine(row); + } + + public void close() { + } + +} diff --git a/org.argeo.util/src/main/java/org/argeo/util/tabular/TabularColumn.java b/org.argeo.util/src/main/java/org/argeo/util/tabular/TabularColumn.java new file mode 100644 index 000000000..a5ee32f27 --- /dev/null +++ b/org.argeo.util/src/main/java/org/argeo/util/tabular/TabularColumn.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.util.tabular; + +/** The column in a tabular content */ +public class TabularColumn { + private String name; + /** + * JCR types, see + * http://www.day.com/maven/javax.jcr/javadocs/jcr-2.0/index.html + * ?javax/jcr/PropertyType.html + */ + private Integer type; + + /** column with default type */ + public TabularColumn(String name) { + super(); + this.name = name; + } + + public TabularColumn(String name, Integer type) { + super(); + this.name = name; + this.type = type; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getType() { + return type; + } + + public void setType(Integer type) { + this.type = type; + } + +} diff --git a/org.argeo.util/src/main/java/org/argeo/util/tabular/TabularContent.java b/org.argeo.util/src/main/java/org/argeo/util/tabular/TabularContent.java new file mode 100644 index 000000000..a2da86668 --- /dev/null +++ b/org.argeo.util/src/main/java/org/argeo/util/tabular/TabularContent.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.util.tabular; + +import java.util.List; + +/** + * Content organized as a table, possibly with headers. Only JCR types are + * supported even though there is not direct dependency on JCR. + */ +public interface TabularContent { + /** The headers of this table or null is none available. */ + public List getColumns(); + + public TabularRowIterator read(); +} diff --git a/org.argeo.util/src/main/java/org/argeo/util/tabular/TabularRow.java b/org.argeo.util/src/main/java/org/argeo/util/tabular/TabularRow.java new file mode 100644 index 000000000..05b8a40a9 --- /dev/null +++ b/org.argeo.util/src/main/java/org/argeo/util/tabular/TabularRow.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.util.tabular; + +/** A row of tabular data */ +public interface TabularRow { + /** The value at this column index */ + public Object get(Integer col); + + /** The raw objects (direct references) */ + public Object[] toArray(); + + /** Number of columns */ + public int size(); +} diff --git a/org.argeo.util/src/main/java/org/argeo/util/tabular/TabularRowIterator.java b/org.argeo.util/src/main/java/org/argeo/util/tabular/TabularRowIterator.java new file mode 100644 index 000000000..043463dd7 --- /dev/null +++ b/org.argeo.util/src/main/java/org/argeo/util/tabular/TabularRowIterator.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.util.tabular; + +import java.util.Iterator; + +/** Navigation of rows */ +public interface TabularRowIterator extends Iterator { + /** + * Current row number, has to be incremented by each call to next() ; starts at 0, will + * therefore be 1 for the first row returned. + */ + public Long getCurrentRowNumber(); +} diff --git a/org.argeo.util/src/main/java/org/argeo/util/tabular/TabularWriter.java b/org.argeo.util/src/main/java/org/argeo/util/tabular/TabularWriter.java new file mode 100644 index 000000000..20d6519fa --- /dev/null +++ b/org.argeo.util/src/main/java/org/argeo/util/tabular/TabularWriter.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.util.tabular; + + +/** Write to a tabular content */ +public interface TabularWriter { + /** Append a new row of data */ + public void appendRow(Object[] row); + + /** Finish persisting data and release resources */ + public void close(); +} diff --git a/org.argeo.util/src/test/java/org/argeo/util/CsvParserEncodingTestCase.java b/org.argeo.util/src/test/java/org/argeo/util/CsvParserEncodingTestCase.java new file mode 100644 index 000000000..111a8738c --- /dev/null +++ b/org.argeo.util/src/test/java/org/argeo/util/CsvParserEncodingTestCase.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.util; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.util.List; + +import junit.framework.TestCase; + +public class CsvParserEncodingTestCase extends TestCase { + + private String iso = "ISO-8859-1"; + private String utf8 = "UTF-8"; + + public void testParse() throws Exception { + + String xml = new String("áéíóúñ,éééé"); + byte[] utfBytes = xml.getBytes(utf8); + byte[] isoBytes = xml.getBytes(iso); + + InputStream inUtf = new ByteArrayInputStream(utfBytes); + InputStream inIso = new ByteArrayInputStream(isoBytes); + + CsvParser csvParser = new CsvParser() { + protected void processLine(Integer lineNumber, List header, + List tokens) { + assertEquals(header.size(), tokens.size()); + assertEquals(2, tokens.size()); + assertEquals("áéíóúñ", tokens.get(0)); + assertEquals("éééé", tokens.get(1)); + } + }; + + csvParser.parse(inUtf, utf8); + inUtf.close(); + csvParser.parse(inIso, iso); + inIso.close(); + } +} diff --git a/org.argeo.util/src/test/java/org/argeo/util/CsvParserParseFileTest.java b/org.argeo.util/src/test/java/org/argeo/util/CsvParserParseFileTest.java new file mode 100644 index 000000000..a937ee7c7 --- /dev/null +++ b/org.argeo.util/src/test/java/org/argeo/util/CsvParserParseFileTest.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.util; + +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; + +import junit.framework.TestCase; + +public class CsvParserParseFileTest extends TestCase { + public void testParse() throws Exception { + + final Map> lines = new HashMap>(); + InputStream in = getClass().getResourceAsStream( + "/org/argeo/util/ReferenceFile.csv"); + CsvParserWithLinesAsMap parser = new CsvParserWithLinesAsMap() { + protected void processLine(Integer lineNumber, + Map line) { + lines.put(lineNumber, line); + } + }; + + parser.parse(in); + in.close(); + + assertEquals(5, lines.size()); + } + +} diff --git a/org.argeo.util/src/test/java/org/argeo/util/CsvParserTestCase.java b/org.argeo.util/src/test/java/org/argeo/util/CsvParserTestCase.java new file mode 100644 index 000000000..02e8d1b59 --- /dev/null +++ b/org.argeo.util/src/test/java/org/argeo/util/CsvParserTestCase.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.util; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.util.List; + +import junit.framework.TestCase; + +public class CsvParserTestCase extends TestCase { + public void testParse() throws Exception { + String toParse = "Header1,\"Header\n2\",Header3,\"Header4\"\n" + + "Col1,\"Col\n2\",Col3,\"\"\"Col4\"\"\"\n" + + "Col1,\"Col\n2\",Col3,\"\"\"Col4\"\"\"\n" + + "Col1,\"Col\n2\",Col3,\"\"\"Col4\"\"\"\n"; + + InputStream in = new ByteArrayInputStream(toParse.getBytes()); + + CsvParser csvParser = new CsvParser() { + protected void processLine(Integer lineNumber, List header, + List tokens) { + assertEquals(header.size(), tokens.size()); + assertEquals(4, tokens.size()); + assertEquals("Col1", tokens.get(0)); + assertEquals("Col\n2", tokens.get(1)); + assertEquals("Col3", tokens.get(2)); + assertEquals("\"Col4\"", tokens.get(3)); + } + }; + + csvParser.parse(in); + in.close(); + } + +} diff --git a/org.argeo.util/src/test/java/org/argeo/util/CsvParserWithQuotedSeparatorTest.java b/org.argeo.util/src/test/java/org/argeo/util/CsvParserWithQuotedSeparatorTest.java new file mode 100644 index 000000000..d4131a046 --- /dev/null +++ b/org.argeo.util/src/test/java/org/argeo/util/CsvParserWithQuotedSeparatorTest.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.util; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import junit.framework.TestCase; + +public class CsvParserWithQuotedSeparatorTest extends TestCase { + public void testSimpleParse() throws Exception { + String toParse = "Header1,\"Header2\",Header3,\"Header4\"\n" + + "\"Col1, Col2\",\"Col\n2\",Col3,\"\"\"Col4\"\"\"\n"; + + InputStream in = new ByteArrayInputStream(toParse.getBytes()); + + CsvParser csvParser = new CsvParser() { + protected void processLine(Integer lineNumber, List header, + List tokens) { + assertEquals(header.size(), tokens.size()); + assertEquals(4, tokens.size()); + assertEquals("Col1, Col2", tokens.get(0)); + } + }; + // System.out.println(toParse); + csvParser.parse(in); + in.close(); + + } + + public void testParseFile() throws Exception { + + final Map> lines = new HashMap>(); + InputStream in = getClass().getResourceAsStream( + "/org/argeo/util/ReferenceFile.csv"); + + CsvParserWithLinesAsMap parser = new CsvParserWithLinesAsMap() { + protected void processLine(Integer lineNumber, + Map line) { + // System.out.println("processing line #" + lineNumber); + lines.put(lineNumber, line); + } + }; + + parser.parse(in); + in.close(); + + Map line = lines.get(2); + assertEquals(",,,,", line.get("Coma testing")); + line = lines.get(3); + assertEquals(",, ,,", line.get("Coma testing")); + line = lines.get(4); + assertEquals("module1, module2", line.get("Coma testing")); + line = lines.get(5); + assertEquals("module1,module2", line.get("Coma testing")); + line = lines.get(6); + assertEquals(",module1,module2, \nmodule3, module4", + line.get("Coma testing")); + assertEquals(5, lines.size()); + + } +} diff --git a/org.argeo.util/src/test/java/org/argeo/util/CsvWriterTestCase.java b/org.argeo.util/src/test/java/org/argeo/util/CsvWriterTestCase.java new file mode 100644 index 000000000..26b356def --- /dev/null +++ b/org.argeo.util/src/test/java/org/argeo/util/CsvWriterTestCase.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.util; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import junit.framework.TestCase; + +public class CsvWriterTestCase extends TestCase { + public void testWrite() throws Exception { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + final CsvWriter csvWriter = new CsvWriter(out); + + String[] header = { "Header1", "Header 2", "Header,3", "Header\n4", + "Header\"5\"" }; + String[] line1 = { "Value1", "Value 2", "Value,3", "Value\n4", + "Value\"5\"" }; + csvWriter.writeLine(Arrays.asList(header)); + csvWriter.writeLine(Arrays.asList(line1)); + + String reference = "Header1,Header 2,\"Header,3\",\"Header\n4\",\"Header\"\"5\"\"\"\n" + + "Value1,Value 2,\"Value,3\",\"Value\n4\",\"Value\"\"5\"\"\"\n"; + String written = new String(out.toByteArray()); + assertEquals(reference, written); + out.close(); + System.out.println(written); + + final List allTokens = new ArrayList(); + CsvParser csvParser = new CsvParser() { + protected void processLine(Integer lineNumber, List header, + List tokens) { + if (lineNumber == 2) + allTokens.addAll(header); + allTokens.addAll(tokens); + } + }; + ByteArrayInputStream in = new ByteArrayInputStream(written.getBytes()); + csvParser.parse(in); + in.close(); + List allTokensRef = new ArrayList(); + allTokensRef.addAll(Arrays.asList(header)); + allTokensRef.addAll(Arrays.asList(line1)); + + assertEquals(allTokensRef.size(), allTokens.size()); + for (int i = 0; i < allTokensRef.size(); i++) + assertEquals(allTokensRef.get(i), allTokens.get(i)); + } + +} diff --git a/org.argeo.util/src/test/java/org/argeo/util/ThroughputTest.java b/org.argeo.util/src/test/java/org/argeo/util/ThroughputTest.java new file mode 100644 index 000000000..fc8007efd --- /dev/null +++ b/org.argeo.util/src/test/java/org/argeo/util/ThroughputTest.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.util; + +import junit.framework.TestCase; + +public class ThroughputTest extends TestCase { + public void testParse() { + Throughput t; + t = new Throughput("3.54/s"); + assertEquals(3.54d, t.getValue()); + assertEquals(Throughput.Unit.s, t.getUnit()); + assertEquals(282l, (long) t.asMsPeriod()); + + t = new Throughput("35698.2569/h"); + assertEquals(Throughput.Unit.h, t.getUnit()); + assertEquals(101l, (long) t.asMsPeriod()); + } +} diff --git a/org.argeo.util/src/test/resources/org/argeo/util/ReferenceFile.csv b/org.argeo.util/src/test/resources/org/argeo/util/ReferenceFile.csv new file mode 100644 index 000000000..351453d10 --- /dev/null +++ b/org.argeo.util/src/test/resources/org/argeo/util/ReferenceFile.csv @@ -0,0 +1,37 @@ +"ID","A long Text","Name","Other","Number","Reference","Target","Date","Update","Language","ID Ref","Weird chars","line feeds","after line feed","Empty column","Status comment","Comments","Empty","Coma testing" +"AK251","Everything & with some line feed + more “some” quote","Marge S.",,78.6,"A1155222221111268515131",,12/12/12,03/12/08,,9821308500721,"%%%ùù","ao","Nothing special",,,"Some very usefull comment",,",,,," +"AG254","same","Roger “wallace” Big","15 – JI",78.5,"A1155222221111268515131","next milestone",12/12/12,03/12/08,"_fr (French - France)",9812309500953,"***µ”","a + + + + +o","after line feed",,"Do the job",,,",, ,," +"FG211","Very long text with some bullets. +1 first +2 second +3. some more very very very long. some more very very very long. some more very very very long. some more very very very long. some more very very very long. some more very very very long. some more very very very long. some more very very very long. some more very very very long. some more very very very long. some more very very very long. some more very very very long","Father & Son","15 – JI",15.4,"A1155222221111268515131","next milestone",12/12/12,03/12/08,"_fr (French - France)",9812309500952,"///","a + + + + + + +o","module1,module2",,"Be fast",,,"module1, module2" +"RRT152","Very long text with some bullets. +1 first +2 second +3. some more very very very long. some more very very very long. some more very very very long. some more very very very long. some more very very very long. some more very very very long. some more very very very long. some more very very very long. some more very very very long. some more very very very long. some more very very very long. some more very very very long","Another $$","15 – JI",12.3,"A1155222221111268515131","next milestone",12/12/12,03/12/08,"_fr (French - France)",9812309500950,"---","a + +o + + +","module1,module2",,,,,"module1,module2" +"YU121","Another use case : “blank line” + +After the blank.","nothing with brackets( )","15 – JI",15.2,"A1155222221111268515131",,12/12/12,03/12/08,"_fr (French - France)",9812309500925,",;:?./","ao"," + + + +After line feed again",,,,,",module1,module2, +module3, module4" diff --git a/org.argeo.util/src/test/resources/org/argeo/util/TestParse-ISO.csv b/org.argeo.util/src/test/resources/org/argeo/util/TestParse-ISO.csv new file mode 100644 index 000000000..0bec61111 --- /dev/null +++ b/org.argeo.util/src/test/resources/org/argeo/util/TestParse-ISO.csv @@ -0,0 +1,8 @@ +"Date d'imputation","N° de compte","Code journal","Pièce interne","Pièce externe","Libellé d'écriture","Débit","Crédit","Lettrage","Quantité","Code analytique","Date d'échéance","Date d'imputation origine","Code journal origine","Mode de règlement","Date début de période","Date fin de période" +26.01.2010,"101300","BQ","BQ01.10",,"Depot société en formation",,"3.000,00",,,," ",26.01.2010,"BQ"," "," "," " +26.01.2010,"101300","BQ","BQ01.10",,"Depot société en formation",,"7.000,00",,,," ",26.01.2010,"BQ"," "," "," " +26.01.2010,"411OPEN","BQ","BQ01.10",,"Vir Client ",,"2.508,00","A",,," ",26.01.2010,"BQ"," "," "," " +26.01.2010,"455100","BQ","BQ01.10",,"Bankomat Raiffeise","250,00",,,,," ",26.01.2010,"BQ"," "," "," " +26.01.2010,"512101","BQ","BQ01.10",,"Extrait bancaire 01.10","12.250,55",,,,," ",26.01.2010,"BQ"," "," "," " +26.01.2010,"627800","BQ","BQ01.10",,"Envoi de chequier","2,30",,,,," ",26.01.2010,"BQ"," "," "," " +26.01.2010,"627800","BQ","BQ01.10",,"Frais d'expedition","5,15",,,,," ",26.01.2010,"BQ"," "," "," " diff --git a/org.argeo.util/src/test/resources/org/argeo/util/TestParse-UTF-8.csv b/org.argeo.util/src/test/resources/org/argeo/util/TestParse-UTF-8.csv new file mode 100644 index 000000000..0bec61111 --- /dev/null +++ b/org.argeo.util/src/test/resources/org/argeo/util/TestParse-UTF-8.csv @@ -0,0 +1,8 @@ +"Date d'imputation","N° de compte","Code journal","Pièce interne","Pièce externe","Libellé d'écriture","Débit","Crédit","Lettrage","Quantité","Code analytique","Date d'échéance","Date d'imputation origine","Code journal origine","Mode de règlement","Date début de période","Date fin de période" +26.01.2010,"101300","BQ","BQ01.10",,"Depot société en formation",,"3.000,00",,,," ",26.01.2010,"BQ"," "," "," " +26.01.2010,"101300","BQ","BQ01.10",,"Depot société en formation",,"7.000,00",,,," ",26.01.2010,"BQ"," "," "," " +26.01.2010,"411OPEN","BQ","BQ01.10",,"Vir Client ",,"2.508,00","A",,," ",26.01.2010,"BQ"," "," "," " +26.01.2010,"455100","BQ","BQ01.10",,"Bankomat Raiffeise","250,00",,,,," ",26.01.2010,"BQ"," "," "," " +26.01.2010,"512101","BQ","BQ01.10",,"Extrait bancaire 01.10","12.250,55",,,,," ",26.01.2010,"BQ"," "," "," " +26.01.2010,"627800","BQ","BQ01.10",,"Envoi de chequier","2,30",,,,," ",26.01.2010,"BQ"," "," "," " +26.01.2010,"627800","BQ","BQ01.10",,"Frais d'expedition","5,15",,,,," ",26.01.2010,"BQ"," "," "," " diff --git a/pom.xml b/pom.xml index 776d239d4..dbd3ed3cf 100644 --- a/pom.xml +++ b/pom.xml @@ -1,11 +1,11 @@ - + 4.0.0 org.argeo.commons argeo-commons 2.1.12-SNAPSHOT Argeo Commons - Generic layers integrating free / open source technologies in order to quickly develop custom enterprise systems: security, JCR, user interface, monitoring pom 2.1.12-SNAPSHOT @@ -21,9 +21,51 @@ UTF-8 - base - server - security + + org.argeo.util + org.argeo.osgi.boot + org.argeo.server.jcr + + org.argeo.eclipse.ui + org.argeo.eclipse.ui.jcr + org.argeo.eclipse.ui.rap + org.argeo.eclipse.ui.rcp + + org.argeo.security.core + org.argeo.security.jackrabbit + org.argeo.security.ldap + org.argeo.security.mvc + + org.argeo.security.auth.ldap + org.argeo.security.dao.ldap + org.argeo.security.dao.cli + org.argeo.security.dao.os + org.argeo.security.dao.jackrabbit + + org.argeo.server.jcr.mvc + org.argeo.server.jackrabbit + org.argeo.jackrabbit.webapp + org.argeo.server.ads + org.argeo.server.ads.server + org.argeo.server.rap.webapp + + org.argeo.node.repo.jackrabbit + + org.argeo.osgi.ui.explorer + org.argeo.jcr.ui.explorer + org.argeo.security.equinox + org.argeo.security.ui + org.argeo.security.ui.admin + + org.argeo.security.ui.rap + org.argeo.security.ui.rcp + + org.argeo.support.junit + org.argeo.server.core + org.argeo.ext.jdbm + + dep + dist Argeo @@ -94,7 +136,7 @@ limitations under the License. org.apache.maven.wagon wagon-webdav-jackrabbit - 2.2 + 2.8 @@ -104,19 +146,18 @@ limitations under the License. . - plugin.xml - META-INF/** - WEB-INF/** - icons/** - branding/** - img/** - theme/** - *.properties - properties/*.properties - p2.inf + ** + .* + .*/** + src/** + target/** + bin/** + pom.xml build.properties + *.bnd + *.target @@ -125,7 +166,7 @@ limitations under the License. maven-compiler-plugin - 2.3.2 + 3.2 1.6 1.6 @@ -133,7 +174,7 @@ limitations under the License. maven-source-plugin - 2.1.2 + 2.4 attach-sources @@ -143,10 +184,17 @@ limitations under the License. + + + + plugin.xml + META-INF/MANIFEST.MF + + maven-clean-plugin - 2.4.1 + 2.6.1 @@ -160,11 +208,11 @@ limitations under the License. maven-surefire-plugin - 2.12 + 2.18 maven-jar-plugin - 2.4 + 2.5 META-INF/MANIFEST.MF @@ -177,22 +225,22 @@ limitations under the License. maven-resources-plugin - 2.5 + 2.7 maven-dependency-plugin - 2.4 + 2.9 maven-release-plugin - 2.2.2 + 2.5.1 true maven-javadoc-plugin - 2.8.1 + 2.10.1 @@ -230,7 +278,7 @@ limitations under the License. org.codehaus.mojo rpm-maven-plugin - 2.1-alpha-1 + 2.1 true ${project.version} @@ -245,13 +293,13 @@ limitations under the License. org.codehaus.mojo exec-maven-plugin - 1.2.1 + 1.3.2 org.argeo.maven.plugins maven-argeo-osgi-plugin - 1.1.2 + 1.1.3-SNAPSHOT @@ -259,11 +307,11 @@ limitations under the License. maven-license-plugin 1.9.0 - - com.agilejava.docbkx - docbkx-maven-plugin - 2.0.14 - + + + + + maven-site-plugin @@ -446,34 +494,34 @@ limitations under the License. - - com.agilejava.docbkx - docbkx-maven-plugin - - doc/reference - target/site/reference - css/style.css - - - - - - - - - - - - - - - generate-html - generate-pdf - - pre-site - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/security/dep/org.argeo.security.dep.node.eclipse/p2.inf b/security/dep/org.argeo.security.dep.node.eclipse/p2.inf deleted file mode 100644 index 0423aa509..000000000 --- a/security/dep/org.argeo.security.dep.node.eclipse/p2.inf +++ /dev/null @@ -1,2 +0,0 @@ -properties.1.name=org.eclipse.equinox.p2.type.category -properties.1.value=true \ No newline at end of file diff --git a/security/dep/org.argeo.security.dep.node.eclipse/pom.xml b/security/dep/org.argeo.security.dep.node.eclipse/pom.xml deleted file mode 100644 index 5abb5f021..000000000 --- a/security/dep/org.argeo.security.dep.node.eclipse/pom.xml +++ /dev/null @@ -1,137 +0,0 @@ - - 4.0.0 - - org.argeo.commons.security - 2.1.12-SNAPSHOT - dep - .. - - org.argeo.security.dep.node.eclipse - Node Eclipse Perspectives - - - - org.argeo.maven.plugins - maven-argeo-osgi-plugin - - - generate-descriptors - - descriptors - - generate-resources - - - - - - - - - org.argeo.commons.server - org.argeo.jcr.ui.explorer - 2.1.12-SNAPSHOT - - - org.argeo.commons.base - org.argeo.osgi.ui.explorer - 2.1.12-SNAPSHOT - - - org.argeo.commons.security - org.argeo.security.ui.admin - 2.1.12-SNAPSHOT - - - - - org.argeo.commons.base - org.argeo.eclipse.ui - 2.1.12-SNAPSHOT - - - org.argeo.commons.base - org.argeo.eclipse.ui.jcr - 2.1.12-SNAPSHOT - - - org.argeo.commons.security - org.argeo.security.equinox - 2.1.12-SNAPSHOT - - - org.argeo.commons.security - org.argeo.security.ui - 2.1.12-SNAPSHOT - - - - - org.argeo.commons.security - org.argeo.security.dep.node - 2.1.12-SNAPSHOT - pom - - - - - rpmbuild - - - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-direct - package - - copy-dependencies - - - jar - true - ${project.build.directory}/argeo-node-eclipse - - - - - - org.codehaus.mojo - rpm-maven-plugin - - - rpm-node-eclipse - package - - rpm - - - argeo-node-eclipse - rpm-eclipse - - - /usr/share/osgi/eclipse - root - root - 644 - false - - - ${project.build.directory}/argeo-node-eclipse - - - - - - argeo-node - - - - - - - - - - diff --git a/security/dep/org.argeo.security.dep.node.rap/p2.inf b/security/dep/org.argeo.security.dep.node.rap/p2.inf deleted file mode 100644 index 0423aa509..000000000 --- a/security/dep/org.argeo.security.dep.node.rap/p2.inf +++ /dev/null @@ -1,2 +0,0 @@ -properties.1.name=org.eclipse.equinox.p2.type.category -properties.1.value=true \ No newline at end of file diff --git a/security/dep/org.argeo.security.dep.node.rap/pom.xml b/security/dep/org.argeo.security.dep.node.rap/pom.xml deleted file mode 100644 index 728f22e56..000000000 --- a/security/dep/org.argeo.security.dep.node.rap/pom.xml +++ /dev/null @@ -1,198 +0,0 @@ - - 4.0.0 - - org.argeo.commons.security - 2.1.12-SNAPSHOT - dep - .. - - org.argeo.security.dep.node.rap - Node Eclipse RAP - - - - org.apache.felix - maven-bundle-plugin - - - default - - - - - org.argeo.maven.plugins - maven-argeo-osgi-plugin - - - generate-descriptors - - descriptors - - generate-resources - - - - - - - - - org.argeo.commons.server - org.argeo.jcr.ui.explorer - 2.1.12-SNAPSHOT - - - org.argeo.commons.base - org.argeo.osgi.ui.explorer - 2.1.12-SNAPSHOT - - - org.argeo.commons.security - org.argeo.security.ui.admin - 2.1.12-SNAPSHOT - - - org.argeo.commons.security - org.argeo.security.mvc - 2.1.12-SNAPSHOT - - - - - org.argeo.commons.security - org.argeo.security.dep.node - 2.1.12-SNAPSHOT - pom - - - org.argeo.commons.security - org.argeo.security.dao.jackrabbit - - - org.argeo.commons.security - org.argeo.security.dao.os - - - org.argeo.commons.server - org.argeo.server.catalina.start - - - org.argeo.commons.server - org.argeo.server.webextender - - - org.argeo.tp - org.apache.jasper - - - org.argeo.tp - org.springframework.osgi.web.extender - - - - - org.argeo.commons.security - org.argeo.security.ui.rap - 2.1.12-SNAPSHOT - - - - - - - check-osgi - - - - org.argeo.maven.plugins - maven-argeo-osgi-plugin - - - check-osgi - test - - equinox - - - true - - - - - - - - - - org.argeo.commons.base - org.argeo.osgi.boot - 2.1.12-SNAPSHOT - test - - - - - rpmbuild - - - - org.codehaus.mojo - rpm-maven-plugin - - - rpm-node-rap - package - - rpm - - - argeo-node-rap - - - - - - - - - - - - - - - - /usr/share/osgi/rap - root - root - 644 - false - - - org.argeo.commons.base:org.argeo.eclipse.ui.rap - org.argeo.commons.server:org.argeo.server.rap.webapp - org.argeo.commons.security:org.argeo.security.ui.rap - - - - - - argeo-node - argeo-node-eclipse - eclipse-rap - - - - - - - - - - diff --git a/security/dep/org.argeo.security.dep.node.rap/src/assembly/dist.xml b/security/dep/org.argeo.security.dep.node.rap/src/assembly/dist.xml deleted file mode 100644 index 2cbbd389b..000000000 --- a/security/dep/org.argeo.security.dep.node.rap/src/assembly/dist.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - dist - argeo-node-server - - tar.gz - - - - false - ${artifact.artifactId}-${artifact.baseVersion}.${artifact.extension} - - lib - - *:jar - - - - \ No newline at end of file diff --git a/security/dep/org.argeo.security.dep.node.rcp/p2.inf b/security/dep/org.argeo.security.dep.node.rcp/p2.inf deleted file mode 100644 index 0423aa509..000000000 --- a/security/dep/org.argeo.security.dep.node.rcp/p2.inf +++ /dev/null @@ -1,2 +0,0 @@ -properties.1.name=org.eclipse.equinox.p2.type.category -properties.1.value=true \ No newline at end of file diff --git a/security/dep/org.argeo.security.dep.node.rcp/pom.xml b/security/dep/org.argeo.security.dep.node.rcp/pom.xml deleted file mode 100644 index d94b6040d..000000000 --- a/security/dep/org.argeo.security.dep.node.rcp/pom.xml +++ /dev/null @@ -1,129 +0,0 @@ - - 4.0.0 - - org.argeo.commons.security - 2.1.12-SNAPSHOT - dep - .. - - org.argeo.security.dep.node.rcp - Node Eclipse RCP - - - - org.apache.felix - maven-bundle-plugin - - - default - - - - - org.argeo.maven.plugins - maven-argeo-osgi-plugin - - - generate-descriptors - - descriptors - - generate-resources - - - - - - - - org.argeo.commons.security - org.argeo.security.dep.node.eclipse - 2.1.12-SNAPSHOT - pom - - - org.argeo.commons.security - org.argeo.security.ui.rcp - 2.1.12-SNAPSHOT - - - - - check-osgi - - - - org.argeo.maven.plugins - maven-argeo-osgi-plugin - - - check-osgi - test - - equinox - - - true - - - - - - - - - - org.argeo.commons.base - org.argeo.osgi.boot - 2.1.12-SNAPSHOT - test - - - - - rpmbuild - - - - org.codehaus.mojo - rpm-maven-plugin - - - - - rpm-node-rcp - package - - rpm - - - argeo-node-rcp - - - /usr/share/osgi/rcp - root - root - 644 - false - - - org.argeo.commons.base:org.argeo.eclipse.ui.rcp - org.argeo.commons.security:org.argeo.security.ui.rcp - - - - - - argeo-node - argeo-node-eclipse - eclipse-platform - - - - - - - - - - diff --git a/security/dep/org.argeo.security.dep.node.rcp/src/assembly/linux.x86.xml b/security/dep/org.argeo.security.dep.node.rcp/src/assembly/linux.x86.xml deleted file mode 100644 index 0b321cdca..000000000 --- a/security/dep/org.argeo.security.dep.node.rcp/src/assembly/linux.x86.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - linux.x86 - argeo-node-ui - - tar.gz - - - - false - ${artifact.artifactId}-${artifact.baseVersion}.${artifact.extension} - - lib - - *:jar - - - org.eclipse.swt:org.eclipse.swt*:jar - - - - false - ${artifact.artifactId}-${artifact.baseVersion}.${artifact.extension} - - lib - - org.eclipse.swt:org.eclipse.swt.gtk.linux.x86:jar - - - - \ No newline at end of file diff --git a/security/dep/org.argeo.security.dep.node.rcp/src/assembly/linux.x86_64.xml b/security/dep/org.argeo.security.dep.node.rcp/src/assembly/linux.x86_64.xml deleted file mode 100644 index 12a0a3278..000000000 --- a/security/dep/org.argeo.security.dep.node.rcp/src/assembly/linux.x86_64.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - linux.x86_64 - argeo-node-ui - - tar.gz - - - - false - ${artifact.artifactId}-${artifact.baseVersion}.${artifact.extension} - - lib - - *:jar - - - org.eclipse.swt:org.eclipse.swt*:jar - - - - false - ${artifact.artifactId}-${artifact.baseVersion}.${artifact.extension} - - lib - - org.eclipse.swt:org.eclipse.swt.gtk.linux.x86_64:jar - - - - \ No newline at end of file diff --git a/security/dep/org.argeo.security.dep.node.rcp/src/assembly/win32.x86.xml b/security/dep/org.argeo.security.dep.node.rcp/src/assembly/win32.x86.xml deleted file mode 100644 index 15cec0da6..000000000 --- a/security/dep/org.argeo.security.dep.node.rcp/src/assembly/win32.x86.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - win32.x86 - argeo-node-ui - - zip - - - - false - ${artifact.artifactId}-${artifact.baseVersion}.${artifact.extension} - - lib - - *:jar - - - org.eclipse.swt:org.eclipse.swt*:jar - - - - false - ${artifact.artifactId}-${artifact.baseVersion}.${artifact.extension} - - lib - - org.eclipse.swt:org.eclipse.swt.win32.win32.x86:jar - - - - \ No newline at end of file diff --git a/security/dep/org.argeo.security.dep.node/p2.inf b/security/dep/org.argeo.security.dep.node/p2.inf deleted file mode 100644 index 0423aa509..000000000 --- a/security/dep/org.argeo.security.dep.node/p2.inf +++ /dev/null @@ -1,2 +0,0 @@ -properties.1.name=org.eclipse.equinox.p2.type.category -properties.1.value=true \ No newline at end of file diff --git a/security/dep/org.argeo.security.dep.node/pom.xml b/security/dep/org.argeo.security.dep.node/pom.xml deleted file mode 100644 index 09c3f3bdf..000000000 --- a/security/dep/org.argeo.security.dep.node/pom.xml +++ /dev/null @@ -1,415 +0,0 @@ - - - 4.0.0 - - org.argeo.commons.security - 2.1.12-SNAPSHOT - dep - .. - - org.argeo.security.dep.node - Node Backend - - - - org.apache.felix - maven-bundle-plugin - - - default - - - - - org.argeo.maven.plugins - maven-argeo-osgi-plugin - - - generate-descriptors - - descriptors - - generate-resources - - - - - - - - - org.argeo.commons.server - org.argeo.node.repo.jackrabbit - 2.1.12-SNAPSHOT - - - - - org.argeo.commons.base - org.argeo.osgi.boot - 2.1.12-SNAPSHOT - - - - - org.argeo.commons.base - org.argeo.dep.log4j - 2.1.12-SNAPSHOT - pom - - - - - org.argeo.commons.server - org.argeo.server.core - 2.1.12-SNAPSHOT - - - - - org.argeo.commons.security - org.argeo.security.core - 2.1.12-SNAPSHOT - - - - - org.argeo.tp - org.apache.xmlcommons - - - org.argeo.tp - org.apache.xalan - - - - - org.argeo.tp - javax.annotation - - - org.argeo.tp - javax.mail - - - - - org.argeo.tp - bcprov - - - org.argeo.tp - bcmail - - - - - org.argeo.tp - org.apache.commons.vfs - - - org.argeo.tp - org.apache.commons.exec - - - org.argeo.tp - org.apache.commons.cli - - - org.argeo.tp - org.apache.commons.dbcp - - - - - org.argeo.tp - jxl - - - org.argeo.tp - org.apache.pdfbox - - - - - org.argeo.tp - org.springframework.context.support - - - - - org.argeo.tp - org.springframework.osgi.extender - - - - - org.argeo.commons.server - org.argeo.server.jackrabbit - 2.1.12-SNAPSHOT - - - org.argeo.commons.security - org.argeo.security.jackrabbit - 2.1.12-SNAPSHOT - - - - - org.argeo.tp - org.quartz - - - - - org.argeo.commons.security - org.argeo.security.dao.ldap - 2.1.12-SNAPSHOT - - - org.argeo.commons.security - org.argeo.security.auth.ldap - 2.1.12-SNAPSHOT - - - org.argeo.commons.security - org.argeo.security.ldap - 2.1.12-SNAPSHOT - - - - - org.argeo.commons.security - org.argeo.security.dao.jackrabbit - 2.1.12-SNAPSHOT - - - - - org.argeo.commons.security - org.argeo.security.dao.os - 2.1.12-SNAPSHOT - - - - - org.argeo.tp - org.springframework.osgi.web.extender - - - org.argeo.tp - org.springframework.osgi.web - - - org.argeo.commons.server - org.argeo.server.dep.tomcat - 2.1.12-SNAPSHOT - pom - - - org.argeo.commons.server - org.argeo.server.webextender - 2.1.12-SNAPSHOT - - - org.argeo.commons.server - org.argeo.server.jcr.mvc - 2.1.12-SNAPSHOT - - - org.argeo.commons.server - org.argeo.jackrabbit.webapp - 2.1.12-SNAPSHOT - - - - - org.argeo.tp - org.h2 - - - org.argeo.tp - com.mysql.jdbc - - - org.argeo.tp - org.postgresql.jdbc3 - - - - - org.argeo.commons.server - org.argeo.server.dep.ads - 2.1.12-SNAPSHOT - pom - - - org.argeo.commons.server - org.argeo.server.ads.server - 2.1.12-SNAPSHOT - - - org.argeo.commons.server - org.argeo.server.ads - 2.1.12-SNAPSHOT - - - - - org.argeo.commons.base - org.argeo.support.junit - 2.1.12-SNAPSHOT - - - - - check-osgi - - - - org.argeo.maven.plugins - maven-argeo-osgi-plugin - - - check-osgi - test - - equinox - - - true - - - - - - - - - - org.argeo.commons.base - org.argeo.osgi.boot - 2.1.12-SNAPSHOT - test - - - - - rpmbuild - - - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-node - package - - copy-dependencies - - - jar - org.argeo.commons.base,org.argeo.commons.server,org.argeo.commons.security - org.argeo.osgi.boot - ${project.build.directory}/node - - - - - - org.codehaus.mojo - rpm-maven-plugin - - - rpm-node - package - - rpm - - - argeo-node - - - /usr/share/osgi - root - root - 644 - false - - - ${project.build.directory}/node - - - - - - argeo-node-tp - - - - - - - - - - rpmbuild-tp - - - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-tp - package - - copy-dependencies - - - jar - org.argeo.commons.base,org.argeo.commons.server,org.argeo.commons.security - org.eclipse.osgi - ${project.build.directory}/node-tp - - - - - - org.codehaus.mojo - rpm-maven-plugin - - - rpm-node-tp - package - - rpm - - - argeo-node-tp - rpm-tp - ${version.argeo-distribution} - - - /usr/share/osgi - root - root - 644 - false - - - ${project.build.directory}/node-tp - - - - - - - - - - - - - \ No newline at end of file diff --git a/security/dep/pom.xml b/security/dep/pom.xml index 30ad62ec0..21884a008 100644 --- a/security/dep/pom.xml +++ b/security/dep/pom.xml @@ -7,7 +7,7 @@ security .. - org.argeo.commons.security + org.argeo.commons dep Commons Security Features pom diff --git a/security/modules/org.argeo.security.auth.ldap/.project b/security/modules/org.argeo.security.auth.ldap/.project deleted file mode 100644 index 0c72d5914..000000000 --- a/security/modules/org.argeo.security.auth.ldap/.project +++ /dev/null @@ -1,22 +0,0 @@ - - - org.argeo.security.auth.ldap - - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - - diff --git a/security/modules/org.argeo.security.auth.ldap/META-INF/spring/security-ldap-jcr.xml b/security/modules/org.argeo.security.auth.ldap/META-INF/spring/security-ldap-jcr.xml deleted file mode 100644 index 3235e66f4..000000000 --- a/security/modules/org.argeo.security.auth.ldap/META-INF/spring/security-ldap-jcr.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - /org/argeo/jcr/argeo.cnd - - - - - - - - - - - - - ${argeo.ldap.userClass} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/security/modules/org.argeo.security.auth.ldap/META-INF/spring/security-ldap-osgi.xml b/security/modules/org.argeo.security.auth.ldap/META-INF/spring/security-ldap-osgi.xml deleted file mode 100644 index d817f9644..000000000 --- a/security/modules/org.argeo.security.auth.ldap/META-INF/spring/security-ldap-osgi.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/security/modules/org.argeo.security.auth.ldap/META-INF/spring/security-ldap-services.xml b/security/modules/org.argeo.security.auth.ldap/META-INF/spring/security-ldap-services.xml deleted file mode 100644 index 0b9a8b8f0..000000000 --- a/security/modules/org.argeo.security.auth.ldap/META-INF/spring/security-ldap-services.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/security/modules/org.argeo.security.auth.ldap/META-INF/spring/security-ldap.xml b/security/modules/org.argeo.security.auth.ldap/META-INF/spring/security-ldap.xml deleted file mode 100644 index f367aba1d..000000000 --- a/security/modules/org.argeo.security.auth.ldap/META-INF/spring/security-ldap.xml +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - - osgibundle:ldap.properties - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/security/modules/org.argeo.security.auth.ldap/build.properties b/security/modules/org.argeo.security.auth.ldap/build.properties deleted file mode 100644 index 5f22cdd44..000000000 --- a/security/modules/org.argeo.security.auth.ldap/build.properties +++ /dev/null @@ -1 +0,0 @@ -bin.includes = META-INF/ diff --git a/security/modules/org.argeo.security.auth.ldap/ldap.properties b/security/modules/org.argeo.security.auth.ldap/ldap.properties deleted file mode 100644 index 0f5164ff3..000000000 --- a/security/modules/org.argeo.security.auth.ldap/ldap.properties +++ /dev/null @@ -1,32 +0,0 @@ -argeo.security.defaultRole=ROLE_USER -argeo.security.rolePrefix=ROLE_ - -argeo.security.systemKey=argeo -argeo.security.superUsername=root - -argeo.ldap.rootdn=dc=demo,dc=example,dc=org -argeo.ldap.protocol=ldap -argeo.ldap.host=localhost -# default are for Apache Directory Server -argeo.ldap.port=10389 -argeo.ldap.manager.userdn=uid=admin,ou=system -argeo.ldap.manager.password=secret - -# USER -argeo.ldap.userClass=inetOrgPerson -argeo.ldap.osUserClass=posixAccount -argeo.ldap.userBase=ou=People -argeo.ldap.usernameAttribute=uid -argeo.ldap.passwordAttribute=userPassword -# ROLES -argeo.ldap.groupClass=groupOfNames -argeo.ldap.groupBase=ou=Roles -argeo.ldap.groupRoleAttribute=cn -argeo.ldap.groupMemberAttribute=member -# OS GROUPS -argeo.ldap.osGroupClass=posixGroup -argeo.ldap.osGroupBase=ou=Group -argeo.ldap.osGroupNameAttribute=cn -argeo.ldap.osGroupMemberAttribute=memberUid - -argeo.ldap.password.useSalt=false \ No newline at end of file diff --git a/security/modules/org.argeo.security.auth.ldap/pom.xml b/security/modules/org.argeo.security.auth.ldap/pom.xml deleted file mode 100644 index a6c8a07b6..000000000 --- a/security/modules/org.argeo.security.auth.ldap/pom.xml +++ /dev/null @@ -1,30 +0,0 @@ - - 4.0.0 - - org.argeo.commons.security - 2.1.12-SNAPSHOT - modules - .. - - org.argeo.security.auth.ldap - Commons Security Auth LDAP - - - - org.apache.felix - maven-bundle-plugin - - - - *, - org.argeo.jcr, - com.sun.jndi.ldap;resolution:=optional, - org.springframework.ldap.core.support, - org.springframework.security - - - - - - - \ No newline at end of file diff --git a/security/modules/org.argeo.security.dao.cli/.project b/security/modules/org.argeo.security.dao.cli/.project deleted file mode 100644 index 807ba67a3..000000000 --- a/security/modules/org.argeo.security.dao.cli/.project +++ /dev/null @@ -1,22 +0,0 @@ - - - org.argeo.security.dao.cli - - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - - diff --git a/security/modules/org.argeo.security.dao.cli/META-INF/spring/security-cli-osgi.xml b/security/modules/org.argeo.security.dao.cli/META-INF/spring/security-cli-osgi.xml deleted file mode 100644 index c46f2764c..000000000 --- a/security/modules/org.argeo.security.dao.cli/META-INF/spring/security-cli-osgi.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/security/modules/org.argeo.security.dao.cli/META-INF/spring/security-cli.xml b/security/modules/org.argeo.security.dao.cli/META-INF/spring/security-cli.xml deleted file mode 100644 index c3f6c8122..000000000 --- a/security/modules/org.argeo.security.dao.cli/META-INF/spring/security-cli.xml +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - osgibundle:security.properties - - - - - - - - /org/argeo/jcr/argeo.cnd - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/security/modules/org.argeo.security.dao.cli/pom.xml b/security/modules/org.argeo.security.dao.cli/pom.xml deleted file mode 100644 index c2ea1c6a1..000000000 --- a/security/modules/org.argeo.security.dao.cli/pom.xml +++ /dev/null @@ -1,27 +0,0 @@ - - 4.0.0 - - org.argeo.commons.security - 2.1.12-SNAPSHOT - modules - .. - - org.argeo.security.dao.cli - Commons Security DAO CLI - - - - org.apache.felix - maven-bundle-plugin - - - - *, - org.argeo.jcr, - - - - - - - \ No newline at end of file diff --git a/security/modules/org.argeo.security.dao.cli/security.properties b/security/modules/org.argeo.security.dao.cli/security.properties deleted file mode 100644 index 42df9259a..000000000 --- a/security/modules/org.argeo.security.dao.cli/security.properties +++ /dev/null @@ -1,3 +0,0 @@ -argeo.security.systemKey=argeo -argeo.node.repo.securityWorkspace=security -argeo.keyring.secreteKeyLength=256 diff --git a/security/modules/org.argeo.security.dao.jackrabbit/.project b/security/modules/org.argeo.security.dao.jackrabbit/.project deleted file mode 100644 index b537a75a5..000000000 --- a/security/modules/org.argeo.security.dao.jackrabbit/.project +++ /dev/null @@ -1,22 +0,0 @@ - - - org.argeo.security.dao.jackrabbit - - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - - diff --git a/security/modules/org.argeo.security.dao.jackrabbit/META-INF/spring/repofactory.xml b/security/modules/org.argeo.security.dao.jackrabbit/META-INF/spring/repofactory.xml deleted file mode 100644 index a00c9b00d..000000000 --- a/security/modules/org.argeo.security.dao.jackrabbit/META-INF/spring/repofactory.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/security/modules/org.argeo.security.dao.jackrabbit/META-INF/spring/security-jcr-osgi.xml b/security/modules/org.argeo.security.dao.jackrabbit/META-INF/spring/security-jcr-osgi.xml deleted file mode 100644 index 9f6d43256..000000000 --- a/security/modules/org.argeo.security.dao.jackrabbit/META-INF/spring/security-jcr-osgi.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/security/modules/org.argeo.security.dao.jackrabbit/META-INF/spring/security-jcr-services.xml b/security/modules/org.argeo.security.dao.jackrabbit/META-INF/spring/security-jcr-services.xml deleted file mode 100644 index 1300a0550..000000000 --- a/security/modules/org.argeo.security.dao.jackrabbit/META-INF/spring/security-jcr-services.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - osgibundle:security.properties - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/security/modules/org.argeo.security.dao.jackrabbit/build.properties b/security/modules/org.argeo.security.dao.jackrabbit/build.properties deleted file mode 100644 index 5f22cdd44..000000000 --- a/security/modules/org.argeo.security.dao.jackrabbit/build.properties +++ /dev/null @@ -1 +0,0 @@ -bin.includes = META-INF/ diff --git a/security/modules/org.argeo.security.dao.jackrabbit/pom.xml b/security/modules/org.argeo.security.dao.jackrabbit/pom.xml deleted file mode 100644 index 4d3658ef7..000000000 --- a/security/modules/org.argeo.security.dao.jackrabbit/pom.xml +++ /dev/null @@ -1,19 +0,0 @@ - - 4.0.0 - - org.argeo.commons.security - 2.1.12-SNAPSHOT - modules - .. - - org.argeo.security.dao.jackrabbit - Commons Security DAO Jackrabbit - - - - org.apache.felix - maven-bundle-plugin - - - - \ No newline at end of file diff --git a/security/modules/org.argeo.security.dao.jackrabbit/security.properties b/security/modules/org.argeo.security.dao.jackrabbit/security.properties deleted file mode 100644 index beebcb5dc..000000000 --- a/security/modules/org.argeo.security.dao.jackrabbit/security.properties +++ /dev/null @@ -1,2 +0,0 @@ -argeo.security.systemKey=argeo -argeo.node.repo.alias=node diff --git a/security/modules/org.argeo.security.dao.ldap/.project b/security/modules/org.argeo.security.dao.ldap/.project deleted file mode 100644 index cd8b39380..000000000 --- a/security/modules/org.argeo.security.dao.ldap/.project +++ /dev/null @@ -1,22 +0,0 @@ - - - org.argeo.security.dao.ldap - - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - - diff --git a/security/modules/org.argeo.security.dao.ldap/META-INF/spring/security-ldap-jcr.xml b/security/modules/org.argeo.security.dao.ldap/META-INF/spring/security-ldap-jcr.xml deleted file mode 100644 index 3235e66f4..000000000 --- a/security/modules/org.argeo.security.dao.ldap/META-INF/spring/security-ldap-jcr.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - /org/argeo/jcr/argeo.cnd - - - - - - - - - - - - - ${argeo.ldap.userClass} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/security/modules/org.argeo.security.dao.ldap/META-INF/spring/security-ldap-osgi.xml b/security/modules/org.argeo.security.dao.ldap/META-INF/spring/security-ldap-osgi.xml deleted file mode 100644 index aa3b67ac6..000000000 --- a/security/modules/org.argeo.security.dao.ldap/META-INF/spring/security-ldap-osgi.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/security/modules/org.argeo.security.dao.ldap/META-INF/spring/security-ldap-services.xml b/security/modules/org.argeo.security.dao.ldap/META-INF/spring/security-ldap-services.xml deleted file mode 100644 index 36dedf389..000000000 --- a/security/modules/org.argeo.security.dao.ldap/META-INF/spring/security-ldap-services.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/security/modules/org.argeo.security.dao.ldap/META-INF/spring/security-ldap.xml b/security/modules/org.argeo.security.dao.ldap/META-INF/spring/security-ldap.xml deleted file mode 100644 index 3777f8853..000000000 --- a/security/modules/org.argeo.security.dao.ldap/META-INF/spring/security-ldap.xml +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - - osgibundle:ldap.properties - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - top - ${argeo.ldap.groupClass} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/security/modules/org.argeo.security.dao.ldap/build.properties b/security/modules/org.argeo.security.dao.ldap/build.properties deleted file mode 100644 index 5f22cdd44..000000000 --- a/security/modules/org.argeo.security.dao.ldap/build.properties +++ /dev/null @@ -1 +0,0 @@ -bin.includes = META-INF/ diff --git a/security/modules/org.argeo.security.dao.ldap/ldap.properties b/security/modules/org.argeo.security.dao.ldap/ldap.properties deleted file mode 100644 index 0f5164ff3..000000000 --- a/security/modules/org.argeo.security.dao.ldap/ldap.properties +++ /dev/null @@ -1,32 +0,0 @@ -argeo.security.defaultRole=ROLE_USER -argeo.security.rolePrefix=ROLE_ - -argeo.security.systemKey=argeo -argeo.security.superUsername=root - -argeo.ldap.rootdn=dc=demo,dc=example,dc=org -argeo.ldap.protocol=ldap -argeo.ldap.host=localhost -# default are for Apache Directory Server -argeo.ldap.port=10389 -argeo.ldap.manager.userdn=uid=admin,ou=system -argeo.ldap.manager.password=secret - -# USER -argeo.ldap.userClass=inetOrgPerson -argeo.ldap.osUserClass=posixAccount -argeo.ldap.userBase=ou=People -argeo.ldap.usernameAttribute=uid -argeo.ldap.passwordAttribute=userPassword -# ROLES -argeo.ldap.groupClass=groupOfNames -argeo.ldap.groupBase=ou=Roles -argeo.ldap.groupRoleAttribute=cn -argeo.ldap.groupMemberAttribute=member -# OS GROUPS -argeo.ldap.osGroupClass=posixGroup -argeo.ldap.osGroupBase=ou=Group -argeo.ldap.osGroupNameAttribute=cn -argeo.ldap.osGroupMemberAttribute=memberUid - -argeo.ldap.password.useSalt=false \ No newline at end of file diff --git a/security/modules/org.argeo.security.dao.ldap/pom.xml b/security/modules/org.argeo.security.dao.ldap/pom.xml deleted file mode 100644 index c62f973c5..000000000 --- a/security/modules/org.argeo.security.dao.ldap/pom.xml +++ /dev/null @@ -1,30 +0,0 @@ - - 4.0.0 - - org.argeo.commons.security - 2.1.12-SNAPSHOT - modules - .. - - org.argeo.security.dao.ldap - Commons Security DAO LDAP - - - - org.apache.felix - maven-bundle-plugin - - - - *, - org.argeo.jcr, - com.sun.jndi.ldap;resolution:=optional, - org.springframework.ldap.core.support, - org.springframework.security - - - - - - - \ No newline at end of file diff --git a/security/modules/org.argeo.security.dao.os/.project b/security/modules/org.argeo.security.dao.os/.project deleted file mode 100644 index cefcc33f3..000000000 --- a/security/modules/org.argeo.security.dao.os/.project +++ /dev/null @@ -1,22 +0,0 @@ - - - org.argeo.security.dao.os - - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - - diff --git a/security/modules/org.argeo.security.dao.os/META-INF/spring/security-os-osgi.xml b/security/modules/org.argeo.security.dao.os/META-INF/spring/security-os-osgi.xml deleted file mode 100644 index 5d827b4a5..000000000 --- a/security/modules/org.argeo.security.dao.os/META-INF/spring/security-os-osgi.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/security/modules/org.argeo.security.dao.os/META-INF/spring/security-os.xml b/security/modules/org.argeo.security.dao.os/META-INF/spring/security-os.xml deleted file mode 100644 index 3d94f502d..000000000 --- a/security/modules/org.argeo.security.dao.os/META-INF/spring/security-os.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - osgibundle:security.properties - - - - - - - - /org/argeo/jcr/argeo.cnd - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/security/modules/org.argeo.security.dao.os/build.properties b/security/modules/org.argeo.security.dao.os/build.properties deleted file mode 100644 index 5f22cdd44..000000000 --- a/security/modules/org.argeo.security.dao.os/build.properties +++ /dev/null @@ -1 +0,0 @@ -bin.includes = META-INF/ diff --git a/security/modules/org.argeo.security.dao.os/pom.xml b/security/modules/org.argeo.security.dao.os/pom.xml deleted file mode 100644 index fc599d877..000000000 --- a/security/modules/org.argeo.security.dao.os/pom.xml +++ /dev/null @@ -1,27 +0,0 @@ - - 4.0.0 - - org.argeo.commons.security - 2.1.12-SNAPSHOT - modules - .. - - org.argeo.security.dao.os - Commons Security DAO OS - - - - org.apache.felix - maven-bundle-plugin - - - - *, - org.argeo.jcr, - - - - - - - \ No newline at end of file diff --git a/security/modules/org.argeo.security.dao.os/security.properties b/security/modules/org.argeo.security.dao.os/security.properties deleted file mode 100644 index ae77bf04d..000000000 --- a/security/modules/org.argeo.security.dao.os/security.properties +++ /dev/null @@ -1,2 +0,0 @@ -argeo.security.systemKey=argeo -argeo.node.repo.securityWorkspace=security diff --git a/security/modules/org.argeo.security.webapp/pom.xml b/security/modules/org.argeo.security.webapp/pom.xml index f72a93c6d..1f5cc2f57 100644 --- a/security/modules/org.argeo.security.webapp/pom.xml +++ b/security/modules/org.argeo.security.webapp/pom.xml @@ -1,9 +1,9 @@ 4.0.0 - org.argeo.commons.security + org.argeo.commons 2.1.12-SNAPSHOT - modules + argeo-commons .. org.argeo.security.webapp diff --git a/security/modules/pom.xml b/security/modules/pom.xml index 28bdb5582..129e5b700 100644 --- a/security/modules/pom.xml +++ b/security/modules/pom.xml @@ -6,8 +6,8 @@ security .. - org.argeo.commons.security - modules + org.argeo.commons + argeo-commons pom Commons Security Modules diff --git a/security/plugins/org.argeo.security.equinox/.classpath b/security/plugins/org.argeo.security.equinox/.classpath deleted file mode 100644 index 848725036..000000000 --- a/security/plugins/org.argeo.security.equinox/.classpath +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/security/plugins/org.argeo.security.equinox/.project b/security/plugins/org.argeo.security.equinox/.project deleted file mode 100644 index e4dd594e8..000000000 --- a/security/plugins/org.argeo.security.equinox/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - org.argeo.security.equinox - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - - diff --git a/security/plugins/org.argeo.security.equinox/.settings/org.eclipse.pde.core.prefs b/security/plugins/org.argeo.security.equinox/.settings/org.eclipse.pde.core.prefs deleted file mode 100644 index 87ab38102..000000000 --- a/security/plugins/org.argeo.security.equinox/.settings/org.eclipse.pde.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -#Sun Jan 16 11:19:07 CET 2011 -eclipse.preferences.version=1 -pluginProject.extensions=false -resolve.requirebundle=false diff --git a/security/plugins/org.argeo.security.equinox/META-INF/spring/loginModules.xml b/security/plugins/org.argeo.security.equinox/META-INF/spring/loginModules.xml deleted file mode 100644 index 7a3e8025a..000000000 --- a/security/plugins/org.argeo.security.equinox/META-INF/spring/loginModules.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - osgibundle:security.properties - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/security/plugins/org.argeo.security.equinox/META-INF/spring/osgi.xml b/security/plugins/org.argeo.security.equinox/META-INF/spring/osgi.xml deleted file mode 100644 index 8003fb277..000000000 --- a/security/plugins/org.argeo.security.equinox/META-INF/spring/osgi.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - \ No newline at end of file diff --git a/security/plugins/org.argeo.security.equinox/build.properties b/security/plugins/org.argeo.security.equinox/build.properties deleted file mode 100644 index 3e2615fae..000000000 --- a/security/plugins/org.argeo.security.equinox/build.properties +++ /dev/null @@ -1,4 +0,0 @@ -bin.includes = META-INF/,\ - plugin.xml -source.. = src/main/java/ -output.. = target/classes/ diff --git a/security/plugins/org.argeo.security.equinox/plugin.xml b/security/plugins/org.argeo.security.equinox/plugin.xml deleted file mode 100644 index 2cc81f137..000000000 --- a/security/plugins/org.argeo.security.equinox/plugin.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/security/plugins/org.argeo.security.equinox/pom.xml b/security/plugins/org.argeo.security.equinox/pom.xml deleted file mode 100644 index 4859c8d5a..000000000 --- a/security/plugins/org.argeo.security.equinox/pom.xml +++ /dev/null @@ -1,74 +0,0 @@ - - 4.0.0 - - org.argeo.commons.security - 2.1.12-SNAPSHOT - plugins - .. - - org.argeo.security.equinox - Commons Security Equinox - jar - - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-source-plugin - - - org.apache.maven.plugins - maven-jar-plugin - - - org.apache.felix - maven-bundle-plugin - - - *, - org.springframework.core, - org.argeo.eclipse.spring - - - - - - - - - - - org.argeo.tp - org.eclipse.osgi - - - - - org.argeo.commons.base - org.argeo.eclipse.dep.rcp - 2.1.12-SNAPSHOT - provided - - - - - org.argeo.commons.base - org.argeo.util - 2.1.12-SNAPSHOT - - - org.argeo.commons.security - org.argeo.security.core - 2.1.12-SNAPSHOT - - - - - org.argeo.tp - org.springframework.security.core - - - \ No newline at end of file diff --git a/security/plugins/org.argeo.security.equinox/security.properties b/security/plugins/org.argeo.security.equinox/security.properties deleted file mode 100644 index 70e75cce2..000000000 --- a/security/plugins/org.argeo.security.equinox/security.properties +++ /dev/null @@ -1,5 +0,0 @@ -argeo.security.systemKey=argeo - -argeo.security.anonymousRole=ROLE_ANONYMOUS - -argeo.i18n.availableLocales= \ No newline at end of file diff --git a/security/plugins/org.argeo.security.equinox/src/main/java/org/argeo/security/equinox/OsSpringLoginModule.java b/security/plugins/org.argeo.security.equinox/src/main/java/org/argeo/security/equinox/OsSpringLoginModule.java deleted file mode 100644 index 1a7ebb4d7..000000000 --- a/security/plugins/org.argeo.security.equinox/src/main/java/org/argeo/security/equinox/OsSpringLoginModule.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.equinox; - -import java.util.Map; - -import javax.security.auth.Subject; -import javax.security.auth.callback.CallbackHandler; -import javax.security.auth.login.LoginException; - -import org.argeo.security.OsAuthenticationToken; -import org.springframework.security.Authentication; -import org.springframework.security.AuthenticationManager; -import org.springframework.security.context.SecurityContextHolder; -import org.springframework.security.providers.jaas.SecurityContextLoginModule; - -/** Login module which caches one subject per thread. */ -public class OsSpringLoginModule extends SecurityContextLoginModule { - // private final static Log log = - // LogFactory.getLog(OsSpringLoginModule.class); - - private AuthenticationManager authenticationManager; - - private Subject subject; - - public OsSpringLoginModule() { - - } - - @SuppressWarnings("rawtypes") - public void initialize(Subject subject, CallbackHandler callbackHandler, - Map sharedState, Map options) { - super.initialize(subject, callbackHandler, sharedState, options); - this.subject = subject; - } - - public boolean login() throws LoginException { - // thread already logged in - if (SecurityContextHolder.getContext().getAuthentication() != null) - return super.login(); - - OsAuthenticationToken oat = new OsAuthenticationToken(); - Authentication authentication = authenticationManager.authenticate(oat); - registerAuthentication(authentication); - return super.login(); - } - - @Override - public boolean logout() throws LoginException { - subject.getPrincipals().clear(); - return super.logout(); - } - - /** - * Register an {@link Authentication} in the security context. - * - * @param authentication - * has to implement {@link Authentication}. - */ - protected void registerAuthentication(Object authentication) { - SecurityContextHolder.getContext().setAuthentication( - (Authentication) authentication); - } - - public void setAuthenticationManager( - AuthenticationManager authenticationManager) { - this.authenticationManager = authenticationManager; - } -} diff --git a/security/plugins/org.argeo.security.equinox/src/main/java/org/argeo/security/equinox/SpringLoginModule.java b/security/plugins/org.argeo.security.equinox/src/main/java/org/argeo/security/equinox/SpringLoginModule.java deleted file mode 100644 index 6fd179ead..000000000 --- a/security/plugins/org.argeo.security.equinox/src/main/java/org/argeo/security/equinox/SpringLoginModule.java +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.equinox; - -import java.util.Locale; -import java.util.Map; -import java.util.UUID; - -import javax.security.auth.Subject; -import javax.security.auth.callback.Callback; -import javax.security.auth.callback.CallbackHandler; -import javax.security.auth.callback.NameCallback; -import javax.security.auth.callback.PasswordCallback; -import javax.security.auth.login.LoginException; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.security.NodeAuthenticationToken; -import org.argeo.util.LocaleCallback; -import org.argeo.util.LocaleUtils; -import org.springframework.security.Authentication; -import org.springframework.security.AuthenticationManager; -import org.springframework.security.BadCredentialsException; -import org.springframework.security.GrantedAuthority; -import org.springframework.security.GrantedAuthorityImpl; -import org.springframework.security.context.SecurityContextHolder; -import org.springframework.security.providers.anonymous.AnonymousAuthenticationToken; -import org.springframework.security.providers.jaas.SecurityContextLoginModule; - -/** Login module which caches one subject per thread. */ -public class SpringLoginModule extends SecurityContextLoginModule { - final static String NODE_REPO_URI = "argeo.node.repo.uri"; - - private final static Log log = LogFactory.getLog(SpringLoginModule.class); - - private AuthenticationManager authenticationManager; - - private CallbackHandler callbackHandler; - - private Subject subject; - - private Long waitBetweenFailedLoginAttempts = 5 * 1000l; - - private Boolean remote = false; - private Boolean anonymous = false; - /** Comma separated list of locales */ - private String availableLocales = ""; - - private String key = null; - private String anonymousRole = "ROLE_ANONYMOUS"; - - public SpringLoginModule() { - - } - - @SuppressWarnings("rawtypes") - public void initialize(Subject subject, CallbackHandler callbackHandler, - Map sharedState, Map options) { - super.initialize(subject, callbackHandler, sharedState, options); - this.callbackHandler = callbackHandler; - this.subject = subject; - } - - public boolean login() throws LoginException { - try { - // thread already logged in - if (SecurityContextHolder.getContext().getAuthentication() != null) - return super.login(); - - if (remote && anonymous) - throw new LoginException( - "Cannot have a Spring login module which is remote and anonymous"); - - // reset all principals and credentials - if (log.isTraceEnabled()) - log.trace("Resetting all principals and credentials of " - + subject); - if (subject.getPrincipals() != null) - subject.getPrincipals().clear(); - if (subject.getPrivateCredentials() != null) - subject.getPrivateCredentials().clear(); - if (subject.getPublicCredentials() != null) - subject.getPublicCredentials().clear(); - - Locale selectedLocale = null; - // deals first with public access since it's simple - if (anonymous) { - // multi locale - if (callbackHandler != null && availableLocales != null - && !availableLocales.trim().equals("")) { - LocaleCallback localeCallback = new LocaleCallback( - availableLocales); - callbackHandler.handle(new Callback[] { localeCallback }); - selectedLocale = localeCallback.getSelectedLocale(); - } - - // TODO integrate with JCR? - Object principal = UUID.randomUUID().toString(); - GrantedAuthority[] authorities = { new GrantedAuthorityImpl( - anonymousRole) }; - AnonymousAuthenticationToken anonymousToken = new AnonymousAuthenticationToken( - key, principal, authorities); - Authentication auth = authenticationManager - .authenticate(anonymousToken); - registerAuthentication(auth); - } else { - if (callbackHandler == null) - throw new LoginException("No call back handler available"); - - // ask for username and password - NameCallback nameCallback = new NameCallback("User"); - PasswordCallback passwordCallback = new PasswordCallback( - "Password", false); - final String defaultNodeUrl = System - .getProperty(NODE_REPO_URI, - "http://localhost:7070/org.argeo.jcr.webapp/remoting/node"); - NameCallback urlCallback = new NameCallback("Site URL", - defaultNodeUrl); - LocaleCallback localeCallback = new LocaleCallback( - availableLocales); - - // handle callbacks - if (remote) - callbackHandler.handle(new Callback[] { nameCallback, - passwordCallback, urlCallback, localeCallback }); - else - callbackHandler.handle(new Callback[] { nameCallback, - passwordCallback, localeCallback }); - - selectedLocale = localeCallback.getSelectedLocale(); - - // create credentials - String username = nameCallback.getName(); - if (username == null || username.trim().equals("")) - return false; - - String password = ""; - if (passwordCallback.getPassword() != null) - password = String.valueOf(passwordCallback.getPassword()); - - NodeAuthenticationToken credentials; - if (remote) { - String url = urlCallback.getName(); - credentials = new NodeAuthenticationToken(username, - password, url); - } else { - credentials = new NodeAuthenticationToken(username, - password); - } - - Authentication authentication; - try { - authentication = authenticationManager - .authenticate(credentials); - } catch (BadCredentialsException e) { - // wait between failed login attempts - Thread.sleep(waitBetweenFailedLoginAttempts); - throw e; - } - registerAuthentication(authentication); - } - - if (selectedLocale != null) - LocaleUtils.threadLocale.set(selectedLocale); - - return super.login(); - } catch (LoginException e) { - throw e; - } catch (ThreadDeath e) { - LoginException le = new LoginException( - "Spring Security login thread died"); - le.initCause(e); - throw le; - } catch (Exception e) { - LoginException le = new LoginException( - "Spring Security login failed"); - le.initCause(e); - throw le; - } - } - - @Override - public boolean logout() throws LoginException { - subject.getPrincipals().clear(); - return super.logout(); - } - - /** - * Register an {@link Authentication} in the security context. - * - * @param authentication - * has to implement {@link Authentication}. - */ - protected void registerAuthentication(Object authentication) { - SecurityContextHolder.getContext().setAuthentication( - (Authentication) authentication); - } - - public void setAuthenticationManager( - AuthenticationManager authenticationManager) { - this.authenticationManager = authenticationManager; - } - - /** Authenticates on a remote node */ - public void setRemote(Boolean remote) { - this.remote = remote; - } - - /** - * Request anonymous authentication (incompatible with remote) - */ - public void setAnonymous(Boolean anonymous) { - this.anonymous = anonymous; - } - - /** Role identifying an anonymous user */ - public void setAnonymousRole(String anonymousRole) { - this.anonymousRole = anonymousRole; - } - - /** System key */ - public void setKey(String key) { - this.key = key; - } - - public void setAvailableLocales(String locales) { - this.availableLocales = locales; - } - -} diff --git a/security/plugins/org.argeo.security.ui.admin/.classpath b/security/plugins/org.argeo.security.ui.admin/.classpath deleted file mode 100644 index 848725036..000000000 --- a/security/plugins/org.argeo.security.ui.admin/.classpath +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/security/plugins/org.argeo.security.ui.admin/.project b/security/plugins/org.argeo.security.ui.admin/.project deleted file mode 100644 index 9821dd947..000000000 --- a/security/plugins/org.argeo.security.ui.admin/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - org.argeo.security.ui.admin - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - - diff --git a/security/plugins/org.argeo.security.ui.admin/META-INF/spring/commands.xml b/security/plugins/org.argeo.security.ui.admin/META-INF/spring/commands.xml deleted file mode 100644 index e0a435e07..000000000 --- a/security/plugins/org.argeo.security.ui.admin/META-INF/spring/commands.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/security/plugins/org.argeo.security.ui.admin/META-INF/spring/common.xml b/security/plugins/org.argeo.security.ui.admin/META-INF/spring/common.xml deleted file mode 100644 index 737f30430..000000000 --- a/security/plugins/org.argeo.security.ui.admin/META-INF/spring/common.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - osgibundle:security-admin.properties - - - - - - - - - \ No newline at end of file diff --git a/security/plugins/org.argeo.security.ui.admin/META-INF/spring/editors.xml b/security/plugins/org.argeo.security.ui.admin/META-INF/spring/editors.xml deleted file mode 100644 index 740792a61..000000000 --- a/security/plugins/org.argeo.security.ui.admin/META-INF/spring/editors.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - diff --git a/security/plugins/org.argeo.security.ui.admin/META-INF/spring/osgi.xml b/security/plugins/org.argeo.security.ui.admin/META-INF/spring/osgi.xml deleted file mode 100644 index 2fa51446c..000000000 --- a/security/plugins/org.argeo.security.ui.admin/META-INF/spring/osgi.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/security/plugins/org.argeo.security.ui.admin/META-INF/spring/views.xml b/security/plugins/org.argeo.security.ui.admin/META-INF/spring/views.xml deleted file mode 100644 index 2ddb05f60..000000000 --- a/security/plugins/org.argeo.security.ui.admin/META-INF/spring/views.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - diff --git a/security/plugins/org.argeo.security.ui.admin/build.properties b/security/plugins/org.argeo.security.ui.admin/build.properties deleted file mode 100644 index c41623e1f..000000000 --- a/security/plugins/org.argeo.security.ui.admin/build.properties +++ /dev/null @@ -1,5 +0,0 @@ -bin.includes = plugin.xml,\ - META-INF/,\ - security-admin.properties -source.. = src/main/java/ -output.. = target/classes/ diff --git a/security/plugins/org.argeo.security.ui.admin/icons/add.gif b/security/plugins/org.argeo.security.ui.admin/icons/add.gif deleted file mode 100644 index 252d7ebcb..000000000 Binary files a/security/plugins/org.argeo.security.ui.admin/icons/add.gif and /dev/null differ diff --git a/security/plugins/org.argeo.security.ui.admin/icons/batch.gif b/security/plugins/org.argeo.security.ui.admin/icons/batch.gif deleted file mode 100644 index b8ca14a8b..000000000 Binary files a/security/plugins/org.argeo.security.ui.admin/icons/batch.gif and /dev/null differ diff --git a/security/plugins/org.argeo.security.ui.admin/icons/clear.gif b/security/plugins/org.argeo.security.ui.admin/icons/clear.gif deleted file mode 100644 index 6bc10f9d0..000000000 Binary files a/security/plugins/org.argeo.security.ui.admin/icons/clear.gif and /dev/null differ diff --git a/security/plugins/org.argeo.security.ui.admin/icons/refresh.png b/security/plugins/org.argeo.security.ui.admin/icons/refresh.png deleted file mode 100644 index a3884fb48..000000000 Binary files a/security/plugins/org.argeo.security.ui.admin/icons/refresh.png and /dev/null differ diff --git a/security/plugins/org.argeo.security.ui.admin/icons/remove.gif b/security/plugins/org.argeo.security.ui.admin/icons/remove.gif deleted file mode 100644 index 0ae6decd0..000000000 Binary files a/security/plugins/org.argeo.security.ui.admin/icons/remove.gif and /dev/null differ diff --git a/security/plugins/org.argeo.security.ui.admin/icons/role.gif b/security/plugins/org.argeo.security.ui.admin/icons/role.gif deleted file mode 100644 index 274a850e4..000000000 Binary files a/security/plugins/org.argeo.security.ui.admin/icons/role.gif and /dev/null differ diff --git a/security/plugins/org.argeo.security.ui.admin/icons/save.gif b/security/plugins/org.argeo.security.ui.admin/icons/save.gif deleted file mode 100644 index 654ad7b42..000000000 Binary files a/security/plugins/org.argeo.security.ui.admin/icons/save.gif and /dev/null differ diff --git a/security/plugins/org.argeo.security.ui.admin/icons/save_security.png b/security/plugins/org.argeo.security.ui.admin/icons/save_security.png deleted file mode 100644 index ca41dc92b..000000000 Binary files a/security/plugins/org.argeo.security.ui.admin/icons/save_security.png and /dev/null differ diff --git a/security/plugins/org.argeo.security.ui.admin/icons/save_security_disabled.png b/security/plugins/org.argeo.security.ui.admin/icons/save_security_disabled.png deleted file mode 100644 index fb7d08d9a..000000000 Binary files a/security/plugins/org.argeo.security.ui.admin/icons/save_security_disabled.png and /dev/null differ diff --git a/security/plugins/org.argeo.security.ui.admin/icons/security.gif b/security/plugins/org.argeo.security.ui.admin/icons/security.gif deleted file mode 100644 index 57fb95edc..000000000 Binary files a/security/plugins/org.argeo.security.ui.admin/icons/security.gif and /dev/null differ diff --git a/security/plugins/org.argeo.security.ui.admin/icons/sync.gif b/security/plugins/org.argeo.security.ui.admin/icons/sync.gif deleted file mode 100644 index b4fa052de..000000000 Binary files a/security/plugins/org.argeo.security.ui.admin/icons/sync.gif and /dev/null differ diff --git a/security/plugins/org.argeo.security.ui.admin/icons/user.gif b/security/plugins/org.argeo.security.ui.admin/icons/user.gif deleted file mode 100644 index 90a00147b..000000000 Binary files a/security/plugins/org.argeo.security.ui.admin/icons/user.gif and /dev/null differ diff --git a/security/plugins/org.argeo.security.ui.admin/icons/users.gif b/security/plugins/org.argeo.security.ui.admin/icons/users.gif deleted file mode 100644 index 2de7edd64..000000000 Binary files a/security/plugins/org.argeo.security.ui.admin/icons/users.gif and /dev/null differ diff --git a/security/plugins/org.argeo.security.ui.admin/plugin.xml b/security/plugins/org.argeo.security.ui.admin/plugin.xml deleted file mode 100644 index e260bdea4..000000000 --- a/security/plugins/org.argeo.security.ui.admin/plugin.xml +++ /dev/null @@ -1,153 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/security/plugins/org.argeo.security.ui.admin/pom.xml b/security/plugins/org.argeo.security.ui.admin/pom.xml deleted file mode 100644 index 465ff88c7..000000000 --- a/security/plugins/org.argeo.security.ui.admin/pom.xml +++ /dev/null @@ -1,112 +0,0 @@ - - - 4.0.0 - - org.argeo.commons.security - 2.1.12-SNAPSHOT - plugins - .. - - org.argeo.security.ui.admin - Commons Security Admin UI - jar - - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-source-plugin - - - org.apache.maven.plugins - maven-jar-plugin - - - org.apache.felix - maven-bundle-plugin - - - lazy - org.argeo.security.ui.admin.SecurityAdminPlugin - - org.eclipse.core.runtime - - *, - org.eclipse.swt, - org.eclipse.ui.services, - org.eclipse.jface.window, - org.argeo.eclipse.spring, - org.springframework.dao, - org.springframework.core, - - org.argeo.security.ui.admin.* - - - - - - - - - org.argeo.commons.security - org.argeo.security.ui - 2.1.12-SNAPSHOT - - - - org.argeo.commons.security - org.argeo.security.core - 2.1.12-SNAPSHOT - - - - - org.argeo.commons.base - org.argeo.eclipse.ui.jcr - 2.1.12-SNAPSHOT - - - - org.argeo.commons.base - org.argeo.eclipse.ui - 2.1.12-SNAPSHOT - - - - - org.argeo.commons.base - org.argeo.eclipse.dep.rcp - 2.1.12-SNAPSHOT - provided - - - org.argeo.commons.base - org.argeo.eclipse.ui.rcp - 2.1.12-SNAPSHOT - provided - - - - - org.argeo.commons.base - org.argeo.util - 2.1.12-SNAPSHOT - - - - - org.argeo.tp - org.springframework.security.core - - - - - org.argeo.tp - slf4j.org.apache.commons.logging - - - - \ No newline at end of file diff --git a/security/plugins/org.argeo.security.ui.admin/security-admin.properties b/security/plugins/org.argeo.security.ui.admin/security-admin.properties deleted file mode 100644 index e69de29bb..000000000 diff --git a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/SecurityAdminImages.java b/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/SecurityAdminImages.java deleted file mode 100644 index f7ffa9c8d..000000000 --- a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/SecurityAdminImages.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Argeo Connect - Data management and communications - * Copyright (C) 2012 Argeo GmbH - * - * This program 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 3 of the License, or - * (at your option) any later version. - * - * This program 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 this program. If not, see - * - * Additional permission under GNU GPL version 3 section 7 - * - * If you modify this Program, or any covered work, by linking or combining it - * with software covered by the terms of the Eclipse Public License, the - * licensors of this Program grant you additional permission to convey the - * resulting work. Corresponding Source for a non-source form of such a - * combination shall include the source code for the parts of such software - * which are used as well as that of the covered work. - */ -package org.argeo.security.ui.admin; - -/** Shared icons that must be declared programmatically . */ -public class SecurityAdminImages { - @SuppressWarnings("unused") - private final static String PREFIX = "icons/"; -} diff --git a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/SecurityAdminPerspective.java b/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/SecurityAdminPerspective.java deleted file mode 100644 index c743f56bd..000000000 --- a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/SecurityAdminPerspective.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.admin; - -import org.argeo.security.ui.admin.views.RolesView; -import org.argeo.security.ui.admin.views.UsersView; -import org.eclipse.ui.IFolderLayout; -import org.eclipse.ui.IPageLayout; -import org.eclipse.ui.IPerspectiveFactory; - -public class SecurityAdminPerspective implements IPerspectiveFactory { - public void createInitialLayout(IPageLayout layout) { - String editorArea = layout.getEditorArea(); - layout.setEditorAreaVisible(true); - layout.setFixed(false); - - IFolderLayout left = layout.createFolder("left", IPageLayout.LEFT, - 0.65f, editorArea); - left.addView(UsersView.ID); - left.addView(RolesView.ID); - } - -} diff --git a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/SecurityAdminPlugin.java b/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/SecurityAdminPlugin.java deleted file mode 100644 index 06e9bd5b9..000000000 --- a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/SecurityAdminPlugin.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.admin; - -import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.ui.plugin.AbstractUIPlugin; -import org.osgi.framework.BundleContext; - -public class SecurityAdminPlugin extends AbstractUIPlugin { - public static final String PLUGIN_ID = "org.argeo.security.ui.admin"; //$NON-NLS-1$ - private static SecurityAdminPlugin plugin; - - public SecurityAdminPlugin() { - } - - public void start(BundleContext context) throws Exception { - super.start(context); - plugin = this; - } - - public void stop(BundleContext context) throws Exception { - plugin = null; - super.stop(context); - } - - public static SecurityAdminPlugin getDefault() { - return plugin; - } - - public static ImageDescriptor getImageDescriptor(String path) { - return imageDescriptorFromPlugin(PLUGIN_ID, path); - } - -} diff --git a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/UserTableComposite.java b/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/UserTableComposite.java deleted file mode 100644 index 720faded4..000000000 --- a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/UserTableComposite.java +++ /dev/null @@ -1,367 +0,0 @@ -package org.argeo.security.ui.admin; - -import java.util.ArrayList; -import java.util.List; - -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.Property; -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.query.QueryManager; -import javax.jcr.query.QueryResult; -import javax.jcr.query.qom.Constraint; -import javax.jcr.query.qom.Ordering; -import javax.jcr.query.qom.QueryObjectModel; -import javax.jcr.query.qom.QueryObjectModelFactory; -import javax.jcr.query.qom.Selector; -import javax.jcr.query.qom.StaticOperand; - -import org.argeo.ArgeoException; -import org.argeo.eclipse.ui.EclipseUiUtils; -import org.argeo.eclipse.ui.jcr.JcrUiUtils; -import org.argeo.eclipse.ui.jcr.lists.ColumnDefinition; -import org.argeo.eclipse.ui.jcr.lists.NodeViewerComparator; -import org.argeo.eclipse.ui.jcr.lists.SimpleJcrNodeLabelProvider; -import org.argeo.eclipse.ui.specific.EclipseUiSpecificUtils; -import org.argeo.eclipse.ui.utils.ViewerUtils; -import org.argeo.jcr.ArgeoNames; -import org.argeo.jcr.ArgeoTypes; -import org.argeo.jcr.JcrUtils; -import org.eclipse.jface.viewers.CheckboxTableViewer; -import org.eclipse.jface.viewers.ColumnLabelProvider; -import org.eclipse.jface.viewers.IStructuredContentProvider; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.jface.viewers.TableViewerColumn; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.graphics.Font; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Table; -import org.eclipse.swt.widgets.Text; - -public class UserTableComposite extends Composite implements ArgeoNames { - // private final static Log log = - // LogFactory.getLog(UserTableComposite.class); - - private static final long serialVersionUID = -7385959046279360420L; - - private TableViewer usersViewer; - private Text filterTxt; - private final static String FILTER_HELP_MSG = "Type filter criterion " - + "separated by a space"; - private Session session; - - private Font italic; - private Font bold; - - private boolean hasFilter; - private boolean hasSelectionColumn; - - // private List selectedItems = new ArrayList(); - - /** - * Overwrite to display other columns - */ - public List getColumnsDef() { - List columnDefs = new ArrayList(); - - // User ID - columnDefs.add(new ColumnDefinition(null, ARGEO_USER_ID, - PropertyType.STRING, "User ID", 100)); - // Displayed name - columnDefs.add(new ColumnDefinition(null, Property.JCR_TITLE, - PropertyType.STRING, "Name", 150)); - - // E-mail - columnDefs.add(new ColumnDefinition(null, ARGEO_PRIMARY_EMAIL, - PropertyType.STRING, "E-mail", 150)); - - // Description - columnDefs.add(new ColumnDefinition(null, Property.JCR_DESCRIPTION, - PropertyType.STRING, "Description", 200)); - - return columnDefs; - } - - public UserTableComposite(Composite parent, int style, Session session) { - super(parent, style); - this.session = session; - } - - /** - * - * @param addFilter - * choose to add a field to filter results or not - * @param addSelection - * choose to add a column to select some of the displayed results - * or not - */ - public void populate(boolean addFilter, boolean addSelection) { - // initialization - Composite parent = this; - italic = EclipseUiUtils.getItalicFont(parent); - bold = EclipseUiUtils.getBoldFont(parent); - hasFilter = addFilter; - hasSelectionColumn = addSelection; - - // Main Layout - this.setLayout(new GridLayout(1, false)); - if (hasFilter) - createFilterPart(parent); - usersViewer = createTableViewer(parent); - EclipseUiSpecificUtils.enableToolTipSupport(usersViewer); - usersViewer.setContentProvider(new UsersContentProvider()); - refreshFilteredList(); - } - - public List getSelectedUsers() { - if (hasSelectionColumn) { - Object[] elements = ((CheckboxTableViewer) usersViewer) - .getCheckedElements(); - - List result = new ArrayList(); - for (Object obj : elements) { - result.add((Node) obj); - } - return result; - } else - throw new ArgeoException("Unvalid request: no selection column " - + "has been created for the current table"); - } - - /** Returns the User table viewer, typically to add doubleclick listener */ - public TableViewer getTableViewer() { - return usersViewer; - } - - /** Returns filter String or null*/ - protected String getFilterString() { - return hasFilter ? filterTxt.getText() : null; - } - - - - private TableViewer createTableViewer(final Composite parent) { - int style = SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL; - if (hasSelectionColumn) - style = style | SWT.CHECK; - - Table table = new Table(parent, style); - table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - - TableViewer viewer; - if (hasSelectionColumn) - viewer = new CheckboxTableViewer(table); - else - viewer = new TableViewer(table); - table.setLinesVisible(true); - table.setHeaderVisible(true); - - // pass a mapping between col index and property name to the comparator. - // List propertiesList = new ArrayList(); - - TableViewerColumn column; - int offset = 0; - if (hasSelectionColumn) { - offset = 1; - column = ViewerUtils.createTableViewerColumn(viewer, "", SWT.NONE, - 25); - column.setLabelProvider(new ColumnLabelProvider() { - private static final long serialVersionUID = 1L; - - @Override - public String getText(Object element) { - return null; - } - }); - SelectionAdapter selectionAdapter = new SelectionAdapter() { - private static final long serialVersionUID = 1L; - - boolean allSelected = false; - - @Override - public void widgetSelected(SelectionEvent e) { - allSelected = !allSelected; - ((CheckboxTableViewer) usersViewer) - .setAllChecked(allSelected); - } - }; - column.getColumn().addSelectionListener(selectionAdapter); - } - - // Create other columns - List colDefs = getColumnsDef(); - - NodeViewerComparator comparator = new NodeViewerComparator(); - int i = offset; - for (ColumnDefinition colDef : colDefs) { - column = ViewerUtils.createTableViewerColumn(viewer, - colDef.getHeaderLabel(), SWT.NONE, colDef.getColumnSize()); - column.setLabelProvider(new CLProvider(colDef.getPropertyName())); - column.getColumn().addSelectionListener( - JcrUiUtils.getNodeSelectionAdapter(i, - colDef.getPropertyType(), colDef.getPropertyName(), - comparator, viewer)); - i++; - } - - // IMPORTANT: initialize comparator before setting it - ColumnDefinition firstCol = colDefs.get(0); - comparator.setColumn(firstCol.getPropertyType(), - firstCol.getPropertyName()); - viewer.setComparator(comparator); - - return viewer; - } - - private class CLProvider extends SimpleJcrNodeLabelProvider { - - private static final long serialVersionUID = 1L; - - public CLProvider(String propertyName) { - super(propertyName); - } - - public String getToolTipText(Object element) { - return getText(element); - } - - @Override - public Font getFont(Object elem) { - // self - String username = getProperty(elem, ARGEO_USER_ID); - if (username.equals(session.getUserID())) - return bold; - - // disabled - try { - Node userProfile = (Node) elem; - // Node userProfile = userHome.getNode(ARGEO_PROFILE); - if (!userProfile.getProperty(ARGEO_ENABLED).getBoolean()) - return italic; - else - return null; - } catch (RepositoryException e) { - throw new ArgeoException("Cannot get font for " + username, e); - } - } - } - - @Override - public boolean setFocus() { - usersViewer.getTable().setFocus(); - return true; - } - - @Override - public void dispose() { - super.dispose(); - } - - public void refresh() { - refreshFilteredList(); - } - - private String getProperty(Object element, String name) { - try { - Node userProfile = (Node) element; - return userProfile.hasProperty(name) ? userProfile - .getProperty(name).getString() : ""; - } catch (RepositoryException e) { - throw new ArgeoException("Cannot get property " + name, e); - } - } - - private class UsersContentProvider implements IStructuredContentProvider { - private static final long serialVersionUID = 1L; - - public Object[] getElements(Object inputElement) { - return (Object[]) inputElement; - } - - public void dispose() { - } - - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - } - } - - /* MANAGE FILTER */ - private void createFilterPart(Composite parent) { - // Text Area for the filter - filterTxt = new Text(parent, SWT.BORDER | SWT.SEARCH | SWT.ICON_SEARCH - | SWT.ICON_CANCEL); - filterTxt.setMessage(FILTER_HELP_MSG); - filterTxt.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL - | GridData.HORIZONTAL_ALIGN_FILL)); - filterTxt.addModifyListener(new ModifyListener() { - private static final long serialVersionUID = 1L; - - public void modifyText(ModifyEvent event) { - refreshFilteredList(); - } - }); - } - - /** - * Refresh the user list: caller might overwrite in order to display a - * subset of all users, typically to remove current user from the list - */ - protected void refreshFilteredList() { - List nodes; - try { - nodes = JcrUtils.nodeIteratorToList(listFilteredElements(session, - hasFilter ? filterTxt.getText() : null)); - usersViewer.setInput(nodes.toArray()); - } catch (RepositoryException e) { - throw new ArgeoException("Unable to list users", e); - } - } - - /** - * Build repository request : caller might overwrite in order to display a - * subset of all users - */ - protected NodeIterator listFilteredElements(Session session, String filter) - throws RepositoryException { - QueryManager queryManager = session.getWorkspace().getQueryManager(); - QueryObjectModelFactory factory = queryManager.getQOMFactory(); - - Selector source = factory.selector(ArgeoTypes.ARGEO_USER_PROFILE, - ArgeoTypes.ARGEO_USER_PROFILE); - - // Dynamically build constraint depending on the filter String - Constraint defaultC = null; - if (filter != null && !"".equals(filter.trim())) { - String[] strs = filter.trim().split(" "); - for (String token : strs) { - StaticOperand so = factory.literal(session.getValueFactory() - .createValue("*" + token + "*")); - Constraint currC = factory.fullTextSearch( - source.getSelectorName(), null, so); - if (defaultC == null) - defaultC = currC; - else - defaultC = factory.and(defaultC, currC); - } - } - - Ordering order = factory.ascending(factory.propertyValue( - source.getSelectorName(), ARGEO_USER_ID)); - Ordering[] orderings = { order }; - - QueryObjectModel query = factory.createQuery(source, defaultC, - orderings, null); - - QueryResult result = query.execute(); - return result.getNodes(); - } -} \ No newline at end of file diff --git a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/AddRole.java b/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/AddRole.java deleted file mode 100644 index a1008f699..000000000 --- a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/AddRole.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.admin.commands; - -import org.argeo.ArgeoException; -import org.argeo.security.UserAdminService; -import org.argeo.security.ui.admin.editors.ArgeoUserEditor; -import org.argeo.security.ui.admin.views.RolesView; -import org.eclipse.core.commands.AbstractHandler; -import org.eclipse.core.commands.ExecutionEvent; -import org.eclipse.core.commands.ExecutionException; -import org.eclipse.ui.IEditorReference; -import org.eclipse.ui.IWorkbenchPage; -import org.eclipse.ui.handlers.HandlerUtil; - -/** Add a new role. */ -public class AddRole extends AbstractHandler { - public final static String COMMAND_ID = "org.argeo.security.ui.admin.addRole"; - private UserAdminService userAdminService; - private String rolePrefix = "ROLE_"; - - public Object execute(ExecutionEvent event) throws ExecutionException { - RolesView rolesView = (RolesView) HandlerUtil - .getActiveWorkbenchWindow(event).getActivePage() - .findView(RolesView.ID); - String role = rolesView.getNewRole(); - if (role.trim().equals("")) - return null; - if (role.equals(rolesView.getAddNewRoleText())) - return null; - role = role.trim().toUpperCase(); - if (!role.startsWith(rolePrefix)) - role = rolePrefix + role; - if (userAdminService.listEditableRoles().contains(role)) - throw new ArgeoException("Role " + role + " already exists"); - userAdminService.newRole(role); - rolesView.refresh(); - - // refresh editors - IEditorReference[] refs = HandlerUtil.getActiveWorkbenchWindow(event) - .getActivePage() - .findEditors(null, ArgeoUserEditor.ID, IWorkbenchPage.MATCH_ID); - for (IEditorReference ref : refs) { - ArgeoUserEditor userEditor = (ArgeoUserEditor) ref.getEditor(false); - if (userEditor != null) { - userEditor.refresh(); - } - } - return null; - } - - public void setUserAdminService(UserAdminService userAdminService) { - this.userAdminService = userAdminService; - } - -} diff --git a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/DeleteRole.java b/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/DeleteRole.java deleted file mode 100644 index 6cba11eb9..000000000 --- a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/DeleteRole.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.admin.commands; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import org.argeo.security.UserAdminService; -import org.argeo.security.ui.admin.views.RolesView; -import org.eclipse.core.commands.AbstractHandler; -import org.eclipse.core.commands.ExecutionEvent; -import org.eclipse.core.commands.ExecutionException; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.ui.handlers.HandlerUtil; - -/** Deletes the selected roles */ -public class DeleteRole extends AbstractHandler { - private UserAdminService userAdminService; - - @SuppressWarnings("unchecked") - public Object execute(ExecutionEvent event) throws ExecutionException { - ISelection selection = HandlerUtil.getCurrentSelection(event); - if (selection.isEmpty()) - return null; - - List toDelete = new ArrayList(); - Iterator it = ((IStructuredSelection) selection).iterator(); - while (it.hasNext()) { - toDelete.add(it.next()); - } - - if (!MessageDialog - .openQuestion( - HandlerUtil.getActiveShell(event), - "Delete Role", - "Are you sure that you want to delete " - + toDelete - + "?\n" - + "This may lead to inconsistencies in the application.")) - return null; - - for (String role : toDelete) { - userAdminService.deleteRole(role); - } - - RolesView view = (RolesView) HandlerUtil - .getActiveWorkbenchWindow(event).getActivePage() - .findView(RolesView.ID); - view.refresh(); - return null; - } - - public void setUserAdminService(UserAdminService userAdminService) { - this.userAdminService = userAdminService; - } -} \ No newline at end of file diff --git a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/DeleteUser.java b/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/DeleteUser.java deleted file mode 100644 index ccf360fd0..000000000 --- a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/DeleteUser.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.admin.commands; - -import java.util.Iterator; -import java.util.Map; -import java.util.TreeMap; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.ArgeoException; -import org.argeo.jcr.ArgeoNames; -import org.argeo.jcr.JcrUtils; -import org.argeo.security.UserAdminService; -import org.eclipse.core.commands.AbstractHandler; -import org.eclipse.core.commands.ExecutionEvent; -import org.eclipse.core.commands.ExecutionException; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.ui.handlers.HandlerUtil; - -/** Deletes the selected user nodes */ -public class DeleteUser extends AbstractHandler { - private final static Log log = LogFactory.getLog(DeleteUser.class); - - private UserAdminService userAdminService; - - @SuppressWarnings("unchecked") - public Object execute(ExecutionEvent event) throws ExecutionException { - ISelection selection = HandlerUtil.getCurrentSelection(event); - if (selection.isEmpty()) - return null; - - Map toDelete = new TreeMap(); - Iterator it = ((IStructuredSelection) selection).iterator(); - nodes: while (it.hasNext()) { - Node profileNode = it.next(); - try { - String userName = profileNode.getProperty( - ArgeoNames.ARGEO_USER_ID).getString(); - if (userName.equals(profileNode.getSession().getUserID())) { - log.warn("Cannot delete its own user: " + userName); - continue nodes; - } - toDelete.put(userName, profileNode); - } catch (RepositoryException e) { - log.warn("Cannot interpred user " + profileNode); - } - } - - if (!MessageDialog - .openQuestion( - HandlerUtil.getActiveShell(event), - "Delete User", - "Are you sure that you want to delete users " - + toDelete.keySet() - + "?\n" - + "This may lead to inconsistencies in the application.")) - return null; - - for (String username : toDelete.keySet()) { - Session session = null; - try { - Node profileNode = toDelete.get(username); - userAdminService.deleteUser(username); - profileNode.getParent().remove(); - session = profileNode.getSession(); - session.save(); - } catch (RepositoryException e) { - JcrUtils.discardQuietly(session); - throw new ArgeoException("Cannot list users", e); - } - } - - userAdminService.synchronize(); - // UsersView view = (UsersView) HandlerUtil - // .getActiveWorkbenchWindow(event).getActivePage() - // .findView(UsersView.ID); - // view.refresh(); - return null; - } - - public void setUserAdminService(UserAdminService userAdminService) { - this.userAdminService = userAdminService; - } -} \ No newline at end of file diff --git a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/NewUser.java b/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/NewUser.java deleted file mode 100644 index 660896de8..000000000 --- a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/NewUser.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.admin.commands; - -import javax.jcr.Repository; -import javax.jcr.Session; - -import org.argeo.jcr.JcrUtils; -import org.argeo.security.UserAdminService; -import org.argeo.security.jcr.JcrSecurityModel; -import org.argeo.security.ui.admin.wizards.NewUserWizard; -import org.eclipse.core.commands.AbstractHandler; -import org.eclipse.core.commands.ExecutionEvent; -import org.eclipse.core.commands.ExecutionException; -import org.eclipse.jface.wizard.WizardDialog; -import org.eclipse.ui.handlers.HandlerUtil; - -/** Launch a wizard that enables creation of a new user. */ -public class NewUser extends AbstractHandler { - private Repository repository; - private UserAdminService userAdminService; - private JcrSecurityModel jcrSecurityModel; - - public Object execute(ExecutionEvent event) throws ExecutionException { - Session session = null; - try { - session = repository.login(); - NewUserWizard newUserWizard = new NewUserWizard(session, - userAdminService, jcrSecurityModel); - WizardDialog dialog = new WizardDialog( - HandlerUtil.getActiveShell(event), newUserWizard); - dialog.open(); - } catch (Exception e) { - throw new ExecutionException("Cannot open wizard", e); - } finally { - JcrUtils.logoutQuietly(session); - } - return null; - } - - public void setRepository(Repository repository) { - this.repository = repository; - } - - public void setUserAdminService(UserAdminService userAdminService) { - this.userAdminService = userAdminService; - } - - public void setJcrSecurityModel(JcrSecurityModel jcrSecurityModel) { - this.jcrSecurityModel = jcrSecurityModel; - } - -} diff --git a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/OpenArgeoUserEditor.java b/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/OpenArgeoUserEditor.java deleted file mode 100644 index bae928c22..000000000 --- a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/OpenArgeoUserEditor.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.admin.commands; - -import org.argeo.security.ui.admin.editors.ArgeoUserEditor; -import org.argeo.security.ui.admin.editors.ArgeoUserEditorInput; -import org.eclipse.core.commands.AbstractHandler; -import org.eclipse.core.commands.ExecutionEvent; -import org.eclipse.core.commands.ExecutionException; -import org.eclipse.ui.IWorkbenchPage; -import org.eclipse.ui.handlers.HandlerUtil; - -/** Command handler to set visible or open a Argeo user. */ -public class OpenArgeoUserEditor extends AbstractHandler { - public final static String COMMAND_ID = "org.argeo.security.ui.admin.openArgeoUserEditor"; - public final static String PARAM_USERNAME = "org.argeo.security.ui.admin.username"; - - public Object execute(ExecutionEvent event) throws ExecutionException { - try { - ArgeoUserEditorInput editorInput = new ArgeoUserEditorInput( - event.getParameter(PARAM_USERNAME)); - IWorkbenchPage activePage = HandlerUtil.getActiveWorkbenchWindow( - event).getActivePage(); - activePage.openEditor(editorInput, ArgeoUserEditor.ID); - } catch (Exception e) { - throw new ExecutionException("Cannot open editor", e); - } - return null; - } -} diff --git a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/RefreshRoles.java b/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/RefreshRoles.java deleted file mode 100644 index 41c78f077..000000000 --- a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/RefreshRoles.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.admin.commands; - -import org.eclipse.core.commands.AbstractHandler; -import org.eclipse.core.commands.ExecutionEvent; -import org.eclipse.core.commands.ExecutionException; - -/** - * Refreshes the roles view. - */ -public class RefreshRoles extends AbstractHandler { - public Object execute(ExecutionEvent event) throws ExecutionException { - - return null; - } - -} \ No newline at end of file diff --git a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/RefreshUsersList.java b/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/RefreshUsersList.java deleted file mode 100644 index e4c14ab21..000000000 --- a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/RefreshUsersList.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.admin.commands; - -import java.util.Set; - -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.query.Query; - -import org.argeo.ArgeoException; -import org.argeo.jcr.ArgeoNames; -import org.argeo.jcr.ArgeoTypes; -import org.argeo.jcr.JcrUtils; -import org.argeo.security.UserAdminService; -import org.argeo.security.ui.admin.views.UsersView; -import org.eclipse.core.commands.AbstractHandler; -import org.eclipse.core.commands.ExecutionEvent; -import org.eclipse.core.commands.ExecutionException; -import org.eclipse.ui.IWorkbenchPart; -import org.eclipse.ui.handlers.HandlerUtil; - -/** - * Refreshes the main user list, removing nodes which are not referenced by user - * admin service. - */ -public class RefreshUsersList extends AbstractHandler { - private UserAdminService userAdminService; - private Repository repository; - - public Object execute(ExecutionEvent event) throws ExecutionException { - Set users = userAdminService.listUsers(); - Session session = null; - try { - session = repository.login(); - Query query = session - .getWorkspace() - .getQueryManager() - .createQuery( - "select * from [" + ArgeoTypes.ARGEO_USER_HOME - + "]", Query.JCR_SQL2); - NodeIterator nit = query.execute().getNodes(); - while (nit.hasNext()) { - Node node = nit.nextNode(); - String username = node.getProperty(ArgeoNames.ARGEO_USER_ID) - .getString(); - if (!users.contains(username)) - node.remove(); - } - session.save(); - } catch (RepositoryException e) { - JcrUtils.discardQuietly(session); - throw new ArgeoException("Cannot list users", e); - } finally { - JcrUtils.logoutQuietly(session); - } - userAdminService.synchronize(); - - // FIXME try to refresh views that extend the UsersView and have another - // ID - IWorkbenchPart part = HandlerUtil.getActiveWorkbenchWindow(event) - .getActivePage().getActivePart(); - if (part instanceof UsersView) - ((UsersView) part).refresh(); - - // Try to refresh UsersView if opened - UsersView view = (UsersView) HandlerUtil - .getActiveWorkbenchWindow(event).getActivePage() - .findView(UsersView.ID); - if (view != null) - view.refresh(); - - return null; - } - - public void setUserAdminService(UserAdminService userAdminService) { - this.userAdminService = userAdminService; - } - - public void setRepository(Repository repository) { - this.repository = repository; - } - -} \ No newline at end of file diff --git a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/SaveArgeoUser.java b/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/SaveArgeoUser.java deleted file mode 100644 index bd16f8bcf..000000000 --- a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/SaveArgeoUser.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.admin.commands; - -import org.eclipse.core.commands.AbstractHandler; -import org.eclipse.core.commands.ExecutionEvent; -import org.eclipse.core.commands.ExecutionException; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.swt.widgets.Display; -import org.eclipse.ui.IEditorPart; -import org.eclipse.ui.IWorkbenchPart; -import org.eclipse.ui.handlers.HandlerUtil; - -/** Save the currently edited Argeo user. */ -public class SaveArgeoUser extends AbstractHandler { - public final static String COMMAND_ID = "org.argeo.security.ui.admin.saveArgeoUser"; - - public Object execute(ExecutionEvent event) throws ExecutionException { - try { - IWorkbenchPart iwp = HandlerUtil.getActiveWorkbenchWindow(event) - .getActivePage().getActivePart(); - - if (!(iwp instanceof IEditorPart)) - return null; - IEditorPart editor = (IEditorPart) iwp; - editor.doSave(null); - } catch (Exception e) { - MessageDialog.openError(Display.getDefault().getActiveShell(), - "Error", "Cannot save user: " + e.getMessage()); - } - return null; - } - -} diff --git a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/UserBatchUpdate.java b/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/UserBatchUpdate.java deleted file mode 100644 index 657dfc70a..000000000 --- a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/UserBatchUpdate.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.admin.commands; - -import javax.jcr.Repository; -import javax.jcr.Session; - -import org.argeo.jcr.JcrUtils; -import org.argeo.security.UserAdminService; -import org.argeo.security.jcr.JcrSecurityModel; -import org.argeo.security.ui.admin.wizards.UserBatchUpdateWizard; -import org.eclipse.core.commands.AbstractHandler; -import org.eclipse.core.commands.ExecutionEvent; -import org.eclipse.core.commands.ExecutionException; -import org.eclipse.jface.wizard.WizardDialog; -import org.eclipse.ui.handlers.HandlerUtil; - -/** Launch a wizard to update various properties about users in JCR. */ -public class UserBatchUpdate extends AbstractHandler { - private Repository repository; - private UserAdminService userAdminService; - private JcrSecurityModel jcrSecurityModel; - - public Object execute(ExecutionEvent event) throws ExecutionException { - Session session = null; - try { - session = repository.login(); - UserBatchUpdateWizard userBatchUpdateWizard = new UserBatchUpdateWizard(session, - userAdminService, jcrSecurityModel); - WizardDialog dialog = new WizardDialog( - HandlerUtil.getActiveShell(event), userBatchUpdateWizard); - dialog.open(); - } catch (Exception e) { - throw new ExecutionException("Cannot open wizard", e); - } finally { - JcrUtils.logoutQuietly(session); - } - return null; - } - - public void setRepository(Repository repository) { - this.repository = repository; - } - - public void setUserAdminService(UserAdminService userAdminService) { - this.userAdminService = userAdminService; - } - - public void setJcrSecurityModel(JcrSecurityModel jcrSecurityModel) { - this.jcrSecurityModel = jcrSecurityModel; - } - -} diff --git a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/ArgeoUserEditor.java b/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/ArgeoUserEditor.java deleted file mode 100644 index ebc08319e..000000000 --- a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/ArgeoUserEditor.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.admin.editors; - -import javax.jcr.Node; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.argeo.ArgeoException; -import org.argeo.jcr.JcrUtils; -import org.argeo.jcr.UserJcrUtils; -import org.argeo.security.UserAdminService; -import org.argeo.security.jcr.JcrUserDetails; -import org.argeo.security.ui.admin.SecurityAdminPlugin; -import org.argeo.security.ui.admin.views.UsersView; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.IEditorSite; -import org.eclipse.ui.IWorkbench; -import org.eclipse.ui.PartInitException; -import org.eclipse.ui.forms.editor.FormEditor; -import org.springframework.security.GrantedAuthority; - -/** Editor for an Argeo user. */ -public class ArgeoUserEditor extends FormEditor { - public final static String ID = SecurityAdminPlugin.PLUGIN_ID - + ".adminArgeoUserEditor"; - - /* DEPENDENCY INJECTION */ - private Session session; - private UserAdminService userAdminService; - - // private Node userHome; - private Node userProfile; - private JcrUserDetails userDetails; - - public void init(IEditorSite site, IEditorInput input) - throws PartInitException { - super.init(site, input); - String username = ((ArgeoUserEditorInput) getEditorInput()) - .getUsername(); - userProfile = UserJcrUtils.getUserProfile(session, username); - - if (userAdminService.userExists(username)) { - userDetails = (JcrUserDetails) userAdminService - .loadUserByUsername(username); - } else { - GrantedAuthority[] authorities = {}; - try { - userDetails = new JcrUserDetails(session, username, null, - authorities); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot retrieve disabled JCR profile"); - } - } - - this.setPartProperty("name", username != null ? username : ""); - setPartName(username != null ? username : ""); - } - - protected void addPages() { - try { - addPage(new DefaultUserMainPage(this, userProfile)); - addPage(new UserRolesPage(this, userDetails, userAdminService)); - } catch (Exception e) { - throw new ArgeoException("Cannot add pages", e); - } - } - - @Override - public void doSave(IProgressMonitor monitor) { - // list pages - // TODO: make it more generic - DefaultUserMainPage defaultUserMainPage = (DefaultUserMainPage) findPage(DefaultUserMainPage.ID); - if (defaultUserMainPage.isDirty()) { - defaultUserMainPage.doSave(monitor); - String newPassword = defaultUserMainPage.getNewPassword(); - defaultUserMainPage.resetNewPassword(); - if (newPassword != null) - userDetails = userDetails.cloneWithNewPassword(newPassword); - } - - UserRolesPage userRolesPage = (UserRolesPage) findPage(UserRolesPage.ID); - if (userRolesPage.isDirty()) { - userRolesPage.doSave(monitor); - userDetails = userDetails.cloneWithNewRoles(userRolesPage - .getRoles()); - } - - userAdminService.updateUser(userDetails); - - // if (userAdminService.userExists(user.getUsername())) - // userAdminService.updateUser(user); - // else { - // userAdminService.newUser(user); - // setPartName(user.getUsername()); - // } - firePropertyChange(PROP_DIRTY); - - userRolesPage.setUserDetails(userDetails); - - // FIXME rather use a refresh command. Fails when called by another - // view. - // refresh users view - IWorkbench iw = SecurityAdminPlugin.getDefault().getWorkbench(); - UsersView usersView = (UsersView) iw.getActiveWorkbenchWindow() - .getActivePage().findView(UsersView.ID); - if (usersView != null) - usersView.refresh(); - } - - @Override - public void doSaveAs() { - } - - @Override - public boolean isSaveAsAllowed() { - return false; - } - - public void refresh() { - UserRolesPage userRolesPage = (UserRolesPage) findPage(UserRolesPage.ID); - userRolesPage.refresh(); - } - - @Override - public void dispose() { - JcrUtils.logoutQuietly(session); - super.dispose(); - } - - /* DEPENDENCY INJECTION */ - public void setUserAdminService(UserAdminService userAdminService) { - this.userAdminService = userAdminService; - } - - public void setRepository(Repository repository) { - try { - session = repository.login(); - } catch (RepositoryException re) { - throw new ArgeoException("Unable to initialise local session", re); - } - } -} diff --git a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/ArgeoUserEditorInput.java b/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/ArgeoUserEditorInput.java deleted file mode 100644 index 9d1d99573..000000000 --- a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/ArgeoUserEditorInput.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.admin.editors; - -import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.IPersistableElement; - -/** Editor input for an Argeo user. */ -public class ArgeoUserEditorInput implements IEditorInput { - private final String username; - - public ArgeoUserEditorInput(String username) { - this.username = username; - } - - public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) { - return null; - } - - public boolean exists() { - return username != null; - } - - public ImageDescriptor getImageDescriptor() { - return null; - } - - public String getName() { - return username != null ? username : ""; - } - - public IPersistableElement getPersistable() { - return null; - } - - public String getToolTipText() { - return username != null ? username : ""; - } - - public boolean equals(Object obj) { - if (!(obj instanceof ArgeoUserEditorInput)) - return false; - if (((ArgeoUserEditorInput) obj).getUsername() == null) - return false; - return ((ArgeoUserEditorInput) obj).getUsername().equals(username); - } - - public String getUsername() { - return username; - } -} diff --git a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/DefaultUserMainPage.java b/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/DefaultUserMainPage.java deleted file mode 100644 index 5f99e195b..000000000 --- a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/DefaultUserMainPage.java +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.admin.editors; - -import java.util.Arrays; - -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.RepositoryException; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.ArgeoException; -import org.argeo.jcr.ArgeoNames; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Text; -import org.eclipse.ui.forms.AbstractFormPart; -import org.eclipse.ui.forms.IManagedForm; -import org.eclipse.ui.forms.SectionPart; -import org.eclipse.ui.forms.editor.FormEditor; -import org.eclipse.ui.forms.editor.FormPage; -import org.eclipse.ui.forms.widgets.FormToolkit; -import org.eclipse.ui.forms.widgets.ScrolledForm; -import org.eclipse.ui.forms.widgets.Section; - -/** - * Display/edit the properties common to all Argeo users - */ -public class DefaultUserMainPage extends FormPage implements ArgeoNames { - final static String ID = "argeoUserEditor.mainPage"; - - private final static Log log = LogFactory.getLog(DefaultUserMainPage.class); - private Node userProfile; - - private char[] newPassword; - - public DefaultUserMainPage(FormEditor editor, Node userProfile) { - super(editor, ID, "Main"); - this.userProfile = userProfile; - } - - protected void createFormContent(final IManagedForm mf) { - try { - ScrolledForm form = mf.getForm(); - refreshFormTitle(form); - GridLayout mainLayout = new GridLayout(1, true); - form.getBody().setLayout(mainLayout); - - createGeneralPart(form.getBody()); - createPassworPart(form.getBody()); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot create form content", e); - } - } - - /** Creates the general section */ - protected void createGeneralPart(Composite parent) - throws RepositoryException { - FormToolkit tk = getManagedForm().getToolkit(); - Section section = tk.createSection(parent, Section.TITLE_BAR); - section.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); - section.setText("General"); - Composite body = tk.createComposite(section, SWT.WRAP); - section.setClient(body); - GridLayout layout = new GridLayout(2, false); - body.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); - body.setLayout(layout); - - final Text commonName = createLT(body, "Displayed Name", - getProperty(Property.JCR_TITLE)); - final Text firstName = createLT(body, "First name", - getProperty(ARGEO_FIRST_NAME)); - final Text lastName = createLT(body, "Last name", - getProperty(ARGEO_LAST_NAME)); - final Text email = createLT(body, "Email", - getProperty(ARGEO_PRIMARY_EMAIL)); - final Text description = createLMT(body, "Description", - getProperty(Property.JCR_DESCRIPTION)); - - // create form part (controller) - AbstractFormPart part = new SectionPart(section) { - public void commit(boolean onSave) { - try { - userProfile.getSession().getWorkspace().getVersionManager() - .checkout(userProfile.getPath()); - userProfile.setProperty(Property.JCR_TITLE, - commonName.getText()); - userProfile.setProperty(ARGEO_FIRST_NAME, - firstName.getText()); - userProfile - .setProperty(ARGEO_LAST_NAME, lastName.getText()); - userProfile.setProperty(ARGEO_PRIMARY_EMAIL, - email.getText()); - userProfile.setProperty(Property.JCR_DESCRIPTION, - description.getText()); - userProfile.getSession().save(); - userProfile.getSession().getWorkspace().getVersionManager() - .checkin(userProfile.getPath()); - super.commit(onSave); - refreshFormTitle(getManagedForm().getForm()); - if (log.isTraceEnabled()) - log.trace("General part committed"); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot commit", e); - } - } - }; - // if (username != null) - // username.addModifyListener(new FormPartML(part)); - commonName.addModifyListener(new FormPartML(part)); - firstName.addModifyListener(new FormPartML(part)); - lastName.addModifyListener(new FormPartML(part)); - email.addModifyListener(new FormPartML(part)); - description.addModifyListener(new FormPartML(part)); - getManagedForm().addPart(part); - } - - private void refreshFormTitle(ScrolledForm form) throws RepositoryException { - form.setText(getProperty(Property.JCR_TITLE) - + (userProfile.getProperty(ARGEO_ENABLED).getBoolean() ? "" - : " [DISABLED]")); - } - - /** @return the property, or the empty string if not set */ - protected String getProperty(String name) throws RepositoryException { - return userProfile.hasProperty(name) ? userProfile.getProperty(name) - .getString() : ""; - } - - /** Creates the password section */ - protected void createPassworPart(Composite parent) { - FormToolkit tk = getManagedForm().getToolkit(); - Section section = tk.createSection(parent, Section.TITLE_BAR); - section.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); - section.setText("Password"); - - Composite body = tk.createComposite(section, SWT.WRAP); - section.setClient(body); - GridLayout layout = new GridLayout(2, false); - body.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); - body.setLayout(layout); - - // add widgets (view) - final Text password1 = createLP(body, "New password", ""); - final Text password2 = createLP(body, "Repeat password", ""); - // create form part (controller) - AbstractFormPart part = new SectionPart(section) { - - public void commit(boolean onSave) { - if (!password1.getText().equals("") - || !password2.getText().equals("")) { - if (password1.getText().equals(password2.getText())) { - newPassword = password1.getText().toCharArray(); - password1.setText(""); - password2.setText(""); - super.commit(onSave); - } else { - password1.setText(""); - password2.setText(""); - throw new ArgeoException("Passwords are not equals"); - } - } - } - - }; - password1.addModifyListener(new FormPartML(part)); - password2.addModifyListener(new FormPartML(part)); - getManagedForm().addPart(part); - } - - /** Creates label and text. */ - protected Text createLT(Composite body, String label, String value) { - FormToolkit toolkit = getManagedForm().getToolkit(); - Label lbl = toolkit.createLabel(body, label); - lbl.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false)); - Text text = toolkit.createText(body, value, SWT.BORDER); - text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); - return text; - } - - /** Creates label and multiline text. */ - protected Text createLMT(Composite body, String label, String value) { - FormToolkit toolkit = getManagedForm().getToolkit(); - Label lbl = toolkit.createLabel(body, label); - lbl.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false)); - Text text = toolkit.createText(body, value, SWT.BORDER | SWT.MULTI); - text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true)); - return text; - } - - /** Creates label and password. */ - protected Text createLP(Composite body, String label, String value) { - FormToolkit toolkit = getManagedForm().getToolkit(); - Label lbl = toolkit.createLabel(body, label); - lbl.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false)); - Text text = toolkit.createText(body, value, SWT.BORDER | SWT.PASSWORD); - text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); - return text; - } - - private class FormPartML implements ModifyListener { - private AbstractFormPart formPart; - - public FormPartML(AbstractFormPart generalPart) { - this.formPart = generalPart; - } - - public void modifyText(ModifyEvent e) { - formPart.markDirty(); - } - - } - - public String getNewPassword() { - if (newPassword != null) - return new String(newPassword); - else - return null; - } - - public void resetNewPassword() { - if (newPassword != null) - Arrays.fill(newPassword, 'x'); - newPassword = null; - } -} diff --git a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/UserRolesPage.java b/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/UserRolesPage.java deleted file mode 100644 index 08cd457ad..000000000 --- a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/UserRolesPage.java +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.admin.editors; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.jcr.ArgeoNames; -import org.argeo.security.UserAdminService; -import org.argeo.security.ui.admin.SecurityAdminPlugin; -import org.eclipse.jface.viewers.CellEditor; -import org.eclipse.jface.viewers.CheckboxCellEditor; -import org.eclipse.jface.viewers.ColumnLabelProvider; -import org.eclipse.jface.viewers.EditingSupport; -import org.eclipse.jface.viewers.IStructuredContentProvider; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.jface.viewers.TableViewerColumn; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.layout.FillLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Table; -import org.eclipse.swt.widgets.TableColumn; -import org.eclipse.ui.forms.AbstractFormPart; -import org.eclipse.ui.forms.IManagedForm; -import org.eclipse.ui.forms.editor.FormEditor; -import org.eclipse.ui.forms.editor.FormPage; -import org.eclipse.ui.forms.widgets.ScrolledForm; -import org.springframework.security.GrantedAuthority; -import org.springframework.security.userdetails.UserDetails; - -/** - * Display/edit the roles of a user. - */ -public class UserRolesPage extends FormPage implements ArgeoNames { - final static String ID = "argeoUserEditor.rolesPage"; - - private final static Log log = LogFactory.getLog(UserRolesPage.class); - private final static Image ROLE_CHECKED = SecurityAdminPlugin - .getImageDescriptor("icons/security.gif").createImage(); - - private TableViewer rolesViewer; - private UserAdminService userAdminService; - private List roles; - - public UserRolesPage(FormEditor editor, UserDetails userDetails, - UserAdminService userAdminService) { - super(editor, ID, "Roles"); - setUserDetails(userDetails); - this.userAdminService = userAdminService; - } - - public void setUserDetails(UserDetails userDetails) { - this.roles = new ArrayList(); - for (GrantedAuthority ga : userDetails.getAuthorities()) - roles.add(ga.getAuthority()); - if (rolesViewer != null) - rolesViewer.refresh(); - } - - protected void createFormContent(final IManagedForm mf) { - ScrolledForm form = mf.getForm(); - form.setText("Roles"); - FillLayout mainLayout = new FillLayout(); - // ColumnLayout mainLayout = new ColumnLayout(); - // mainLayout.minNumColumns = 1; - // mainLayout.maxNumColumns = 4; - // mainLayout.topMargin = 0; - // mainLayout.bottomMargin = 5; - // mainLayout.leftMargin = mainLayout.rightMargin = - // mainLayout.horizontalSpacing = mainLayout.verticalSpacing = 10; - form.getBody().setLayout(mainLayout); - createRolesPart(form.getBody()); - } - - /** Creates the role section */ - protected void createRolesPart(Composite parent) { - Table table = new Table(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); - - AbstractFormPart part = new AbstractFormPart() { - public void commit(boolean onSave) { - // roles have already been modified in editing - super.commit(onSave); - if (log.isTraceEnabled()) - log.trace("Role part committed"); - } - }; - getManagedForm().addPart(part); - - // GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true); - // gridData.verticalSpan = 20; - // table.setLayoutData(gridData); - table.setLinesVisible(true); - table.setHeaderVisible(false); - rolesViewer = new TableViewer(table); - - // check column - TableViewerColumn column = createTableViewerColumn(rolesViewer, - "checked", 20); - column.setLabelProvider(new ColumnLabelProvider() { - public String getText(Object element) { - return null; - } - - public Image getImage(Object element) { - String role = element.toString(); - if (roles.contains(role)) { - return ROLE_CHECKED; - } else { - return null; - } - } - }); - column.setEditingSupport(new RoleEditingSupport(rolesViewer, part)); - - // role column - column = createTableViewerColumn(rolesViewer, "Role", 200); - column.setLabelProvider(new ColumnLabelProvider() { - public String getText(Object element) { - return element.toString(); - } - - public Image getImage(Object element) { - return null; - } - }); - rolesViewer.setContentProvider(new RolesContentProvider()); - rolesViewer.setInput(getEditorSite()); - } - - protected TableViewerColumn createTableViewerColumn(TableViewer viewer, - String title, int bound) { - final TableViewerColumn viewerColumn = new TableViewerColumn(viewer, - SWT.NONE); - final TableColumn column = viewerColumn.getColumn(); - column.setText(title); - column.setWidth(bound); - column.setResizable(true); - column.setMoveable(true); - return viewerColumn; - - } - - public List getRoles() { - return roles; - } - - public void refresh() { - rolesViewer.refresh(); - } - - private class RolesContentProvider implements IStructuredContentProvider { - public Object[] getElements(Object inputElement) { - return userAdminService.listEditableRoles().toArray(); - } - - public void dispose() { - } - - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - } - } - - /** Select the columns by editing the checkbox in the first column */ - class RoleEditingSupport extends EditingSupport { - - private final TableViewer viewer; - private final AbstractFormPart formPart; - - public RoleEditingSupport(TableViewer viewer, AbstractFormPart formPart) { - super(viewer); - this.viewer = viewer; - this.formPart = formPart; - } - - @Override - protected CellEditor getCellEditor(Object element) { - return new CheckboxCellEditor(null, SWT.CHECK | SWT.READ_ONLY); - - } - - @Override - protected boolean canEdit(Object element) { - return true; - } - - @Override - protected Object getValue(Object element) { - String role = element.toString(); - return roles.contains(role); - - } - - @Override - protected void setValue(Object element, Object value) { - Boolean inRole = (Boolean) value; - String role = element.toString(); - if (inRole && !roles.contains(role)) { - roles.add(role); - formPart.markDirty(); - } else if (!inRole && roles.contains(role)) { - roles.remove(role); - formPart.markDirty(); - } - viewer.refresh(); - } - } - -} diff --git a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/views/RolesView.java b/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/views/RolesView.java deleted file mode 100644 index fbe7dd570..000000000 --- a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/views/RolesView.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.admin.views; - -import org.argeo.ArgeoException; -import org.argeo.security.UserAdminService; -import org.argeo.security.ui.admin.SecurityAdminPlugin; -import org.argeo.security.ui.admin.commands.AddRole; -import org.eclipse.jface.viewers.IStructuredContentProvider; -import org.eclipse.jface.viewers.ITableLabelProvider; -import org.eclipse.jface.viewers.LabelProvider; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Listener; -import org.eclipse.swt.widgets.Table; -import org.eclipse.swt.widgets.Text; -import org.eclipse.ui.IWorkbench; -import org.eclipse.ui.handlers.IHandlerService; -import org.eclipse.ui.part.ViewPart; - -/** List all roles. */ -public class RolesView extends ViewPart { - public final static String ID = SecurityAdminPlugin.PLUGIN_ID - + ".adminRolesView"; - - private Text newRole; - - private TableViewer viewer; - private UserAdminService userAdminService; - - private String addNewRoleText = ""; - - @Override - public void createPartControl(Composite parent) { - parent.setLayout(new GridLayout(1, false)); - - // new role text field - newRole = new Text(parent, SWT.BORDER); - newRole.setText(addNewRoleText); - newRole.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); - // default action is add role - newRole.addListener(SWT.DefaultSelection, new Listener() { - public void handleEvent(Event evt) { - IWorkbench iw = SecurityAdminPlugin.getDefault().getWorkbench(); - IHandlerService handlerService = (IHandlerService) iw - .getService(IHandlerService.class); - try { - handlerService.executeCommand(AddRole.COMMAND_ID, evt); - } catch (Exception e) { - throw new ArgeoException("Cannot execute add role command", - e); - } - } - }); - // select all on focus - newRole.addListener(SWT.FocusIn, new Listener() { - public void handleEvent(Event e) { - newRole.selectAll(); - } - }); - - // roles table - Table table = new Table(parent, SWT.V_SCROLL | SWT.BORDER); - table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - table.setLinesVisible(false); - table.setHeaderVisible(false); - viewer = new TableViewer(table); - viewer.setContentProvider(new RolesContentProvider()); - viewer.setLabelProvider(new UsersLabelProvider()); - getViewSite().setSelectionProvider(viewer); - viewer.setInput(getViewSite()); - } - - @Override - public void setFocus() { - viewer.getTable().setFocus(); - } - - public void setUserAdminService(UserAdminService userAdminService) { - this.userAdminService = userAdminService; - } - - public String getAddNewRoleText() { - return addNewRoleText; - } - - private class RolesContentProvider implements IStructuredContentProvider { - - public Object[] getElements(Object inputElement) { - return userAdminService.listEditableRoles().toArray(); - } - - public void dispose() { - } - - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - } - - } - - private class UsersLabelProvider extends LabelProvider implements - ITableLabelProvider { - public String getColumnText(Object element, int columnIndex) { - return element.toString(); - } - - public Image getColumnImage(Object element, int columnIndex) { - return null; - } - - } - - public String getNewRole() { - return newRole.getText(); - } - - public void refresh() { - viewer.refresh(); - newRole.setText(addNewRoleText); - } -} diff --git a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/views/UsersView.java b/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/views/UsersView.java deleted file mode 100644 index a7437156d..000000000 --- a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/views/UsersView.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.admin.views; - -import javax.jcr.Node; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.observation.Event; -import javax.jcr.observation.EventIterator; -import javax.jcr.observation.EventListener; - -import org.argeo.ArgeoException; -import org.argeo.eclipse.ui.utils.CommandUtils; -import org.argeo.jcr.ArgeoJcrConstants; -import org.argeo.jcr.ArgeoNames; -import org.argeo.jcr.ArgeoTypes; -import org.argeo.jcr.JcrUtils; -import org.argeo.security.ui.admin.SecurityAdminPlugin; -import org.argeo.security.ui.admin.UserTableComposite; -import org.argeo.security.ui.admin.commands.OpenArgeoUserEditor; -import org.eclipse.jface.viewers.DoubleClickEvent; -import org.eclipse.jface.viewers.IDoubleClickListener; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.FillLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.eclipse.ui.part.ViewPart; - -/** List all users with filter. */ -public class UsersView extends ViewPart implements ArgeoNames { - public final static String ID = SecurityAdminPlugin.PLUGIN_ID - + ".adminUsersView"; - - /* DEPENDENCY INJECTION */ - private Session session; - - private UserTableComposite userTableCmp; - private JcrUserListener userStructureListener; - private JcrUserListener userPropertiesListener; - - @Override - public void createPartControl(Composite parent) { - parent.setLayout(new FillLayout()); - - // Create the composite that displays the list and a filter - userTableCmp = new UserTableComposite(parent, SWT.NO_FOCUS, session); - userTableCmp.populate(true, false); - - // Configure - userTableCmp.getTableViewer().addDoubleClickListener( - new ViewDoubleClickListener()); - getViewSite().setSelectionProvider(userTableCmp.getTableViewer()); - - // Add listener to refresh the list when something changes - userStructureListener = new JcrUserListener(getSite().getShell() - .getDisplay()); - JcrUtils.addListener(session, userStructureListener, Event.NODE_ADDED - | Event.NODE_REMOVED, ArgeoJcrConstants.PEOPLE_BASE_PATH, null); - userPropertiesListener = new JcrUserListener(getSite().getShell() - .getDisplay()); - JcrUtils.addListener(session, userStructureListener, - Event.PROPERTY_CHANGED | Event.PROPERTY_ADDED - | Event.PROPERTY_REMOVED, - ArgeoJcrConstants.PEOPLE_BASE_PATH, - ArgeoTypes.ARGEO_USER_PROFILE); - } - - @Override - public void setFocus() { - userTableCmp.setFocus(); - } - - @Override - public void dispose() { - JcrUtils.removeListenerQuietly(session, userStructureListener); - JcrUtils.removeListenerQuietly(session, userPropertiesListener); - JcrUtils.logoutQuietly(session); - super.dispose(); - } - - // public void setSession(Session session) { - // this.session = session; - // } - - public void refresh() { - this.getSite().getShell().getDisplay().asyncExec(new Runnable() { - @Override - public void run() { - userTableCmp.refresh(); - } - }); - } - - private class JcrUserListener implements EventListener { - private final Display display; - - public JcrUserListener(Display display) { - super(); - this.display = display; - } - - @Override - public void onEvent(EventIterator events) { - display.asyncExec(new Runnable() { - @Override - public void run() { - userTableCmp.refresh(); - } - }); - } - } - - class ViewDoubleClickListener implements IDoubleClickListener { - public void doubleClick(DoubleClickEvent evt) { - if (evt.getSelection().isEmpty()) - return; - - Object obj = ((IStructuredSelection) evt.getSelection()) - .getFirstElement(); - if (obj instanceof Node) { - try { - String username = ((Node) obj).getProperty(ARGEO_USER_ID) - .getString(); - String commandId = OpenArgeoUserEditor.COMMAND_ID; - String paramName = OpenArgeoUserEditor.PARAM_USERNAME; - CommandUtils.callCommand(commandId, paramName, username); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot open user editor", e); - } - } - } - } - - /* DEPENDENCY INJECTION */ - public void setRepository(Repository repository) { - try { - session = repository.login(); - } catch (RepositoryException re) { - throw new ArgeoException("Unable to initialise local session", re); - } - } - -} \ No newline at end of file diff --git a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/wizards/MainUserInfoWizardPage.java b/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/wizards/MainUserInfoWizardPage.java deleted file mode 100644 index ad3662b6f..000000000 --- a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/wizards/MainUserInfoWizardPage.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.admin.wizards; - -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.RepositoryException; - -import org.argeo.ArgeoException; -import org.argeo.eclipse.ui.EclipseUiUtils; -import org.argeo.jcr.ArgeoNames; -import org.argeo.security.UserAdminService; -import org.eclipse.jface.wizard.WizardPage; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Text; -import org.springframework.security.userdetails.UserDetails; -import org.springframework.security.userdetails.UsernameNotFoundException; - -public class MainUserInfoWizardPage extends WizardPage implements - ModifyListener, ArgeoNames { - private Text username, firstName, lastName, primaryEmail, password1, - password2; - private UserAdminService userAdminService; - - public MainUserInfoWizardPage(UserAdminService userAdminService) { - super("Main"); - this.userAdminService = userAdminService; - setTitle("Required Information"); - } - - @Override - public void createControl(Composite parent) { - Composite composite = new Composite(parent, SWT.NONE); - composite.setLayout(new GridLayout(2, false)); - username = EclipseUiUtils.createGridLT(composite, "Username", this); - primaryEmail = EclipseUiUtils.createGridLT(composite, "Email", this); - firstName = EclipseUiUtils.createGridLT(composite, "First name", this); - lastName = EclipseUiUtils.createGridLT(composite, "Last name", this); - password1 = EclipseUiUtils.createGridLP(composite, "Password", this); - password2 = EclipseUiUtils.createGridLP(composite, "Repeat password", - this); - setControl(composite); - - // Initialize buttons - setPageComplete(false); - getContainer().updateButtons(); - } - - @Override - public void modifyText(ModifyEvent event) { - String message = checkComplete(); - if (message != null) { - setMessage(message, WizardPage.ERROR); - setPageComplete(false); - } else { - setMessage("Complete", WizardPage.INFORMATION); - setPageComplete(true); - } - getContainer().updateButtons(); - } - - /** @return error message or null if complete */ - protected String checkComplete() { - // if (!username.getText().matches(UserAdminService.USERNAME_PATTERN)) - // return - // "Wrong user name format, should be lower case, between 3 and 64 characters with only '_' an '@' as acceptable special character."; - - if (username.getText().trim().equals("")) - return "User name must not be empty"; - - try { - UserDetails userDetails = userAdminService - .loadUserByUsername(username.getText()); - return "User " + userDetails.getUsername() + " already exists"; - } catch (UsernameNotFoundException e) { - // silent - } - if (!primaryEmail.getText().matches(UserAdminService.EMAIL_PATTERN)) - return "Not a valid email address"; - if (firstName.getText().trim().equals("")) - return "Specify a first name"; - if (lastName.getText().trim().equals("")) - return "Specify a last name"; - if (password1.getText().trim().equals("")) - return "Specify a password"; - if (password2.getText().trim().equals("")) - return "Repeat the password"; - if (!password2.getText().equals(password1.getText())) - return "Passwords are different"; - return null; - } - - public String getUsername() { - return username.getText(); - } - - public String getPassword() { - return password1.getText(); - } - - public void mapToProfileNode(Node up) { - try { - up.setProperty(ARGEO_PRIMARY_EMAIL, primaryEmail.getText()); - up.setProperty(ARGEO_FIRST_NAME, firstName.getText()); - up.setProperty(ARGEO_LAST_NAME, lastName.getText()); - - // derived values - // TODO add wizard pages to do it - up.setProperty(Property.JCR_TITLE, firstName.getText() + " " - + lastName.getText()); - up.setProperty(Property.JCR_DESCRIPTION, ""); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot map to " + up, e); - } - } -} diff --git a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/wizards/NewUserWizard.java b/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/wizards/NewUserWizard.java deleted file mode 100644 index c2d041f56..000000000 --- a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/wizards/NewUserWizard.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.admin.wizards; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.eclipse.ui.ErrorFeedback; -import org.argeo.jcr.JcrUtils; -import org.argeo.jcr.UserJcrUtils; -import org.argeo.security.UserAdminService; -import org.argeo.security.jcr.JcrSecurityModel; -import org.argeo.security.jcr.JcrUserDetails; -import org.eclipse.jface.wizard.Wizard; -import org.springframework.security.GrantedAuthority; - -/** Wizard to create a new user */ -public class NewUserWizard extends Wizard { - private final static Log log = LogFactory.getLog(NewUserWizard.class); - private Session session; - private UserAdminService userAdminService; - private JcrSecurityModel jcrSecurityModel; - - // pages - private MainUserInfoWizardPage mainUserInfo; - - public NewUserWizard(Session session, UserAdminService userAdminService, - JcrSecurityModel jcrSecurityModel) { - this.session = session; - this.userAdminService = userAdminService; - this.jcrSecurityModel = jcrSecurityModel; - } - - @Override - public void addPages() { - mainUserInfo = new MainUserInfoWizardPage(userAdminService); - addPage(mainUserInfo); - } - - @Override - public boolean performFinish() { - if (!canFinish()) - return false; - - String username = mainUserInfo.getUsername(); - try { - // Node userProfile = SecurityJcrUtils.createUserProfile(session, - // username); - Node userProfile = jcrSecurityModel.sync(session, username, null); - session.getWorkspace().getVersionManager() - .checkout(userProfile.getPath()); - mainUserInfo.mapToProfileNode(userProfile); - String password = mainUserInfo.getPassword(); - // TODO add roles - JcrUserDetails jcrUserDetails = new JcrUserDetails(userProfile, - password, new GrantedAuthority[0]); - session.save(); - session.getWorkspace().getVersionManager() - .checkin(userProfile.getPath()); - userAdminService.createUser(jcrUserDetails); - return true; - } catch (Exception e) { - JcrUtils.discardQuietly(session); - Node userHome = UserJcrUtils.getUserHome(session, username); - if (userHome != null) { - try { - userHome.remove(); - session.save(); - } catch (RepositoryException e1) { - JcrUtils.discardQuietly(session); - log.warn("Error when trying to clean up failed new user " - + username, e1); - } - } - ErrorFeedback.show("Cannot create new user " + username, e); - return false; - } - } - - public void setSession(Session session) { - this.session = session; - } - -} diff --git a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/wizards/UserBatchUpdateWizard.java b/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/wizards/UserBatchUpdateWizard.java deleted file mode 100644 index 71e4a1b73..000000000 --- a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/wizards/UserBatchUpdateWizard.java +++ /dev/null @@ -1,607 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.admin.wizards; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.version.VersionManager; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.ArgeoException; -import org.argeo.ArgeoMonitor; -import org.argeo.eclipse.ui.EclipseArgeoMonitor; -import org.argeo.jcr.ArgeoNames; -import org.argeo.jcr.JcrUtils; -import org.argeo.security.UserAdminService; -import org.argeo.security.jcr.JcrSecurityModel; -import org.argeo.security.jcr.JcrUserDetails; -import org.argeo.security.ui.PrivilegedJob; -import org.argeo.security.ui.admin.SecurityAdminPlugin; -import org.argeo.security.ui.admin.UserTableComposite; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.jface.dialogs.IPageChangeProvider; -import org.eclipse.jface.dialogs.IPageChangedListener; -import org.eclipse.jface.dialogs.PageChangedEvent; -import org.eclipse.jface.wizard.IWizardContainer; -import org.eclipse.jface.wizard.Wizard; -import org.eclipse.jface.wizard.WizardPage; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.SelectionListener; -import org.eclipse.swt.layout.FillLayout; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Combo; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Text; - -/** Wizard to update users */ -public class UserBatchUpdateWizard extends Wizard { - private final static Log log = LogFactory - .getLog(UserBatchUpdateWizard.class); - private Session session; - private UserAdminService userAdminService; - - // pages - private ChooseCommandWizardPage chooseCommandPage; - private ChooseUsersWizardPage userListPage; - private ValidateAndLaunchWizardPage validatePage; - - // ///////////////////////////////////////////////// - // / Definition of the various implemented commands - private final static String CMD_UPDATE_PASSWORD = "resetPassword"; - private final static String CMD_GROUP_MEMBERSHIP = "groupMembership"; - - private final Map commands = new HashMap() { - private static final long serialVersionUID = 1L; - { - put("Enable user(s)", ArgeoNames.ARGEO_ENABLED); - put("Expire credentials", ArgeoNames.ARGEO_CREDENTIALS_NON_EXPIRED); - put("Expire account(s)", ArgeoNames.ARGEO_ACCOUNT_NON_EXPIRED); - put("Lock account(s)", ArgeoNames.ARGEO_ACCOUNT_NON_LOCKED); - put("Reset password(s)", CMD_UPDATE_PASSWORD); - // TODO implement role / group management - // put("Add/Remove from group", CMD_GROUP_MEMBERSHIP); - } - }; - - public UserBatchUpdateWizard(Session session, - UserAdminService userAdminService, JcrSecurityModel jcrSecurityModel) { - this.session = session; - this.userAdminService = userAdminService; - // this.jcrSecurityModel = jcrSecurityModel; - } - - @Override - public void addPages() { - chooseCommandPage = new ChooseCommandWizardPage(); - addPage(chooseCommandPage); - userListPage = new ChooseUsersWizardPage(session); - addPage(userListPage); - validatePage = new ValidateAndLaunchWizardPage(session); - addPage(validatePage); - } - - @Override - public boolean performFinish() { - if (!canFinish()) - return false; - - UpdateJob job = null; - if (ArgeoNames.ARGEO_ENABLED.equals(chooseCommandPage.getCommand())) { - job = new UpdateBoolean(session, userListPage.getSelectedUsers(), - ArgeoNames.ARGEO_ENABLED, - chooseCommandPage.getBoleanValue()); - } else if (ArgeoNames.ARGEO_CREDENTIALS_NON_EXPIRED - .equals(chooseCommandPage.getCommand())) { - job = new UpdateBoolean(session, userListPage.getSelectedUsers(), - ArgeoNames.ARGEO_CREDENTIALS_NON_EXPIRED, - chooseCommandPage.getBoleanValue()); - } else if (ArgeoNames.ARGEO_ACCOUNT_NON_EXPIRED - .equals(chooseCommandPage.getCommand())) { - job = new UpdateBoolean(session, userListPage.getSelectedUsers(), - ArgeoNames.ARGEO_ACCOUNT_NON_EXPIRED, - chooseCommandPage.getBoleanValue()); - } else if (ArgeoNames.ARGEO_ACCOUNT_NON_LOCKED.equals(chooseCommandPage - .getCommand())) { - job = new UpdateBoolean(session, userListPage.getSelectedUsers(), - ArgeoNames.ARGEO_ACCOUNT_NON_LOCKED, - chooseCommandPage.getBoleanValue()); - } else if (CMD_UPDATE_PASSWORD.equals(chooseCommandPage.getCommand())) { - String newValue = chooseCommandPage.getPwdValue(); - if (newValue == null) - throw new ArgeoException( - "Password cannot be null or an empty string"); - job = new ResetPassword(session, userAdminService, - userListPage.getSelectedUsers(), newValue); - } - - if (job != null) - job.schedule(); - return true; - } - - public void setSession(Session session) { - this.session = session; - } - - public boolean canFinish() { - if (this.getContainer().getCurrentPage() == validatePage) - return true; - return false; - } - - // ///////////////////////// - // REEL UPDATE JOB - private class UpdateBoolean extends UpdateJob { - private String propertyName; - private boolean value; - - public UpdateBoolean(Session session, List nodesToUpdate, - String propertyName, boolean value) { - super(session, nodesToUpdate); - this.propertyName = propertyName; - this.value = value; - } - - protected void doUpdate(Node node) { - try { - node.setProperty(propertyName, value); - } catch (RepositoryException re) { - throw new ArgeoException( - "Unable to update boolean value for node " + node, re); - } - } - } - - private class ResetPassword extends UpdateJob { - private String newValue; - private UserAdminService userAdminService; - - public ResetPassword(Session session, - UserAdminService userAdminService, List nodesToUpdate, - String newValue) { - super(session, nodesToUpdate); - this.newValue = newValue; - this.userAdminService = userAdminService; - } - - protected void doUpdate(Node node) { - try { - String userId = node.getProperty(ArgeoNames.ARGEO_USER_ID) - .getString(); - if (userAdminService.userExists(userId)) { - JcrUserDetails userDetails = (JcrUserDetails) userAdminService - .loadUserByUsername(userId); - userAdminService.updateUser(userDetails - .cloneWithNewPassword(newValue)); - } - } catch (RepositoryException re) { - throw new ArgeoException( - "Unable to update boolean value for node " + node, re); - } - } - } - - @SuppressWarnings("unused") - private class AddToGroup extends UpdateJob { - private String groupID; - private Session session; - - public AddToGroup(Session session, List nodesToUpdate, - String groupID) { - super(session, nodesToUpdate); - this.session = session; - this.groupID = groupID; - } - - protected void doUpdate(Node node) { - log.info("Add/Remove to group actions are not yet implemented"); - // TODO implement this - // try { - // throw new ArgeoException("Not yet implemented"); - // } catch (RepositoryException re) { - // throw new ArgeoException( - // "Unable to update boolean value for node " + node, re); - // } - } - } - - /** - * Base privileged job that will be run asynchronously to perform the batch - * update - */ - private abstract class UpdateJob extends PrivilegedJob { - - private final Session currSession; - private final List nodesToUpdate; - - protected abstract void doUpdate(Node node); - - public UpdateJob(Session session, List nodesToUpdate) { - super("Perform update"); - try { - this.currSession = session.getRepository().login(); - // "move" nodes to update in the new session - // the "old" session will be closed by the calling command - // before the job has effectively ran - // TODO there must be a cleaner way to do. - List nodes = new ArrayList(); - for (Node node : nodesToUpdate) { - nodes.add(currSession.getNode(node.getPath())); - } - this.nodesToUpdate = nodes; - } catch (RepositoryException e) { - throw new ArgeoException("Error while dupplicating " - + "session for job", e); - } - } - - @Override - protected IStatus doRun(IProgressMonitor progressMonitor) { - try { - ArgeoMonitor monitor = new EclipseArgeoMonitor(progressMonitor); - VersionManager vm = currSession.getWorkspace() - .getVersionManager(); - int total = nodesToUpdate.size(); - monitor.beginTask("Performing change", total); - for (Node node : nodesToUpdate) { - String path = node.getPath(); - vm.checkout(path); - doUpdate(node); - currSession.save(); - vm.checkin(path); - monitor.worked(1); - } - } catch (Exception e) { - log.error("Cannot perform batch update on users", e); - // e.printStackTrace(); - - // Dig exception to find the root cause that will enable the - // user to understand the problem - Throwable cause = e; - Throwable originalCause = e; - while (cause != null) { - if (log.isTraceEnabled()) - log.trace("Parent Cause message : " - + cause.getMessage()); - originalCause = cause; - cause = cause.getCause(); - } - return new Status(IStatus.ERROR, SecurityAdminPlugin.PLUGIN_ID, - "Cannot perform updates.", originalCause); - } finally { - JcrUtils.logoutQuietly(currSession); - } - return Status.OK_STATUS; - } - } - - // ////////////////////// - // Pages definition - /** Displays a combo box that enables user to choose which action to perform */ - private class ChooseCommandWizardPage extends WizardPage { - private static final long serialVersionUID = 1L; - - private Combo chooseCommandCmb; - private Button trueChk; - private Text valueTxt; - private Text pwdTxt; - private Text pwd2Txt; - - public ChooseCommandWizardPage() { - super("Choose a command to run."); - setTitle("Choose a command to run."); - } - - @Override - public void createControl(Composite parent) { - GridLayout gl = new GridLayout(); - Composite container = new Composite(parent, SWT.NO_FOCUS); - container.setLayout(gl); - - chooseCommandCmb = new Combo(container, SWT.NO_FOCUS); - String[] values = commands.keySet().toArray( - new String[commands.size()]); - chooseCommandCmb.setItems(values); - chooseCommandCmb.setLayoutData(new GridData(SWT.FILL, SWT.TOP, - true, false)); - - final Composite bottomPart = new Composite(container, SWT.NO_FOCUS); - gl = new GridLayout(); - gl.horizontalSpacing = gl.marginWidth = gl.verticalSpacing = 0; - bottomPart.setLayout(gl); - bottomPart.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, - true)); - - chooseCommandCmb.addSelectionListener(new SelectionListener() { - private static final long serialVersionUID = 1L; - - @Override - public void widgetSelected(SelectionEvent e) { - if (getCommand().equals(CMD_UPDATE_PASSWORD)) - populatePasswordCmp(bottomPart); - else if (getCommand().equals(CMD_GROUP_MEMBERSHIP)) - populateGroupCmp(bottomPart); - else - populateBooleanFlagCmp(bottomPart); - bottomPart.pack(true); - bottomPart.layout(); - } - - @Override - public void widgetDefaultSelected(SelectionEvent e) { - } - }); - - setControl(container); - } - - private void cleanParent(Composite parent) { - if (parent.getChildren().length > 0) { - for (Control control : parent.getChildren()) - control.dispose(); - } - } - - private void populateBooleanFlagCmp(Composite parent) { - cleanParent(parent); - trueChk = new Button(parent, SWT.CHECK); - trueChk.setText("Do it. (It will to the contrary if unchecked)"); - trueChk.setSelection(true); - trueChk.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false)); - } - - private void populatePasswordCmp(Composite parent) { - cleanParent(parent); - Composite body = new Composite(parent, SWT.NO_FOCUS); - body.setLayout(new GridLayout(2, false)); - body.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - pwdTxt = createLP(body, "New password", ""); - pwd2Txt = createLP(body, "Repeat password", ""); - } - - /** Creates label and password. */ - protected Text createLP(Composite body, String label, String value) { - Label lbl = new Label(body, SWT.NONE); - lbl.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false)); - lbl.setText(label); - Text text = new Text(body, SWT.BORDER | SWT.PASSWORD); - text.setText(value); - text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); - return text; - } - - private void populateGroupCmp(Composite parent) { - if (parent.getChildren().length > 0) { - for (Control control : parent.getChildren()) - control.dispose(); - } - trueChk = new Button(parent, SWT.CHECK); - trueChk.setText("Add to group. (It will remove user(s) from the " - + "corresponding group if unchecked)"); - trueChk.setSelection(true); - trueChk.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false)); - } - - protected String getCommand() { - return commands.get(chooseCommandCmb.getItem(chooseCommandCmb - .getSelectionIndex())); - } - - protected String getCommandLbl() { - return chooseCommandCmb.getItem(chooseCommandCmb - .getSelectionIndex()); - } - - protected boolean getBoleanValue() { - // FIXME this is not consistent and will lead to errors. - if (ArgeoNames.ARGEO_ENABLED.equals(getCommand())) - return trueChk.getSelection(); - else - return !trueChk.getSelection(); - } - - @SuppressWarnings("unused") - protected String getStringValue() { - String value = null; - if (valueTxt != null) { - value = valueTxt.getText(); - if ("".equals(value.trim())) - value = null; - } - return value; - } - - protected String getPwdValue() { - String newPwd = null; - if (pwdTxt == null || pwd2Txt == null) - return null; - if (!pwdTxt.getText().equals("") || !pwd2Txt.getText().equals("")) { - if (pwdTxt.getText().equals(pwd2Txt.getText())) { - newPwd = pwdTxt.getText(); - pwdTxt.setText(""); - pwd2Txt.setText(""); - } else { - pwdTxt.setText(""); - pwd2Txt.setText(""); - throw new ArgeoException("Passwords are not equals"); - } - } - return newPwd; - } - } - - /** - * Displays a list of users with a check box to be able to choose some of - * them - */ - private class ChooseUsersWizardPage extends WizardPage implements - IPageChangedListener { - private static final long serialVersionUID = 1L; - private UserTableComposite userTableCmp; - private Composite container; - private Session session; - - public ChooseUsersWizardPage(Session session) { - super("Choose Users"); - this.session = session; - setTitle("Select users who will be impacted"); - } - - @Override - public void createControl(Composite parent) { - container = new Composite(parent, SWT.NONE); - container.setLayout(new FillLayout()); - userTableCmp = new MyUserTableCmp(container, SWT.NO_FOCUS, session); - userTableCmp.populate(true, true); - setControl(container); - - // Add listener to update message when shown - final IWizardContainer container = this.getContainer(); - if (container instanceof IPageChangeProvider) { - ((IPageChangeProvider) container).addPageChangedListener(this); - } - - } - - @Override - public void pageChanged(PageChangedEvent event) { - if (event.getSelectedPage() == this) { - String msg = "Chosen batch action: " - + chooseCommandPage.getCommandLbl(); - ((WizardPage) event.getSelectedPage()).setMessage(msg); - } - } - - protected List getSelectedUsers() { - return userTableCmp.getSelectedUsers(); - } - - private class MyUserTableCmp extends UserTableComposite { - - private static final long serialVersionUID = 1L; - - public MyUserTableCmp(Composite parent, int style, Session session) { - super(parent, style, session); - } - - @Override - protected void refreshFilteredList() { - List nodes = new ArrayList(); - try { - NodeIterator ni = listFilteredElements(session, - getFilterString()); - - users: while (ni.hasNext()) { - Node currNode = ni.nextNode(); - String username = currNode.hasProperty(ARGEO_USER_ID) ? currNode - .getProperty(ARGEO_USER_ID).getString() : ""; - if (username.equals(session.getUserID())) - continue users; - else - nodes.add(currNode); - } - getTableViewer().setInput(nodes.toArray()); - } catch (RepositoryException e) { - throw new ArgeoException("Unable to list users", e); - } - } - } - } - - /** - * Recapitulation of input data before running real update - */ - private class ValidateAndLaunchWizardPage extends WizardPage implements - IPageChangedListener { - private static final long serialVersionUID = 1L; - private UserTableComposite userTableCmp; - private Session session; - - public ValidateAndLaunchWizardPage(Session session) { - super("Validate and launch"); - this.session = session; - setTitle("Validate and launch"); - } - - @Override - public void createControl(Composite parent) { - Composite mainCmp = new Composite(parent, SWT.NO_FOCUS); - mainCmp.setLayout(new FillLayout()); - - // Add listener to update user list when shown - final IWizardContainer container = this.getContainer(); - if (container instanceof IPageChangeProvider) { - ((IPageChangeProvider) container).addPageChangedListener(this); - } - - userTableCmp = new UserTableComposite(mainCmp, SWT.NO_FOCUS, - session); - userTableCmp.populate(false, false); - setControl(mainCmp); - } - - @Override - public void pageChanged(PageChangedEvent event) { - if (event.getSelectedPage() == this) { - @SuppressWarnings({ "unchecked", "rawtypes" }) - Object[] values = ((ArrayList) userListPage.getSelectedUsers()) - .toArray(new Object[userListPage.getSelectedUsers() - .size()]); - userTableCmp.getTableViewer().setInput(values); - String msg = "Following batch action: [" - + chooseCommandPage.getCommandLbl() - + "] will be perfomed on the users listed below.\n" - + "Are you sure you want to proceed?"; - ((WizardPage) event.getSelectedPage()).setMessage(msg); - } - } - - // private class MyUserTableCmp extends UserTableComposite { - // public MyUserTableCmp(Composite parent, int style, Session session) { - // super(parent, style, session); - // } - // - // @Override - // protected void refreshFilteredList() { - // @SuppressWarnings({ "unchecked", "rawtypes" }) - // - // setFilteredList(values); - // } - // - // @Override - // public void setVisible(boolean visible) { - // super.setVisible(visible); - // if (visible) - // refreshFilteredList(); - // } - // } - } -} \ No newline at end of file diff --git a/security/plugins/org.argeo.security.ui.rap/.classpath b/security/plugins/org.argeo.security.ui.rap/.classpath deleted file mode 100644 index 5641c7ca3..000000000 --- a/security/plugins/org.argeo.security.ui.rap/.classpath +++ /dev/null @@ -1,7 +0,0 @@ - - - - >> - - - diff --git a/security/plugins/org.argeo.security.ui.rap/.project b/security/plugins/org.argeo.security.ui.rap/.project deleted file mode 100644 index d20bec7fc..000000000 --- a/security/plugins/org.argeo.security.ui.rap/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - org.argeo.security.ui.rap - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - - diff --git a/security/plugins/org.argeo.security.ui.rap/META-INF/jaas_default.txt b/security/plugins/org.argeo.security.ui.rap/META-INF/jaas_default.txt deleted file mode 100644 index c74797b93..000000000 --- a/security/plugins/org.argeo.security.ui.rap/META-INF/jaas_default.txt +++ /dev/null @@ -1,23 +0,0 @@ -UNIX { - org.eclipse.equinox.security.auth.module.ExtensionLoginModule sufficient - extensionId="org.argeo.security.equinox.unixLoginModule"; -}; - -SPRING { - org.eclipse.equinox.security.auth.module.ExtensionLoginModule sufficient - extensionId="org.argeo.security.equinox.springLoginModule"; -}; - -SPRING_ANONYMOUS { - org.eclipse.equinox.security.auth.module.ExtensionLoginModule sufficient - extensionId="org.argeo.security.equinox.anonymousSpringLoginModule"; -}; - -SPRING_SECURITY_CONTEXT { - org.eclipse.equinox.security.auth.module.ExtensionLoginModule sufficient - extensionId="org.argeo.security.equinox.springSecurityContextLoginModule"; -}; - -KEYRING { - org.argeo.security.crypto.KeyringLoginModule required; -}; diff --git a/security/plugins/org.argeo.security.ui.rap/META-INF/spring/commands.xml b/security/plugins/org.argeo.security.ui.rap/META-INF/spring/commands.xml deleted file mode 100644 index 3dd037a3c..000000000 --- a/security/plugins/org.argeo.security.ui.rap/META-INF/spring/commands.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/security/plugins/org.argeo.security.ui.rap/META-INF/spring/osgi.xml b/security/plugins/org.argeo.security.ui.rap/META-INF/spring/osgi.xml deleted file mode 100644 index 9e357a36d..000000000 --- a/security/plugins/org.argeo.security.ui.rap/META-INF/spring/osgi.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - \ No newline at end of file diff --git a/security/plugins/org.argeo.security.ui.rap/branding/afterLogout.html b/security/plugins/org.argeo.security.ui.rap/branding/afterLogout.html deleted file mode 100644 index ae0901bff..000000000 --- a/security/plugins/org.argeo.security.ui.rap/branding/afterLogout.html +++ /dev/null @@ -1,18 +0,0 @@ - - - -
- - - - -
- Login... -
-
- - \ No newline at end of file diff --git a/security/plugins/org.argeo.security.ui.rap/branding/empty.html b/security/plugins/org.argeo.security.ui.rap/branding/empty.html deleted file mode 100644 index 94fe28ac8..000000000 --- a/security/plugins/org.argeo.security.ui.rap/branding/empty.html +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/security/plugins/org.argeo.security.ui.rap/branding/favicon.ico b/security/plugins/org.argeo.security.ui.rap/branding/favicon.ico deleted file mode 100644 index 213cdf73f..000000000 Binary files a/security/plugins/org.argeo.security.ui.rap/branding/favicon.ico and /dev/null differ diff --git a/security/plugins/org.argeo.security.ui.rap/branding/login.html b/security/plugins/org.argeo.security.ui.rap/branding/login.html deleted file mode 100644 index 6de7eb216..000000000 --- a/security/plugins/org.argeo.security.ui.rap/branding/login.html +++ /dev/null @@ -1,18 +0,0 @@ - - - -
- - - - -
- Login... -
-
- - \ No newline at end of file diff --git a/security/plugins/org.argeo.security.ui.rap/branding/public.html b/security/plugins/org.argeo.security.ui.rap/branding/public.html deleted file mode 100644 index e50f6e943..000000000 --- a/security/plugins/org.argeo.security.ui.rap/branding/public.html +++ /dev/null @@ -1,18 +0,0 @@ - - - -
- - - - -
- Refresh... -
-
- - \ No newline at end of file diff --git a/security/plugins/org.argeo.security.ui.rap/build.properties b/security/plugins/org.argeo.security.ui.rap/build.properties deleted file mode 100644 index 5618fae36..000000000 --- a/security/plugins/org.argeo.security.ui.rap/build.properties +++ /dev/null @@ -1,6 +0,0 @@ -bin.includes = plugin.xml,\ - META-INF/,\ - branding/,\ - icons/ -source.. = src/main/java/ -output.. = target/classes/ diff --git a/security/plugins/org.argeo.security.ui.rap/icons/closeAll.gif b/security/plugins/org.argeo.security.ui.rap/icons/closeAll.gif deleted file mode 100644 index 28a3785aa..000000000 Binary files a/security/plugins/org.argeo.security.ui.rap/icons/closeAll.gif and /dev/null differ diff --git a/security/plugins/org.argeo.security.ui.rap/icons/exit.png b/security/plugins/org.argeo.security.ui.rap/icons/exit.png deleted file mode 100644 index cfbf9d15e..000000000 Binary files a/security/plugins/org.argeo.security.ui.rap/icons/exit.png and /dev/null differ diff --git a/security/plugins/org.argeo.security.ui.rap/icons/home.gif b/security/plugins/org.argeo.security.ui.rap/icons/home.gif deleted file mode 100644 index fd0c66950..000000000 Binary files a/security/plugins/org.argeo.security.ui.rap/icons/home.gif and /dev/null differ diff --git a/security/plugins/org.argeo.security.ui.rap/icons/main.gif b/security/plugins/org.argeo.security.ui.rap/icons/main.gif deleted file mode 100644 index 90a00147b..000000000 Binary files a/security/plugins/org.argeo.security.ui.rap/icons/main.gif and /dev/null differ diff --git a/security/plugins/org.argeo.security.ui.rap/icons/password.gif b/security/plugins/org.argeo.security.ui.rap/icons/password.gif deleted file mode 100644 index a6b251fc8..000000000 Binary files a/security/plugins/org.argeo.security.ui.rap/icons/password.gif and /dev/null differ diff --git a/security/plugins/org.argeo.security.ui.rap/icons/preferences.png b/security/plugins/org.argeo.security.ui.rap/icons/preferences.png deleted file mode 100644 index aa0dc0be9..000000000 Binary files a/security/plugins/org.argeo.security.ui.rap/icons/preferences.png and /dev/null differ diff --git a/security/plugins/org.argeo.security.ui.rap/plugin.xml b/security/plugins/org.argeo.security.ui.rap/plugin.xml deleted file mode 100644 index 49506de26..000000000 --- a/security/plugins/org.argeo.security.ui.rap/plugin.xml +++ /dev/null @@ -1,222 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/security/plugins/org.argeo.security.ui.rap/pom.xml b/security/plugins/org.argeo.security.ui.rap/pom.xml deleted file mode 100644 index 200f373e1..000000000 --- a/security/plugins/org.argeo.security.ui.rap/pom.xml +++ /dev/null @@ -1,83 +0,0 @@ - - 4.0.0 - - org.argeo.commons.security - 2.1.12-SNAPSHOT - plugins - .. - - org.argeo.security.ui.rap - Commons Security UI RAP - jar - - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-source-plugin - - - org.apache.maven.plugins - maven-jar-plugin - - - org.apache.felix - maven-bundle-plugin - - - org.argeo.security.ui.rap.SecureRapActivator - lazy - org.eclipse.rap.ui,org.eclipse.core.runtime - - org.springframework.core, - org.argeo.eclipse.spring, - org.argeo.eclipse.ui.specific, - * - - - - - - - - - - org.argeo.commons.base - org.argeo.util - 2.1.12-SNAPSHOT - - - - - org.argeo.tp - slf4j.org.apache.commons.logging - - - - - org.argeo.commons.security - org.argeo.security.ui - 2.1.12-SNAPSHOT - - - org.argeo.commons.security - org.argeo.security.equinox - 2.1.12-SNAPSHOT - - - - - org.argeo.commons.base - org.argeo.eclipse.dep.rap - 2.1.12-SNAPSHOT - - - org.argeo.commons.base - org.argeo.eclipse.ui.rap - 2.1.12-SNAPSHOT - - - \ No newline at end of file diff --git a/security/plugins/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/AnonymousEntryPoint.java b/security/plugins/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/AnonymousEntryPoint.java deleted file mode 100644 index 16d24897c..000000000 --- a/security/plugins/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/AnonymousEntryPoint.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.rap; - -import java.security.PrivilegedAction; - -import javax.security.auth.Subject; -import javax.security.auth.login.LoginException; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.ArgeoException; -import org.eclipse.equinox.security.auth.ILoginContext; -import org.eclipse.rap.rwt.RWT; -import org.eclipse.rap.rwt.application.IEntryPoint; -import org.eclipse.swt.widgets.Display; -import org.eclipse.ui.PlatformUI; - -/** - * RAP entry point which authenticates the subject as anonymous, for public - * unauthenticated access. - */ -public class AnonymousEntryPoint implements IEntryPoint { - private final static Log log = LogFactory.getLog(AnonymousEntryPoint.class); - - /** - * How many seconds to wait before invalidating the session if the user has - * not yet logged in. - */ - private Integer loginTimeout = 1 * 60; - private Integer sessionTimeout = 15 * 60; - - @Override - public int createUI() { - // Short login timeout so that the modal dialog login doesn't hang - // around too long - RWT.getRequest().getSession().setMaxInactiveInterval(loginTimeout); - - if (log.isDebugEnabled()) - log.debug("Anonymous THREAD=" + Thread.currentThread().getId() - + ", sessionStore=" + RWT.getSessionStore().getId()); - - // create display - final Display display = PlatformUI.createDisplay(); - - // log in - final ILoginContext loginContext = SecureRapActivator - .createLoginContext(SecureRapActivator.CONTEXT_SPRING_ANONYMOUS); - Subject subject = null; - try { - loginContext.login(); - subject = loginContext.getSubject(); - } catch (LoginException e) { - throw new ArgeoException( - "Unexpected exception during authentication", e); - } - - // identify after successful login - if (log.isDebugEnabled()) - log.debug("Authenticated " + subject); - final String username = subject.getPrincipals().iterator().next() - .getName(); - - // Once the user is logged in, she can have a longer session timeout - RWT.getRequest().getSession().setMaxInactiveInterval(sessionTimeout); - - // Logout callback when the display is disposed - display.disposeExec(new Runnable() { - public void run() { - log.debug("Display disposed"); - logout(loginContext, username); - } - }); - - // - // RUN THE WORKBENCH - // - Integer returnCode = null; - try { - returnCode = Subject.doAs(subject, new PrivilegedAction() { - public Integer run() { - RapWorkbenchAdvisor workbenchAdvisor = new RapWorkbenchAdvisor( - null); - int result = PlatformUI.createAndRunWorkbench(display, - workbenchAdvisor); - return new Integer(result); - } - }); - logout(loginContext, username); - } finally { - display.dispose(); - } - return returnCode; - } - - private void logout(ILoginContext secureContext, String username) { - try { - secureContext.logout(); - log.info("Logged out " + (username != null ? username : "") - + " (THREAD=" + Thread.currentThread().getId() + ")"); - } catch (LoginException e) { - log.error("Erorr when logging out", e); - } - } -} diff --git a/security/plugins/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/LogoutEntryPoint.java b/security/plugins/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/LogoutEntryPoint.java deleted file mode 100644 index 733754901..000000000 --- a/security/plugins/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/LogoutEntryPoint.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.rap; - -import javax.security.auth.login.LoginException; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.eclipse.equinox.security.auth.ILoginContext; -import org.eclipse.rap.rwt.RWT; -import org.eclipse.rap.rwt.application.IEntryPoint; -import org.eclipse.ui.PlatformUI; -import org.springframework.security.context.SecurityContextHolder; - -/** - * RAP entry point which logs out the currently authenticated user - */ -public class LogoutEntryPoint implements IEntryPoint { - private final static Log log = LogFactory.getLog(LogoutEntryPoint.class); - - /** - * From org.springframework.security.context. - * HttpSessionContextIntegrationFilter - */ - protected static final String SPRING_SECURITY_CONTEXT_KEY = "SPRING_SECURITY_CONTEXT"; - - @Override - public int createUI() { - // create display - PlatformUI.createDisplay(); - - final ILoginContext loginContext = SecureRapActivator - .createLoginContext(SecureRapActivator.CONTEXT_SPRING); - try { - loginContext.logout(); - } catch (LoginException e) { - e.printStackTrace(); - } - - RWT.getRequest().getSession() - .removeAttribute(SPRING_SECURITY_CONTEXT_KEY); - SecurityContextHolder.clearContext(); - RWT.getRequest().getSession().setMaxInactiveInterval(1); - - if (log.isDebugEnabled()) - log.debug("Logged out session " + RWT.getSessionStore().getId()); - return 0; - } -} diff --git a/security/plugins/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/NullEntryPoint.java b/security/plugins/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/NullEntryPoint.java deleted file mode 100644 index 811cc2821..000000000 --- a/security/plugins/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/NullEntryPoint.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.rap; - -import org.eclipse.rap.rwt.application.IEntryPoint; -import org.eclipse.ui.PlatformUI; - -/** - * RAP entry point which does doesing except creating the display - */ -public class NullEntryPoint implements IEntryPoint { - @Override - public int createUI() { - // create display - PlatformUI.createDisplay(); - return 0; - } -} diff --git a/security/plugins/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/RapActionBarAdvisor.java b/security/plugins/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/RapActionBarAdvisor.java deleted file mode 100644 index 074b798c7..000000000 --- a/security/plugins/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/RapActionBarAdvisor.java +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.rap; - -import org.argeo.security.ui.commands.OpenHomePerspective; -import org.eclipse.core.commands.Category; -import org.eclipse.core.commands.Command; -import org.eclipse.jface.action.ICoolBarManager; -import org.eclipse.jface.action.IMenuManager; -import org.eclipse.jface.action.IToolBarManager; -import org.eclipse.jface.action.ToolBarManager; -import org.eclipse.swt.SWT; -import org.eclipse.ui.IWorkbenchWindow; -import org.eclipse.ui.actions.ActionFactory; -import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction; -import org.eclipse.ui.application.ActionBarAdvisor; -import org.eclipse.ui.application.IActionBarConfigurer; -import org.eclipse.ui.commands.ICommandService; - -/** Eclipse rap specific action bar advisor */ -public class RapActionBarAdvisor extends ActionBarAdvisor { - private final static String ID_BASE = "org.argeo.security.ui.rap"; - // private final static Log log = LogFactory - // .getLog(SecureActionBarAdvisor.class); - - /** Null means anonymous */ - private String username = null; - - // private IAction logoutAction; - // private IWorkbenchAction openPerspectiveDialogAction; - // private IWorkbenchAction showViewMenuAction; - // private IWorkbenchAction preferences; - private IWorkbenchAction saveAction; - private IWorkbenchAction saveAllAction; - - // private IWorkbenchAction closeAllAction; - - public RapActionBarAdvisor(IActionBarConfigurer configurer, String username) { - super(configurer); - this.username = username; - } - - protected void makeActions(IWorkbenchWindow window) { - // preferences = ActionFactory.PREFERENCES.create(window); - // register(preferences); - // openPerspectiveDialogAction = ActionFactory.OPEN_PERSPECTIVE_DIALOG - // .create(window); - // register(openPerspectiveDialogAction); - // showViewMenuAction = ActionFactory.SHOW_VIEW_MENU.create(window); - // register(showViewMenuAction); - // - // // logout - // logoutAction = ActionFactory.QUIT.create(window); - // // logoutAction = createLogoutAction(); - // register(logoutAction); - // - // Save semantics - saveAction = ActionFactory.SAVE.create(window); - register(saveAction); - saveAllAction = ActionFactory.SAVE_ALL.create(window); - register(saveAllAction); - // closeAllAction = ActionFactory.CLOSE_ALL.create(window); - // register(closeAllAction); - - } - - protected void fillMenuBar(IMenuManager menuBar) { - // MenuManager fileMenu = new MenuManager("&File", - // IWorkbenchActionConstants.M_FILE); - // MenuManager editMenu = new MenuManager("&Edit", - // IWorkbenchActionConstants.M_EDIT); - // MenuManager windowMenu = new MenuManager("&Window", - // IWorkbenchActionConstants.M_WINDOW); - // - // menuBar.add(fileMenu); - // menuBar.add(editMenu); - // menuBar.add(windowMenu); - // // Add a group marker indicating where action set menus will appear. - // menuBar.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS)); - // - // // File - // fileMenu.add(saveAction); - // fileMenu.add(saveAllAction); - // fileMenu.add(closeAllAction); - // fileMenu.add(new - // GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS)); - // fileMenu.add(new Separator()); - // fileMenu.add(logoutAction); - // - // // Edit - // editMenu.add(preferences); - // - // // Window - // windowMenu.add(openPerspectiveDialogAction); - // windowMenu.add(showViewMenuAction); - } - - @Override - protected void fillCoolBar(ICoolBarManager coolBar) { - if (username != null) { - ICommandService cmdService = (ICommandService) getActionBarConfigurer() - .getWindowConfigurer().getWorkbenchConfigurer() - .getWorkbench().getService(ICommandService.class); - Category userMenus = cmdService.getCategory(ID_BASE + ".userMenus"); - if (!userMenus.isDefined()) - userMenus.define("User Menus", "User related menus"); - - Command userMenu = cmdService.getCommand(ID_BASE - + ".userMenuCommand"); - if (userMenu.isDefined()) - userMenu.undefine(); - userMenu.define(username, "User menu actions", userMenus); - userMenu.setHandler(new OpenHomePerspective()); - - // userToolbar.add(new UserMenuAction()); - // coolBar.add(userToolbar); - } else {// anonymous - IToolBarManager userToolbar = new ToolBarManager(SWT.FLAT - | SWT.RIGHT); - // userToolbar.add(logoutAction); - coolBar.add(userToolbar); - } - // IToolBarManager saveToolbar = new ToolBarManager(SWT.FLAT | - // SWT.RIGHT); - // saveToolbar.add(saveAction); - // saveToolbar.add(saveAllAction); - // coolBar.add(saveToolbar); - } - - // class UserMenuAction extends Action implements IWorkbenchAction { - // - // public UserMenuAction() { - // super(username, IAction.AS_DROP_DOWN_MENU); - // // setMenuCreator(new UserMenu()); - // } - // - // @Override - // public String getId() { - // return "org.argeo.security.ui.rap.userMenu"; - // } - // - // @Override - // public void dispose() { - // } - // - // } - - // class UserMenu implements IMenuCreator { - // private Menu menu; - // - // public Menu getMenu(Control parent) { - // Menu menu = new Menu(parent); - // addActionToMenu(menu, logoutAction); - // return menu; - // } - // - // private void addActionToMenu(Menu menu, IAction action) { - // ActionContributionItem item = new ActionContributionItem(action); - // item.fill(menu, -1); - // } - // - // public void dispose() { - // if (menu != null) { - // menu.dispose(); - // } - // } - // - // public Menu getMenu(Menu parent) { - // // Not use - // return null; - // } - // - // } - - // protected IAction createLogoutAction() { - // Subject subject = Subject.getSubject(AccessController.getContext()); - // final String username = subject.getPrincipals().iterator().next() - // .getName(); - // - // IAction logoutAction = new Action() { - // public String getId() { - // return SecureRapActivator.ID + ".logoutAction"; - // } - // - // public String getText() { - // return "Logout " + username; - // } - // - // public void run() { - // // try { - // // Subject subject = SecureRapActivator.getLoginContext() - // // .getSubject(); - // // String subjectStr = subject.toString(); - // // subject.getPrincipals().clear(); - // // SecureRapActivator.getLoginContext().logout(); - // // log.info(subjectStr + " logged out"); - // // } catch (LoginException e) { - // // log.error("Error when logging out", e); - // // } - // // SecureEntryPoint.logout(username); - // // PlatformUI.getWorkbench().close(); - // // try { - // // RWT.getRequest().getSession().setMaxInactiveInterval(1); - // // } catch (Exception e) { - // // if (log.isTraceEnabled()) - // // log.trace("Error when invalidating session", e); - // // } - // } - // - // }; - // return logoutAction; - // } - -} diff --git a/security/plugins/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/RapWindowAdvisor.java b/security/plugins/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/RapWindowAdvisor.java deleted file mode 100644 index 480815279..000000000 --- a/security/plugins/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/RapWindowAdvisor.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.rap; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Listener; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.ui.IWorkbenchWindow; -import org.eclipse.ui.actions.ActionFactory; -import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction; -import org.eclipse.ui.application.ActionBarAdvisor; -import org.eclipse.ui.application.IActionBarConfigurer; -import org.eclipse.ui.application.IWorkbenchWindowConfigurer; -import org.eclipse.ui.application.WorkbenchWindowAdvisor; -import org.eclipse.ui.internal.UIPlugin; - -/** Eclipse RAP specific window advisor */ -public class RapWindowAdvisor extends WorkbenchWindowAdvisor { - - private String username; - - public RapWindowAdvisor(IWorkbenchWindowConfigurer configurer, - String username) { - super(configurer); - this.username = username; - } - - @Override - public ActionBarAdvisor createActionBarAdvisor( - IActionBarConfigurer configurer) { - return new RapActionBarAdvisor(configurer, username); - } - - public void preWindowOpen() { - IWorkbenchWindowConfigurer configurer = getWindowConfigurer(); - configurer.setShowCoolBar(true); - configurer.setShowMenuBar(false); - configurer.setShowStatusLine(false); - configurer.setShowPerspectiveBar(true); - configurer.setTitle("Argeo Web UI"); //$NON-NLS-1$ - // Full screen, see - // http://wiki.eclipse.org/RAP/FAQ#How_to_create_a_fullscreen_application - configurer.setShellStyle(SWT.NO_TRIM); - Rectangle bounds = Display.getCurrent().getBounds(); - configurer.setInitialSize(new Point(bounds.width, bounds.height)); - - // Handle window resize in Rap 2.1+ see https://bugs.eclipse.org/bugs/show_bug.cgi?id=417254 - Display.getCurrent().addListener(SWT.Resize, new Listener() { - @Override - public void handleEvent(Event event) { - Rectangle bounds = event.display.getBounds(); - IWorkbenchWindow iww = UIPlugin.getDefault().getWorkbench() - .getActiveWorkbenchWindow(); - iww.getShell().setBounds(bounds); - } - }); - } - - @Override - public void postWindowCreate() { - Shell shell = getWindowConfigurer().getWindow().getShell(); - shell.setMaximized(true); - } - - @Override - public void postWindowOpen() { - String defaultPerspective = getWindowConfigurer() - .getWorkbenchConfigurer().getWorkbench() - .getPerspectiveRegistry().getDefaultPerspective(); - if (defaultPerspective == null) { - IWorkbenchWindow window = getWindowConfigurer().getWindow(); - if (window == null) - return; - - IWorkbenchAction openPerspectiveDialogAction = ActionFactory.OPEN_PERSPECTIVE_DIALOG - .create(window); - openPerspectiveDialogAction.run(); - } - } - -} diff --git a/security/plugins/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/RapWorkbenchAdvisor.java b/security/plugins/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/RapWorkbenchAdvisor.java deleted file mode 100644 index edde41f14..000000000 --- a/security/plugins/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/RapWorkbenchAdvisor.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.rap; - -import org.eclipse.ui.IPerspectiveDescriptor; -import org.eclipse.ui.application.IWorkbenchConfigurer; -import org.eclipse.ui.application.IWorkbenchWindowConfigurer; -import org.eclipse.ui.application.WorkbenchAdvisor; -import org.eclipse.ui.application.WorkbenchWindowAdvisor; - -/** Eclipse RAP specific workbench advisor */ -public class RapWorkbenchAdvisor extends WorkbenchAdvisor { - public final static String INITIAL_PERSPECTIVE_PROPERTY = "org.argeo.security.ui.initialPerspective"; - public final static String SAVE_AND_RESTORE_PROPERTY = "org.argeo.security.ui.saveAndRestore"; - - private String initialPerspective = System.getProperty( - INITIAL_PERSPECTIVE_PROPERTY, null); - - private String username; - - public RapWorkbenchAdvisor(String username) { - this.username = username; - } - - @Override - public void initialize(IWorkbenchConfigurer configurer) { - super.initialize(configurer); - Boolean saveAndRestore = Boolean.parseBoolean(System.getProperty( - SAVE_AND_RESTORE_PROPERTY, "false")); - configurer.setSaveAndRestore(saveAndRestore); - } - - public WorkbenchWindowAdvisor createWorkbenchWindowAdvisor( - IWorkbenchWindowConfigurer configurer) { - return new RapWindowAdvisor(configurer, username); - } - - public String getInitialWindowPerspectiveId() { - if (initialPerspective != null) { - // check whether this user can see the declared perspective - // (typically the perspective won't be listed if this user doesn't - // have the right to see it) - IPerspectiveDescriptor pd = getWorkbenchConfigurer().getWorkbench() - .getPerspectiveRegistry() - .findPerspectiveWithId(initialPerspective); - if (pd == null) - return null; - } - return initialPerspective; - } -} diff --git a/security/plugins/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/SecureEntryPoint.java b/security/plugins/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/SecureEntryPoint.java deleted file mode 100644 index 288ca623b..000000000 --- a/security/plugins/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/SecureEntryPoint.java +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.rap; - -import java.security.PrivilegedAction; - -import javax.security.auth.Subject; -import javax.security.auth.login.LoginException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.ArgeoException; -import org.argeo.eclipse.ui.ErrorFeedback; -import org.argeo.util.LocaleUtils; -import org.eclipse.equinox.security.auth.ILoginContext; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.rap.rwt.RWT; -import org.eclipse.rap.rwt.application.IEntryPoint; -import org.eclipse.swt.widgets.Display; -import org.eclipse.ui.PlatformUI; -import org.springframework.security.BadCredentialsException; -import org.springframework.security.context.SecurityContext; -import org.springframework.security.context.SecurityContextHolder; - -/** - * RAP entry point with login capabilities. Once the user has been - * authenticated, the workbench is run as a privileged action by the related - * subject. - */ -public class SecureEntryPoint implements IEntryPoint { - private final static Log log = LogFactory.getLog(SecureEntryPoint.class); - - /** - * From org.springframework.security.context. - * HttpSessionContextIntegrationFilter - */ - protected static final String SPRING_SECURITY_CONTEXT_KEY = "SPRING_SECURITY_CONTEXT"; - - /** - * How many seconds to wait before invalidating the session if the user has - * not yet logged in. - */ - private Integer loginTimeout = 1 * 60; - // TODO make it configurable - /** Default session timeout is 8 hours (European working day length) */ - private Integer sessionTimeout = 8 * 60 * 60; - - /** Override to provide an application specific workbench advisor */ - protected RapWorkbenchAdvisor createRapWorkbenchAdvisor(String username) { - return new RapWorkbenchAdvisor(username); - } - - @Override - public final int createUI() { - // Short login timeout so that the modal dialog login doesn't hang - // around too long - RWT.getRequest().getSession().setMaxInactiveInterval(loginTimeout); - - // Try to load security context thanks to the session processing filter - HttpServletRequest httpRequest = RWT.getRequest(); - HttpSession httpSession = httpRequest.getSession(); - Object contextFromSessionObject = httpSession - .getAttribute(SPRING_SECURITY_CONTEXT_KEY); - if (contextFromSessionObject != null) - SecurityContextHolder - .setContext((SecurityContext) contextFromSessionObject); - -// if (log.isDebugEnabled()) -// log.debug("THREAD=" + Thread.currentThread().getId() -// + ", sessionStore=" + RWT.getSessionStore().getId() -// + ", remote user=" + httpRequest.getRemoteUser()); - - // create display - final Display display = PlatformUI.createDisplay(); - - // log in - final ILoginContext loginContext = SecureRapActivator - .createLoginContext(SecureRapActivator.CONTEXT_SPRING); - Subject subject = null; - tryLogin: while (subject == null && !display.isDisposed()) { - try { - loginContext.login(); - subject = loginContext.getSubject(); - - // add security context to session - if (httpSession.getAttribute(SPRING_SECURITY_CONTEXT_KEY) == null) - httpSession.setAttribute(SPRING_SECURITY_CONTEXT_KEY, - SecurityContextHolder.getContext()); - // add thread locale to RWT session - log.info("Locale "+LocaleUtils.threadLocale.get()); - RWT.setLocale(LocaleUtils.threadLocale.get()); - - // Once the user is logged in, she can have a longer session - // timeout - RWT.getRequest().getSession() - .setMaxInactiveInterval(sessionTimeout); - if (log.isDebugEnabled()) - log.debug("Authenticated " + subject); - } catch (LoginException e) { - BadCredentialsException bce = wasCausedByBadCredentials(e); - if (bce != null) { - MessageDialog.openInformation(display.getActiveShell(), - "Bad Credentials", bce.getMessage()); - // retry login - continue tryLogin; - } - return processLoginDeath(display, e); - } - } - - final String username = subject.getPrincipals().iterator().next() - .getName(); - // Logout callback when the display is disposed - display.disposeExec(new Runnable() { - public void run() { - log.debug("Display disposed"); - logout(loginContext, username); - } - }); - - // - // RUN THE WORKBENCH - // - Integer returnCode = null; - try { - returnCode = Subject.doAs(subject, new PrivilegedAction() { - public Integer run() { - RapWorkbenchAdvisor workbenchAdvisor = createRapWorkbenchAdvisor(username); - int result = PlatformUI.createAndRunWorkbench(display, - workbenchAdvisor); - return new Integer(result); - } - }); - // logout(loginContext, username); - } finally { - display.dispose(); - } - return returnCode; - } - - private Integer processLoginDeath(Display display, LoginException e) { - // check thread death - ThreadDeath td = wasCausedByThreadDeath(e); - if (td != null) { - display.dispose(); - throw td; - } - if (!display.isDisposed()) { - ErrorFeedback.show("Unexpected exception during authentication", e); - // this was not just bad credentials or death thread - RWT.getRequest().getSession().setMaxInactiveInterval(1); - display.dispose(); - return -1; - } else { - throw new ArgeoException( - "Unexpected exception during authentication", e); - } - - } - - /** Recursively look for {@link BadCredentialsException} in the root causes. */ - private BadCredentialsException wasCausedByBadCredentials(Throwable t) { - if (t instanceof BadCredentialsException) - return (BadCredentialsException) t; - - if (t.getCause() != null) - return wasCausedByBadCredentials(t.getCause()); - else - return null; - } - - /** - * If there is a {@link ThreadDeath} in the root causes, rethrow it - * (important for RAP cleaning mechanism) - */ - protected ThreadDeath wasCausedByThreadDeath(Throwable t) { - if (t instanceof ThreadDeath) - return (ThreadDeath) t; - - if (t.getCause() != null) - return wasCausedByThreadDeath(t.getCause()); - else - return null; - } - - protected void logout(ILoginContext secureContext, String username) { - try { - HttpServletRequest httpRequest = RWT.getRequest(); - HttpSession httpSession = httpRequest.getSession(); - httpSession.setAttribute(SPRING_SECURITY_CONTEXT_KEY, null); - RWT.getRequest().getSession().setMaxInactiveInterval(1); - SecurityContextHolder.clearContext(); - secureContext.logout(); - log.info("Logged out " + (username != null ? username : "") - + " (THREAD=" + Thread.currentThread().getId() + ")"); - } catch (LoginException e) { - log.error("Erorr when logging out", e); - } - } -} diff --git a/security/plugins/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/SecureRapActivator.java b/security/plugins/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/SecureRapActivator.java deleted file mode 100644 index 4cbb441e7..000000000 --- a/security/plugins/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/SecureRapActivator.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.rap; - -import java.net.URL; - -import org.eclipse.equinox.security.auth.ILoginContext; -import org.eclipse.equinox.security.auth.LoginContextFactory; -import org.osgi.framework.BundleActivator; -import org.osgi.framework.BundleContext; - -/** Configure Equinox login context from the bundle context. */ -public class SecureRapActivator implements BundleActivator { - - public final static String ID = "org.argeo.security.ui.rap"; - public final static String CONTEXT_SPRING = "SPRING"; - public final static String CONTEXT_SPRING_ANONYMOUS = "SPRING_ANONYMOUS"; - private static final String JAAS_CONFIG_FILE = "/META-INF/jaas_default.txt"; - - private BundleContext bundleContext; - private static SecureRapActivator activator = null; - - public void start(BundleContext bundleContext) throws Exception { - activator = this; - this.bundleContext = bundleContext; - } - - public void stop(BundleContext context) throws Exception { - bundleContext = null; - activator = null; - } - - public BundleContext getBundleContext() { - return bundleContext; - } - - public static SecureRapActivator getActivator() { - return activator; - } - - static ILoginContext createLoginContext(String contextName) { - URL configUrl = getActivator().getBundleContext().getBundle() - .getEntry(JAAS_CONFIG_FILE); - return LoginContextFactory.createContext(contextName, configUrl); - } -} diff --git a/security/plugins/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/commands/UserMenu.java b/security/plugins/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/commands/UserMenu.java deleted file mode 100644 index 98674303b..000000000 --- a/security/plugins/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/commands/UserMenu.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.rap.commands; - -import org.eclipse.core.commands.AbstractHandler; -import org.eclipse.core.commands.ExecutionEvent; -import org.eclipse.core.commands.ExecutionException; - -/** Default action of the user menu */ -public class UserMenu extends AbstractHandler { - - @Override - public Object execute(ExecutionEvent event) throws ExecutionException { - return null; - } - -} diff --git a/security/plugins/org.argeo.security.ui.rcp/.classpath b/security/plugins/org.argeo.security.ui.rcp/.classpath deleted file mode 100644 index 8cf7f48a0..000000000 --- a/security/plugins/org.argeo.security.ui.rcp/.classpath +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/security/plugins/org.argeo.security.ui.rcp/.project b/security/plugins/org.argeo.security.ui.rcp/.project deleted file mode 100644 index feeafcf5b..000000000 --- a/security/plugins/org.argeo.security.ui.rcp/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - org.argeo.security.ui.rcp - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - - diff --git a/security/plugins/org.argeo.security.ui.rcp/.settings/org.eclipse.jdt.core.prefs b/security/plugins/org.argeo.security.ui.rcp/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 1f382cb9d..000000000 --- a/security/plugins/org.argeo.security.ui.rcp/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,8 +0,0 @@ -#Sat Jan 15 17:51:30 CET 2011 -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 -org.eclipse.jdt.core.compiler.compliance=1.5 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.5 diff --git a/security/plugins/org.argeo.security.ui.rcp/META-INF/jaas_default.txt b/security/plugins/org.argeo.security.ui.rcp/META-INF/jaas_default.txt deleted file mode 100644 index 16d476daf..000000000 --- a/security/plugins/org.argeo.security.ui.rcp/META-INF/jaas_default.txt +++ /dev/null @@ -1,27 +0,0 @@ -OS_SPRING { - org.eclipse.equinox.security.auth.module.ExtensionLoginModule required - extensionId="org.argeo.security.equinox.osSpringLoginModule"; -}; - -NIX { - org.eclipse.equinox.security.auth.module.ExtensionLoginModule requisite - extensionId="org.argeo.security.equinox.unixLoginModule"; - org.eclipse.equinox.security.auth.module.ExtensionLoginModule required - extensionId="org.argeo.security.equinox.osSpringLoginModule"; -}; - -WINDOWS { - org.eclipse.equinox.security.auth.module.ExtensionLoginModule requisite - extensionId="org.argeo.security.equinox.ntLoginModule"; - org.eclipse.equinox.security.auth.module.ExtensionLoginModule required - extensionId="org.argeo.security.equinox.osSpringLoginModule"; -}; - -REMOTE { - org.eclipse.equinox.security.auth.module.ExtensionLoginModule sufficient - extensionId="org.argeo.security.equinox.springLoginModuleRemote"; -}; - -KEYRING { - org.argeo.security.crypto.KeyringLoginModule required; -}; diff --git a/security/plugins/org.argeo.security.ui.rcp/build.properties b/security/plugins/org.argeo.security.ui.rcp/build.properties deleted file mode 100644 index 5ac3de985..000000000 --- a/security/plugins/org.argeo.security.ui.rcp/build.properties +++ /dev/null @@ -1,6 +0,0 @@ -source.. = src/main/java/ -output.. = target/classes/ -bin.includes = plugin.xml,\ - META-INF/,\ - .,\ - log4j.properties diff --git a/security/plugins/org.argeo.security.ui.rcp/icons/alt_about.gif b/security/plugins/org.argeo.security.ui.rcp/icons/alt_about.gif deleted file mode 100644 index 20d9ad2d9..000000000 Binary files a/security/plugins/org.argeo.security.ui.rcp/icons/alt_about.gif and /dev/null differ diff --git a/security/plugins/org.argeo.security.ui.rcp/icons/alt_launcher.icns b/security/plugins/org.argeo.security.ui.rcp/icons/alt_launcher.icns deleted file mode 100644 index b77a6a639..000000000 Binary files a/security/plugins/org.argeo.security.ui.rcp/icons/alt_launcher.icns and /dev/null differ diff --git a/security/plugins/org.argeo.security.ui.rcp/icons/alt_launcher.ico b/security/plugins/org.argeo.security.ui.rcp/icons/alt_launcher.ico deleted file mode 100644 index d548f7109..000000000 Binary files a/security/plugins/org.argeo.security.ui.rcp/icons/alt_launcher.ico and /dev/null differ diff --git a/security/plugins/org.argeo.security.ui.rcp/icons/alt_launcher.xpm b/security/plugins/org.argeo.security.ui.rcp/icons/alt_launcher.xpm deleted file mode 100644 index b0c139e06..000000000 --- a/security/plugins/org.argeo.security.ui.rcp/icons/alt_launcher.xpm +++ /dev/null @@ -1,307 +0,0 @@ -/* XPM */ -static char * icon48_xpm[] = { -"48 48 256 2", -" c #4B4B3B3B9090", -". c #0D0D0E0E5454", -"X c #11110E0E5B5B", -"o c #17170F0F6363", -"O c #1D1D13136969", -"+ c #212114146C6C", -"@ c #252514147171", -"# c #282811116C6C", -"$ c #26260D0D6363", -"% c #22220B0B5E5E", -"& c #1C1C0B0B5A5A", -"* c #1C1C0B0B5252", -"= c #1B1B05055353", -"- c #161606064D4D", -"; c #161605054949", -": c #111104044848", -"> c #131304044545", -", c #131305054242", -"< c #141410105E5E", -"1 c #2C2C15157373", -"2 c #2B2B1B1B7575", -"3 c #343416167272", -"4 c #313113136E6E", -"5 c #222209095757", -"6 c #1B1B06064D4D", -"7 c #15150B0B4242", -"8 c #13130C0C5555", -"9 c #2E2E1B1B7878", -"0 c #33331F1F7C7C", -"q c #343418187878", -"w c #3B3B1C1C7575", -"e c #2E2E10106767", -"r c #1B1B07074747", -"t c #18180B0B4646", -"y c #151513136262", -"u c #1A1A15156464", -"i c #34341F1F7777", -"p c #40401E1E8080", -"a c #42421B1B7A7A", -"s c #3B3B15157474", -"d c #2B2B0B0B5B5B", -"f c #222207075252", -"g c #373727277A7A", -"h c #474724248484", -"j c #393915156E6E", -"k c #373711116A6A", -"l c #343413136363", -"z c #232319196E6E", -"x c #292919197070", -"c c #3C3C2C2C8282", -"v c #444431318585", -"b c #494934348A8A", -"n c #505026268A8A", -"m c #3D3D1B1B6E6E", -"M c #31310E0E5C5C", -"N c #2B2B0D0D5353", -"B c #222207074A4A", -"V c #52523C3C9292", -"C c #58583C3C9494", -"Z c #5D5D44449797", -"A c #5C5C2E2E9292", -"S c #676733339595", -"D c #424228287575", -"F c #29290A0A4F4F", -"G c #6C6C4A4A9E9E", -"H c #72725454A7A7", -"J c #8C8C6D6DB2B2", -"K c #343424246E6E", -"L c #3A3A23236A6A", -"P c #3A3A1C1C6767", -"I c #24240A0A4B4B", -"U c #151518186161", -"Y c #76766F6FA5A5", -"T c #ADAD9191CCCC", -"R c #98988989D3D3", -"E c #45453B3B8686", -"W c #3C3C35357979", -"Q c #363631317575", -"! c #32322D2D6B6B", -"~ c #323229296363", -"^ c #30301F1F6262", -"/ c #323218185E5E", -"( c #272707074B4B", -") c #202028286C6C", -"_ c #1E1E1D1D6868", -"` c #9A9A8282BBBB", -"' c #C8C8B3B3D3D3", -"] c #B3B3AFAFE7E7", -"[ c #84847272C6C6", -"{ c #58585757A3A3", -"} c #3F3F3C3C8A8A", -"| c #3B3B3A3A8484", -" . c #414139397D7D", -".. c #3D3D39397A7A", -"X. c #37372E2E6E6E", -"o. c #2C2C21215A5A", -"O. c #2E2E1B1B5B5B", -"+. c #F5F5EFEFF5F5", -"@. c #656566669A9A", -"#. c #47474B4B8E8E", -"$. c #3C3C44447B7B", -"%. c #444442428080", -"&. c #45453E3E8181", -"*. c #40403C3C8181", -"=. c #3D3D33337474", -"-. c #3B3B30306E6E", -";. c #38382D2D6969", -":. c #303026265D5D", -">. c #2C2C15155A5A", -",. c #1F1F1C1C7070", -"<. c #25251E1E7171", -"1. c #59595C5C9191", -"2. c #4D4D53538989", -"3. c #4C4C49498484", -"4. c #484845458585", -"5. c #494941418585", -"6. c #494940408181", -"7. c #2F2F1C1C5353", -"8. c #2B2B28287676", -"9. c #323231317F7F", -"0. c #545452528B8B", -"q. c #51514E4E8989", -"w. c #4E4E4B4B8C8C", -"e. c #4C4C47478686", -"r. c #46463D3D7E7E", -"t. c #434336367A7A", -"y. c #2B2B13135555", -"u. c #47473D3D8D8D", -"i. c #575757578E8E", -"p. c #48483E3E7F7F", -"a. c #46463A3A7D7D", -"s. c #424235357575", -"d. c #404034347171", -"f. c #BFBFCBCBFAFA", -"g. c #B8B8A8A8DDDD", -"h. c #5E5E60609292", -"j. c #565655558C8C", -"k. c #4B4B44448282", -"l. c #454539397B7B", -"z. c #434338387878", -"x. c #3F3F32326D6D", -"c. c #3D3D30306969", -"v. c #3A3A2E2E6363", -"b. c #36362A2A5C5C", -"n. c #343424245555", -"m. c #30301E1E4D4D", -"M. c #49493C3C8282", -"N. c #5E5E4F4F8C8C", -"B. c #56563B3B8B8B", -"V. c #545407078585", -"C. c #424234347272", -"Z. c #9797A4A4F7F7", -"A. c #444436367676", -"S. c #7D7D7979D5D5", -"D. c #464640408A8A", -"F. c #44444B4B8282", -"G. c #414107077777", -"H. c #71716161C1C1", -"J. c #303039397979", -"K. c #8E8E8E8EE6E6", -"L. c #404033338B8B", -"P. c #4A4A45458C8C", -"I. c #46463A3A8080", -"U. c #363629295454", -"Y. c #303022224848", -"T. c #424237377575", -"R. c #2E2E1D1D6363", -"E. c #79798383EAEA", -"W. c #74747B7BE4E4", -"Q. c #6D6D7676D6D6", -"!. c #6A6A7171CECE", -"~. c #66666969C6C6", -"^. c #62626565BCBC", -"/. c #5F5F6060B5B5", -"(. c #5B5B5B5BACAC", -"). c #535353539898", -"_. c #4F4F4F4FA4A4", -"`. c #54544D4DA4A4", -"'. c #323204046B6B", -"]. c #303035357979", -"[. c #313122224343", -"{. c #5A5A5B5BB7B7", -"}. c #484846468080", -"|. c #454541417575", -" X c #4B4B31318282", -".X c #47473C3C8484", -"XX c #3E3E35356E6E", -"oX c #2F2F26264040", -"OX c #2B2B23233A3A", -"+X c #262619195C5C", -"@X c #252515155A5A", -"#X c #55555151B3B3", -"$X c #3C3C2D2D5D5D", -"%X c #39392F2F5656", -"&X c #37372D2D5050", -"*X c #25251F1F3030", -"=X c #24241D1D4343", -"-X c #202013135656", -";X c #41413B3B6C6C", -":X c #444442429696", -">X c #212100005E5E", -",X c #444436367272", -" > , , , ", -" . . X X < < o o O O + @ 1 2 2 1 1 1 1 1 1 1 1 3 4 # # $ $ $ % % % 5 = = 6 6 - ; ; > > , , 7 ", -" . 8 < < < o O O + @ @ 2 9 9 0 0 q q q q q q q w 3 4 4 e e $ $ $ $ % 5 = = 6 6 6 ; ; > > r t ", -" . X < y u O O + @ 1 2 i 0 0 p p p p p p p a a p a s 3 4 4 e e e e d 5 5 f f 6 6 6 ; ; r r t ", -" X < y u O + + @ 2 9 0 g p p h h h h h h h p h h a a s s j k k j l d d 5 5 f f 6 6 r r r r r ", -" X < y O z x x 9 0 g c v b n n n n n n n n n n n h a a s s j j m l M d d N f f B B B B r r r ", -" < y u + z 2 0 c c b V C Z C C A A A A A S S S n h D w w m m m m k l M d d N f F F F B r r r ", -" < y O z z 9 c b V Z G H H H G S G G J J H V v c g g K K K K L P l l l M M N N N N I B B r r ", -" U u + z x i v C H Y J J J J H J T R H V E W W Q Q Q Q ! ! ! ~ ^ ^ / / M M M M M N ( B B r r ", -" ) _ z x 9 g b Z Y ` ' ' ' T T ] [ { } | .........W W Q Q X.! ~ ~ o.O./ / / / N F ( B B B r ", -" ) ) z x i c V G J ' +.+.+.+.] [ @.#.$.%.%.%.&.*. . .....W =.-.X.;.~ :.o.O.^ >.N F ( B B B B ", -" ) ,.<.2 g v C H J ' +.+.+.+.T Y 1.2.3.4.4.4.5.6.&.&. . ...W =.=.-.;.~ :.o.7.>.N F F ( B I I ", -" ) ,.<.8.9.b C H J T +.+.+.' J @.1.0.q.q.w.e.4.5.6.&.r. . .t.W =.=.-.;.~ :.o.7.y.N F ( ( I I ", -" 8.8.8.9.| u.C G J T +.+.' ` Y @.1.i.0.q.q.e.e.5.6.p.r.a. .t.t.s.d.d.-.;.~ :.7.7.y.F F ( I I ", -" 9.c c c v b A S H ' f.g.` Y @.h.1.i.j.0.q.q.e.k.6.p.r.a.l.t.z.s.s.d.x.c.v.b.n.m.7.N F F F I ", -" <.g M.N.B.B.n V.J f.R J @.h.h.1.i.i.j.j.0.q.3.k.6.p.r.a.l.l.z.s.C.d.x.x.c.v.b.n.m.y.N F F F ", -" + x i v B.Z Z G g.Z.[ @.2.i.i.j.j.j.j.j.0.q.3.k.6.p.p.a.l.l.A.s.C.C.d.x.c.v.b.n.m.7.y.N N y. ", -" O # 3 w p n Z ` f.S.H D.F.q.0.0.0.0.j.0.q.q.3.k.6.p.r.a.a.l.A.s.s.C.d.x.x.c.v.b.n.m.y.y.y.y. ", -" O # 4 s a G.V.T Z.H.V J.%.e.w.q.0.0.0.0.q.q.e.k.6.p.r.a.a.l.z.A.s.C.d.d.x.c.v.b.n.m.7.>.y.y. ", -" O # 4 s w G.A f.K.H L...4.P.w.w.w.q.q.q.q.e.e.5.6.M.I.I.a.a.l.z.A.s.d.d.x.c.v.v.U.Y.7.O.>.y. ", -" $ # 4 3 s G.G f.S.Z 9.*.D.P.P.w.w.w.w.w.e.e.5.5.M.M.I.I.a.a.l.z.T.s.d.d.x.x.c.v.U.Y.m.R.>.>. ", -" E.E.W.W.W.W.E.Z.E.W.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.!.!.!.!.!.~.~.~.~.~.~.^.^.^.^.^./././.(.{ { )._.`._. ", -" + # 3 w s '.` f.H.V ].*.D.P.P.P.P.P.P.P.5.5.5.M.M.M.I.I.a.l.z.z.T.T.s.d.d.x.c.v.U.Y.[.^ O.>. ", -" ~.~.~.~.~.~.K.Z.S.~.{.^.^.^.^.^.^.^.^././././././.(.(.(.(.(.(.{ { { { { ).).).w.w.}.|.P.u.} ", -" .I.6. X X XT f.H.b ].*.E D.D.D.D.5.5..X.XM.M.I.I.a.a.l.l.z.z.T.T.T.d.XXx.c.v.b.U.oXOXR.+X@X ", -" E.E.E.W.W.W.K.Z.E.W.Q.Q.Q.Q.Q.Q.Q.Q.!.!.!.!.!.!.~.~.~.~.~.~.^.^.^.^.^./././.(.{ { ).).#X_._. ", -" & % $ e '.= H f.H.b 8.W *.E E E .X.X.XI.I.I.I.a.a.l.l.z.z.T.T.T.C.XXXXc.v.$X%X&XY.*X=X2 @X-X ", -" {.{.{.{.{.#X~.Z.W.~.{.{./././././././././.(.(.(.(.(.(.(.{ { { { { { ).).).w.w.3.}.;X%.:X} } ", -" & & % $ e >XV.f.S.C K X.W t. . .l.l.t.t.t.t.A.A.A.,X,X,X,X,XX7X` Z.Z D ! =.=.s.t.t.t.A.A.s.A.,X,X,X,X > > t t t cX ", -" nXbXbXzXzXlXaXXXY +Xf = f = 7XtXR R mXn.Y.[.[.[.[.OX*X*X8X5X*X=X,.u vXvX; > > MXMX, 7 t t ", -" nXnXnXbXzXvX-.Y +XcX6 6 = = = d L B.G H `.X.:.7.m.=X=X=X=X=X6X,.u cXvXNX: BX> MXVXCXVX7 7 7 ", -" ZXZXnXbXAXgX@.+XvX; - - - - * @XR.>.sX>.R.i 0 x eXeXeXeXO hXaXcXvXNX: BXMXMXMXVXCXCXCXVX7 7 ", -" SXZXZXAXgXN.aXNX: : NXNXNX- * +X+X* 6 6 6 * * * * * * * vXvX- NX: DXBXMXMXFXCXCXCXCXGXVXVX7 ", -" SXSXHXgX0.JXKXLXKXKXDX: : NX* @X-X- - - - - - - - - - - NX: DXDXDXMXMXFXFXCXCXCXCXGXGXGXVXVX ", -" SXHXPX3.JXnXnXnXnXbXLXKXKXNXaX-XvX: : NX: : : : : : : BXDXDXLXMXMXFXFXCXCXCXCXGXGXGXGXGXGXGX ", -" IXUX$.AXZXZXZXZXnXnXnXLXLXNXJXvXBXDXBXBXBXBXDXDXDXDXLXDXLXLXFXFXFXFXCXCXCXCXGXGXGXGXGXGXGXGX ", -" "}; diff --git a/security/plugins/org.argeo.security.ui.rcp/icons/alt_window_16.gif b/security/plugins/org.argeo.security.ui.rcp/icons/alt_window_16.gif deleted file mode 100644 index 05626b17d..000000000 Binary files a/security/plugins/org.argeo.security.ui.rcp/icons/alt_window_16.gif and /dev/null differ diff --git a/security/plugins/org.argeo.security.ui.rcp/icons/alt_window_32.gif b/security/plugins/org.argeo.security.ui.rcp/icons/alt_window_32.gif deleted file mode 100644 index b432f8833..000000000 Binary files a/security/plugins/org.argeo.security.ui.rcp/icons/alt_window_32.gif and /dev/null differ diff --git a/security/plugins/org.argeo.security.ui.rcp/plugin.xml b/security/plugins/org.argeo.security.ui.rcp/plugin.xml deleted file mode 100644 index 4ddf700d5..000000000 --- a/security/plugins/org.argeo.security.ui.rcp/plugin.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/security/plugins/org.argeo.security.ui.rcp/plugin_customization.ini b/security/plugins/org.argeo.security.ui.rcp/plugin_customization.ini deleted file mode 100644 index baf9cefe7..000000000 --- a/security/plugins/org.argeo.security.ui.rcp/plugin_customization.ini +++ /dev/null @@ -1,5 +0,0 @@ -org.eclipse.ui/DOCK_PERSPECTIVE_BAR=topRight -org.eclipse.ui/SHOW_TEXT_ON_PERSPECTIVE_BAR=true -org.eclipse.ui/PERSPECTIVE_BAR_SIZE=100 -org.eclipse.ui/SHOW_TRADITIONAL_STYLE_TABS=true -org.eclipse.ui/SHOW_PROGRESS_ON_STARTUP = false diff --git a/security/plugins/org.argeo.security.ui.rcp/pom.xml b/security/plugins/org.argeo.security.ui.rcp/pom.xml deleted file mode 100644 index 98daf7dba..000000000 --- a/security/plugins/org.argeo.security.ui.rcp/pom.xml +++ /dev/null @@ -1,83 +0,0 @@ - - - 4.0.0 - - org.argeo.commons.security - 2.1.12-SNAPSHOT - plugins - .. - - org.argeo.security.ui.rcp - Commons Security UI RCP - jar - - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-source-plugin - - - org.apache.maven.plugins - maven-jar-plugin - - - org.apache.felix - maven-bundle-plugin - - - org.argeo.security.ui.rcp.SecureApplicationActivator - lazy - org.eclipse.ui,org.eclipse.core.runtime - - org.argeo.eclipse.ui.specific, - org.argeo.eclipse.spring, - * - - - - - - - - - - org.argeo.commons.base - org.argeo.util - 2.1.12-SNAPSHOT - - - - - org.argeo.tp - slf4j.org.apache.commons.logging - - - - - org.argeo.commons.security - org.argeo.security.ui - 2.1.12-SNAPSHOT - - - org.argeo.commons.security - org.argeo.security.equinox - 2.1.12-SNAPSHOT - - - - - org.argeo.commons.base - org.argeo.eclipse.ui.rcp - 2.1.12-SNAPSHOT - - - org.argeo.commons.base - org.argeo.eclipse.dep.rcp - 2.1.12-SNAPSHOT - - - \ No newline at end of file diff --git a/security/plugins/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/AbstractSecureApplication.java b/security/plugins/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/AbstractSecureApplication.java deleted file mode 100644 index 75184cbab..000000000 --- a/security/plugins/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/AbstractSecureApplication.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.rcp; - -import java.security.PrivilegedAction; - -import javax.security.auth.Subject; -import javax.security.auth.login.LoginException; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.OperatingSystem; -import org.eclipse.equinox.app.IApplication; -import org.eclipse.equinox.app.IApplicationContext; -import org.eclipse.equinox.security.auth.ILoginContext; -import org.eclipse.swt.widgets.Display; -import org.eclipse.ui.IWorkbench; -import org.eclipse.ui.PlatformUI; -import org.eclipse.ui.application.WorkbenchAdvisor; - -/** - * RCP workbench initialization - */ -public abstract class AbstractSecureApplication implements IApplication { - final static String NODE_REPO_URI = "argeo.node.repo.uri"; - - private static final Log log = LogFactory - .getLog(AbstractSecureApplication.class); - - protected WorkbenchAdvisor createWorkbenchAdvisor(String username) { - return new SecureWorkbenchAdvisor(username); - } - - public Object start(IApplicationContext context) throws Exception { - // wait for the system to be initialized - // try { - // Thread.sleep(3000); - // } catch (Exception e2) { - // // silent - // } - - boolean remote = System.getProperty(NODE_REPO_URI) != null; - - // choose login context - final ILoginContext loginContext; - if (remote) { - loginContext = SecureApplicationActivator - .createLoginContext(SecureApplicationActivator.CONTEXT_REMOTE); - } else { - if (OperatingSystem.os == OperatingSystem.WINDOWS) - loginContext = SecureApplicationActivator - .createLoginContext(SecureApplicationActivator.CONTEXT_WINDOWS); - else - loginContext = SecureApplicationActivator - .createLoginContext(SecureApplicationActivator.CONTEXT_NIX); - } - - final Display display = PlatformUI.createDisplay(); - - // login - Subject subject = null; - try { - loginContext.login(); - subject = loginContext.getSubject(); - } catch (LoginException e) { - log.error("Error when logging in.", e); - display.dispose(); - try { - Thread.sleep(2000); - } catch (InterruptedException e1) { - // silent - } - return null; - } - - // identify after successful login - if (log.isDebugEnabled()) - log.debug("subject=" + subject); - final String username = subject.getPrincipals().iterator().next() - .getName(); - if (log.isDebugEnabled()) - log.debug(username + " logged in"); -// display.disposeExec(new Runnable() { -// public void run() { -// log.debug("Display disposed"); -// logout(loginContext, username); -// } -// }); - - try { - PrivilegedAction privilegedAction = new PrivilegedAction() { - public Object run() { - int result = PlatformUI.createAndRunWorkbench(display, - createWorkbenchAdvisor(username)); - return new Integer(result); - } - }; - - Integer returnCode = (Integer) Subject.doAs(subject, - privilegedAction); - logout(loginContext, username); - return processReturnCode(returnCode); - } catch (Exception e) { - if (subject != null) - logout(loginContext, username); - log.error("Unexpected error", e); - } finally { - display.dispose(); - } - return null; - } - - protected Integer processReturnCode(Integer returnCode) { - if (returnCode == PlatformUI.RETURN_RESTART) - return IApplication.EXIT_RESTART; - else - return IApplication.EXIT_OK; - } - - static void logout(ILoginContext secureContext, String username) { - try { - secureContext.logout(); - log.info("Logged out " + (username != null ? username : "") - + " (THREAD=" + Thread.currentThread().getId() + ")"); - } catch (LoginException e) { - log.error("Erorr when logging out", e); - } - } - - public void stop() { - final IWorkbench workbench; - try { - workbench = PlatformUI.getWorkbench(); - } catch (Exception e) { - return; - } - if (workbench == null) - return; - final Display display = workbench.getDisplay(); - if (display != null && !display.isDisposed()) - display.syncExec(new Runnable() { - - public void run() { - if (!display.isDisposed()) - workbench.close(); - } - }); - - if (log.isDebugEnabled()) - log.debug("workbench stopped"); - } - -} diff --git a/security/plugins/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureActionBarAdvisor.java b/security/plugins/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureActionBarAdvisor.java deleted file mode 100644 index 481865bfa..000000000 --- a/security/plugins/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureActionBarAdvisor.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.rcp; - -import org.eclipse.jface.action.GroupMarker; -import org.eclipse.jface.action.ICoolBarManager; -import org.eclipse.jface.action.IMenuManager; -import org.eclipse.jface.action.IToolBarManager; -import org.eclipse.jface.action.MenuManager; -import org.eclipse.jface.action.Separator; -import org.eclipse.jface.action.ToolBarManager; -import org.eclipse.swt.SWT; -import org.eclipse.ui.IWorkbenchActionConstants; -import org.eclipse.ui.IWorkbenchWindow; -import org.eclipse.ui.actions.ActionFactory; -import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction; -import org.eclipse.ui.application.ActionBarAdvisor; -import org.eclipse.ui.application.IActionBarConfigurer; - -public class SecureActionBarAdvisor extends ActionBarAdvisor { - private IWorkbenchAction exitAction; - private IWorkbenchAction openPerspectiveDialogAction; - private IWorkbenchAction showViewMenuAction; - private IWorkbenchAction preferences; - private IWorkbenchAction saveAction; - private IWorkbenchAction saveAsAction; - private IWorkbenchAction saveAllAction; - private IWorkbenchAction closeAllAction; - - // private final Boolean isRcp; - - public SecureActionBarAdvisor(IActionBarConfigurer configurer, Boolean isRcp) { - super(configurer); - // this.isRcp = isRcp; - } - - protected void makeActions(IWorkbenchWindow window) { - preferences = ActionFactory.PREFERENCES.create(window); - register(preferences); - openPerspectiveDialogAction = ActionFactory.OPEN_PERSPECTIVE_DIALOG - .create(window); - register(openPerspectiveDialogAction); - showViewMenuAction = ActionFactory.SHOW_VIEW_MENU.create(window); - register(showViewMenuAction); - - exitAction = ActionFactory.QUIT.create(window); - register(exitAction); - - // Save semantiocs - saveAction = ActionFactory.SAVE.create(window); - register(saveAction); - saveAsAction = ActionFactory.SAVE_AS.create(window); - register(saveAsAction); - saveAllAction = ActionFactory.SAVE_ALL.create(window); - register(saveAllAction); - closeAllAction = ActionFactory.CLOSE_ALL.create(window); - register(closeAllAction); - - } - - protected void fillMenuBar(IMenuManager menuBar) { - MenuManager fileMenu = new MenuManager("&File", - IWorkbenchActionConstants.M_FILE); - MenuManager editMenu = new MenuManager("&Edit", - IWorkbenchActionConstants.M_EDIT); - MenuManager windowMenu = new MenuManager("&Window", - IWorkbenchActionConstants.M_WINDOW); - - menuBar.add(fileMenu); - menuBar.add(editMenu); - menuBar.add(windowMenu); - // Add a group marker indicating where action set menus will appear. - menuBar.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS)); - - // File - fileMenu.add(saveAction); - fileMenu.add(saveAsAction); - fileMenu.add(saveAllAction); - fileMenu.add(closeAllAction); - fileMenu.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS)); - fileMenu.add(new Separator()); - fileMenu.add(exitAction); - - // Edit - editMenu.add(preferences); - - // Window - windowMenu.add(openPerspectiveDialogAction); - windowMenu.add(showViewMenuAction); - } - - @Override - protected void fillCoolBar(ICoolBarManager coolBar) { - IToolBarManager saveToolbar = new ToolBarManager(SWT.FLAT | SWT.RIGHT); - saveToolbar.add(saveAction); - saveToolbar.add(saveAllAction); - coolBar.add(saveToolbar); - } - -} diff --git a/security/plugins/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureApplicationActivator.java b/security/plugins/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureApplicationActivator.java deleted file mode 100644 index 9c0425c5b..000000000 --- a/security/plugins/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureApplicationActivator.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.rcp; - -import java.net.URL; - -import org.eclipse.equinox.security.auth.ILoginContext; -import org.eclipse.equinox.security.auth.LoginContextFactory; -import org.osgi.framework.BundleActivator; -import org.osgi.framework.BundleContext; - -/** Activator able to create {@link ILoginContext} */ -public class SecureApplicationActivator implements BundleActivator { - - public final static String CONTEXT_REMOTE = "REMOTE"; - public final static String CONTEXT_NIX = "NIX"; - public final static String CONTEXT_WINDOWS = "WINDOWS"; - private static final String JAAS_CONFIG_FILE = "/META-INF/jaas_default.txt"; - - private static BundleContext bundleContext; - - public void start(BundleContext bundleContext) throws Exception { - SecureApplicationActivator.bundleContext = bundleContext; - } - - public void stop(BundleContext context) throws Exception { - } - - static ILoginContext createLoginContext(String context) { - URL configUrl = bundleContext.getBundle().getEntry(JAAS_CONFIG_FILE); - return LoginContextFactory.createContext(context, configUrl); - } -} diff --git a/security/plugins/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureRcp.java b/security/plugins/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureRcp.java deleted file mode 100644 index d8125cf6f..000000000 --- a/security/plugins/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureRcp.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.rcp; - - -public class SecureRcp extends AbstractSecureApplication { -} diff --git a/security/plugins/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureWorkbenchAdvisor.java b/security/plugins/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureWorkbenchAdvisor.java deleted file mode 100644 index 33b781ee5..000000000 --- a/security/plugins/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureWorkbenchAdvisor.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.rcp; - -import org.eclipse.ui.IPerspectiveDescriptor; -import org.eclipse.ui.application.IWorkbenchConfigurer; -import org.eclipse.ui.application.IWorkbenchWindowConfigurer; -import org.eclipse.ui.application.WorkbenchAdvisor; -import org.eclipse.ui.application.WorkbenchWindowAdvisor; - -/** - * Workbench configuration which is aware of the logged in user and can remember - * workbench state. - */ -public class SecureWorkbenchAdvisor extends WorkbenchAdvisor { - public final static String INITIAL_PERSPECTIVE_PROPERTY = "org.argeo.security.ui.initialPerspective"; - public final static String SAVE_AND_RESTORE_PROPERTY = "org.argeo.security.ui.saveAndRestore"; - - private String initialPerspective = System.getProperty( - INITIAL_PERSPECTIVE_PROPERTY, null); - - private final String username; - - public SecureWorkbenchAdvisor(String username) { - this.username = username; - } - - @Override - public void initialize(final IWorkbenchConfigurer configurer) { - super.initialize(configurer); - Boolean saveAndRestore = Boolean.parseBoolean(System.getProperty( - SAVE_AND_RESTORE_PROPERTY, "true")); - configurer.setSaveAndRestore(saveAndRestore); - } - - public WorkbenchWindowAdvisor createWorkbenchWindowAdvisor( - IWorkbenchWindowConfigurer configurer) { - return new SecureWorkbenchWindowAdvisor(configurer, username); - } - - public String getInitialWindowPerspectiveId() { - if (initialPerspective != null) { - // check whether this user can see the declared perspective - // (typically the perspective won't be listed if this user doesn't - // have the right to see it) - IPerspectiveDescriptor pd = getWorkbenchConfigurer().getWorkbench() - .getPerspectiveRegistry() - .findPerspectiveWithId(initialPerspective); - if (pd == null) - return null; - } - return initialPerspective; - } - - protected String getUsername() { - return username; - } -} diff --git a/security/plugins/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureWorkbenchWindowAdvisor.java b/security/plugins/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureWorkbenchWindowAdvisor.java deleted file mode 100644 index d8aaec443..000000000 --- a/security/plugins/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureWorkbenchWindowAdvisor.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.rcp; - -import org.eclipse.swt.graphics.Point; -import org.eclipse.ui.application.ActionBarAdvisor; -import org.eclipse.ui.application.IActionBarConfigurer; -import org.eclipse.ui.application.IWorkbenchWindowConfigurer; -import org.eclipse.ui.application.WorkbenchWindowAdvisor; - -public class SecureWorkbenchWindowAdvisor extends WorkbenchWindowAdvisor { - private final String username; - - public SecureWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer, - String username) { - super(configurer); - this.username = username; - } - - public ActionBarAdvisor createActionBarAdvisor( - IActionBarConfigurer configurer) { - return new SecureActionBarAdvisor(configurer, true); - } - - public void preWindowOpen() { - IWorkbenchWindowConfigurer configurer = getWindowConfigurer(); - configurer.setInitialSize(new Point(1200, 900)); - configurer.setShowCoolBar(true); - configurer.setShowMenuBar(true); - configurer.setShowStatusLine(true); - configurer.setShowProgressIndicator(true); - - configurer.setShowPerspectiveBar(true); - String remoteUri = System - .getProperty(AbstractSecureApplication.NODE_REPO_URI); - if (remoteUri != null) - configurer - .setTitle("Argeo UI - " + username + " (" + remoteUri + ")"); //$NON-NLS-1$ - else - configurer.setTitle("Argeo UI - " + username); //$NON-NLS-1$ - - } -} diff --git a/security/plugins/org.argeo.security.ui/.classpath b/security/plugins/org.argeo.security.ui/.classpath deleted file mode 100644 index 5641c7ca3..000000000 --- a/security/plugins/org.argeo.security.ui/.classpath +++ /dev/null @@ -1,7 +0,0 @@ - - - - >> - - - diff --git a/security/plugins/org.argeo.security.ui/.project b/security/plugins/org.argeo.security.ui/.project deleted file mode 100644 index a052e9a57..000000000 --- a/security/plugins/org.argeo.security.ui/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - org.argeo.security.ui - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - - diff --git a/security/plugins/org.argeo.security.ui/.settings/org.eclipse.pde.core.prefs b/security/plugins/org.argeo.security.ui/.settings/org.eclipse.pde.core.prefs deleted file mode 100644 index dfa507d81..000000000 --- a/security/plugins/org.argeo.security.ui/.settings/org.eclipse.pde.core.prefs +++ /dev/null @@ -1,3 +0,0 @@ -#Sat Jan 15 18:15:48 CET 2011 -eclipse.preferences.version=1 -resolve.requirebundle=false diff --git a/security/plugins/org.argeo.security.ui/META-INF/spring/commands.xml b/security/plugins/org.argeo.security.ui/META-INF/spring/commands.xml deleted file mode 100644 index 3b2e6ccb0..000000000 --- a/security/plugins/org.argeo.security.ui/META-INF/spring/commands.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/security/plugins/org.argeo.security.ui/META-INF/spring/keyring.xml b/security/plugins/org.argeo.security.ui/META-INF/spring/keyring.xml deleted file mode 100644 index 906c0b731..000000000 --- a/security/plugins/org.argeo.security.ui/META-INF/spring/keyring.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - osgibundle:securityui.properties - - - - - - - - - - - - - - diff --git a/security/plugins/org.argeo.security.ui/META-INF/spring/osgi.xml b/security/plugins/org.argeo.security.ui/META-INF/spring/osgi.xml deleted file mode 100644 index 01e21244b..000000000 --- a/security/plugins/org.argeo.security.ui/META-INF/spring/osgi.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/security/plugins/org.argeo.security.ui/META-INF/spring/views.xml b/security/plugins/org.argeo.security.ui/META-INF/spring/views.xml deleted file mode 100644 index e5363dcc0..000000000 --- a/security/plugins/org.argeo.security.ui/META-INF/spring/views.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - diff --git a/security/plugins/org.argeo.security.ui/build.properties b/security/plugins/org.argeo.security.ui/build.properties deleted file mode 100644 index 3868784bf..000000000 --- a/security/plugins/org.argeo.security.ui/build.properties +++ /dev/null @@ -1,6 +0,0 @@ -source.. = src/main/java/ -output.. = target/classes/ -bin.includes = META-INF/,\ - .,\ - plugin.xml,\ - icons/ diff --git a/security/plugins/org.argeo.security.ui/icons/adminLog.gif b/security/plugins/org.argeo.security.ui/icons/adminLog.gif deleted file mode 100644 index 6ef3bca66..000000000 Binary files a/security/plugins/org.argeo.security.ui/icons/adminLog.gif and /dev/null differ diff --git a/security/plugins/org.argeo.security.ui/icons/home.gif b/security/plugins/org.argeo.security.ui/icons/home.gif deleted file mode 100644 index fd0c66950..000000000 Binary files a/security/plugins/org.argeo.security.ui/icons/home.gif and /dev/null differ diff --git a/security/plugins/org.argeo.security.ui/icons/log.gif b/security/plugins/org.argeo.security.ui/icons/log.gif deleted file mode 100644 index e3ecc5535..000000000 Binary files a/security/plugins/org.argeo.security.ui/icons/log.gif and /dev/null differ diff --git a/security/plugins/org.argeo.security.ui/icons/maintenance.gif b/security/plugins/org.argeo.security.ui/icons/maintenance.gif deleted file mode 100644 index e5690ecb1..000000000 Binary files a/security/plugins/org.argeo.security.ui/icons/maintenance.gif and /dev/null differ diff --git a/security/plugins/org.argeo.security.ui/icons/password.gif b/security/plugins/org.argeo.security.ui/icons/password.gif deleted file mode 100644 index a6b251fc8..000000000 Binary files a/security/plugins/org.argeo.security.ui/icons/password.gif and /dev/null differ diff --git a/security/plugins/org.argeo.security.ui/icons/user.gif b/security/plugins/org.argeo.security.ui/icons/user.gif deleted file mode 100644 index 90a00147b..000000000 Binary files a/security/plugins/org.argeo.security.ui/icons/user.gif and /dev/null differ diff --git a/security/plugins/org.argeo.security.ui/plugin.xml b/security/plugins/org.argeo.security.ui/plugin.xml deleted file mode 100644 index cb139d7b6..000000000 --- a/security/plugins/org.argeo.security.ui/plugin.xml +++ /dev/null @@ -1,114 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/security/plugins/org.argeo.security.ui/pom.xml b/security/plugins/org.argeo.security.ui/pom.xml deleted file mode 100644 index a03cb84f5..000000000 --- a/security/plugins/org.argeo.security.ui/pom.xml +++ /dev/null @@ -1,91 +0,0 @@ - - 4.0.0 - - org.argeo.commons.security - 2.1.12-SNAPSHOT - plugins - .. - - org.argeo.security.ui - Commons Security UI - jar - - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-source-plugin - - - org.apache.maven.plugins - maven-jar-plugin - - - org.apache.felix - maven-bundle-plugin - - - lazy - org.argeo.security.ui.SecurityUiPlugin - org.eclipse.ui;resolution:=optional,org.eclipse.rap.ui;resolution:=optional,org.eclipse.core.runtime - - org.argeo.eclipse.spring, - org.apache.log4j;resolution:=optional, - * - - - !org.argeo.security.ui.internal.*, - org.argeo.security.ui.* - - - - - - - - - - org.argeo.commons.security - org.argeo.security.core - 2.1.12-SNAPSHOT - - - - - org.argeo.commons.base - org.argeo.eclipse.ui - 2.1.12-SNAPSHOT - - - - - org.argeo.commons.base - org.argeo.eclipse.dep.rcp - 2.1.12-SNAPSHOT - provided - - - - - org.argeo.commons.base - org.argeo.util - 2.1.12-SNAPSHOT - - - - - org.argeo.tp - org.springframework.security.core - - - - - org.argeo.tp - slf4j.org.apache.commons.logging - - - - \ No newline at end of file diff --git a/security/plugins/org.argeo.security.ui/securityui.properties b/security/plugins/org.argeo.security.ui/securityui.properties deleted file mode 100644 index 0228d47ee..000000000 --- a/security/plugins/org.argeo.security.ui/securityui.properties +++ /dev/null @@ -1 +0,0 @@ -argeo.keyring.secreteKeyLength=256 \ No newline at end of file diff --git a/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/MaintenancePerspective.java b/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/MaintenancePerspective.java deleted file mode 100644 index 86307abd2..000000000 --- a/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/MaintenancePerspective.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui; - -import org.argeo.security.ui.views.AdminLogView; -import org.argeo.security.ui.views.UserProfile; -import org.eclipse.ui.IFolderLayout; -import org.eclipse.ui.IPageLayout; -import org.eclipse.ui.IPerspectiveFactory; - -/** Home perspective for the current user */ -public class MaintenancePerspective implements IPerspectiveFactory { - public final static String ID = SecurityUiPlugin.PLUGIN_ID - + ".adminMaintenancePerspective"; - - public void createInitialLayout(IPageLayout layout) { - String editorArea = layout.getEditorArea(); - layout.setEditorAreaVisible(true); - layout.setFixed(false); - - IFolderLayout bottom = layout.createFolder("bottom", - IPageLayout.BOTTOM, 0.50f, editorArea); - bottom.addView(AdminLogView.ID); - - IFolderLayout left = layout.createFolder("left", IPageLayout.LEFT, - 0.30f, editorArea); - left.addView(UserProfile.ID); - // left.addView(RolesView.ID); - - } - -} diff --git a/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/PrivilegedJob.java b/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/PrivilegedJob.java deleted file mode 100644 index 1ded50fdb..000000000 --- a/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/PrivilegedJob.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.argeo.security.ui; - -import java.security.AccessController; -import java.security.PrivilegedAction; - -import javax.security.auth.Subject; - -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.jobs.Job; -import org.springframework.security.Authentication; -import org.springframework.security.context.SecurityContextHolder; - -/** - * Propagate authentication to an eclipse job. Typically to execute a privileged - * action outside the UI thread - */ -public abstract class PrivilegedJob extends Job { - - private final Authentication authentication; - private Subject subject; - - public PrivilegedJob(String jobName) { - super(jobName); - authentication = SecurityContextHolder.getContext().getAuthentication(); - subject = Subject.getSubject(AccessController.getContext()); - } - - @Override - protected IStatus run(final IProgressMonitor progressMonitor) { - PrivilegedAction privilegedAction = new PrivilegedAction() { - public IStatus run() { - SecurityContextHolder.getContext().setAuthentication( - authentication); - return doRun(progressMonitor); - } - }; - return Subject.doAs(subject, privilegedAction); - } - - /** - * Implement here what should be executed with default context - * authentication - */ - protected abstract IStatus doRun(IProgressMonitor progressMonitor); -} \ No newline at end of file diff --git a/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/RolesSourceProvider.java b/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/RolesSourceProvider.java deleted file mode 100644 index a81dc200a..000000000 --- a/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/RolesSourceProvider.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -import org.argeo.security.ui.internal.CurrentUser; -import org.eclipse.ui.AbstractSourceProvider; - -/** - * Provides the roles of the current user as a variable to be used for activity - * binding - */ -public class RolesSourceProvider extends AbstractSourceProvider { - public final static String ROLES_VARIABLE = "roles"; - private final static String[] PROVIDED_SOURCE_NAMES = new String[] { ROLES_VARIABLE }; - - public Map> getCurrentState() { - Map> stateMap = new HashMap>(); - stateMap.put(ROLES_VARIABLE, CurrentUser.roles()); - return stateMap; - } - - public String[] getProvidedSourceNames() { - return PROVIDED_SOURCE_NAMES; - } - - public void updateRoles() { - fireSourceChanged(0, getCurrentState()); - } - - public void dispose() { - } -} \ No newline at end of file diff --git a/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/SecurityUiPlugin.java b/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/SecurityUiPlugin.java deleted file mode 100644 index 03584185b..000000000 --- a/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/SecurityUiPlugin.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui; - -import java.io.IOException; - -import javax.security.auth.callback.Callback; -import javax.security.auth.callback.CallbackHandler; -import javax.security.auth.callback.UnsupportedCallbackException; - -import org.argeo.ArgeoException; -import org.argeo.security.ui.dialogs.DefaultLoginDialog; -import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.swt.widgets.Display; -import org.eclipse.ui.plugin.AbstractUIPlugin; -import org.osgi.framework.BundleContext; -import org.osgi.framework.ServiceRegistration; - -/** - * The activator class controls the plug-in life cycle - */ -public class SecurityUiPlugin extends AbstractUIPlugin { - - // The plug-in ID - public static final String PLUGIN_ID = "org.argeo.security.ui"; //$NON-NLS-1$ - - public final static String CONTEXT_KEYRING = "KEYRING"; - - private CallbackHandler defaultCallbackHandler; - private ServiceRegistration defaultCallbackHandlerReg; - - private static SecurityUiPlugin plugin; - - public static InheritableThreadLocal display = new InheritableThreadLocal() { - - @Override - protected Display initialValue() { - return Display.getCurrent(); - } - }; - - public void start(BundleContext context) throws Exception { - super.start(context); - plugin = this; - - defaultCallbackHandler = new DefaultCallbackHandler(); - defaultCallbackHandlerReg = context.registerService( - CallbackHandler.class.getName(), defaultCallbackHandler, null); - } - - public void stop(BundleContext context) throws Exception { - plugin = null; - defaultCallbackHandlerReg.unregister(); - super.stop(context); - } - - /** - * Returns the shared instance - * - * @return the shared instance - */ - public static SecurityUiPlugin getDefault() { - return plugin; - } - - public static ImageDescriptor getImageDescriptor(String path) { - return imageDescriptorFromPlugin(PLUGIN_ID, path); - } - - protected class DefaultCallbackHandler implements CallbackHandler { - public void handle(final Callback[] callbacks) throws IOException, - UnsupportedCallbackException { - - // if (display != null) // RCP - Display displayToUse = display.get(); - if (displayToUse == null)// RCP - displayToUse = Display.getDefault(); - displayToUse.syncExec(new Runnable() { - public void run() { - DefaultLoginDialog dialog = new DefaultLoginDialog(display - .get().getActiveShell()); - try { - dialog.handle(callbacks); - } catch (IOException e) { - throw new ArgeoException("Cannot open dialog", e); - } - } - }); - // else {// RAP - // DefaultLoginDialog dialog = new DefaultLoginDialog(); - // dialog.handle(callbacks); - // } - } - - } -} diff --git a/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/UserHomePerspective.java b/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/UserHomePerspective.java deleted file mode 100644 index 119549ffd..000000000 --- a/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/UserHomePerspective.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui; - -import org.argeo.security.ui.views.LogView; -import org.argeo.security.ui.views.UserProfile; -import org.eclipse.ui.IFolderLayout; -import org.eclipse.ui.IPageLayout; -import org.eclipse.ui.IPerspectiveFactory; - -/** Home perspective for the current user */ -public class UserHomePerspective implements IPerspectiveFactory { - public final static String ID = SecurityUiPlugin.PLUGIN_ID - + ".userHomePerspective"; - - public void createInitialLayout(IPageLayout layout) { - String editorArea = layout.getEditorArea(); - layout.setEditorAreaVisible(true); - layout.setFixed(false); - - IFolderLayout left = layout.createFolder("left", IPageLayout.LEFT, - 0.30f, editorArea); - left.addView(UserProfile.ID); - left.addView(LogView.ID); - } - -} diff --git a/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/commands/OpenChangePasswordDialog.java b/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/commands/OpenChangePasswordDialog.java deleted file mode 100644 index 3044e2c6c..000000000 --- a/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/commands/OpenChangePasswordDialog.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.commands; - -import org.argeo.security.ui.dialogs.ChangePasswordDialog; -import org.eclipse.core.commands.AbstractHandler; -import org.eclipse.core.commands.ExecutionEvent; -import org.eclipse.core.commands.ExecutionException; -import org.eclipse.jface.dialogs.Dialog; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.ui.handlers.HandlerUtil; -import org.springframework.security.userdetails.UserDetailsManager; - -/** Opens the change password dialog. */ -public class OpenChangePasswordDialog extends AbstractHandler { - private UserDetailsManager userDetailsManager; - - public Object execute(ExecutionEvent event) throws ExecutionException { - ChangePasswordDialog dialog = new ChangePasswordDialog( - HandlerUtil.getActiveShell(event), userDetailsManager); - if (dialog.open() == Dialog.OK) { - MessageDialog.openInformation(HandlerUtil.getActiveShell(event), - "Password changed", "Password changed."); - } - return null; - } - - public void setUserDetailsManager(UserDetailsManager userDetailsManager) { - this.userDetailsManager = userDetailsManager; - } - -} diff --git a/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/commands/OpenHomePerspective.java b/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/commands/OpenHomePerspective.java deleted file mode 100644 index d56498a15..000000000 --- a/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/commands/OpenHomePerspective.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.commands; - -import org.argeo.eclipse.ui.ErrorFeedback; -import org.argeo.security.ui.UserHomePerspective; -import org.eclipse.core.commands.AbstractHandler; -import org.eclipse.core.commands.ExecutionEvent; -import org.eclipse.core.commands.ExecutionException; -import org.eclipse.ui.WorkbenchException; -import org.eclipse.ui.handlers.HandlerUtil; - -/** Default action of the user menu */ -public class OpenHomePerspective extends AbstractHandler { - - public Object execute(ExecutionEvent event) throws ExecutionException { - try { - HandlerUtil.getActiveSite(event).getWorkbenchWindow() - .openPage(UserHomePerspective.ID, null); - } catch (WorkbenchException e) { - ErrorFeedback.show("Cannot open home perspective", e); - } - return null; - } - -} diff --git a/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/dialogs/AbstractLoginDialog.java b/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/dialogs/AbstractLoginDialog.java deleted file mode 100644 index 7c7e0c6b6..000000000 --- a/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/dialogs/AbstractLoginDialog.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.dialogs; - -import java.io.IOException; - -import javax.security.auth.callback.Callback; -import javax.security.auth.callback.CallbackHandler; -import javax.security.auth.callback.NameCallback; -import javax.security.auth.callback.PasswordCallback; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.security.ui.SecurityUiPlugin; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.NullProgressMonitor; -import org.eclipse.jface.dialogs.IDialogConstants; -import org.eclipse.jface.dialogs.TrayDialog; -import org.eclipse.jface.operation.IRunnableWithProgress; -import org.eclipse.jface.operation.ModalContext; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.SelectionListener; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Shell; - -/** Base for login dialogs */ -public abstract class AbstractLoginDialog extends TrayDialog implements - CallbackHandler { - - private final static Log log = LogFactory.getLog(AbstractLoginDialog.class); - - private Thread modalContextThread = null; - boolean processCallbacks = false; - boolean isCancelled = false; - Callback[] callbackArray; - - protected final Callback[] getCallbacks() { - return this.callbackArray; - } - - public abstract void internalHandle(); - - public boolean isCancelled() { - return isCancelled; - } - - protected AbstractLoginDialog(Shell parentShell) { - super(parentShell); - } - - /* - * (non-Javadoc) - * - * @see - * javax.security.auth.callback.CallbackHandler#handle(javax.security.auth - * .callback.Callback[]) - */ - public void handle(final Callback[] callbacks) throws IOException { - // clean previous usage - if (processCallbacks) { - // this handler was already used - processCallbacks = false; - } - - if (modalContextThread != null) { - try { - modalContextThread.join(1000); - } catch (InterruptedException e) { - // silent - } - modalContextThread = null; - } - - // initialize - this.callbackArray = callbacks; - final Display display = Display.getDefault(); - display.syncExec(new Runnable() { - - public void run() { - isCancelled = false; - setBlockOnOpen(false); - open(); - - final Button okButton = getButton(IDialogConstants.OK_ID); - okButton.setText("Login"); - okButton.addSelectionListener(new SelectionListener() { - - public void widgetSelected(final SelectionEvent event) { - processCallbacks = true; - } - - public void widgetDefaultSelected(final SelectionEvent event) { - // nothing to do - } - }); - final Button cancel = getButton(IDialogConstants.CANCEL_ID); - cancel.addSelectionListener(new SelectionListener() { - - public void widgetSelected(final SelectionEvent event) { - isCancelled = true; - processCallbacks = true; - } - - public void widgetDefaultSelected(final SelectionEvent event) { - // nothing to do - } - }); - } - }); - try { - ModalContext.setAllowReadAndDispatch(true); // Works for now. - ModalContext.run(new IRunnableWithProgress() { - - public void run(final IProgressMonitor monitor) { - modalContextThread = Thread.currentThread(); - // Wait here until OK or cancel is pressed, then let it rip. - // The event - // listener - // is responsible for closing the dialog (in the - // loginSucceeded - // event). - while (!processCallbacks && (modalContextThread != null) - && (modalContextThread == Thread.currentThread()) - && SecurityUiPlugin.getDefault() != null) { - // Note: SecurityUiPlugin.getDefault() != null is false - // when the OSGi runtime is shut down - try { - Thread.sleep(100); - // if (display.isDisposed()) { - // log.warn("Display is disposed, killing login dialog thread"); - // throw new ThreadDeath(); - // } - } catch (final Exception e) { - // do nothing - } - } - processCallbacks = false; - // Call the adapter to handle the callbacks - if (!isCancelled()) - internalHandle(); - else - // clear callbacks are when cancelling - for (Callback callback : callbacks) - if (callback instanceof PasswordCallback) - ((PasswordCallback) callback).setPassword(null); - else if (callback instanceof NameCallback) - ((NameCallback) callback).setName(null); - } - }, true, new NullProgressMonitor(), Display.getDefault()); - } catch (ThreadDeath e) { - isCancelled = true; - log.debug("Thread " + Thread.currentThread().getId() + " died"); - throw e; - } catch (Exception e) { - isCancelled = true; - IOException ioe = new IOException( - "Unexpected issue in login dialog, see root cause for more details"); - ioe.initCause(e); - throw ioe; - } finally { - // so that the modal thread dies - processCallbacks = true; - // try { - // // wait for the modal context thread to gracefully exit - // modalContextThread.join(); - // } catch (InterruptedException ie) { - // // silent - // } - modalContextThread = null; - } - } - - protected void configureShell(Shell shell) { - super.configureShell(shell); - shell.setText("Authentication"); - } -} diff --git a/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/dialogs/ChangePasswordDialog.java b/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/dialogs/ChangePasswordDialog.java deleted file mode 100644 index fe9b6ae9d..000000000 --- a/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/dialogs/ChangePasswordDialog.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.dialogs; - -import org.argeo.ArgeoException; -import org.argeo.eclipse.ui.ErrorFeedback; -import org.eclipse.jface.dialogs.IMessageProvider; -import org.eclipse.jface.dialogs.TitleAreaDialog; -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Text; -import org.springframework.security.userdetails.UserDetailsManager; - -/** Dialog to change the current user password */ -public class ChangePasswordDialog extends TitleAreaDialog { - private Text currentPassword, newPassword1, newPassword2; - private UserDetailsManager userDetailsManager; - - public ChangePasswordDialog(Shell parentShell, - UserDetailsManager securityService) { - super(parentShell); - this.userDetailsManager = securityService; - } - - protected Point getInitialSize() { - return new Point(300, 250); - } - - protected Control createDialogArea(Composite parent) { - Composite dialogarea = (Composite) super.createDialogArea(parent); - dialogarea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - Composite composite = new Composite(dialogarea, SWT.NONE); - composite.setLayout(new GridLayout(2, false)); - composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); - currentPassword = createLP(composite, "Current password"); - newPassword1 = createLP(composite, "New password"); - newPassword2 = createLP(composite, "Repeat new password"); - - setMessage("Change password", IMessageProvider.INFORMATION); - parent.pack(); - return composite; - } - - @Override - protected void okPressed() { - if (!newPassword1.getText().equals(newPassword2.getText())) - throw new ArgeoException("Passwords are different"); - try { - userDetailsManager.changePassword(currentPassword.getText(), - newPassword1.getText()); - close(); - } catch (Exception e) { - ErrorFeedback.show("Cannot change password", e); - } - } - - /** Creates label and password. */ - protected Text createLP(Composite parent, String label) { - new Label(parent, SWT.NONE).setText(label); - Text text = new Text(parent, SWT.SINGLE | SWT.LEAD | SWT.PASSWORD - | SWT.BORDER); - text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); - return text; - } - - protected void configureShell(Shell shell) { - super.configureShell(shell); - shell.setText("Change password"); - } - -} diff --git a/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/dialogs/DefaultLoginDialog.java b/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/dialogs/DefaultLoginDialog.java deleted file mode 100644 index 57ba01b5b..000000000 --- a/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/dialogs/DefaultLoginDialog.java +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.dialogs; - -import javax.security.auth.callback.Callback; -import javax.security.auth.callback.CallbackHandler; -import javax.security.auth.callback.NameCallback; -import javax.security.auth.callback.PasswordCallback; -import javax.security.auth.callback.TextOutputCallback; - -import org.argeo.security.ui.SecurityUiPlugin; -import org.argeo.util.LocaleCallback; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.SelectionListener; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Combo; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Text; - -/** Default authentication dialog, to be used as {@link CallbackHandler}. */ -public class DefaultLoginDialog extends AbstractLoginDialog { - public DefaultLoginDialog() { - this(SecurityUiPlugin.display.get().getActiveShell()); - } - - public DefaultLoginDialog(Shell parentShell) { - super(parentShell); - } - - protected Point getInitialSize() { - return new Point(350, 180); - } - - @Override - protected Control createContents(Composite parent) { - Control control = super.createContents(parent); - parent.pack(); - - // Move the dialog to the center of the top level shell. - Rectangle shellBounds; - if (Display.getCurrent().getActiveShell() != null) // RCP - shellBounds = Display.getCurrent().getActiveShell().getBounds(); - else - shellBounds = Display.getCurrent().getBounds();// RAP - Point dialogSize = parent.getSize(); - int x = shellBounds.x + (shellBounds.width - dialogSize.x) / 2; - int y = shellBounds.y + (shellBounds.height - dialogSize.y) / 2; - parent.setLocation(x, y); - return control; - } - - protected Control createDialogArea(Composite parent) { - Composite dialogarea = (Composite) super.createDialogArea(parent); - Composite composite = new Composite(dialogarea, SWT.NONE); - composite.setLayout(new GridLayout(2, false)); - composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); - createCallbackHandlers(composite); - // parent.pack(); - return composite; - } - - private void createCallbackHandlers(Composite composite) { - Callback[] callbacks = getCallbacks(); - for (int i = 0; i < callbacks.length; i++) { - Callback callback = callbacks[i]; - if (callback instanceof TextOutputCallback) { - createLabelTextoutputHandler(composite, - (TextOutputCallback) callback); - } else if (callback instanceof NameCallback) { - createNameHandler(composite, (NameCallback) callback); - } else if (callback instanceof PasswordCallback) { - createPasswordHandler(composite, (PasswordCallback) callback); - } else if (callback instanceof LocaleCallback) { - createLocaleHandler(composite, (LocaleCallback) callback); - } - } - } - - private void createPasswordHandler(Composite composite, - final PasswordCallback callback) { - Label label = new Label(composite, SWT.NONE); - label.setText(callback.getPrompt()); - final Text passwordText = new Text(composite, SWT.SINGLE | SWT.LEAD - | SWT.PASSWORD | SWT.BORDER); - passwordText - .setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - passwordText.addModifyListener(new ModifyListener() { - - public void modifyText(ModifyEvent event) { - // FIXME use getTextChars() in Eclipse 3.7 - callback.setPassword(passwordText.getText().toCharArray()); - } - }); - } - - private void createLocaleHandler(Composite composite, - final LocaleCallback callback) { - String[] labels = callback.getSupportedLocalesLabels(); - if (labels.length == 0) - return; - Label label = new Label(composite, SWT.NONE); - label.setText(callback.getPrompt()); - - final Combo combo = new Combo(composite, SWT.READ_ONLY); - combo.setItems(labels); - combo.select(callback.getDefaultIndex()); - combo.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - combo.addSelectionListener(new SelectionListener() { - @Override - public void widgetSelected(SelectionEvent e) { - callback.setSelectedIndex(combo.getSelectionIndex()); - } - - @Override - public void widgetDefaultSelected(SelectionEvent e) { - } - }); - } - - private void createNameHandler(Composite composite, - final NameCallback callback) { - Label label = new Label(composite, SWT.NONE); - label.setText(callback.getPrompt()); - final Text text = new Text(composite, SWT.SINGLE | SWT.LEAD - | SWT.BORDER); - if (callback.getDefaultName() != null) { - // set default value, if provided - text.setText(callback.getDefaultName()); - callback.setName(callback.getDefaultName()); - } - text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - text.addModifyListener(new ModifyListener() { - - public void modifyText(ModifyEvent event) { - callback.setName(text.getText()); - } - }); - } - - private void createLabelTextoutputHandler(Composite composite, - final TextOutputCallback callback) { - Label label = new Label(composite, SWT.NONE); - label.setText(callback.getMessage()); - GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); - data.horizontalSpan = 2; - label.setLayoutData(data); - // TODO: find a way to pass this information - // int messageType = callback.getMessageType(); - // int dialogMessageType = IMessageProvider.NONE; - // switch (messageType) { - // case TextOutputCallback.INFORMATION: - // dialogMessageType = IMessageProvider.INFORMATION; - // break; - // case TextOutputCallback.WARNING: - // dialogMessageType = IMessageProvider.WARNING; - // break; - // case TextOutputCallback.ERROR: - // dialogMessageType = IMessageProvider.ERROR; - // break; - // } - // setMessage(callback.getMessage(), dialogMessageType); - } - - public void internalHandle() { - } -} diff --git a/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/internal/CurrentUser.java b/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/internal/CurrentUser.java deleted file mode 100644 index 43ca5884e..000000000 --- a/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/internal/CurrentUser.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.internal; - -import java.security.AccessController; -import java.security.Principal; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -import javax.security.auth.Subject; - -import org.argeo.ArgeoException; -import org.springframework.security.Authentication; -import org.springframework.security.GrantedAuthority; - -/** - * Retrieves information about the current user. Not an API, can change without - * notice. - */ -public class CurrentUser { - public final static String getUsername() { - Subject subject = getSubject(); - if (subject == null) - return null; - Principal principal = subject.getPrincipals().iterator().next(); - return principal.getName(); - - } - - public final static Set roles() { - Set roles = Collections.synchronizedSet(new HashSet()); - Authentication authentication = getAuthentication(); - for (GrantedAuthority ga : authentication.getAuthorities()) { - roles.add(ga.getAuthority()); - } - return Collections.unmodifiableSet(roles); - } - - public final static Authentication getAuthentication() { - Set authens = getSubject().getPrincipals( - Authentication.class); - if (authens != null && !authens.isEmpty()) { - Principal principal = authens.iterator().next(); - Authentication authentication = (Authentication) principal; - return authentication; - } - throw new ArgeoException("No authentication found"); - } - - public final static Subject getSubject() { - Subject subject = Subject.getSubject(AccessController.getContext()); - if (subject == null) - throw new ArgeoException("Not authenticated."); - return subject; - } -} diff --git a/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/views/AdminLogView.java b/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/views/AdminLogView.java deleted file mode 100644 index d59edf883..000000000 --- a/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/views/AdminLogView.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.views; - -import java.util.ArrayList; - -import org.argeo.ArgeoLogger; -import org.argeo.security.ui.SecurityUiPlugin; -import org.eclipse.jface.resource.JFaceResources; -import org.eclipse.jface.viewers.LabelProvider; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Font; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Table; -import org.eclipse.ui.part.ViewPart; - -/** - * Display log lines for all users with a virtual table. - */ -public class AdminLogView extends ViewPart { - public static String ID = SecurityUiPlugin.PLUGIN_ID + ".adminLogView"; - - private TableViewer viewer; - - private LogContentProvider logContentProvider; - private ArgeoLogger argeoLogger; - - @Override - public void createPartControl(Composite parent) { - // FIXME doesn't return a monospace font in RAP - Font font = JFaceResources.getTextFont(); - Table table = new Table(parent, SWT.VIRTUAL | SWT.MULTI | SWT.H_SCROLL - | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER); - table.setFont(font); - - viewer = new TableViewer(table); - viewer.setLabelProvider(new LabelProvider()); - logContentProvider = new LogContentProvider(viewer) { - - @Override - protected StringBuffer prefix(String username, Long timestamp, - String level, String category, String thread) { - return super - .prefix(username, timestamp, level, category, thread) - .append(norm(level, 5)) - .append(' ') - .append(norm(username != null ? username - : "", 16)).append(' '); - } - }; - viewer.setContentProvider(logContentProvider); - // viewer.setUseHashlookup(true); - viewer.setInput(new ArrayList()); - - if (argeoLogger != null) - argeoLogger.registerForAll(logContentProvider, 1000, true); - } - - @Override - public void setFocus() { - viewer.getTable().setFocus(); - } - - @Override - public void dispose() { - if (argeoLogger != null) - argeoLogger.unregisterForAll(logContentProvider); - } - - public void setArgeoLogger(ArgeoLogger argeoLogger) { - this.argeoLogger = argeoLogger; - } - -} diff --git a/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/views/LogContentProvider.java b/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/views/LogContentProvider.java deleted file mode 100644 index 72f205932..000000000 --- a/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/views/LogContentProvider.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.views; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Arrays; -import java.util.Date; -import java.util.LinkedList; -import java.util.List; - -import org.argeo.ArgeoLogListener; -import org.eclipse.jface.viewers.ILazyContentProvider; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.swt.widgets.Table; -import org.eclipse.swt.widgets.TableItem; - -/** A content provider maintaining an array of lines */ -class LogContentProvider implements ILazyContentProvider, ArgeoLogListener { - private DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss"); - - private final Long start; - /** current - start = line number. first line is number '1' */ - private Long current; - - // TODO make it configurable - private final Integer maxLineBufferSize = 10 * 1000; - - private final TableViewer viewer; - private LinkedList lines; - - public LogContentProvider(TableViewer viewer) { - this.viewer = viewer; - start = System.currentTimeMillis(); - lines = new LinkedList(); - current = start; - } - - public synchronized void dispose() { - lines.clear(); - lines = null; - } - - @SuppressWarnings("unchecked") - public synchronized void inputChanged(Viewer viewer, Object oldInput, - Object newInput) { - List lin = (List) newInput; - if (lin == null) - return; - for (String line : lin) { - addLine(line); - } - this.viewer.setItemCount(lines.size()); - } - - public void updateElement(int index) { - viewer.replace(lines.get(index), index); - } - - public synchronized void appendLog(String username, Long timestamp, - String level, String category, String thread, Object msg, - String[] exception) { - // check if valid - if (lines == null) - return; - - String message = msg.toString(); - int count = 0; - String prefix = prefix(username, timestamp, level, category, thread) - .toString(); - // String suffix = suffix(username, timestamp, level, category, thread); - for (String line : message.split("\n")) { - addLine(count == 0 ? prefix + line : line); - count++; - } - - if (exception != null) { - for (String ste : exception) { - addLine(ste); - } - } - - viewer.getTable().getDisplay().asyncExec(new Runnable() { - public void run() { - if (lines == null) - return; - viewer.setItemCount(lines.size()); - // doesn't work with syncExec - scrollToLastLine(); - } - }); - } - - protected StringBuffer prefix(String username, Long timestamp, - String level, String category, String thread) { - StringBuffer buf = new StringBuffer(""); - buf.append(dateFormat.format(new Date(timestamp))).append(" "); - // buf.append(level).append(" "); - return buf; - } - - /** Normalize string to the given size */ - protected String norm(String str, Integer size) { - int length = str.length(); - if (length == size) - return str; - else if (length > size) - return str.substring(0, size); - else { - char[] arr = new char[size - length]; - Arrays.fill(arr, ' '); - return str + new String(arr); - } - } - - // protected String suffix(String username, Long timestamp, String level, - // String category, String thread) { - // return ""; - // } - - /** Scroll to the last line */ - protected synchronized void scrollToLastLine() { - // we try to show last line with two methods - // viewer.reveal(lines.peekLast()); - - Table table = viewer.getTable(); - TableItem ti = table.getItem(table.getItemCount() - 1); - table.showItem(ti); - } - - protected synchronized LogLine addLine(String line) { - // check for maximal size and purge if necessary - while (lines.size() >= maxLineBufferSize) { - for (int i = 0; i < maxLineBufferSize / 10; i++) { - lines.poll(); - } - } - - current++; - LogLine logLine = new LogLine(current, line); - lines.add(logLine); - return logLine; - } - - private class LogLine { - private Long linenumber; - private String message; - - public LogLine(Long linenumber, String message) { - this.linenumber = linenumber; - this.message = message; - } - - @Override - public int hashCode() { - return linenumber.intValue(); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof LogLine) - return ((LogLine) obj).linenumber.equals(linenumber); - else - return false; - } - - @Override - public String toString() { - return message; - } - - } -} \ No newline at end of file diff --git a/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/views/LogView.java b/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/views/LogView.java deleted file mode 100644 index c7c47b352..000000000 --- a/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/views/LogView.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.views; - -import java.util.ArrayList; - -import org.argeo.ArgeoLogListener; -import org.argeo.ArgeoLogger; -import org.argeo.security.ui.SecurityUiPlugin; -import org.eclipse.jface.resource.JFaceResources; -import org.eclipse.jface.viewers.LabelProvider; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Font; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Table; -import org.eclipse.ui.part.ViewPart; - -/** - * Display log lines with a virtual table. Register and unregisters a - * {@link ArgeoLogListener} via OSGi services. - */ -public class LogView extends ViewPart { - public static String ID = SecurityUiPlugin.PLUGIN_ID + ".logView"; - - private TableViewer viewer; - - private LogContentProvider logContentProvider; - private ArgeoLogger argeoLogger; - - @Override - public void createPartControl(Composite parent) { - Font font = JFaceResources.getTextFont(); - Table table = new Table(parent, SWT.VIRTUAL | SWT.MULTI | SWT.H_SCROLL - | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER); - table.setFont(font); - - viewer = new TableViewer(table); - viewer.setLabelProvider(new LabelProvider()); - logContentProvider = new LogContentProvider(viewer); - viewer.setContentProvider(logContentProvider); - // viewer.setUseHashlookup(true); - viewer.setInput(new ArrayList()); - - if (argeoLogger != null) - argeoLogger.register(logContentProvider, 1000); - } - - @Override - public void setFocus() { - viewer.getTable().setFocus(); - } - - @Override - public void dispose() { - if (argeoLogger != null) - argeoLogger.unregister(logContentProvider); - } - - public void setArgeoLogger(ArgeoLogger argeoLogger) { - this.argeoLogger = argeoLogger; - } - -} diff --git a/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/views/UserProfile.java b/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/views/UserProfile.java deleted file mode 100644 index 3f1f000bf..000000000 --- a/security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/views/UserProfile.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.views; - -import java.util.TreeSet; - -import org.argeo.eclipse.ui.EclipseUiUtils; -import org.argeo.security.ui.SecurityUiPlugin; -import org.argeo.security.ui.internal.CurrentUser; -import org.eclipse.jface.viewers.IStructuredContentProvider; -import org.eclipse.jface.viewers.LabelProvider; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Table; -import org.eclipse.ui.part.ViewPart; -import org.springframework.security.Authentication; - -/** Information about the currently logged in user */ -public class UserProfile extends ViewPart { - public static String ID = SecurityUiPlugin.PLUGIN_ID + ".userProfile"; - - private TableViewer viewer; - - @Override - public void createPartControl(Composite parent) { - parent.setLayout(new GridLayout(2, false)); - - Authentication authentication = CurrentUser.getAuthentication(); - EclipseUiUtils.createGridLL(parent, "Name", authentication - .getPrincipal().toString()); - EclipseUiUtils.createGridLL(parent, "User ID", - CurrentUser.getUsername()); - - // roles table - Table table = new Table(parent, SWT.V_SCROLL | SWT.BORDER); - table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1)); - table.setLinesVisible(false); - table.setHeaderVisible(false); - viewer = new TableViewer(table); - viewer.setContentProvider(new RolesContentProvider()); - viewer.setLabelProvider(new LabelProvider()); - getViewSite().setSelectionProvider(viewer); - viewer.setInput(getViewSite()); - } - - @Override - public void setFocus() { - viewer.getTable(); - } - - private class RolesContentProvider implements IStructuredContentProvider { - public Object[] getElements(Object inputElement) { - return new TreeSet(CurrentUser.roles()).toArray(); - } - - public void dispose() { - } - - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - } - - } - -} diff --git a/security/plugins/pom.xml b/security/plugins/pom.xml index 3ff81b961..ad5bc115f 100644 --- a/security/plugins/pom.xml +++ b/security/plugins/pom.xml @@ -6,8 +6,8 @@ security .. - org.argeo.commons.security - plugins + org.argeo.commons + argeo-commons Commons Security Eclipse Plugins pom diff --git a/security/runtime/org.argeo.security.activemq/pom.xml b/security/runtime/org.argeo.security.activemq/pom.xml index b568ab4dc..bcbec028b 100644 --- a/security/runtime/org.argeo.security.activemq/pom.xml +++ b/security/runtime/org.argeo.security.activemq/pom.xml @@ -1,8 +1,8 @@ 4.0.0 - org.argeo.commons.security - runtime + org.argeo.commons + argeo-commons 2.1.12-SNAPSHOT .. @@ -38,12 +38,12 @@ - org.argeo.commons.base + org.argeo.commons org.argeo.util 2.1.12-SNAPSHOT - org.argeo.commons.security + org.argeo.commons org.argeo.security.core 2.1.12-SNAPSHOT diff --git a/security/runtime/org.argeo.security.core/.classpath b/security/runtime/org.argeo.security.core/.classpath deleted file mode 100644 index b639b537c..000000000 --- a/security/runtime/org.argeo.security.core/.classpath +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - >> - - - diff --git a/security/runtime/org.argeo.security.core/.project b/security/runtime/org.argeo.security.core/.project deleted file mode 100644 index a8e385a9c..000000000 --- a/security/runtime/org.argeo.security.core/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - org.argeo.security.core - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.jdt.core.javanature - org.eclipse.pde.PluginNature - - diff --git a/security/runtime/org.argeo.security.core/META-INF/spring/logger.xml b/security/runtime/org.argeo.security.core/META-INF/spring/logger.xml deleted file mode 100644 index 02f48c8a8..000000000 --- a/security/runtime/org.argeo.security.core/META-INF/spring/logger.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/security/runtime/org.argeo.security.core/META-INF/spring/osgi.xml b/security/runtime/org.argeo.security.core/META-INF/spring/osgi.xml deleted file mode 100644 index 5e1433c2f..000000000 --- a/security/runtime/org.argeo.security.core/META-INF/spring/osgi.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/security/runtime/org.argeo.security.core/build.properties b/security/runtime/org.argeo.security.core/build.properties deleted file mode 100644 index 788870d98..000000000 --- a/security/runtime/org.argeo.security.core/build.properties +++ /dev/null @@ -1,13 +0,0 @@ -additional.bundles = org.springframework.transaction,\ - org.springframework.core,\ - junit,\ - org.apache.commons.io,\ - org.apache.commons.codec,\ - org.springframework.security.core,\ - org.apache.log4j,\ - slf4j.api,\ - slf4j.org.apache.commons.logging -source.. = src/main/java/,\ - src/main/resources/,\ - src/test/java/,\ - src/test/resources/ diff --git a/security/runtime/org.argeo.security.core/pom.xml b/security/runtime/org.argeo.security.core/pom.xml deleted file mode 100644 index e2daa3826..000000000 --- a/security/runtime/org.argeo.security.core/pom.xml +++ /dev/null @@ -1,138 +0,0 @@ - - - 4.0.0 - - org.argeo.commons.security - runtime - 2.1.12-SNAPSHOT - .. - - org.argeo.security.core - Commons Security Core - - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-source-plugin - - - org.apache.maven.plugins - maven-jar-plugin - - - org.apache.felix - maven-bundle-plugin - - - - lazy - - org.argeo.security.* - - - - org.bouncycastle.*;resolution:=optional, - javax.jcr.security, - *, - - - - - - - - - org.argeo.commons.base - org.argeo.util - 2.1.12-SNAPSHOT - - - org.argeo.commons.server - org.argeo.server.jcr - 2.1.12-SNAPSHOT - - - - - org.argeo.tp - bcprov - true - - - org.argeo.tp - org.apache.commons.codec - - - - - org.argeo.tp - org.springframework.core - - - org.argeo.tp - org.springframework.beans - - - org.argeo.tp - org.springframework.context - - - org.argeo.tp - org.springframework.security.core - - - org.argeo.tp - org.springframework.transaction - - - - - org.argeo.tp - org.eclipse.osgi - provided - - - - - org.argeo.tp - slf4j.org.apache.commons.logging - - - - org.argeo.tp - org.apache.log4j - true - - - - - org.argeo.tp - junit - test - - - org.argeo.commons.base - org.argeo.dep.log4j - 2.1.12-SNAPSHOT - pom - test - - - org.argeo.commons.server - org.argeo.server.json - 2.1.12-SNAPSHOT - test - - - org.argeo.tp - com.springsource.json - test - - - - \ No newline at end of file diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/NodeAuthenticationToken.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/NodeAuthenticationToken.java deleted file mode 100644 index 1870675d8..000000000 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/NodeAuthenticationToken.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security; - -import org.springframework.security.GrantedAuthority; -import org.springframework.security.providers.UsernamePasswordAuthenticationToken; - -/** Credentials required for the authentication to a node. */ -public class NodeAuthenticationToken extends - UsernamePasswordAuthenticationToken { - private static final long serialVersionUID = 1955222132884795213L; - private final String url; - - /** Non authenticated local constructor */ - public NodeAuthenticationToken(Object principal, Object credentials) { - super(principal, credentials); - this.url = null; - } - - /** Non authenticated remote constructor */ - public NodeAuthenticationToken(Object principal, Object credentials, - String url) { - super(principal, credentials); - this.url = url; - } - - /** Authenticated constructor */ - public NodeAuthenticationToken(NodeAuthenticationToken sat, - GrantedAuthority[] authorities) { - super(sat.getPrincipal(), sat.getCredentials(), authorities); - this.url = sat.getUrl(); - } - - public String getUrl() { - return url; - } - - public Boolean isRemote() { - return url != null; - } -} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/OsAuthenticationToken.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/OsAuthenticationToken.java deleted file mode 100644 index b3727b26f..000000000 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/OsAuthenticationToken.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security; - -import java.security.AccessController; -import java.security.Principal; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Set; - -import javax.security.auth.Subject; - -import org.argeo.ArgeoException; -import org.argeo.OperatingSystem; -import org.springframework.security.Authentication; -import org.springframework.security.GrantedAuthority; -import org.springframework.security.GrantedAuthorityImpl; -import org.springframework.security.userdetails.UserDetails; - -/** Abstracts principals provided by com.sun.security.auth.module login modules. */ -public class OsAuthenticationToken implements Authentication { - private static final long serialVersionUID = -7544626794250917244L; - - final Class osUserPrincipalClass; - final Class osUserIdPrincipalClass; - final Class osGroupIdPrincipalClass; - - private List grantedAuthorities; - - private UserDetails details; - - /** Request */ - public OsAuthenticationToken(GrantedAuthority[] grantedAuthorities) { - this.grantedAuthorities = grantedAuthorities != null ? Arrays - .asList(grantedAuthorities) : null; - ClassLoader cl = getClass().getClassLoader(); - switch (OperatingSystem.os) { - case OperatingSystem.WINDOWS: - osUserPrincipalClass = getPrincipalClass(cl, - "com.sun.security.auth.NTUserPrincipal"); - osUserIdPrincipalClass = getPrincipalClass(cl, - "com.sun.security.auth.NTSidUserPrincipal"); - osGroupIdPrincipalClass = getPrincipalClass(cl, - "com.sun.security.auth.NTSidGroupPrincipal"); - break; - case OperatingSystem.NIX: - osUserPrincipalClass = getPrincipalClass(cl, - "com.sun.security.auth.UnixPrincipal"); - osUserIdPrincipalClass = getPrincipalClass(cl, - "com.sun.security.auth.UnixNumericUserPrincipal"); - osGroupIdPrincipalClass = getPrincipalClass(cl, - "com.sun.security.auth.UnixNumericGroupPrincipal"); - break; - case OperatingSystem.SOLARIS: - osUserPrincipalClass = getPrincipalClass(cl, - "com.sun.security.auth.SolarisPrincipal"); - osUserIdPrincipalClass = getPrincipalClass(cl, - "com.sun.security.auth.SolarisNumericUserPrincipal"); - osGroupIdPrincipalClass = getPrincipalClass(cl, - "com.sun.security.auth.SolarisNumericGroupPrincipal"); - break; - - default: - throw new ArgeoException("Unsupported operating system " - + OperatingSystem.os); - } - - } - - /** Authenticated */ - public OsAuthenticationToken() { - this(null); - } - - /** @return the name, or null if not yet logged */ - public String getName() { - Subject subject = Subject.getSubject(AccessController.getContext()); - if (subject == null) - return null; - return getUser().getName(); - } - - /** - * Should not be called during authentication since group IDs are not yet - * available {@link Subject} has been set - */ - public GrantedAuthority[] getAuthorities() { - // grantedAuthorities should not be null at this stage - List gas = new ArrayList( - grantedAuthorities); - for (Principal groupPrincipal : getGroupsIds()) { - gas.add(new GrantedAuthorityImpl("OSGROUP_" - + groupPrincipal.getName())); - } - return gas.toArray(new GrantedAuthority[gas.size()]); - } - - public UserDetails getDetails() { - return details; - } - - public void setDetails(UserDetails details) { - this.details = details; - } - - public boolean isAuthenticated() { - return grantedAuthorities != null; - } - - public void setAuthenticated(boolean isAuthenticated) - throws IllegalArgumentException { - if (grantedAuthorities != null) - grantedAuthorities.clear(); - grantedAuthorities = null; - } - - @SuppressWarnings("unchecked") - protected static Class getPrincipalClass( - ClassLoader cl, String className) { - try { - return (Class) cl.loadClass(className); - } catch (ClassNotFoundException e) { - throw new ArgeoException("Cannot load principal class", e); - } - } - - public Object getPrincipal() { - return getUser(); - } - - public Principal getUser() { - Subject subject = getSubject(); - Set userPrincipals = subject - .getPrincipals(osUserPrincipalClass); - if (userPrincipals == null || userPrincipals.size() == 0) - throw new ArgeoException("No OS principal"); - if (userPrincipals.size() > 1) - throw new ArgeoException("More than one OS principal"); - Principal user = userPrincipals.iterator().next(); - return user; - } - - public Principal getUserId() { - Subject subject = getSubject(); - Set userIdsPrincipals = subject - .getPrincipals(osUserIdPrincipalClass); - if (userIdsPrincipals == null || userIdsPrincipals.size() == 0) - throw new ArgeoException("No user id principal"); - if (userIdsPrincipals.size() > 1) - throw new ArgeoException("More than one user id principal"); - Principal userId = userIdsPrincipals.iterator().next(); - return userId; - } - - public Set getGroupsIds() { - Subject subject = getSubject(); - return (Set) subject - .getPrincipals(osGroupIdPrincipalClass); - } - - /** @return the subject always non null */ - protected Subject getSubject() { - Subject subject = Subject.getSubject(AccessController.getContext()); - if (subject == null) - throw new ArgeoException("No subject in JAAS context"); - return subject; - } - - public Object getCredentials() { - return ""; - } - -} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/SecurityUtils.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/SecurityUtils.java deleted file mode 100644 index e5b8ae79c..000000000 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/SecurityUtils.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import org.springframework.security.Authentication; -import org.springframework.security.GrantedAuthority; -import org.springframework.security.context.SecurityContext; -import org.springframework.security.context.SecurityContextHolder; -import org.springframework.security.providers.anonymous.AnonymousAuthenticationToken; - -/** Static utilities */ -public class SecurityUtils { - - private SecurityUtils() { - } - - /** Whether the current thread has the admin role */ - public static boolean hasCurrentThreadAuthority(String authority) { - SecurityContext securityContext = SecurityContextHolder.getContext(); - if (securityContext != null) { - Authentication authentication = securityContext.getAuthentication(); - if (authentication != null) { - for (GrantedAuthority ga : authentication.getAuthorities()) - if (ga.getAuthority().equals(authority)) - return true; - } - } - return false; - } - - /** - * @return the authenticated username or null if not authenticated / - * anonymous - */ - public static String getCurrentThreadUsername() { - SecurityContext securityContext = SecurityContextHolder.getContext(); - if (securityContext != null) { - Authentication authentication = securityContext.getAuthentication(); - if (authentication != null) { - if (authentication instanceof AnonymousAuthenticationToken) { - return null; - } - return authentication.getName(); - } - } - return null; - } - - /** - * Returns the display name of the user details (by calling toString() on - * it) - */ - public static String getUserDetailsDisplayName() { - SecurityContext securityContext = SecurityContextHolder.getContext(); - if (securityContext != null) { - Authentication authentication = securityContext.getAuthentication(); - if (authentication != null) { - if (authentication instanceof AnonymousAuthenticationToken) { - return null; - } - Object details = authentication.getDetails(); - if (details != null) - return details.toString(); - return authentication.getName(); - } - } - return null; - } - - /** - * Converts an array of Spring Security {@link GrantedAuthority} to a - * read-only list of strings, for portability and integration - */ - public static List authoritiesToStringList( - GrantedAuthority[] authorities) { - List lst = new ArrayList(); - for (GrantedAuthority ga : authorities) - lst.add(ga.getAuthority()); - return Collections.unmodifiableList(lst); - } -} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/SystemAuthentication.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/SystemAuthentication.java deleted file mode 100644 index 2722c1f7d..000000000 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/SystemAuthentication.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security; - -/** - * Marks a system authentication, that is which did not require a login process. - */ -public interface SystemAuthentication { - -} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/SystemExecutionService.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/SystemExecutionService.java deleted file mode 100644 index 075a6c3d8..000000000 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/SystemExecutionService.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security; - -import java.util.concurrent.Callable; -import java.util.concurrent.Executor; -import java.util.concurrent.Future; - -/** - * Allows to execute code authenticated as a system user (that is not a real - * person). The {@link Executor} interface is not used directly in order to - * allow future extension of this interface and to simplify its publication - * (e.g. as an OSGi service) and interception. - */ -public interface SystemExecutionService extends Executor { - /** - * Executes this {@link Runnable} within a system authenticated context. - * Implementations should make sure that this method is properly secured via - * Java permissions since it could access everything without credentials. - */ - public void execute(Runnable runnable); - - /** - * Executes this {@link Callable} within a system authenticated context. - * Implementations should make sure that this method is properly secured via - * Java permissions since it could access everything without credentials. - */ - public Future submit(Callable task); -} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/UserAdminService.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/UserAdminService.java deleted file mode 100644 index 0a84cf66f..000000000 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/UserAdminService.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security; - -import java.util.Set; - -import org.springframework.security.userdetails.UserDetailsManager; - -/** Enrich {@link UserDetailsManager} in order to provide roles semantics. */ -public interface UserAdminService extends UserDetailsManager { - /** - * Usernames must match this regexp pattern ({@value #USERNAME_PATTERN}). - * Thanks to this tip (modified to add upper-case, add '@') - */ - //public final static String USERNAME_PATTERN = "^[a-zA-Z0-9_-@]{3,64}$"; - - /** - * Email addresses must match this regexp pattern ({@value #EMAIL_PATTERN}. - * Thanks to this tip. - */ - public final static String EMAIL_PATTERN = "^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$"; - - /* - * USERS - */ - /** List all users. */ - public Set listUsers(); - - /** List users having this role (except the super user). */ - public Set listUsersInRole(String role); - - /** Synchronize with the underlying DAO. */ - public void synchronize(); - - /* - * ROLES - */ - public void newRole(String role); - - public Set listEditableRoles(); - - public void deleteRole(String role); -} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/AbstractSystemExecution.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/AbstractSystemExecution.java deleted file mode 100644 index b84f3de00..000000000 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/AbstractSystemExecution.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.core; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.ArgeoException; -import org.argeo.security.SystemAuthentication; -import org.springframework.security.Authentication; -import org.springframework.security.AuthenticationManager; -import org.springframework.security.context.SecurityContext; -import org.springframework.security.context.SecurityContextHolder; - -/** Provides base method for executing code with system authorization. */ -public abstract class AbstractSystemExecution { - static { - // Forces Spring Security to use inheritable strategy - // FIXME find a better place for forcing spring security mode - // doesn't work for the time being -// if (System.getProperty(SecurityContextHolder.SYSTEM_PROPERTY) == null) -// SecurityContextHolder -// .setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL); - } - - private final static Log log = LogFactory - .getLog(AbstractSystemExecution.class); - private AuthenticationManager authenticationManager; - private String systemAuthenticationKey; - - /** Whether the current thread was authenticated by this component. */ - private ThreadLocal authenticatedBySelf = new ThreadLocal() { - protected Boolean initialValue() { - return false; - } - }; - - /** - * Authenticate the calling thread to the underlying - * {@link AuthenticationManager} - */ - protected void authenticateAsSystem() { - if (authenticatedBySelf.get()) - return; - SecurityContext securityContext = SecurityContextHolder.getContext(); - Authentication currentAuth = securityContext.getAuthentication(); - if (currentAuth != null) { - if (!(currentAuth instanceof SystemAuthentication)) - throw new ArgeoException( - "System execution on an already authenticated thread: " - + currentAuth + ", THREAD=" - + Thread.currentThread().getId()); - return; - } - // Subject subject = Subject.getSubject(AccessController.getContext()); - // if (subject != null - // && !subject.getPrincipals(Authentication.class).isEmpty()) - // throw new ArgeoException( - // "There is already an authenticated subject: " + subject); - - String key = systemAuthenticationKey != null ? systemAuthenticationKey - : System.getProperty( - InternalAuthentication.SYSTEM_KEY_PROPERTY, - InternalAuthentication.SYSTEM_KEY_DEFAULT); - if (key == null) - throw new ArgeoException("No system key defined"); - Authentication auth = authenticationManager - .authenticate(new InternalAuthentication(key)); - securityContext.setAuthentication(auth); - authenticatedBySelf.set(true); - if (log.isTraceEnabled()) - log.trace("System authenticated"); - } - - // /** Removes the authentication from the calling thread. */ - // protected void deauthenticateAsSystem() { - // // remove the authentication - // // SecurityContext securityContext = SecurityContextHolder.getContext(); - // // securityContext.setAuthentication(null); - // // authenticatedBySelf.set(false); - // if (log.isTraceEnabled()) { - // log.trace("System deauthenticated"); - // // Thread.dumpStack(); - // } - // } - - /** - * Whether the current thread was authenticated by this component or a - * parent thread. - */ - protected Boolean isAuthenticatedBySelf() { - return authenticatedBySelf.get(); - } - - public void setAuthenticationManager( - AuthenticationManager authenticationManager) { - this.authenticationManager = authenticationManager; - } - - public void setSystemAuthenticationKey(String systemAuthenticationKey) { - this.systemAuthenticationKey = systemAuthenticationKey; - } - -} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/AsyncSystemTaskExecutor.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/AsyncSystemTaskExecutor.java deleted file mode 100644 index 0e400c82d..000000000 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/AsyncSystemTaskExecutor.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.core; - -import org.argeo.security.SystemExecutionService; -import org.springframework.core.task.SimpleAsyncTaskExecutor; - -/** - * Asynchronous Spring TaskExecutor (for use in JMS for example) wrapping a - * {@link SystemExecutionService}. - */ -public class AsyncSystemTaskExecutor extends SimpleAsyncTaskExecutor { - private static final long serialVersionUID = -8035527542087963068L; - - private SystemExecutionService systemExecutionService; - - public AsyncSystemTaskExecutor() { - super(); - } - - public AsyncSystemTaskExecutor(String threadNamePrefix) { - super(threadNamePrefix); - } - - @Override - public Thread createThread(final Runnable runnable) { - Runnable systemExecutionRunnable = new Runnable() { - - public void run() { - systemExecutionService.execute(runnable); - - } - }; - return super.createThread(systemExecutionRunnable); - } - - public void setSystemExecutionService( - SystemExecutionService systemExecutionService) { - this.systemExecutionService = systemExecutionService; - } - -} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/AuthenticatedApplicationContextInitialization.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/AuthenticatedApplicationContextInitialization.java deleted file mode 100644 index 97dd6cae0..000000000 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/AuthenticatedApplicationContextInitialization.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.core; - -import java.beans.PropertyDescriptor; -import java.util.ArrayList; -import java.util.List; - -import org.springframework.beans.BeansException; -import org.springframework.beans.PropertyValues; -import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor; -import org.springframework.context.ApplicationEvent; -import org.springframework.context.ApplicationListener; -import org.springframework.context.event.ContextRefreshedEvent; - -/** - * Executes with a system authentication the instantiation and initialization - * methods of the application context where it has been defined. - */ -public class AuthenticatedApplicationContextInitialization extends - AbstractSystemExecution implements InstantiationAwareBeanPostProcessor, - ApplicationListener { - // private Log log = LogFactory - // .getLog(AuthenticatedApplicationContextInitialization.class); - /** If non empty, restricts to these beans */ - private List beanNames = new ArrayList(); - - @SuppressWarnings("rawtypes") - public Object postProcessBeforeInstantiation(Class beanClass, - String beanName) throws BeansException { - // we authenticate when any bean is instantiated - // we will deauthenticate only when the application context has been - // refreshed in order to be able to deal with factory beans has well - if (!isAuthenticatedBySelf()) { - if (beanNames.size() == 0) - authenticateAsSystem(); - else if (beanNames.contains(beanName)) - authenticateAsSystem(); - } - return null; - } - - public boolean postProcessAfterInstantiation(Object bean, String beanName) - throws BeansException { - return true; - } - - public PropertyValues postProcessPropertyValues(PropertyValues pvs, - PropertyDescriptor[] pds, Object bean, String beanName) - throws BeansException { - return pvs; - } - - public Object postProcessBeforeInitialization(Object bean, String beanName) - throws BeansException { - // authenticateAsSystem(); - return bean; - } - - public Object postProcessAfterInitialization(Object bean, String beanName) - throws BeansException { - // NOTE: in case there was an exception in on the initialization method - // we expect the underlying thread to die and thus the system - // authentication to be lost. We have currently no way to catch the - // exception and perform the deauthentication by ourselves. - // deauthenticateAsSystem(); - return bean; - } - - public void onApplicationEvent(ApplicationEvent event) { - if (event instanceof ContextRefreshedEvent) { - // make sure that we have deauthenticated after the application - // context was initialized/refreshed - // deauthenticateAsSystem(); - } - } - - public void setBeanNames(List beanNames) { - this.beanNames = beanNames; - } - -} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/AuthenticationProvidersRegister.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/AuthenticationProvidersRegister.java deleted file mode 100644 index 317815e8b..000000000 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/AuthenticationProvidersRegister.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.core; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.beans.factory.InitializingBean; - -/** - * Maintains a list of authentication providers injected in to a provider - * manager, in order to avoid issues with OSGi services and use packages. - */ -public class AuthenticationProvidersRegister implements InitializingBean { - private Log log = LogFactory.getLog(AuthenticationProvidersRegister.class); - - private List providers = new ArrayList(); - private List defaultProviders = new ArrayList(); - - public void register(Object authenticationProvider, - Map parameters) { - providers.add(authenticationProvider); - if (log.isTraceEnabled()) - log.trace("Registered authentication provider " + parameters); - } - - public void unregister(Object authenticationProvider, - Map parameters) { - providers.remove(authenticationProvider); - if (log.isTraceEnabled()) - log.trace("Unregistered authentication provider " + parameters); - } - - public List getProviders() { - return providers; - } - - public void setDefaultProviders( - List defaultProviders) { - this.defaultProviders = defaultProviders; - } - - public void afterPropertiesSet() throws Exception { - providers.addAll(defaultProviders); - } - -} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/ConsoleCallbackHandler.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/ConsoleCallbackHandler.java deleted file mode 100644 index faa81b004..000000000 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/ConsoleCallbackHandler.java +++ /dev/null @@ -1,70 +0,0 @@ -package org.argeo.security.core; - -import java.io.Console; -import java.io.IOException; -import java.io.PrintWriter; -import java.util.Arrays; -import java.util.Locale; - -import javax.security.auth.callback.Callback; -import javax.security.auth.callback.CallbackHandler; -import javax.security.auth.callback.NameCallback; -import javax.security.auth.callback.PasswordCallback; -import javax.security.auth.callback.TextOutputCallback; -import javax.security.auth.callback.UnsupportedCallbackException; - -import org.argeo.ArgeoException; -import org.argeo.util.LocaleCallback; - -/** Callback handler to be used with a command line UI. */ -public class ConsoleCallbackHandler implements CallbackHandler { - - @Override - public void handle(Callback[] callbacks) throws IOException, - UnsupportedCallbackException { - Console console = System.console(); - if (console == null) - throw new ArgeoException("No console available"); - - PrintWriter writer = console.writer(); - for (int i = 0; i < callbacks.length; i++) { - if (callbacks[i] instanceof TextOutputCallback) { - TextOutputCallback callback = (TextOutputCallback) callbacks[i]; - writer.write(callback.getMessage()); - } else if (callbacks[i] instanceof NameCallback) { - NameCallback callback = (NameCallback) callbacks[i]; - writer.write(callback.getPrompt()); - if (callback.getDefaultName() != null) - writer.write(" (" + callback.getDefaultName() + ")"); - writer.write(" : "); - String answer = console.readLine(); - if (callback.getDefaultName() != null - && answer.trim().equals("")) - callback.setName(callback.getDefaultName()); - else - callback.setName(answer); - } else if (callbacks[i] instanceof PasswordCallback) { - PasswordCallback callback = (PasswordCallback) callbacks[i]; - writer.write(callback.getPrompt()); - char[] answer = console.readPassword(); - callback.setPassword(answer); - Arrays.fill(answer, ' '); - } else if (callbacks[i] instanceof LocaleCallback) { - LocaleCallback callback = (LocaleCallback) callbacks[i]; - writer.write(callback.getPrompt()); - writer.write("\n"); - for (int j = 0; j < callback.getAvailableLocales().size(); j++) { - Locale locale = callback.getAvailableLocales().get(j); - writer.print(j + " : " + locale.getDisplayName() + "\n"); - } - writer.write("(" + callback.getDefaultIndex() + ") : "); - String answer = console.readLine(); - if (answer.trim().equals("")) - callback.setSelectedIndex(callback.getDefaultIndex()); - else - callback.setSelectedIndex(new Integer(answer.trim())); - } - } - } - -} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/InternalAuthentication.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/InternalAuthentication.java deleted file mode 100644 index 267ddd312..000000000 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/InternalAuthentication.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.core; - -import org.argeo.security.SystemAuthentication; -import org.springframework.security.GrantedAuthority; -import org.springframework.security.GrantedAuthorityImpl; -import org.springframework.security.adapters.PrincipalSpringSecurityUserToken; - -/** A token base on a system key used to request a system authentication. */ -public class InternalAuthentication extends PrincipalSpringSecurityUserToken - implements SystemAuthentication { - private static final long serialVersionUID = -6783376375615949315L; - /** 'admin' for consistency with JCR */ - public final static String DEFAULT_SYSTEM_USERNAME = "admin"; - public final static String DEFAULT_SYSTEM_ROLE = "ROLE_SYSTEM"; - public final static String SYSTEM_KEY_PROPERTY = "argeo.security.systemKey"; - public final static String SYSTEM_KEY_DEFAULT = "argeo"; - - public InternalAuthentication(String key, String systemUsername, - String systemRole) { - super( - key, - systemUsername, - key, - new GrantedAuthority[] { new GrantedAuthorityImpl(systemRole) }, - systemUsername); - } - - public InternalAuthentication(String key) { - this(key, DEFAULT_SYSTEM_USERNAME, DEFAULT_SYSTEM_ROLE); - } - -} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/KeyBasedSystemExecutionService.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/KeyBasedSystemExecutionService.java deleted file mode 100644 index 6c85df1d1..000000000 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/KeyBasedSystemExecutionService.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.core; - -import java.util.concurrent.Callable; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.FutureTask; - -import org.argeo.ArgeoException; -import org.argeo.security.SystemExecutionService; - -/** - * Implementation of a {@link SystemExecutionService} using a key-based - * {@link InternalAuthentication} - */ -public class KeyBasedSystemExecutionService extends AbstractSystemExecution - implements SystemExecutionService { - public void execute(Runnable runnable) { - try { - wrapWithSystemAuthentication(Executors.callable(runnable)).call(); - } catch (RuntimeException e) { - throw e; - } catch (Exception e) { - throw new ArgeoException( - "Exception when running system authenticated task", e); - } - } - - public Future submit(Callable task) { - FutureTask future = new FutureTask( - wrapWithSystemAuthentication(task)); - future.run(); - return future; - } - - protected Callable wrapWithSystemAuthentication( - final Callable runnable) { - return new Callable() { - - public T call() throws Exception { - authenticateAsSystem(); - try { - return runnable.call(); - } finally { -// deauthenticateAsSystem(); - } - } - }; - } -} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/MatchingAuthenticationProvider.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/MatchingAuthenticationProvider.java deleted file mode 100644 index 0471151a2..000000000 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/MatchingAuthenticationProvider.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.core; - -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; -import java.util.Properties; - -import org.springframework.core.io.Resource; -import org.springframework.security.AuthenticationException; -import org.springframework.security.BadCredentialsException; -import org.springframework.security.GrantedAuthority; -import org.springframework.security.GrantedAuthorityImpl; -import org.springframework.security.providers.UsernamePasswordAuthenticationToken; -import org.springframework.security.providers.dao.AbstractUserDetailsAuthenticationProvider; -import org.springframework.security.userdetails.User; -import org.springframework.security.userdetails.UserDetails; - -/** @deprecated */ -@Deprecated -public class MatchingAuthenticationProvider extends - AbstractUserDetailsAuthenticationProvider { - - private Resource mapping; - private Properties properties; - - private List defaultRoles = new ArrayList(); - - @Override - protected void doAfterPropertiesSet() throws Exception { - properties = new Properties(); - InputStream propIn = mapping.getInputStream(); - try { - properties.load(propIn); - } finally { - propIn.close(); - } - } - - @Override - protected void additionalAuthenticationChecks(UserDetails userDetails, - UsernamePasswordAuthenticationToken authentication) - throws AuthenticationException { - if (!userDetails.getPassword().equals(authentication.getCredentials())) - throw new BadCredentialsException( - "Invalid credentails provided by " - + authentication.getName()); - } - - @Override - protected UserDetails retrieveUser(String username, - UsernamePasswordAuthenticationToken authentication) - throws AuthenticationException { - String value = properties.getProperty(username); - if (value == null) - throw new BadCredentialsException("User " + username - + " is not registered"); - List grantedAuthorities = new ArrayList(); - for (String role : defaultRoles) - grantedAuthorities.add(new GrantedAuthorityImpl(role)); - return new User( - username, - value, - true, - true, - true, - true, - grantedAuthorities - .toArray(new GrantedAuthority[grantedAuthorities.size()])); - } - - public void setMapping(Resource mapping) { - this.mapping = mapping; - } - - public void setDefaultRoles(List defaultRoles) { - this.defaultRoles = defaultRoles; - } - -} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/OsAuthenticationProvider.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/OsAuthenticationProvider.java deleted file mode 100644 index 0e29ecd59..000000000 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/OsAuthenticationProvider.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.core; - -import java.util.ArrayList; -import java.util.List; - -import org.argeo.security.OsAuthenticationToken; -import org.springframework.security.Authentication; -import org.springframework.security.AuthenticationException; -import org.springframework.security.GrantedAuthority; -import org.springframework.security.GrantedAuthorityImpl; -import org.springframework.security.providers.AuthenticationProvider; - -/** - * Validates an OS authentication. The id is that it will always be - * authenticated since we are always runnign within an OS, but the fact that the - * {@link Authentication} works properly depends on the proper OS login module - * having been called as well. TODO make it more configurable (base roles, is - * admin) - */ -public class OsAuthenticationProvider implements AuthenticationProvider { - final static String osUserRole = "ROLE_OS_USER"; - final static String userRole = "ROLE_USER"; - final static String adminRole = "ROLE_ADMIN"; - - final static Boolean isAdmin = true; - - public Authentication authenticate(Authentication authentication) - throws AuthenticationException { - return new OsAuthenticationToken(getBaseAuthorities()); - } - - public static GrantedAuthority[] getBaseAuthorities() { - List auths = new ArrayList(); - auths.add(new GrantedAuthorityImpl(osUserRole)); - auths.add(new GrantedAuthorityImpl(userRole)); - if (isAdmin) - auths.add(new GrantedAuthorityImpl(adminRole)); - return auths.toArray(new GrantedAuthority[auths.size()]); - } - - @SuppressWarnings("rawtypes") - public boolean supports(Class authentication) { - return OsAuthenticationToken.class.isAssignableFrom(authentication); - } - -} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/OsgiModuleLabel.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/OsgiModuleLabel.java deleted file mode 100644 index 45c9e16b0..000000000 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/OsgiModuleLabel.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.argeo.security.core; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.osgi.framework.Bundle; -import org.osgi.framework.BundleContext; -import org.osgi.framework.Constants; - -/** - * Logs the name and version of an OSGi bundle based on its - * {@link BundleContext}. - */ -public class OsgiModuleLabel { - private final static Log log = LogFactory.getLog(OsgiModuleLabel.class); - - private Bundle bundle; - - public OsgiModuleLabel() { - } - - /** Sets without logging. */ - public OsgiModuleLabel(Bundle bundle) { - this.bundle = bundle; - } - - /** - * Retrieved bundle from a bundle context and logs it. Typically to be set - * as a Spring bean. - */ - public void setBundleContext(BundleContext bundleContext) { - this.bundle = bundleContext.getBundle(); - log.info(msg()); - } - - public String msg() { - String name = bundle.getHeaders().get(Constants.BUNDLE_NAME).toString(); - String symbolicName = bundle.getSymbolicName(); - String version = bundle.getVersion().toString(); - return name + " v" + version + " (" + symbolicName + ")"; - } -} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/SimpleRoleRegistration.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/SimpleRoleRegistration.java deleted file mode 100644 index aa8a5f06e..000000000 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/SimpleRoleRegistration.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.argeo.security.core; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.security.UserAdminService; - -/** - * Register one or many roles via a user admin service. Does nothing if the role - * is already registered. - */ -public class SimpleRoleRegistration implements Runnable { - private final static Log log = LogFactory - .getLog(SimpleRoleRegistration.class); - - private String role; - private List roles = new ArrayList(); - private UserAdminService userAdminService; - - @Override - public void run() { - Set existingRoles = userAdminService.listEditableRoles(); - if (role != null && !existingRoles.contains(role)) - newRole(role); - for (String r : roles) { - if (!existingRoles.contains(r)) - newRole(r); - } - } - - protected void newRole(String r) { - userAdminService.newRole(r); - log.info("Added role " + r + " required by application."); - } - - public void register(UserAdminService userAdminService, Map properties) { - this.userAdminService = userAdminService; - run(); - } - - public void setRole(String role) { - this.role = role; - } - - public void setRoles(List roles) { - this.roles = roles; - } - - public void setUserAdminService(UserAdminService userAdminService) { - this.userAdminService = userAdminService; - } - -} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/crypto/AbstractKeyring.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/crypto/AbstractKeyring.java deleted file mode 100644 index daa1ebd12..000000000 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/crypto/AbstractKeyring.java +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.crypto; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.CharArrayWriter; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.Reader; -import java.io.Writer; -import java.security.AccessController; -import java.security.MessageDigest; -import java.security.Provider; -import java.security.Security; -import java.util.Arrays; -import java.util.Iterator; - -import javax.crypto.SecretKey; -import javax.security.auth.Subject; -import javax.security.auth.callback.Callback; -import javax.security.auth.callback.CallbackHandler; -import javax.security.auth.callback.PasswordCallback; -import javax.security.auth.callback.TextOutputCallback; -import javax.security.auth.callback.UnsupportedCallbackException; -import javax.security.auth.login.LoginContext; -import javax.security.auth.login.LoginException; - -import org.argeo.ArgeoException; -import org.argeo.StreamUtils; -import org.argeo.util.security.Keyring; -import org.bouncycastle.jce.provider.BouncyCastleProvider; - -/** username / password based keyring. TODO internationalize */ -public abstract class AbstractKeyring implements Keyring, CryptoKeyring { - static { - Security.addProvider(new BouncyCastleProvider()); - } - - public final static String DEFAULT_KEYRING_LOGIN_CONTEXT = "KEYRING"; - - private String loginContextName = DEFAULT_KEYRING_LOGIN_CONTEXT; - private CallbackHandler defaultCallbackHandler; - - private String charset = "UTF-8"; - - /** - * Default provider is bouncy castle, in order to have consistent behaviour - * across implementations - */ - private String securityProviderName = "BC"; - - /** - * Whether the keyring has already been created in the past with a master - * password - */ - protected abstract Boolean isSetup(); - - /** - * Setup the keyring persistently, {@link #isSetup()} must return true - * afterwards - */ - protected abstract void setup(char[] password); - - /** Populates the key spec callback */ - protected abstract void handleKeySpecCallback(PBEKeySpecCallback pbeCallback); - - protected abstract void encrypt(String path, InputStream unencrypted); - - protected abstract InputStream decrypt(String path); - - /** Triggers lazy initialization */ - protected SecretKey getSecretKey() { - Subject subject = Subject.getSubject(AccessController.getContext()); - // we assume only one secrete key is available - Iterator iterator = subject.getPrivateCredentials( - SecretKey.class).iterator(); - if (!iterator.hasNext()) {// not initialized - CallbackHandler callbackHandler = new KeyringCallbackHandler(); - try { - LoginContext loginContext = new LoginContext(loginContextName, - subject, callbackHandler); - loginContext.login(); - // FIXME will login even if password is wrong - iterator = subject.getPrivateCredentials(SecretKey.class) - .iterator(); - return iterator.next(); - } catch (LoginException e) { - throw new ArgeoException("Keyring login failed", e); - } - - } else { - SecretKey secretKey = iterator.next(); - if (iterator.hasNext()) - throw new ArgeoException( - "More than one secret key in private credentials"); - return secretKey; - } - } - - public InputStream getAsStream(String path) { - return decrypt(path); - } - - public void set(String path, InputStream in) { - encrypt(path, in); - } - - public char[] getAsChars(String path) { - InputStream in = getAsStream(path); - CharArrayWriter writer = null; - Reader reader = null; - try { - writer = new CharArrayWriter(); - reader = new InputStreamReader(in, charset); - StreamUtils.copy(reader, writer); - return writer.toCharArray(); - } catch (IOException e) { - throw new ArgeoException("Cannot decrypt to char array", e); - } finally { - StreamUtils.closeQuietly(reader); - StreamUtils.closeQuietly(in); - StreamUtils.closeQuietly(writer); - } - } - - public void set(String path, char[] arr) { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - ByteArrayInputStream in = null; - Writer writer = null; - try { - writer = new OutputStreamWriter(out, charset); - writer.write(arr); - writer.flush(); - in = new ByteArrayInputStream(out.toByteArray()); - set(path, in); - } catch (IOException e) { - throw new ArgeoException("Cannot encrypt to char array", e); - } finally { - StreamUtils.closeQuietly(writer); - StreamUtils.closeQuietly(out); - StreamUtils.closeQuietly(in); - } - } - - protected Provider getSecurityProvider() { - return Security.getProvider(securityProviderName); - } - - public void setLoginContextName(String loginContextName) { - this.loginContextName = loginContextName; - } - - public void setDefaultCallbackHandler(CallbackHandler defaultCallbackHandler) { - this.defaultCallbackHandler = defaultCallbackHandler; - } - - public void setCharset(String charset) { - this.charset = charset; - } - - public void setSecurityProviderName(String securityProviderName) { - this.securityProviderName = securityProviderName; - } - - @Deprecated - protected static byte[] hash(char[] password, byte[] salt, - Integer iterationCount) { - ByteArrayOutputStream out = null; - OutputStreamWriter writer = null; - try { - out = new ByteArrayOutputStream(); - writer = new OutputStreamWriter(out, "UTF-8"); - writer.write(password); - MessageDigest pwDigest = MessageDigest.getInstance("SHA-256"); - pwDigest.reset(); - pwDigest.update(salt); - byte[] btPass = pwDigest.digest(out.toByteArray()); - for (int i = 0; i < iterationCount; i++) { - pwDigest.reset(); - btPass = pwDigest.digest(btPass); - } - return btPass; - } catch (Exception e) { - throw new ArgeoException("Cannot hash", e); - } finally { - StreamUtils.closeQuietly(out); - StreamUtils.closeQuietly(writer); - } - - } - - /** - * Convenience method using the underlying callback to ask for a password - * (typically used when the password is not saved in the keyring) - */ - protected char[] ask() { - PasswordCallback passwordCb = new PasswordCallback("Password", false); - Callback[] dialogCbs = new Callback[] { passwordCb }; - try { - defaultCallbackHandler.handle(dialogCbs); - char[] password = passwordCb.getPassword(); - return password; - } catch (Exception e) { - throw new ArgeoException("Cannot ask for a password", e); - } - - } - - class KeyringCallbackHandler implements CallbackHandler { - public void handle(Callback[] callbacks) throws IOException, - UnsupportedCallbackException { - // checks - if (callbacks.length != 2) - throw new IllegalArgumentException( - "Keyring required 2 and only 2 callbacks: {PasswordCallback,PBEKeySpecCallback}"); - if (!(callbacks[0] instanceof PasswordCallback)) - throw new UnsupportedCallbackException(callbacks[0]); - if (!(callbacks[1] instanceof PBEKeySpecCallback)) - throw new UnsupportedCallbackException(callbacks[0]); - - PasswordCallback passwordCb = (PasswordCallback) callbacks[0]; - PBEKeySpecCallback pbeCb = (PBEKeySpecCallback) callbacks[1]; - - if (isSetup()) { - Callback[] dialogCbs = new Callback[] { passwordCb }; - defaultCallbackHandler.handle(dialogCbs); - } else {// setup keyring - TextOutputCallback textCb1 = new TextOutputCallback( - TextOutputCallback.INFORMATION, - "Enter a master password which will protect your private data"); - TextOutputCallback textCb2 = new TextOutputCallback( - TextOutputCallback.INFORMATION, - "(for example your credentials to third-party services)"); - TextOutputCallback textCb3 = new TextOutputCallback( - TextOutputCallback.INFORMATION, - "Don't forget this password since the data cannot be read without it"); - PasswordCallback confirmPasswordCb = new PasswordCallback( - "Confirm password", false); - // first try - Callback[] dialogCbs = new Callback[] { textCb1, textCb2, - textCb3, passwordCb, confirmPasswordCb }; - defaultCallbackHandler.handle(dialogCbs); - - // if passwords different, retry (except if cancelled) - while (passwordCb.getPassword() != null - && !Arrays.equals(passwordCb.getPassword(), - confirmPasswordCb.getPassword())) { - TextOutputCallback textCb = new TextOutputCallback( - TextOutputCallback.ERROR, - "The passwords do not match"); - dialogCbs = new Callback[] { textCb, passwordCb, - confirmPasswordCb }; - defaultCallbackHandler.handle(dialogCbs); - } - - if (passwordCb.getPassword() != null) {// not cancelled - setup(passwordCb.getPassword()); - } - } - - if (passwordCb.getPassword() != null) - handleKeySpecCallback(pbeCb); - } - - } -} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/crypto/CryptoKeyring.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/crypto/CryptoKeyring.java deleted file mode 100644 index d25eccd22..000000000 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/crypto/CryptoKeyring.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.crypto; - -import org.argeo.util.security.Keyring; - -/** - * Advanced keyring based on cryptography that can easily be centralized and - * coordinated with {@link KeyringLoginModule} (since they ar ein the same - * package) - */ -public interface CryptoKeyring extends Keyring { - -} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/crypto/KeyringLoginModule.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/crypto/KeyringLoginModule.java deleted file mode 100644 index 34b7d4015..000000000 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/crypto/KeyringLoginModule.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.crypto; - -import java.security.AccessController; -import java.util.Map; -import java.util.Set; - -import javax.crypto.SecretKey; -import javax.crypto.SecretKeyFactory; -import javax.crypto.spec.PBEKeySpec; -import javax.crypto.spec.SecretKeySpec; -import javax.security.auth.Subject; -import javax.security.auth.callback.Callback; -import javax.security.auth.callback.CallbackHandler; -import javax.security.auth.callback.PasswordCallback; -import javax.security.auth.login.LoginException; -import javax.security.auth.spi.LoginModule; - -/** Adds a secret key to the private credentials */ -public class KeyringLoginModule implements LoginModule { - private Subject subject; - private CallbackHandler callbackHandler; - private SecretKey secretKey; - - public void initialize(Subject subject, CallbackHandler callbackHandler, - Map sharedState, Map options) { - this.subject = subject; - if (subject == null) { - subject = Subject.getSubject(AccessController.getContext()); - } - this.callbackHandler = callbackHandler; - } - - public boolean login() throws LoginException { - Set pbes = subject.getPrivateCredentials(SecretKey.class); - if (pbes.size() > 0) - return true; - PasswordCallback pc = new PasswordCallback("Master password", false); - PBEKeySpecCallback pbeCb = new PBEKeySpecCallback(); - Callback[] callbacks = { pc, pbeCb }; - try { - callbackHandler.handle(callbacks); - char[] password = pc.getPassword(); - - SecretKeyFactory keyFac = SecretKeyFactory.getInstance(pbeCb - .getSecretKeyFactory()); - PBEKeySpec keySpec; - if (pbeCb.getKeyLength() != null) - keySpec = new PBEKeySpec(password, pbeCb.getSalt(), - pbeCb.getIterationCount(), pbeCb.getKeyLength()); - else - keySpec = new PBEKeySpec(password, pbeCb.getSalt(), - pbeCb.getIterationCount()); - - String secKeyEncryption = pbeCb.getSecretKeyEncryption(); - if (secKeyEncryption != null) { - SecretKey tmp = keyFac.generateSecret(keySpec); - secretKey = new SecretKeySpec(tmp.getEncoded(), - secKeyEncryption); - } else { - secretKey = keyFac.generateSecret(keySpec); - } - } catch (Exception e) { - LoginException le = new LoginException("Cannot login keyring"); - le.initCause(e); - throw le; - } - return true; - } - - public boolean commit() throws LoginException { - if (secretKey != null) - subject.getPrivateCredentials().add(secretKey); - return true; - } - - public boolean abort() throws LoginException { - return true; - } - - public boolean logout() throws LoginException { - Set pbes = subject - .getPrivateCredentials(PasswordBasedEncryption.class); - pbes.clear(); - return true; - } - -} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/crypto/PBEKeySpecCallback.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/crypto/PBEKeySpecCallback.java deleted file mode 100644 index e96436664..000000000 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/crypto/PBEKeySpecCallback.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.crypto; - -import javax.crypto.spec.PBEKeySpec; -import javax.security.auth.callback.Callback; -import javax.security.auth.callback.PasswordCallback; - -/** - * All information required to set up a {@link PBEKeySpec} bar the password - * itself (use a {@link PasswordCallback}) - */ -public class PBEKeySpecCallback implements Callback { - private String secretKeyFactory; - private byte[] salt; - private Integer iterationCount; - /** Can be null for some algorithms */ - private Integer keyLength; - /** Can be null, will trigger secret key encryption if not */ - private String secretKeyEncryption; - - private String encryptedPasswordHashCipher; - private byte[] encryptedPasswordHash; - - public void set(String secretKeyFactory, byte[] salt, - Integer iterationCount, Integer keyLength, - String secretKeyEncryption) { - this.secretKeyFactory = secretKeyFactory; - this.salt = salt; - this.iterationCount = iterationCount; - this.keyLength = keyLength; - this.secretKeyEncryption = secretKeyEncryption; -// this.encryptedPasswordHashCipher = encryptedPasswordHashCipher; -// this.encryptedPasswordHash = encryptedPasswordHash; - } - - public String getSecretKeyFactory() { - return secretKeyFactory; - } - - public byte[] getSalt() { - return salt; - } - - public Integer getIterationCount() { - return iterationCount; - } - - public Integer getKeyLength() { - return keyLength; - } - - public String getSecretKeyEncryption() { - return secretKeyEncryption; - } - - public String getEncryptedPasswordHashCipher() { - return encryptedPasswordHashCipher; - } - - public byte[] getEncryptedPasswordHash() { - return encryptedPasswordHash; - } - -} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/crypto/PasswordBasedEncryption.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/crypto/PasswordBasedEncryption.java deleted file mode 100644 index aec25ac17..000000000 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/crypto/PasswordBasedEncryption.java +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.crypto; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.security.GeneralSecurityException; -import java.security.InvalidKeyException; -import java.security.Key; -import java.security.Security; - -import javax.crypto.Cipher; -import javax.crypto.CipherInputStream; -import javax.crypto.CipherOutputStream; -import javax.crypto.SecretKey; -import javax.crypto.SecretKeyFactory; -import javax.crypto.spec.IvParameterSpec; -import javax.crypto.spec.PBEKeySpec; -import javax.crypto.spec.SecretKeySpec; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.ArgeoException; -import org.argeo.StreamUtils; -import org.bouncycastle.jce.provider.BouncyCastleProvider; - -/** Simple password based encryption / decryption */ -public class PasswordBasedEncryption { - private final static Log log = LogFactory - .getLog(PasswordBasedEncryption.class); - - static { - Security.addProvider(new BouncyCastleProvider()); - } - - public final static Integer DEFAULT_ITERATION_COUNT = 1024; - /** Stronger with 256, but causes problem with Oracle JVM */ - public final static Integer DEFAULT_SECRETE_KEY_LENGTH = 256; - public final static Integer DEFAULT_SECRETE_KEY_LENGTH_RESTRICTED = 128; - public final static String DEFAULT_SECRETE_KEY_FACTORY = "PBKDF2WithHmacSHA1"; - public final static String DEFAULT_SECRETE_KEY_ENCRYPTION = "AES"; - public final static String DEFAULT_CIPHER_NAME = "AES/CBC/PKCS5Padding"; - public final static String DEFAULT_CHARSET = "UTF-8"; - - private Integer iterationCount = DEFAULT_ITERATION_COUNT; - private Integer secreteKeyLength = DEFAULT_SECRETE_KEY_LENGTH; - private String secreteKeyFactoryName = DEFAULT_SECRETE_KEY_FACTORY; - private String secreteKeyEncryption = DEFAULT_SECRETE_KEY_ENCRYPTION; - private String cipherName = DEFAULT_CIPHER_NAME; - - private static byte[] DEFAULT_SALT_8 = { (byte) 0xA9, (byte) 0x9B, - (byte) 0xC8, (byte) 0x32, (byte) 0x56, (byte) 0x35, (byte) 0xE3, - (byte) 0x03 }; - private static byte[] DEFAULT_IV_16 = { (byte) 0xA9, (byte) 0x9B, - (byte) 0xC8, (byte) 0x32, (byte) 0x56, (byte) 0x35, (byte) 0xE3, - (byte) 0x03, (byte) 0xA9, (byte) 0x9B, (byte) 0xC8, (byte) 0x32, - (byte) 0x56, (byte) 0x35, (byte) 0xE3, (byte) 0x03 }; - - private Key key; - private Cipher ecipher; - private Cipher dcipher; - - /** - * Default provider is bouncy castle, in order to have consistent behaviour - * across implementations - */ - private String securityProviderName = "BC"; - - /** - * This is up to the caller to clear the passed array. Neither copy of nor - * reference to the passed array is kept - */ - public PasswordBasedEncryption(char[] password) { - this(password, DEFAULT_SALT_8, DEFAULT_IV_16); - } - - /** - * This is up to the caller to clear the passed array. Neither copies of nor - * references to the passed arrays are kept - */ - public PasswordBasedEncryption(char[] password, byte[] passwordSalt, - byte[] initializationVector) { - try { - initKeyAndCiphers(password, passwordSalt, initializationVector); - } catch (InvalidKeyException e) { - Integer previousSecreteKeyLength = secreteKeyLength; - secreteKeyLength = DEFAULT_SECRETE_KEY_LENGTH_RESTRICTED; - log.warn("'" + e.getMessage() + "', will use " + secreteKeyLength - + " secrete key length instead of " - + previousSecreteKeyLength); - try { - initKeyAndCiphers(password, passwordSalt, initializationVector); - } catch (Exception e1) { - throw new ArgeoException( - "Cannot get secret key (with restricted length)", e1); - } - } catch (Exception e) { - throw new ArgeoException("Cannot get secret key", e); - } - } - - protected void initKeyAndCiphers(char[] password, byte[] passwordSalt, - byte[] initializationVector) throws GeneralSecurityException { - byte[] salt = new byte[8]; - System.arraycopy(passwordSalt, 0, salt, 0, salt.length); - // for (int i = 0; i < password.length && i < salt.length; i++) - // salt[i] = (byte) password[i]; - byte[] iv = new byte[16]; - System.arraycopy(initializationVector, 0, iv, 0, iv.length); - - SecretKeyFactory keyFac = SecretKeyFactory - .getInstance(getSecretKeyFactoryName()); - PBEKeySpec keySpec = new PBEKeySpec(password, salt, - getIterationCount(), getKeyLength()); - String secKeyEncryption = getSecretKeyEncryption(); - if (secKeyEncryption != null) { - SecretKey tmp = keyFac.generateSecret(keySpec); - key = new SecretKeySpec(tmp.getEncoded(), getSecretKeyEncryption()); - } else { - key = keyFac.generateSecret(keySpec); - } - ecipher = Cipher.getInstance(getCipherName(), securityProviderName); - ecipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv)); - dcipher = Cipher.getInstance(getCipherName()); - dcipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv)); - } - - public void encrypt(InputStream decryptedIn, OutputStream encryptedOut) - throws IOException { - try { - CipherOutputStream out = new CipherOutputStream(encryptedOut, - ecipher); - StreamUtils.copy(decryptedIn, out); - StreamUtils.closeQuietly(out); - } catch (IOException e) { - throw e; - } catch (Exception e) { - throw new ArgeoException("Cannot encrypt", e); - } finally { - StreamUtils.closeQuietly(decryptedIn); - } - } - - public void decrypt(InputStream encryptedIn, OutputStream decryptedOut) - throws IOException { - try { - CipherInputStream decryptedIn = new CipherInputStream(encryptedIn, - dcipher); - StreamUtils.copy(decryptedIn, decryptedOut); - } catch (IOException e) { - throw e; - } catch (Exception e) { - throw new ArgeoException("Cannot decrypt", e); - } finally { - StreamUtils.closeQuietly(encryptedIn); - } - } - - public byte[] encryptString(String str) { - ByteArrayOutputStream out = null; - ByteArrayInputStream in = null; - try { - out = new ByteArrayOutputStream(); - in = new ByteArrayInputStream(str.getBytes(DEFAULT_CHARSET)); - encrypt(in, out); - return out.toByteArray(); - } catch (Exception e) { - throw new ArgeoException("Cannot encrypt", e); - } finally { - StreamUtils.closeQuietly(out); - } - } - - /** Closes the input stream */ - public String decryptAsString(InputStream in) { - ByteArrayOutputStream out = null; - try { - out = new ByteArrayOutputStream(); - decrypt(in, out); - return new String(out.toByteArray(), DEFAULT_CHARSET); - } catch (Exception e) { - throw new ArgeoException("Cannot decrypt", e); - } finally { - StreamUtils.closeQuietly(out); - } - } - - protected Key getKey() { - return key; - } - - protected Cipher getEcipher() { - return ecipher; - } - - protected Cipher getDcipher() { - return dcipher; - } - - protected Integer getIterationCount() { - return iterationCount; - } - - protected Integer getKeyLength() { - return secreteKeyLength; - } - - protected String getSecretKeyFactoryName() { - return secreteKeyFactoryName; - } - - protected String getSecretKeyEncryption() { - return secreteKeyEncryption; - } - - protected String getCipherName() { - return cipherName; - } - - public void setIterationCount(Integer iterationCount) { - this.iterationCount = iterationCount; - } - - public void setSecreteKeyLength(Integer keyLength) { - this.secreteKeyLength = keyLength; - } - - public void setSecreteKeyFactoryName(String secreteKeyFactoryName) { - this.secreteKeyFactoryName = secreteKeyFactoryName; - } - - public void setSecreteKeyEncryption(String secreteKeyEncryption) { - this.secreteKeyEncryption = secreteKeyEncryption; - } - - public void setCipherName(String cipherName) { - this.cipherName = cipherName; - } - - public void setSecurityProviderName(String securityProviderName) { - this.securityProviderName = securityProviderName; - } -} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/JcrKeyring.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/JcrKeyring.java deleted file mode 100644 index 1b9f24426..000000000 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/JcrKeyring.java +++ /dev/null @@ -1,294 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.jcr; - -import java.io.ByteArrayInputStream; -import java.io.CharArrayReader; -import java.io.InputStream; -import java.io.Reader; -import java.security.SecureRandom; - -import javax.crypto.Cipher; -import javax.crypto.CipherInputStream; -import javax.crypto.SecretKey; -import javax.crypto.spec.IvParameterSpec; -import javax.jcr.Binary; -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.apache.commons.io.IOUtils; -import org.argeo.ArgeoException; -import org.argeo.jcr.ArgeoNames; -import org.argeo.jcr.ArgeoTypes; -import org.argeo.jcr.JcrUtils; -import org.argeo.jcr.UserJcrUtils; -import org.argeo.security.crypto.AbstractKeyring; -import org.argeo.security.crypto.PBEKeySpecCallback; - -/** JCR based implementation of a keyring */ -public class JcrKeyring extends AbstractKeyring implements ArgeoNames { - /** - * Stronger with 256, but causes problem with Oracle JVM, force 128 in this - * case - */ - public final static Long DEFAULT_SECRETE_KEY_LENGTH = 256l; - public final static String DEFAULT_SECRETE_KEY_FACTORY = "PBKDF2WithHmacSHA1"; - public final static String DEFAULT_SECRETE_KEY_ENCRYPTION = "AES"; - public final static String DEFAULT_CIPHER_NAME = "AES/CBC/PKCS5Padding"; - - private Integer iterationCountFactor = 200; - private Long secreteKeyLength = DEFAULT_SECRETE_KEY_LENGTH; - private String secreteKeyFactoryName = DEFAULT_SECRETE_KEY_FACTORY; - private String secreteKeyEncryption = DEFAULT_SECRETE_KEY_ENCRYPTION; - private String cipherName = DEFAULT_CIPHER_NAME; - - private Session session; - - /** - * When setup is called the session has not yet been saved and we don't want - * to save it since there maybe other data which would be inconsistent. So - * we keep a reference to this node which will then be used (an reset to - * null) when handling the PBE callback. We keep one per thread in case - * multiple users are accessing the same instance of a keyring. - */ - private ThreadLocal notYetSavedKeyring = new ThreadLocal() { - - @Override - protected Node initialValue() { - return null; - } - }; - - @Override - protected Boolean isSetup() { - try { - if (notYetSavedKeyring.get() != null) - return true; - - Node userHome = UserJcrUtils.getUserHome(session); - return userHome.hasNode(ARGEO_KEYRING); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot check whether keyring is setup", e); - } - } - - @Override - protected void setup(char[] password) { - Binary binary = null; - InputStream in = null; - try { - Node userHome = UserJcrUtils.getUserHome(session); - if (userHome.hasNode(ARGEO_KEYRING)) - throw new ArgeoException("Keyring already setup"); - Node keyring = userHome.addNode(ARGEO_KEYRING); - keyring.addMixin(ArgeoTypes.ARGEO_PBE_SPEC); - - // deterministic salt and iteration count based on username - String username = session.getUserID(); - byte[] salt = new byte[8]; - byte[] usernameBytes = username.getBytes(); - for (int i = 0; i < salt.length; i++) { - if (i < usernameBytes.length) - salt[i] = usernameBytes[i]; - else - salt[i] = 0; - } - in = new ByteArrayInputStream(salt); - binary = session.getValueFactory().createBinary(in); - keyring.setProperty(ARGEO_SALT, binary); - - Integer iterationCount = username.length() * iterationCountFactor; - keyring.setProperty(ARGEO_ITERATION_COUNT, iterationCount); - - // default algo - // TODO check if algo and key length are available, use DES if not - keyring.setProperty(ARGEO_SECRET_KEY_FACTORY, secreteKeyFactoryName); - keyring.setProperty(ARGEO_KEY_LENGTH, secreteKeyLength); - keyring.setProperty(ARGEO_SECRET_KEY_ENCRYPTION, - secreteKeyEncryption); - keyring.setProperty(ARGEO_CIPHER, cipherName); - - // encrypted password hash - // IOUtils.closeQuietly(in); - // JcrUtils.closeQuietly(binary); - // byte[] btPass = hash(password, salt, iterationCount); - // in = new ByteArrayInputStream(btPass); - // binary = session.getValueFactory().createBinary(in); - // keyring.setProperty(ARGEO_PASSWORD, binary); - - notYetSavedKeyring.set(keyring); - } catch (Exception e) { - throw new ArgeoException("Cannot setup keyring", e); - } finally { - JcrUtils.closeQuietly(binary); - IOUtils.closeQuietly(in); - // JcrUtils.discardQuietly(session); - } - } - - @Override - protected void handleKeySpecCallback(PBEKeySpecCallback pbeCallback) { - try { - Node userHome = UserJcrUtils.getUserHome(session); - Node keyring; - if (userHome.hasNode(ARGEO_KEYRING)) - keyring = userHome.getNode(ARGEO_KEYRING); - else if (notYetSavedKeyring.get() != null) - keyring = notYetSavedKeyring.get(); - else - throw new ArgeoException("Keyring not setup"); - - pbeCallback.set(keyring.getProperty(ARGEO_SECRET_KEY_FACTORY) - .getString(), JcrUtils.getBinaryAsBytes(keyring - .getProperty(ARGEO_SALT)), - (int) keyring.getProperty(ARGEO_ITERATION_COUNT).getLong(), - (int) keyring.getProperty(ARGEO_KEY_LENGTH).getLong(), - keyring.getProperty(ARGEO_SECRET_KEY_ENCRYPTION) - .getString()); - - if (notYetSavedKeyring.get() != null) - notYetSavedKeyring.remove(); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot handle key spec callback", e); - } - } - - /** The parent node must already exist at this path. */ - @Override - protected synchronized void encrypt(String path, InputStream unencrypted) { - // should be called first for lazy initialization - SecretKey secretKey = getSecretKey(); - - Binary binary = null; - InputStream in = null; - try { - Cipher cipher = createCipher(); - Node node; - if (!session.nodeExists(path)) { - String parentPath = JcrUtils.parentPath(path); - if (!session.nodeExists(parentPath)) - throw new ArgeoException("No parent node of " + path); - Node parentNode = session.getNode(parentPath); - node = parentNode.addNode(JcrUtils.nodeNameFromPath(path)); - } else { - node = session.getNode(path); - } - node.addMixin(ArgeoTypes.ARGEO_ENCRYPTED); - SecureRandom random = new SecureRandom(); - byte[] iv = new byte[16]; - random.nextBytes(iv); - cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(iv)); - JcrUtils.setBinaryAsBytes(node, ARGEO_IV, iv); - - in = new CipherInputStream(unencrypted, cipher); - binary = session.getValueFactory().createBinary(in); - node.setProperty(Property.JCR_DATA, binary); - session.save(); - } catch (Exception e) { - throw new ArgeoException("Cannot encrypt", e); - } finally { - IOUtils.closeQuietly(unencrypted); - IOUtils.closeQuietly(in); - JcrUtils.closeQuietly(binary); - } - } - - @Override - protected synchronized InputStream decrypt(String path) { - Binary binary = null; - InputStream encrypted = null; - Reader reader = null; - try { - if (!session.nodeExists(path)) { - char[] password = ask(); - reader = new CharArrayReader(password); - return new ByteArrayInputStream(IOUtils.toByteArray(reader)); - } else { - // should be called first for lazy initialisation - SecretKey secretKey = getSecretKey(); - - Cipher cipher = createCipher(); - - Node node = session.getNode(path); - if (node.hasProperty(ARGEO_IV)) { - byte[] iv = JcrUtils.getBinaryAsBytes(node - .getProperty(ARGEO_IV)); - cipher.init(Cipher.DECRYPT_MODE, secretKey, - new IvParameterSpec(iv)); - } else { - cipher.init(Cipher.DECRYPT_MODE, secretKey); - } - - binary = node.getProperty(Property.JCR_DATA).getBinary(); - encrypted = binary.getStream(); - return new CipherInputStream(encrypted, cipher); - } - } catch (Exception e) { - throw new ArgeoException("Cannot decrypt", e); - } finally { - IOUtils.closeQuietly(encrypted); - IOUtils.closeQuietly(reader); - JcrUtils.closeQuietly(binary); - } - } - - protected Cipher createCipher() { - try { - Node userHome = UserJcrUtils.getUserHome(session); - if (!userHome.hasNode(ARGEO_KEYRING)) - throw new ArgeoException("Keyring not setup"); - Node keyring = userHome.getNode(ARGEO_KEYRING); - Cipher cipher = Cipher.getInstance(keyring - .getProperty(ARGEO_CIPHER).getString(), - getSecurityProvider()); - return cipher; - } catch (Exception e) { - throw new ArgeoException("Cannot get cipher", e); - } - } - - public synchronized void changePassword(char[] oldPassword, - char[] newPassword) { - // TODO decrypt with old pw / encrypt with new pw all argeo:encrypted - } - - public synchronized void setSession(Session session) { - this.session = session; - } - - public void setIterationCountFactor(Integer iterationCountFactor) { - this.iterationCountFactor = iterationCountFactor; - } - - public void setSecreteKeyLength(Long keyLength) { - this.secreteKeyLength = keyLength; - } - - public void setSecreteKeyFactoryName(String secreteKeyFactoryName) { - this.secreteKeyFactoryName = secreteKeyFactoryName; - } - - public void setSecreteKeyEncryption(String secreteKeyEncryption) { - this.secreteKeyEncryption = secreteKeyEncryption; - } - - public void setCipherName(String cipherName) { - this.cipherName = cipherName; - } - -} \ No newline at end of file diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/JcrSecurityModel.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/JcrSecurityModel.java deleted file mode 100644 index e9ab89c2a..000000000 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/JcrSecurityModel.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.jcr; - -import java.util.List; - -import javax.jcr.Node; -import javax.jcr.Session; - -/** - * Manages data expected by the Argeo security model, such as user home and - * profile. - */ -public interface JcrSecurityModel { - /** - * To be called before user details are loaded. Make sure than any logged in - * user has a home directory with full access and a profile with information - * about him (read access) - * - * @return the user profile (whose parent is the user home), never null - */ - public Node sync(Session session, String username, List roles); -} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/JcrUserDetails.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/JcrUserDetails.java deleted file mode 100644 index 2f7b97b78..000000000 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/JcrUserDetails.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.jcr; - -import java.util.ArrayList; -import java.util.List; - -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.argeo.jcr.ArgeoNames; -import org.argeo.jcr.UserJcrUtils; -import org.springframework.security.BadCredentialsException; -import org.springframework.security.DisabledException; -import org.springframework.security.GrantedAuthority; -import org.springframework.security.GrantedAuthorityImpl; -import org.springframework.security.LockedException; -import org.springframework.security.userdetails.User; - -/** User details based on a user profile node. */ -public class JcrUserDetails extends User implements ArgeoNames { - private static final long serialVersionUID = -8142764995842559646L; - private final String homePath; - private final String securityWorkspace; - - /** Human readable user name */ - private String displayName; - - protected JcrUserDetails(String securityWorkspace, String homePath, - String username, String password, boolean enabled, - boolean accountNonExpired, boolean credentialsNonExpired, - boolean accountNonLocked, GrantedAuthority[] authorities) - throws IllegalArgumentException { - super(username, password, enabled, accountNonExpired, - credentialsNonExpired, accountNonLocked, authorities); - this.homePath = homePath; - this.securityWorkspace = securityWorkspace; - } - - public JcrUserDetails(Node userProfile, String password, - GrantedAuthority[] authorities) throws RepositoryException { - super( - userProfile.getProperty(ARGEO_USER_ID).getString(), - password, - userProfile.getProperty(ARGEO_ENABLED).getBoolean(), - userProfile.getProperty(ARGEO_ACCOUNT_NON_EXPIRED).getBoolean(), - userProfile.getProperty(ARGEO_CREDENTIALS_NON_EXPIRED) - .getBoolean(), userProfile.getProperty( - ARGEO_ACCOUNT_NON_LOCKED).getBoolean(), authorities); - // human readable name - if (userProfile.hasProperty(Property.JCR_TITLE)) { - displayName = userProfile.getProperty(Property.JCR_TITLE) - .getString(); - if (displayName.trim().equals("")) - displayName = null; - } - if (displayName == null) - displayName = userProfile.getProperty(ARGEO_USER_ID).getString(); - // home is defined as the parent of the profile - homePath = userProfile.getParent().getPath(); - securityWorkspace = userProfile.getSession().getWorkspace().getName(); - } - - /** - * Convenience constructor - * - * @param session - * the security session - * @param username - * the username - * @param password - * the password, can be null - * @param authorities - * the granted authorities - */ - public JcrUserDetails(Session session, String username, String password, - GrantedAuthority[] authorities) throws RepositoryException { - this(UserJcrUtils.getUserProfile(session, username), - password != null ? password : "", authorities); - } - - /** - * Check the account status in JCR, throwing the exceptions expected by - * Spring security if needed. - */ - public static void checkAccountStatus(Node userProfile) { - try { - if (!userProfile.getProperty(ARGEO_ENABLED).getBoolean()) - throw new DisabledException(userProfile.getPath() - + " is disabled"); - if (!userProfile.getProperty(ARGEO_ACCOUNT_NON_LOCKED).getBoolean()) - throw new LockedException(userProfile.getPath() + " is locked"); - } catch (RepositoryException e) { - throw new BadCredentialsException("Cannot check account status", e); - } - } - - /** Clone immutable with new roles */ - public JcrUserDetails cloneWithNewRoles(List roles) { - List authorities = new ArrayList(); - for (String role : roles) { - authorities.add(new GrantedAuthorityImpl(role)); - } - return new JcrUserDetails(securityWorkspace, homePath, getUsername(), - getPassword(), isEnabled(), isAccountNonExpired(), - isAccountNonExpired(), isAccountNonLocked(), - authorities.toArray(new GrantedAuthority[authorities.size()])); - } - - /** Clone immutable with new password */ - public JcrUserDetails cloneWithNewPassword(String password) { - return new JcrUserDetails(securityWorkspace, homePath, getUsername(), - password, isEnabled(), isAccountNonExpired(), - isAccountNonExpired(), isAccountNonLocked(), getAuthorities()); - } - - public String getHomePath() { - return homePath; - } - - /** Not yet API */ - public String getSecurityWorkspace() { - return securityWorkspace; - } - - /** The human readable name of this user */ - public String getDisplayName() { - return displayName; - } - - @Override - public String toString() { - return getDisplayName(); - } - -} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/OsJcrAuthenticationProvider.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/OsJcrAuthenticationProvider.java deleted file mode 100644 index aa95e322d..000000000 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/OsJcrAuthenticationProvider.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.jcr; - -import javax.jcr.Node; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.argeo.ArgeoException; -import org.argeo.jcr.JcrUtils; -import org.argeo.security.OsAuthenticationToken; -import org.argeo.security.SecurityUtils; -import org.argeo.security.core.OsAuthenticationProvider; -import org.springframework.security.Authentication; -import org.springframework.security.AuthenticationException; -import org.springframework.security.BadCredentialsException; -import org.springframework.security.GrantedAuthority; -import org.springframework.security.providers.UsernamePasswordAuthenticationToken; -import org.springframework.security.userdetails.UserDetails; - -/** Relies on OS to authenticate and additionally setup JCR */ -public class OsJcrAuthenticationProvider extends OsAuthenticationProvider { - private Repository repository; - private Session nodeSession; - - private UserDetails userDetails; - private JcrSecurityModel jcrSecurityModel = new SimpleJcrSecurityModel(); - - private final static String JVM_OSUSER = System.getProperty("user.name"); - - public void init() { - try { - nodeSession = repository.login(); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot initialize", e); - } - } - - public void destroy() { - JcrUtils.logoutQuietly(nodeSession); - } - - public Authentication authenticate(Authentication authentication) - throws AuthenticationException { - if (authentication instanceof UsernamePasswordAuthenticationToken) { - // deal with remote access to internal server - // FIXME very primitive and unsecure at this sSession adminSession - // =tage - // consider using the keyring for username / password authentication - // or certificate - UsernamePasswordAuthenticationToken upat = (UsernamePasswordAuthenticationToken) authentication; - if (!upat.getPrincipal().toString().equals(JVM_OSUSER)) - throw new BadCredentialsException("Wrong credentials"); - UsernamePasswordAuthenticationToken authen = new UsernamePasswordAuthenticationToken( - authentication.getPrincipal(), - authentication.getCredentials(), getBaseAuthorities()); - authen.setDetails(userDetails); - return authen; - } else if (authentication instanceof OsAuthenticationToken) { - OsAuthenticationToken authen = (OsAuthenticationToken) super - .authenticate(authentication); - try { - // WARNING: at this stage we assume that the java properties - // will have the same value - GrantedAuthority[] authorities = getBaseAuthorities(); - String username = JVM_OSUSER; - Node userProfile = jcrSecurityModel.sync(nodeSession, username, - SecurityUtils.authoritiesToStringList(authorities)); - JcrUserDetails.checkAccountStatus(userProfile); - - userDetails = new JcrUserDetails(userProfile, authen - .getCredentials().toString(), authorities); - authen.setDetails(userDetails); - return authen; - } catch (RepositoryException e) { - JcrUtils.discardQuietly(nodeSession); - throw new ArgeoException( - "Unexpected exception when synchronizing OS and JCR security ", - e); - } - } else { - throw new ArgeoException("Unsupported authentication " - + authentication.getClass()); - } - } - - public void setRepository(Repository repository) { - this.repository = repository; - } - - public void setJcrSecurityModel(JcrSecurityModel jcrSecurityModel) { - this.jcrSecurityModel = jcrSecurityModel; - } - - @SuppressWarnings("rawtypes") - public boolean supports(Class authentication) { - return OsAuthenticationToken.class.isAssignableFrom(authentication) - || UsernamePasswordAuthenticationToken.class - .isAssignableFrom(authentication); - } -} \ No newline at end of file diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/OsJcrUserAdminService.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/OsJcrUserAdminService.java deleted file mode 100644 index c25bdb865..000000000 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/OsJcrUserAdminService.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.jcr; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import javax.jcr.Node; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.argeo.ArgeoException; -import org.argeo.jcr.JcrUtils; -import org.argeo.jcr.UserJcrUtils; -import org.argeo.security.UserAdminService; -import org.springframework.dao.DataAccessException; -import org.springframework.security.userdetails.User; -import org.springframework.security.userdetails.UserDetails; -import org.springframework.security.userdetails.UsernameNotFoundException; - -/** - * Dummy user service to be used when running as a single OS user (typically - * desktop). TODO integrate with JCR user / groups - */ -public class OsJcrUserAdminService implements UserAdminService { - private Repository repository; - - /** In memory roles provided by applications. */ - private List roles = new ArrayList(); - - // private Session adminSession; - - public void init() { - // try { - // adminSession = repository.login(); - // } catch (RepositoryException e) { - // throw new ArgeoException("Cannot initialize", e); - // } - } - - public void destroy() { - // JcrUtils.logoutQuietly(adminSession); - } - - /** Unsupported */ - public void createUser(UserDetails user) { - throw new UnsupportedOperationException(); - } - - /** Does nothing */ - public void updateUser(UserDetails user) { - - } - - /** Unsupported */ - public void deleteUser(String username) { - throw new UnsupportedOperationException(); - } - - /** Unsupported */ - public void changePassword(String oldPassword, String newPassword) { - throw new UnsupportedOperationException(); - } - - public boolean userExists(String username) { - if (getSPropertyUsername().equals(username)) - return true; - else - return false; - } - - public UserDetails loadUserByUsername(String username) - throws UsernameNotFoundException, DataAccessException { - if (getSPropertyUsername().equals(username)) { - UserDetails userDetails; - if (repository != null) { - Session adminSession = null; - try { - adminSession = repository.login(); - Node userProfile = UserJcrUtils.getUserProfile( - adminSession, username); - userDetails = new JcrUserDetails(userProfile, "", - OsJcrAuthenticationProvider.getBaseAuthorities()); - } catch (RepositoryException e) { - throw new ArgeoException( - "Cannot retrieve user profile for " + username, e); - } finally { - JcrUtils.logoutQuietly(adminSession); - } - } else { - userDetails = new User(username, "", true, true, true, true, - OsJcrAuthenticationProvider.getBaseAuthorities()); - } - return userDetails; - } else { - throw new UnsupportedOperationException(); - } - } - - protected final String getSPropertyUsername() { - return System.getProperty("user.name"); - } - - public Set listUsers() { - Set set = new HashSet(); - set.add(getSPropertyUsername()); - return set; - } - - public Set listUsersInRole(String role) { - Set set = new HashSet(); - set.add(getSPropertyUsername()); - return set; - } - - /** Does nothing */ - public void synchronize() { - } - - /** Unsupported */ - public void newRole(String role) { - roles.add(role); - } - - public Set listEditableRoles() { - return new HashSet(roles); - } - - /** Unsupported */ - public void deleteRole(String role) { - roles.remove(role); - } - - public void setRepository(Repository repository) { - this.repository = repository; - } -} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/RemoteJcrAuthenticationProvider.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/RemoteJcrAuthenticationProvider.java deleted file mode 100644 index 87208b2a3..000000000 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/RemoteJcrAuthenticationProvider.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.jcr; - -import java.util.ArrayList; -import java.util.Dictionary; -import java.util.Hashtable; -import java.util.List; - -import javax.jcr.Node; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.RepositoryFactory; -import javax.jcr.Session; -import javax.jcr.SimpleCredentials; -import javax.jcr.Value; - -import org.argeo.ArgeoException; -import org.argeo.jcr.ArgeoJcrConstants; -import org.argeo.jcr.ArgeoNames; -import org.argeo.jcr.UserJcrUtils; -import org.argeo.security.NodeAuthenticationToken; -import org.osgi.framework.BundleContext; -import org.springframework.security.Authentication; -import org.springframework.security.AuthenticationException; -import org.springframework.security.BadCredentialsException; -import org.springframework.security.GrantedAuthority; -import org.springframework.security.GrantedAuthorityImpl; -import org.springframework.security.providers.AuthenticationProvider; - -/** Connects to a JCR repository and delegates authentication to it. */ -public class RemoteJcrAuthenticationProvider implements AuthenticationProvider, - ArgeoNames { - private RepositoryFactory repositoryFactory; - private BundleContext bundleContext; - - public final static String ROLE_REMOTE = "ROLE_REMOTE"; - - public Authentication authenticate(Authentication authentication) - throws AuthenticationException { - NodeAuthenticationToken siteAuth = (NodeAuthenticationToken) authentication; - String url = siteAuth.getUrl(); - if (url == null)// TODO? login on own node - throw new ArgeoException("No url set in " + siteAuth); - Session session; - - Node userProfile; - try { - SimpleCredentials sp = new SimpleCredentials(siteAuth.getName(), - siteAuth.getCredentials().toString().toCharArray()); - // get repository - Repository repository = new RemoteJcrRepositoryWrapper( - repositoryFactory, url, sp); - if (bundleContext != null) { - Dictionary serviceProperties = new Hashtable(); - serviceProperties.put(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS, - ArgeoJcrConstants.ALIAS_NODE); - serviceProperties - .put(ArgeoJcrConstants.JCR_REPOSITORY_URI, url); - bundleContext.registerService(Repository.class.getName(), - repository, serviceProperties); - } - // Repository repository = ArgeoJcrUtils.getRepositoryByUri( - // repositoryFactory, url); - // if (repository == null) - // throw new ArgeoException("Cannot connect to " + url); - - session = repository.login(sp, null); - - userProfile = UserJcrUtils.getUserProfile(session, sp.getUserID()); - JcrUserDetails.checkAccountStatus(userProfile); - - // Node userHome = UserJcrUtils.getUserHome(session); - // if (userHome == null || - // !userHome.hasNode(ArgeoNames.ARGEO_PROFILE)) - // throw new ArgeoException("No profile for user " - // + siteAuth.getName() + " in security workspace " - // + siteAuth.getSecurityWorkspace() + " of " - // + siteAuth.getUrl()); - // userProfile = userHome.getNode(ArgeoNames.ARGEO_PROFILE); - } catch (RepositoryException e) { - throw new BadCredentialsException( - "Cannot authenticate " + siteAuth, e); - } - - try { - // Node userHome = UserJcrUtils.getUserHome(session); - // retrieve remote roles - List authoritiesList = new ArrayList(); - if (userProfile != null - && userProfile.hasProperty(ArgeoNames.ARGEO_REMOTE_ROLES)) { - Value[] roles = userProfile.getProperty( - ArgeoNames.ARGEO_REMOTE_ROLES).getValues(); - for (int i = 0; i < roles.length; i++) - authoritiesList.add(new GrantedAuthorityImpl(roles[i] - .getString())); - } - authoritiesList.add(new GrantedAuthorityImpl(ROLE_REMOTE)); - - // create authenticated objects - GrantedAuthority[] authorities = authoritiesList - .toArray(new GrantedAuthority[authoritiesList.size()]); - JcrUserDetails userDetails = new JcrUserDetails(userProfile, - siteAuth.getCredentials().toString(), authorities); - NodeAuthenticationToken authenticated = new NodeAuthenticationToken( - siteAuth, authorities); - authenticated.setDetails(userDetails); - return authenticated; - } catch (RepositoryException e) { - throw new ArgeoException( - "Unexpected exception when authenticating to " + url, e); - } - } - - @SuppressWarnings("rawtypes") - public boolean supports(Class authentication) { - return NodeAuthenticationToken.class.isAssignableFrom(authentication); - } - - public void setRepositoryFactory(RepositoryFactory repositoryFactory) { - this.repositoryFactory = repositoryFactory; - } - - public void setBundleContext(BundleContext bundleContext) { - this.bundleContext = bundleContext; - } - -} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/RemoteJcrRepositoryWrapper.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/RemoteJcrRepositoryWrapper.java deleted file mode 100644 index f0ad3a3a9..000000000 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/RemoteJcrRepositoryWrapper.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.jcr; - -import javax.jcr.Credentials; -import javax.jcr.LoginException; -import javax.jcr.NoSuchWorkspaceException; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.RepositoryFactory; -import javax.jcr.Session; -import javax.jcr.SimpleCredentials; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.ArgeoException; -import org.argeo.jcr.ArgeoJcrUtils; -import org.argeo.jcr.JcrRepositoryWrapper; -import org.argeo.security.NodeAuthenticationToken; -import org.argeo.security.SystemAuthentication; -import org.springframework.security.Authentication; -import org.springframework.security.context.SecurityContextHolder; -import org.springframework.security.providers.UsernamePasswordAuthenticationToken; - -/** - * Wrapper around a remote Jackrabbit repository which allows to simplify - * configuration and intercept some actions. It exposes itself as a - * {@link Repository}. - */ -public class RemoteJcrRepositoryWrapper extends JcrRepositoryWrapper { - private final static Log log = LogFactory - .getLog(RemoteJcrRepositoryWrapper.class); - - private String uri = null; - - private RepositoryFactory repositoryFactory; - - // remote - private Credentials remoteSystemCredentials = null; - - /** - * Empty constructor, {@link #init()} should be called after properties have - * been set - */ - public RemoteJcrRepositoryWrapper() { - } - - /** - * Embedded constructor, calling the {@link #init()} method. - * - * @param alias - * if not null the repository will be published under this alias - */ - public RemoteJcrRepositoryWrapper(RepositoryFactory repositoryFactory, - String uri, Credentials remoteSystemCredentials) { - this.repositoryFactory = repositoryFactory; - this.uri = uri; - this.remoteSystemCredentials = remoteSystemCredentials; - init(); - } - - public void init() { - Repository repository = createJackrabbitRepository(); - setRepository(repository); - } - - /** Actually creates the new repository. */ - protected Repository createJackrabbitRepository() { - long begin = System.currentTimeMillis(); - try { - if (uri == null || uri.trim().equals("")) - throw new ArgeoException("Remote URI not set"); - - Repository repository = ArgeoJcrUtils.getRepositoryByUri( - repositoryFactory, uri); - if (repository == null) - throw new ArgeoException("Remote JCR repository " + uri - + " not found"); - double duration = ((double) (System.currentTimeMillis() - begin)) / 1000; - log.info("Created remote JCR repository in " + duration - + " s from URI " + uri); - // we assume that the data model of the remote repository has - // been properly initialized - return repository; - } catch (Exception e) { - throw new ArgeoException("Cannot create remote JCR repository " - + uri, e); - } - } - - /** Shutdown the repository */ - public void destroy() throws Exception { - super.destroy(); - } - - /** Central login method */ - public Session login(Credentials credentials, String workspaceName) - throws LoginException, NoSuchWorkspaceException, - RepositoryException { - - // retrieve credentials for remote - if (credentials == null) { - Authentication authentication = SecurityContextHolder.getContext() - .getAuthentication(); - if (authentication != null) { - if (authentication instanceof UsernamePasswordAuthenticationToken) { - UsernamePasswordAuthenticationToken upat = (UsernamePasswordAuthenticationToken) authentication; - credentials = new SimpleCredentials(upat.getName(), upat - .getCredentials().toString().toCharArray()); - } else if ((authentication instanceof SystemAuthentication) - || (authentication instanceof NodeAuthenticationToken)) { - credentials = remoteSystemCredentials; - } - } - } - - return super.login(credentials, workspaceName); - } - - public void setUri(String uri) { - this.uri = uri; - } - - public void setRepositoryFactory(RepositoryFactory repositoryFactory) { - this.repositoryFactory = repositoryFactory; - } - - public void setRemoteSystemCredentials(Credentials remoteSystemCredentials) { - this.remoteSystemCredentials = remoteSystemCredentials; - } - -} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/SecureThreadBoundSession.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/SecureThreadBoundSession.java deleted file mode 100644 index b39877420..000000000 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/SecureThreadBoundSession.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.jcr; - -import javax.jcr.Session; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.jcr.spring.ThreadBoundSession; -import org.springframework.security.Authentication; -import org.springframework.security.context.SecurityContextHolder; - -/** - * Thread bounded JCR session factory which checks authentication and is - * autoconfigured in Spring. - */ -public class SecureThreadBoundSession extends ThreadBoundSession { - private final static Log log = LogFactory - .getLog(SecureThreadBoundSession.class); - - @Override - protected Session preCall(Session session) { - Authentication authentication = SecurityContextHolder.getContext() - .getAuthentication(); - if (authentication != null) { - String userID = session.getUserID(); - String currentUserName = authentication.getName(); - if (currentUserName != null) { - if (!userID.equals(currentUserName)) { - log.warn("Current session has user ID " + userID - + " while logged is user is " + currentUserName - + "(authentication=" + authentication + ")" - + ". Re-login."); - // TODO throw an exception - return login(); - } - } - } - return super.preCall(session); - } - -} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/SimpleJcrSecurityModel.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/SimpleJcrSecurityModel.java deleted file mode 100644 index fc0158738..000000000 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/SimpleJcrSecurityModel.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.jcr; - -import java.util.List; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.Value; -import javax.jcr.security.Privilege; -import javax.jcr.version.VersionManager; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.ArgeoException; -import org.argeo.jcr.ArgeoJcrConstants; -import org.argeo.jcr.ArgeoNames; -import org.argeo.jcr.ArgeoTypes; -import org.argeo.jcr.JcrUtils; -import org.argeo.jcr.UserJcrUtils; - -/** - * Manages data expected by the Argeo security model, such as user home and - * profile. - */ -public class SimpleJcrSecurityModel implements JcrSecurityModel { - private final static Log log = LogFactory - .getLog(SimpleJcrSecurityModel.class); - // ArgeoNames not implemented as interface in order to ease derivation by - // Jackrabbit bundles - - /** The home base path. */ - private String homeBasePath = "/home"; - - public synchronized Node sync(Session session, String username, - List roles) { - // TODO check user name validity (e.g. should not start by ROLE_) - - try { - Node userHome = UserJcrUtils.getUserHome(session, username); - if (userHome == null) { - String homePath = generateUserPath(homeBasePath, username); - userHome = JcrUtils.mkdirs(session, homePath); - // userHome = JcrUtils.mkfolders(session, homePath); - userHome.addMixin(ArgeoTypes.ARGEO_USER_HOME); - userHome.setProperty(ArgeoNames.ARGEO_USER_ID, username); - session.save(); - - JcrUtils.clearAccessControList(session, homePath, username); - JcrUtils.addPrivilege(session, homePath, username, - Privilege.JCR_ALL); - } else { - // for backward compatibility with pre 1.0 security model - if (userHome.hasNode(ArgeoNames.ARGEO_PROFILE)) { - userHome.getNode(ArgeoNames.ARGEO_PROFILE).remove(); - userHome.getSession().save(); - } - } - - // Remote roles - if (roles != null) { - // writeRemoteRoles(userHome, roles); - } - - Node userProfile = UserJcrUtils.getUserProfile(session, username); - if (userProfile == null) { - String personPath = generateUserPath( - ArgeoJcrConstants.PEOPLE_BASE_PATH, username); - Node personBase = JcrUtils.mkdirs(session, personPath); - userProfile = personBase.addNode(ArgeoNames.ARGEO_PROFILE); - userProfile.addMixin(ArgeoTypes.ARGEO_USER_PROFILE); - userProfile.setProperty(ArgeoNames.ARGEO_USER_ID, username); - userProfile.setProperty(ArgeoNames.ARGEO_ENABLED, true); - userProfile.setProperty(ArgeoNames.ARGEO_ACCOUNT_NON_EXPIRED, - true); - userProfile.setProperty(ArgeoNames.ARGEO_ACCOUNT_NON_LOCKED, - true); - userProfile.setProperty( - ArgeoNames.ARGEO_CREDENTIALS_NON_EXPIRED, true); - session.save(); - - JcrUtils.clearAccessControList(session, userProfile.getPath(), - username); - JcrUtils.addPrivilege(session, userProfile.getPath(), username, - Privilege.JCR_READ); - - VersionManager versionManager = session.getWorkspace() - .getVersionManager(); - if (versionManager.isCheckedOut(userProfile.getPath())) - versionManager.checkin(userProfile.getPath()); - - } - - // Remote roles - if (roles != null) { - writeRemoteRoles(userProfile, roles); - } - return userProfile; - } catch (RepositoryException e) { - JcrUtils.discardQuietly(session); - throw new ArgeoException("Cannot sync node security model for " - + username, e); - } - } - - /** Generate path for a new user home */ - protected String generateUserPath(String base, String username) { - int atIndex = username.indexOf('@'); - if (atIndex > 0) { - String domain = username.substring(0, atIndex); - String name = username.substring(atIndex + 1); - return base + '/' + JcrUtils.firstCharsToPath(domain, 2) + '/' - + domain + '/' + JcrUtils.firstCharsToPath(name, 2) + '/' - + name; - } else if (atIndex == 0 || atIndex == (username.length() - 1)) { - throw new ArgeoException("Unsupported username " + username); - } else { - return base + '/' + JcrUtils.firstCharsToPath(username, 2) + '/' - + username; - } - } - - /** Write remote roles used by remote access in the home directory */ - protected void writeRemoteRoles(Node userHome, List roles) - throws RepositoryException { - boolean writeRoles = false; - if (userHome.hasProperty(ArgeoNames.ARGEO_REMOTE_ROLES)) { - Value[] remoteRoles = userHome.getProperty( - ArgeoNames.ARGEO_REMOTE_ROLES).getValues(); - if (remoteRoles.length != roles.size()) - writeRoles = true; - else - for (int i = 0; i < remoteRoles.length; i++) - if (!remoteRoles[i].getString().equals(roles.get(i))) - writeRoles = true; - } else - writeRoles = true; - - if (writeRoles) { - userHome.getSession().getWorkspace().getVersionManager() - .checkout(userHome.getPath()); - String[] roleIds = roles.toArray(new String[roles.size()]); - userHome.setProperty(ArgeoNames.ARGEO_REMOTE_ROLES, roleIds); - JcrUtils.updateLastModified(userHome); - userHome.getSession().save(); - userHome.getSession().getWorkspace().getVersionManager() - .checkin(userHome.getPath()); - if (log.isDebugEnabled()) - log.debug("Wrote remote roles " + roles + " for " - + userHome.getProperty(ArgeoNames.ARGEO_USER_ID)); - } - - } - - public void setHomeBasePath(String homeBasePath) { - this.homeBasePath = homeBasePath; - } - -} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/rememberme/JcrPersistentTokenRepository.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/rememberme/JcrPersistentTokenRepository.java deleted file mode 100644 index 37dc98676..000000000 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/rememberme/JcrPersistentTokenRepository.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.jcr.rememberme; - -import java.util.Date; - -import org.springframework.security.ui.rememberme.PersistentRememberMeToken; -import org.springframework.security.ui.rememberme.PersistentTokenRepository; - -public class JcrPersistentTokenRepository implements PersistentTokenRepository { - - public void createNewToken(PersistentRememberMeToken token) { - // TODO Auto-generated method stub - - } - - public void updateToken(String series, String tokenValue, Date lastUsed) { - // TODO Auto-generated method stub - - } - - public PersistentRememberMeToken getTokenForSeries(String seriesId) { - // TODO Auto-generated method stub - return null; - } - - public void removeUserTokens(String username) { - // TODO Auto-generated method stub - - } - -} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/log4j/SecureLogger.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/log4j/SecureLogger.java deleted file mode 100644 index 1da985703..000000000 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/log4j/SecureLogger.java +++ /dev/null @@ -1,360 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.log4j; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; -import java.util.Properties; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; - -import org.apache.log4j.AppenderSkeleton; -import org.apache.log4j.Level; -import org.apache.log4j.LogManager; -import org.apache.log4j.Logger; -import org.apache.log4j.PropertyConfigurator; -import org.apache.log4j.spi.LoggingEvent; -import org.argeo.ArgeoException; -import org.argeo.ArgeoLogListener; -import org.argeo.ArgeoLogger; -import org.argeo.security.SecurityUtils; - -/** Not meant to be used directly in standard log4j config */ -public class SecureLogger implements ArgeoLogger { - - private Boolean disabled = false; - - private String level = null; - - private Level log4jLevel = null; - // private Layout layout; - - private Properties configuration; - - private AppenderImpl appender; - - private final List everythingListeners = Collections - .synchronizedList(new ArrayList()); - private final List allUsersListeners = Collections - .synchronizedList(new ArrayList()); - private final Map> userListeners = Collections - .synchronizedMap(new HashMap>()); - - private BlockingQueue events; - private LogDispatcherThread logDispatcherThread = new LogDispatcherThread(); - - private Integer maxLastEventsCount = 10 * 1000; - - /** Marker to prevent stack overflow */ - private ThreadLocal dispatching = new ThreadLocal() { - - @Override - protected Boolean initialValue() { - return false; - } - }; - - public void init() { - try { - events = new LinkedBlockingQueue(); - - // if (layout != null) - // setLayout(layout); - // else - // setLayout(new PatternLayout(pattern)); - appender = new AppenderImpl(); - reloadConfiguration(); - Logger.getRootLogger().addAppender(appender); - - logDispatcherThread = new LogDispatcherThread(); - logDispatcherThread.start(); - } catch (Exception e) { - throw new ArgeoException("Cannot initialize log4j"); - } - } - - public void destroy() throws Exception { - Logger.getRootLogger().removeAppender(appender); - allUsersListeners.clear(); - for (List lst : userListeners.values()) - lst.clear(); - userListeners.clear(); - - events.clear(); - events = null; - logDispatcherThread.interrupt(); - } - - // public void setLayout(Layout layout) { - // this.layout = layout; - // } - - public synchronized void register(ArgeoLogListener listener, - Integer numberOfPreviousEvents) { - String username = SecurityUtils.getCurrentThreadUsername(); - if (username == null) - throw new ArgeoException( - "Only authenticated users can register a log listener"); - - if (!userListeners.containsKey(username)) { - List lst = Collections - .synchronizedList(new ArrayList()); - userListeners.put(username, lst); - } - userListeners.get(username).add(listener); - List lastEvents = logDispatcherThread.getLastEvents(username, - numberOfPreviousEvents); - for (LogEvent evt : lastEvents) - dispatchEvent(listener, evt); - } - - public synchronized void registerForAll(ArgeoLogListener listener, - Integer numberOfPreviousEvents, boolean everything) { - if (everything) - everythingListeners.add(listener); - else - allUsersListeners.add(listener); - List lastEvents = logDispatcherThread.getLastEvents(null, - numberOfPreviousEvents); - for (LogEvent evt : lastEvents) - if (everything || evt.getUsername() != null) - dispatchEvent(listener, evt); - } - - public synchronized void unregister(ArgeoLogListener listener) { - String username = SecurityUtils.getCurrentThreadUsername(); - if (!userListeners.containsKey(username)) - throw new ArgeoException("No user listeners " + listener - + " registered for user " + username); - if (!userListeners.get(username).contains(listener)) - throw new ArgeoException("No user listeners " + listener - + " registered for user " + username); - userListeners.get(username).remove(listener); - if (userListeners.get(username).isEmpty()) - userListeners.remove(username); - - } - - public synchronized void unregisterForAll(ArgeoLogListener listener) { - everythingListeners.remove(listener); - allUsersListeners.remove(listener); - } - - /** For development purpose, since using regular logging is not easy here */ - static void stdOut(Object obj) { - System.out.println(obj); - } - - // public void setPattern(String pattern) { - // this.pattern = pattern; - // } - - public void setDisabled(Boolean disabled) { - this.disabled = disabled; - } - - public void setLevel(String level) { - this.level = level; - } - - public void setConfiguration(Properties configuration) { - this.configuration = configuration; - } - - public void updateConfiguration(Properties configuration) { - setConfiguration(configuration); - reloadConfiguration(); - } - - public Properties getConfiguration() { - return configuration; - } - - /** Reloads configuration (if the configuration {@link Properties} is set) */ - protected void reloadConfiguration() { - if (configuration != null) { - LogManager.resetConfiguration(); - PropertyConfigurator.configure(configuration); - } - } - - protected synchronized void processLoggingEvent(LogEvent event) { - if (disabled) - return; - - if (dispatching.get()) - return; - - if (level != null && !level.trim().equals("")) { - if (log4jLevel == null || !log4jLevel.toString().equals(level)) - try { - log4jLevel = Level.toLevel(level); - } catch (Exception e) { - System.err - .println("Log4j level could not be set for level '" - + level + "', resetting it to null."); - e.printStackTrace(); - level = null; - } - - if (log4jLevel != null - && !event.getLoggingEvent().getLevel() - .isGreaterOrEqual(log4jLevel)) { - return; - } - } - - try { - // admin listeners - Iterator everythingIt = everythingListeners - .iterator(); - while (everythingIt.hasNext()) - dispatchEvent(everythingIt.next(), event); - - if (event.getUsername() != null) { - Iterator allUsersIt = allUsersListeners - .iterator(); - while (allUsersIt.hasNext()) - dispatchEvent(allUsersIt.next(), event); - - if (userListeners.containsKey(event.getUsername())) { - Iterator userIt = userListeners.get( - event.getUsername()).iterator(); - while (userIt.hasNext()) - dispatchEvent(userIt.next(), event); - } - } - } catch (Exception e) { - stdOut("Cannot process logging event"); - e.printStackTrace(); - } - } - - protected void dispatchEvent(ArgeoLogListener logListener, LogEvent evt) { - LoggingEvent event = evt.getLoggingEvent(); - logListener.appendLog(evt.getUsername(), event.getTimeStamp(), event - .getLevel().toString(), event.getLoggerName(), event - .getThreadName(), event.getMessage(), event - .getThrowableStrRep()); - } - - private class AppenderImpl extends AppenderSkeleton { - public boolean requiresLayout() { - return false; - } - - public void close() { - } - - @Override - protected void append(LoggingEvent event) { - if (events != null) { - try { - String username = SecurityUtils.getCurrentThreadUsername(); - events.put(new LogEvent(username, event)); - } catch (InterruptedException e) { - // silent - } - } - } - - } - - private class LogDispatcherThread extends Thread { - /** encapsulated in order to simplify concurrency management */ - private LinkedList lastEvents = new LinkedList(); - - public LogDispatcherThread() { - super("Argeo Logging Dispatcher Thread"); - } - - public void run() { - while (events != null) { - try { - LogEvent loggingEvent = events.take(); - processLoggingEvent(loggingEvent); - addLastEvent(loggingEvent); - } catch (InterruptedException e) { - if (events == null) - return; - } - } - } - - protected synchronized void addLastEvent(LogEvent loggingEvent) { - if (lastEvents.size() >= maxLastEventsCount) - lastEvents.poll(); - lastEvents.add(loggingEvent); - } - - public synchronized List getLastEvents(String username, - Integer maxCount) { - LinkedList evts = new LinkedList(); - ListIterator it = lastEvents.listIterator(lastEvents - .size()); - int count = 0; - while (it.hasPrevious() && (count < maxCount)) { - LogEvent evt = it.previous(); - if (username == null || username.equals(evt.getUsername())) { - evts.push(evt); - count++; - } - } - return evts; - } - } - - private class LogEvent { - private final String username; - private final LoggingEvent loggingEvent; - - public LogEvent(String username, LoggingEvent loggingEvent) { - super(); - this.username = username; - this.loggingEvent = loggingEvent; - } - - @Override - public int hashCode() { - return loggingEvent.hashCode(); - } - - @Override - public boolean equals(Object obj) { - return loggingEvent.equals(obj); - } - - @Override - public String toString() { - return username + "@ " + loggingEvent.toString(); - } - - public String getUsername() { - return username; - } - - public LoggingEvent getLoggingEvent() { - return loggingEvent; - } - - } -} diff --git a/security/runtime/org.argeo.security.core/src/test/java/org/argeo/security/PasswordSandbox.java b/security/runtime/org.argeo.security.core/src/test/java/org/argeo/security/PasswordSandbox.java deleted file mode 100644 index d8a084607..000000000 --- a/security/runtime/org.argeo.security.core/src/test/java/org/argeo/security/PasswordSandbox.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security; - -import org.apache.commons.codec.DecoderException; -import org.apache.commons.codec.binary.Base64; -import org.apache.commons.codec.binary.Hex; -import org.springframework.security.providers.ldap.authenticator.LdapShaPasswordEncoder; - -public class PasswordSandbox { - public static void main(String[] args) { - try { - // Tested password - String pwdPlain = "demo"; - - // Check Java generated values - LdapShaPasswordEncoder lspe = new LdapShaPasswordEncoder(); - String pwdLdapShaBase64 = lspe.encodePassword(pwdPlain, null); - System.out.println("pwdLdapShaBase64:\t\t" + pwdLdapShaBase64); - - String pwdShaBase64 = pwdLdapShaBase64.substring("{SHA}".length()); - System.out.println("pwdShaBase64:\t\t\t" + pwdShaBase64); - - byte[] pwdShaArray = Base64.decodeBase64(pwdShaBase64.getBytes()); - String pwdShaHex = new String(Hex.encodeHex(pwdShaArray)); - System.out.println("pwdShaHex:\t\t\t" + pwdShaHex); - - // Check that we can use JavaScript generated values in Hex - String jsShaHex = "89e495e7941cf9e40e6980d14a16bf023ccd4c91"; - System.out.println("jsShaHex:\t\t\t" + pwdShaHex); - System.out.println("pwdShaHex==jsShaHex:\t\t" - + (pwdShaHex.equals(jsShaHex))); - - byte[] jsShaArray = Hex.decodeHex(jsShaHex.toCharArray()); - String jsShaBase64 = new String(Base64.encodeBase64(jsShaArray)); - System.out.println("jsShaBase64:\t\t\t" + jsShaBase64); - System.out.println("pwdShaBase64==jsShaBase64:\t" - + (pwdShaBase64.equals(jsShaBase64))); - } catch (DecoderException e) { - e.printStackTrace(); - } - - } - -} \ No newline at end of file diff --git a/security/runtime/org.argeo.security.core/src/test/java/org/argeo/security/crypto/PasswordBasedEncryptionTest.java b/security/runtime/org.argeo.security.core/src/test/java/org/argeo/security/crypto/PasswordBasedEncryptionTest.java deleted file mode 100644 index 6973f5704..000000000 --- a/security/runtime/org.argeo.security.core/src/test/java/org/argeo/security/crypto/PasswordBasedEncryptionTest.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.crypto; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.InputStream; - -import javax.crypto.Cipher; -import javax.crypto.CipherInputStream; -import javax.crypto.CipherOutputStream; -import javax.crypto.SecretKey; -import javax.crypto.SecretKeyFactory; -import javax.crypto.spec.IvParameterSpec; -import javax.crypto.spec.PBEKeySpec; -import javax.crypto.spec.PBEParameterSpec; -import javax.crypto.spec.SecretKeySpec; -import javax.xml.bind.DatatypeConverter; - -import junit.framework.TestCase; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.StreamUtils; -import org.argeo.security.crypto.PasswordBasedEncryption; - -public class PasswordBasedEncryptionTest extends TestCase { - private final static Log log = LogFactory - .getLog(PasswordBasedEncryptionTest.class); - - public void testEncryptDecrypt() { - final String password = "test long password since they are safer"; - PasswordBasedEncryption pbeEnc = new PasswordBasedEncryption( - password.toCharArray()); - String message = "Hello World!"; - log.info("Password:\t'" + password + "'"); - log.info("Message:\t'" + message + "'"); - byte[] encrypted = pbeEnc.encryptString(message); - log.info("Encrypted:\t'" - + DatatypeConverter.printBase64Binary(encrypted) + "'"); - PasswordBasedEncryption pbeDec = new PasswordBasedEncryption( - password.toCharArray()); - InputStream in = null; - in = new ByteArrayInputStream(encrypted); - String decrypted = pbeDec.decryptAsString(in); - log.info("Decrypted:\t'" + decrypted + "'"); - StreamUtils.closeQuietly(in); - assertEquals(message, decrypted); - } - - public void testPBEWithMD5AndDES() throws Exception { - String password = "test"; - String message = "Hello World!"; - - byte[] salt = { (byte) 0xc7, (byte) 0x73, (byte) 0x21, (byte) 0x8c, - (byte) 0x7e, (byte) 0xc8, (byte) 0xee, (byte) 0x99 }; - - int count = 1024; - - String cipherAlgorithm = "PBEWithMD5AndDES"; - String secretKeyAlgorithm = "PBEWithMD5AndDES"; - SecretKeyFactory keyFac = SecretKeyFactory - .getInstance(secretKeyAlgorithm); - PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray()); - PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, count); - SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec); - Cipher ecipher = Cipher.getInstance(cipherAlgorithm); - ecipher.init(Cipher.ENCRYPT_MODE, pbeKey, pbeParamSpec); - Cipher dcipher = Cipher.getInstance(cipherAlgorithm); - dcipher.init(Cipher.DECRYPT_MODE, pbeKey, pbeParamSpec); - - byte[] encrypted = ecipher.doFinal(message.getBytes()); - byte[] decrypted = dcipher.doFinal(encrypted); - assertEquals(message, new String(decrypted)); - - } - - public void testPBEWithSHA1AndAES() throws Exception { - String password = "test"; - String message = "Hello World!"; - - byte[] salt = { (byte) 0xc7, (byte) 0x73, (byte) 0x21, (byte) 0x8c, - (byte) 0x7e, (byte) 0xc8, (byte) 0xee, (byte) 0x99 }; - byte[] iv = { (byte) 0xc7, (byte) 0x73, (byte) 0x21, (byte) 0x8c, - (byte) 0x7e, (byte) 0xc8, (byte) 0xee, (byte) 0x99, - (byte) 0xc7, (byte) 0x73, (byte) 0x21, (byte) 0x8c, - (byte) 0x7e, (byte) 0xc8, (byte) 0xee, (byte) 0x99 }; - - int count = 1024; - // int keyLength = 256; - int keyLength = 128; - - String cipherAlgorithm = "AES/CBC/PKCS5Padding"; - String secretKeyAlgorithm = "PBKDF2WithHmacSHA1"; - SecretKeyFactory keyFac = SecretKeyFactory - .getInstance(secretKeyAlgorithm); - PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray(), salt, - count, keyLength); - SecretKey tmp = keyFac.generateSecret(pbeKeySpec); - SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES"); - Cipher ecipher = Cipher.getInstance(cipherAlgorithm); - ecipher.init(Cipher.ENCRYPT_MODE, secret, new IvParameterSpec(iv)); - - // decrypt - keyFac = SecretKeyFactory.getInstance(secretKeyAlgorithm); - pbeKeySpec = new PBEKeySpec(password.toCharArray(), salt, count, - keyLength); - tmp = keyFac.generateSecret(pbeKeySpec); - secret = new SecretKeySpec(tmp.getEncoded(), "AES"); - // AlgorithmParameters params = ecipher.getParameters(); - // byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV(); - Cipher dcipher = Cipher.getInstance(cipherAlgorithm); - dcipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv)); - - byte[] encrypted = ecipher.doFinal(message.getBytes()); - byte[] decrypted = dcipher.doFinal(encrypted); - assertEquals(message, new String(decrypted)); - - ByteArrayOutputStream out = new ByteArrayOutputStream(); - CipherOutputStream cipherOut = new CipherOutputStream(out, ecipher); - cipherOut.write(message.getBytes()); - StreamUtils.closeQuietly(cipherOut); - byte[] enc = out.toByteArray(); - - ByteArrayInputStream in = new ByteArrayInputStream(enc); - CipherInputStream cipherIn = new CipherInputStream(in, dcipher); - ByteArrayOutputStream dec = new ByteArrayOutputStream(); - StreamUtils.copy(cipherIn, dec); - assertEquals(message, new String(dec.toByteArray())); - } -} diff --git a/security/runtime/org.argeo.security.core/src/test/resources/log4j.properties b/security/runtime/org.argeo.security.core/src/test/resources/log4j.properties deleted file mode 100644 index b33daa9db..000000000 --- a/security/runtime/org.argeo.security.core/src/test/resources/log4j.properties +++ /dev/null @@ -1,28 +0,0 @@ -log4j.rootLogger=WARN, console - -## Levels -log4j.logger.org.argeo=DEBUG - -log4j.logger.org.hibernate=WARN - -log4j.logger.org.springframework=WARN -#log4j.logger.org.springframework.web=DEBUG -#log4j.logger.org.springframework.jms=WARN -#log4j.logger.org.springframework.security=WARN - -log4j.logger.org.apache.activemq=WARN -log4j.logger.org.apache.activemq.transport=WARN -log4j.logger.org.apache.activemq.ActiveMQMessageConsumer=INFO -log4j.logger.org.apache.activemq.ActiveMQMessageProducer=INFO - -log4j.logger.org.apache.catalina=INFO -log4j.logger.org.apache.coyote=INFO -log4j.logger.org.apache.tomcat=INFO - -## Appenders -# console is set to be a ConsoleAppender. -log4j.appender.console=org.apache.log4j.ConsoleAppender - -# console uses PatternLayout. -log4j.appender.console.layout=org.apache.log4j.PatternLayout -log4j.appender.console.layout.ConversionPattern= %-5p %d{ISO8601} %m - %c%n diff --git a/security/runtime/org.argeo.security.core/src/test/resources/org/argeo/security/json/gandalf2.json b/security/runtime/org.argeo.security.core/src/test/resources/org/argeo/security/json/gandalf2.json deleted file mode 100644 index 73918229b..000000000 --- a/security/runtime/org.argeo.security.core/src/test/resources/org/argeo/security/json/gandalf2.json +++ /dev/null @@ -1 +0,0 @@ -{"roles":["ROLE_ADMIN","ROLE_USER"],"userNatures":[{"description":"Superuser","email":"admin@localhost","firstName":"Gandalf","lastName":"User","type":"org.argeo.security.nature.SimpleUserNature"},{"mobile":null,"telephoneNumber":null,"type":"org.argeo.security.nature.CoworkerNature"}],"username":"gandalf2","enabled":true,"password":"{SHA}ieSV55Qc+eQOaYDRSha/AjzNTJE=","authorities":[{"authority":"ROLE_ADMIN"},{"authority":"ROLE_USER"}],"accountNonExpired":true,"accountNonLocked":true,"credentialsNonExpired":true} \ No newline at end of file diff --git a/security/runtime/org.argeo.security.jackrabbit/.classpath b/security/runtime/org.argeo.security.jackrabbit/.classpath deleted file mode 100644 index 5641c7ca3..000000000 --- a/security/runtime/org.argeo.security.jackrabbit/.classpath +++ /dev/null @@ -1,7 +0,0 @@ - - - - >> - - - diff --git a/security/runtime/org.argeo.security.jackrabbit/.project b/security/runtime/org.argeo.security.jackrabbit/.project deleted file mode 100644 index 35bcca28f..000000000 --- a/security/runtime/org.argeo.security.jackrabbit/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - org.argeo.security.jackrabbit - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - - diff --git a/security/runtime/org.argeo.security.jackrabbit/build.properties b/security/runtime/org.argeo.security.jackrabbit/build.properties deleted file mode 100644 index 5fc538bc8..000000000 --- a/security/runtime/org.argeo.security.jackrabbit/build.properties +++ /dev/null @@ -1,4 +0,0 @@ -source.. = src/main/java/ -output.. = target/classes/ -bin.includes = META-INF/,\ - . diff --git a/security/runtime/org.argeo.security.jackrabbit/pom.xml b/security/runtime/org.argeo.security.jackrabbit/pom.xml deleted file mode 100644 index 9b27c41dc..000000000 --- a/security/runtime/org.argeo.security.jackrabbit/pom.xml +++ /dev/null @@ -1,58 +0,0 @@ - - 4.0.0 - - org.argeo.commons.security - runtime - 2.1.12-SNAPSHOT - .. - - org.argeo.security.jackrabbit - Commons Security Jackrabbit - - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-source-plugin - - - org.apache.maven.plugins - maven-jar-plugin - - - org.apache.felix - maven-bundle-plugin - - - - org.apache.jackrabbit - org.argeo.security.jackrabbit.* - *,org.springframework.core,org.argeo.jcr - - - - - - - - org.argeo.commons.security - org.argeo.security.core - 2.1.12-SNAPSHOT - - - org.argeo.tp - javax.jcr - - - org.argeo.tp - org.apache.jackrabbit - - - org.argeo.tp - org.springframework.security.core - - - \ No newline at end of file diff --git a/security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoAccessManager.java b/security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoAccessManager.java deleted file mode 100644 index 52ea3c984..000000000 --- a/security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoAccessManager.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.jackrabbit; - -import javax.jcr.PathNotFoundException; -import javax.jcr.RepositoryException; -import javax.jcr.security.Privilege; - -import org.apache.jackrabbit.core.id.ItemId; -import org.apache.jackrabbit.core.security.DefaultAccessManager; -import org.apache.jackrabbit.spi.Path; - -/** - * Intermediary class in order to have a consistent naming in config files. Does - * nothing for the time being, but may in the future. - */ -public class ArgeoAccessManager extends DefaultAccessManager { - - @Override - public boolean canRead(Path itemPath, ItemId itemId) - throws RepositoryException { - return super.canRead(itemPath, itemId); - } - - @Override - public Privilege[] getPrivileges(String absPath) - throws PathNotFoundException, RepositoryException { - return super.getPrivileges(absPath); - } - - @Override - public boolean hasPrivileges(String absPath, Privilege[] privileges) - throws PathNotFoundException, RepositoryException { - return super.hasPrivileges(absPath, privileges); - } - -} diff --git a/security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoLoginModule.java b/security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoLoginModule.java deleted file mode 100644 index 43c544083..000000000 --- a/security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoLoginModule.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.jackrabbit; - -import java.security.Principal; -import java.security.acl.Group; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Set; - -import javax.jcr.Credentials; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.SimpleCredentials; -import javax.security.auth.callback.CallbackHandler; -import javax.security.auth.login.LoginException; - -import org.apache.jackrabbit.core.security.AnonymousPrincipal; -import org.apache.jackrabbit.core.security.authentication.AbstractLoginModule; -import org.apache.jackrabbit.core.security.authentication.Authentication; -import org.apache.jackrabbit.core.security.principal.AdminPrincipal; -import org.argeo.security.SystemAuthentication; -import org.springframework.security.GrantedAuthority; -import org.springframework.security.context.SecurityContextHolder; -import org.springframework.security.providers.anonymous.AnonymousAuthenticationToken; - -/** Jackrabbit login mechanism based on Spring Security */ -public class ArgeoLoginModule extends AbstractLoginModule { - private String adminRole = "ROLE_ADMIN"; - - @SuppressWarnings("unused") - @Override - public boolean login() throws LoginException { - boolean loginOk = super.login(); - if (!loginOk) { - org.springframework.security.Authentication authen = (org.springframework.security.Authentication) SecurityContextHolder - .getContext().getAuthentication(); - } - return loginOk; - } - - @SuppressWarnings("unused") - @Override - public boolean commit() throws LoginException { - boolean commitOk = super.commit(); - if (!commitOk) { - org.springframework.security.Authentication authen = (org.springframework.security.Authentication) SecurityContextHolder - .getContext().getAuthentication(); - } - return commitOk; - } - - /** - * Returns the Spring {@link org.springframework.security.Authentication} - * (which can be null) - */ - @Override - protected Principal getPrincipal(Credentials credentials) { - org.springframework.security.Authentication authen = SecurityContextHolder - .getContext().getAuthentication(); - return authen; - } - - protected Set getPrincipals() { - // clear already registered Jackrabbit principals - // clearPrincipals(AdminPrincipal.class); - // clearPrincipals(AnonymousPrincipal.class); - // clearPrincipals(GrantedAuthorityPrincipal.class); - - return syncPrincipals(); - } - - protected Set syncPrincipals() { - // use linked HashSet instead of HashSet in order to maintain the order - // of principals (as in the Subject). - org.springframework.security.Authentication authen = (org.springframework.security.Authentication) principal; - - Set principals = new LinkedHashSet(); - principals.add(authen); - - if (authen instanceof SystemAuthentication) { - principals.add(new AdminPrincipal(authen.getName())); - principals.add(new ArgeoSystemPrincipal(authen.getName())); - } else if (authen instanceof AnonymousAuthenticationToken) { - principals.add(new AnonymousPrincipal()); - } else { - for (GrantedAuthority ga : authen.getAuthorities()) { - principals.add(new GrantedAuthorityPrincipal(ga)); - // FIXME: make it more generic - if (adminRole.equals(ga.getAuthority())) - principals.add(new AdminPrincipal(authen.getName())); - } - } - - // remove previous credentials - Set thisCredentials = subject - .getPublicCredentials(SimpleCredentials.class); - if (thisCredentials != null) - thisCredentials.clear(); - // override credentials since we did not used the one passed to us - // credentials = new SimpleCredentials(authen.getName(), authen - // .getCredentials().toString().toCharArray()); - - return principals; - } - - /** - * Super implementation removes all {@link Principal}, the Spring - * {@link org.springframework.security.Authentication} as well. Here we - * simply clear Jackrabbit related {@link Principal}s. - */ - @Override - public boolean logout() throws LoginException { - clearPrincipals(AdminPrincipal.class); - clearPrincipals(ArgeoSystemPrincipal.class); - clearPrincipals(AnonymousPrincipal.class); - clearPrincipals(GrantedAuthorityPrincipal.class); - - // we resync with Spring Security since the subject may have been reused - // in beetween - // TODO: check if this is clean - // subject.getPrincipals().addAll(syncPrincipals()); - - return true; - } - - private void clearPrincipals(Class clss) { - Set principals = subject.getPrincipals(clss); - if (principals != null) - principals.clear(); - } - - @SuppressWarnings("rawtypes") - @Override - protected void doInit(CallbackHandler callbackHandler, Session session, - Map options) throws LoginException { - } - - @Override - protected boolean impersonate(Principal principal, Credentials credentials) - throws RepositoryException, LoginException { - throw new UnsupportedOperationException( - "Impersonation is not yet supported"); - } - - @Override - protected Authentication getAuthentication(final Principal principal, - Credentials creds) throws RepositoryException { - if (principal instanceof Group) { - return null; - } - return new Authentication() { - public boolean canHandle(Credentials credentials) { - return principal instanceof org.springframework.security.Authentication; - } - - public boolean authenticate(Credentials credentials) - throws RepositoryException { - return ((org.springframework.security.Authentication) principal) - .isAuthenticated(); - } - }; - } - -} diff --git a/security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoSecurityManager.java b/security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoSecurityManager.java deleted file mode 100644 index 3450c75d8..000000000 --- a/security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoSecurityManager.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.jackrabbit; - -import java.security.Principal; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.security.auth.Subject; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.jackrabbit.api.security.user.Group; -import org.apache.jackrabbit.api.security.user.User; -import org.apache.jackrabbit.api.security.user.UserManager; -import org.apache.jackrabbit.core.DefaultSecurityManager; -import org.apache.jackrabbit.core.security.AMContext; -import org.apache.jackrabbit.core.security.AccessManager; -import org.apache.jackrabbit.core.security.AnonymousPrincipal; -import org.apache.jackrabbit.core.security.SecurityConstants; -import org.apache.jackrabbit.core.security.authorization.WorkspaceAccessManager; -import org.springframework.security.Authentication; -import org.springframework.security.GrantedAuthority; -import org.springframework.security.context.SecurityContextHolder; - -/** Integrates Spring Security and Jackrabbit Security users and roles. */ -public class ArgeoSecurityManager extends DefaultSecurityManager { - /** Legacy security sync */ - final static String PROPERTY_JACKRABBIT_SECURITY_SYNC_1_1 = "argeo.jackarabbit.securitySync.1.1"; - - private final static Log log = LogFactory - .getLog(ArgeoSecurityManager.class); - - private static Boolean synchronize = Boolean.parseBoolean(System - .getProperty(PROPERTY_JACKRABBIT_SECURITY_SYNC_1_1, "false")); - - /** TODO? use a bounded buffer */ - private Map userRolesCache = Collections - .synchronizedMap(new HashMap()); - - @Override - public AccessManager getAccessManager(Session session, AMContext amContext) - throws RepositoryException { - synchronized (getSystemSession()) { - return super.getAccessManager(session, amContext); - } - } - - @Override - public UserManager getUserManager(Session session) - throws RepositoryException { - synchronized (getSystemSession()) { - return super.getUserManager(session); - } - } - - /** - * Since this is called once when the session is created, we take the - * opportunity to make sure that Jackrabbit users and groups reflect Spring - * Security name and authorities. - */ - @Override - public String getUserID(Subject subject, String workspaceName) - throws RepositoryException { - if (!synchronize) { - Authentication authentication = SecurityContextHolder.getContext() - .getAuthentication(); - if (authentication != null) - return authentication.getName(); - else - return super.getUserID(subject, workspaceName); - } - - if (log.isTraceEnabled()) - log.trace(subject); - // skip anonymous user (no rights) - if (!subject.getPrincipals(AnonymousPrincipal.class).isEmpty()) - return super.getUserID(subject, workspaceName); - // skip Jackrabbit system user (all rights) - if (!subject.getPrincipals(ArgeoSystemPrincipal.class).isEmpty()) - return super.getUserID(subject, workspaceName); - - // retrieve Spring authentication from JAAS - // TODO? use Spring Security context holder - Authentication authen; - Set authens = subject - .getPrincipals(Authentication.class); - String userId = super.getUserID(subject, workspaceName); - if (authens.size() == 0) { - // make sure that logged-in user has a Principal, useful for testing - // using an admin user - UserManager systemUm = getSystemUserManager(null); - if (systemUm.getAuthorizable(userId) == null) - systemUm.createUser(userId, ""); - } else {// Spring Security - authen = authens.iterator().next(); - - if (!userId.equals(authen.getName())) - log.warn("User ID is '" + userId + "' but authen is " - + authen.getName()); - StringBuffer roles = new StringBuffer(""); - GrantedAuthority[] authorities = authen.getAuthorities(); - for (GrantedAuthority ga : authorities) { - roles.append(ga.toString()); - } - - // do not sync if not changed - if (userRolesCache.containsKey(userId) - && userRolesCache.get(userId).equals(roles.toString())) - return userId; - - // sync Spring and Jackrabbit - // workspace is irrelevant here - UserManager systemUm = getSystemUserManager(null); - syncSpringAndJackrabbitSecurity(systemUm, authen); - userRolesCache.put(userId, roles.toString()); - } - return userId; - } - - /** - * Make sure that the Jackrabbit security model contains this user and its - * granted authorities - */ - static private void syncSpringAndJackrabbitSecurity(UserManager systemUm, - Authentication authen) throws RepositoryException { - long begin = System.currentTimeMillis(); - - String userId = authen.getName(); - User user = (User) systemUm.getAuthorizable(userId); - if (user == null) { - user = systemUm.createUser(userId, authen.getCredentials() - .toString(), authen, null); - log.info(userId + " added as " + user); - } - - // process groups - List userGroupIds = new ArrayList(); - for (GrantedAuthority ga : authen.getAuthorities()) { - Group group = (Group) systemUm.getAuthorizable(ga.getAuthority()); - if (group == null) { - group = systemUm.createGroup(ga.getAuthority()); - log.info(ga.getAuthority() + " added as " + group); - } - if (!group.isMember(user)) - group.addMember(user); - userGroupIds.add(ga.getAuthority()); - } - - // check if user has not been removed from some groups - for (Iterator it = user.declaredMemberOf(); it.hasNext();) { - Group group = it.next(); - if (!userGroupIds.contains(group.getID())) - group.removeMember(user); - } - - if (log.isTraceEnabled()) - log.trace("Spring and Jackrabbit Security synchronized for user " - + userId + " in " + (System.currentTimeMillis() - begin) - + " ms"); - } - - @Override - protected WorkspaceAccessManager createDefaultWorkspaceAccessManager() { - WorkspaceAccessManager wam = super - .createDefaultWorkspaceAccessManager(); - return new ArgeoWorkspaceAccessManagerImpl(wam); - } - - private class ArgeoWorkspaceAccessManagerImpl implements SecurityConstants, - WorkspaceAccessManager { - private final WorkspaceAccessManager wam; - - public ArgeoWorkspaceAccessManagerImpl(WorkspaceAccessManager wam) { - super(); - this.wam = wam; - } - - public void init(Session systemSession) throws RepositoryException { - wam.init(systemSession); - } - - public void close() throws RepositoryException { - } - - public boolean grants(Set principals, String workspaceName) - throws RepositoryException { - // TODO: implements finer access to workspaces - return true; - } - } - -} diff --git a/security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoSystemPrincipal.java b/security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoSystemPrincipal.java deleted file mode 100644 index e38981ef4..000000000 --- a/security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoSystemPrincipal.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.jackrabbit; - -import java.security.Principal; - -/** Principal for non-interactive system actions. */ -class ArgeoSystemPrincipal implements Principal { - private String name; - - public ArgeoSystemPrincipal(String name) { - super(); - this.name = name; - } - - public String getName() { - return name; - } - - @Override - public int hashCode() { - return getName().hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof ArgeoSystemPrincipal)) - return false; - return getName().equals(((ArgeoSystemPrincipal) obj).getName()); - } - - @Override - public String toString() { - return "Argeo System (non interactive) name=" + getName(); - } - -} diff --git a/security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/GrantedAuthorityPrincipal.java b/security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/GrantedAuthorityPrincipal.java deleted file mode 100644 index 482214e50..000000000 --- a/security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/GrantedAuthorityPrincipal.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.jackrabbit; - -import java.security.Principal; - -import org.springframework.security.GrantedAuthority; - -/** Wraps a {@link GrantedAuthority} as a principal. */ -class GrantedAuthorityPrincipal implements Principal { - private final GrantedAuthority grantedAuthority; - - public GrantedAuthorityPrincipal(GrantedAuthority grantedAuthority) { - this.grantedAuthority = grantedAuthority; - } - - public String getName() { - return grantedAuthority.getAuthority(); - } - - @Override - public int hashCode() { - return getName().hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof GrantedAuthorityPrincipal)) - return false; - return getName().equals(((GrantedAuthorityPrincipal) obj).getName()); - } - - @Override - public String toString() { - return "Granted Authority " + getName(); - } - -} diff --git a/security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/JackrabbitSecurityModel.java b/security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/JackrabbitSecurityModel.java deleted file mode 100644 index a9985f94f..000000000 --- a/security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/JackrabbitSecurityModel.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.jackrabbit; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.jackrabbit.api.JackrabbitSession; -import org.apache.jackrabbit.api.security.user.Group; -import org.apache.jackrabbit.api.security.user.User; -import org.apache.jackrabbit.api.security.user.UserManager; -import org.argeo.ArgeoException; -import org.argeo.jcr.ArgeoNames; -import org.argeo.security.jcr.SimpleJcrSecurityModel; - -/** Make sure that user authorizable exists before syncing user directories. */ -public class JackrabbitSecurityModel extends SimpleJcrSecurityModel { - private final static Log log = LogFactory - .getLog(JackrabbitSecurityModel.class); - - @Override - public synchronized Node sync(Session session, String username, - List roles) { - if (!(session instanceof JackrabbitSession)) - return super.sync(session, username, roles); - - try { - UserManager userManager = ((JackrabbitSession) session) - .getUserManager(); - User user = (User) userManager.getAuthorizable(username); - if (user != null) { - String principalName = user.getPrincipal().getName(); - if (!principalName.equals(username)) { - log.warn("Jackrabbit principal is '" + principalName - + "' but username is '" + username - + "'. Recreating..."); - user.remove(); - user = userManager.createUser(username, ""); - } - } else { - // create new principal - user = userManager.createUser(username, ""); - log.info(username + " added as Jackrabbit user " + user); - } - - // generic JCR sync - Node userProfile = super.sync(session, username, roles); - - Boolean enabled = userProfile.getProperty(ArgeoNames.ARGEO_ENABLED) - .getBoolean(); - if (enabled && user.isDisabled()) - user.disable(null); - else if (!enabled && !user.isDisabled()) - user.disable(userProfile.getPath() + " is disabled"); - - // Sync Jackrabbit roles - if (roles != null) - syncRoles(userManager, user, roles); - - return userProfile; - } catch (RepositoryException e) { - throw new ArgeoException( - "Cannot perform Jackrabbit specific operations", e); - } - } - - /** Make sure Jackrabbit roles are in line with authentication */ - void syncRoles(UserManager userManager, User user, List roles) - throws RepositoryException { - List userGroupIds = new ArrayList(); - for (String role : roles) { - Group group = (Group) userManager.getAuthorizable(role); - if (group == null) { - group = userManager.createGroup(role); - log.info(role + " added as " + group); - } - if (!group.isMember(user)) - group.addMember(user); - userGroupIds.add(role); - } - - // check if user has not been removed from some groups - for (Iterator it = user.declaredMemberOf(); it.hasNext();) { - Group group = it.next(); - if (!userGroupIds.contains(group.getID())) - group.removeMember(user); - } - } -} diff --git a/security/runtime/org.argeo.security.ldap/.classpath b/security/runtime/org.argeo.security.ldap/.classpath deleted file mode 100644 index 5641c7ca3..000000000 --- a/security/runtime/org.argeo.security.ldap/.classpath +++ /dev/null @@ -1,7 +0,0 @@ - - - - >> - - - diff --git a/security/runtime/org.argeo.security.ldap/.project b/security/runtime/org.argeo.security.ldap/.project deleted file mode 100644 index 942f1404d..000000000 --- a/security/runtime/org.argeo.security.ldap/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - org.argeo.security.ldap - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - - diff --git a/security/runtime/org.argeo.security.ldap/build.properties b/security/runtime/org.argeo.security.ldap/build.properties deleted file mode 100644 index 5fc538bc8..000000000 --- a/security/runtime/org.argeo.security.ldap/build.properties +++ /dev/null @@ -1,4 +0,0 @@ -source.. = src/main/java/ -output.. = target/classes/ -bin.includes = META-INF/,\ - . diff --git a/security/runtime/org.argeo.security.ldap/pom.xml b/security/runtime/org.argeo.security.ldap/pom.xml deleted file mode 100644 index 01f52a0aa..000000000 --- a/security/runtime/org.argeo.security.ldap/pom.xml +++ /dev/null @@ -1,76 +0,0 @@ - - 4.0.0 - - org.argeo.commons.security - runtime - 2.1.12-SNAPSHOT - .. - - org.argeo.security.ldap - Commons Security LDAP - - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-source-plugin - - - org.apache.maven.plugins - maven-jar-plugin - - - org.apache.felix - maven-bundle-plugin - - - - - org.argeo.security.ldap.* - - - org.springframework.core, - org.springframework.dao, - javax.jcr.nodetype, - * - - - - - - - - - org.argeo.commons.base - org.argeo.util - 2.1.12-SNAPSHOT - - - org.argeo.commons.security - org.argeo.security.core - 2.1.12-SNAPSHOT - - - - - org.argeo.tp - javax.jcr - - - - - org.argeo.tp - org.springframework.ldap - - - - - org.argeo.tp - slf4j.org.apache.commons.logging - - - - \ No newline at end of file diff --git a/security/runtime/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/ArgeoLdapShaPasswordEncoder.java b/security/runtime/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/ArgeoLdapShaPasswordEncoder.java deleted file mode 100644 index ea22ef350..000000000 --- a/security/runtime/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/ArgeoLdapShaPasswordEncoder.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ldap; - -import org.springframework.security.providers.ldap.authenticator.LdapShaPasswordEncoder; - -/** - * {@link LdapShaPasswordEncoder} allowing to configure the usage of salt (APache - * Directory Server 1.0 does not support bind with SSHA) - */ -public class ArgeoLdapShaPasswordEncoder extends LdapShaPasswordEncoder { - private Boolean useSalt = true; - - @Override - public String encodePassword(String rawPass, Object salt) { - return super.encodePassword(rawPass, useSalt ? salt : null); - } - - public void setUseSalt(Boolean useSalt) { - this.useSalt = useSalt; - } - -} diff --git a/security/runtime/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/ArgeoLdapUserDetailsManager.java b/security/runtime/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/ArgeoLdapUserDetailsManager.java deleted file mode 100644 index 0c7368f1f..000000000 --- a/security/runtime/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/ArgeoLdapUserDetailsManager.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ldap; - -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.Random; -import java.util.Set; -import java.util.TreeSet; - -import org.argeo.ArgeoException; -import org.argeo.security.UserAdminService; -import org.springframework.ldap.core.ContextSource; -import org.springframework.security.Authentication; -import org.springframework.security.GrantedAuthority; -import org.springframework.security.context.SecurityContextHolder; -import org.springframework.security.providers.encoding.PasswordEncoder; -import org.springframework.security.userdetails.UserDetails; -import org.springframework.security.userdetails.ldap.LdapUserDetailsManager; - -/** Extends {@link LdapUserDetailsManager} by adding password encoding support. */ -public class ArgeoLdapUserDetailsManager extends LdapUserDetailsManager - implements UserAdminService { - private String superUsername = "root"; - private ArgeoUserAdminDaoLdap userAdminDao; - private PasswordEncoder passwordEncoder; - private final Random random; - - public ArgeoLdapUserDetailsManager(ContextSource contextSource) { - super(contextSource); - this.random = createRandom(); - } - - private static Random createRandom() { - try { - return SecureRandom.getInstance("SHA1PRNG"); - } catch (NoSuchAlgorithmException e) { - return new Random(System.currentTimeMillis()); - } - } - - @Override - public void changePassword(String oldPassword, String newPassword) { - Authentication authentication = SecurityContextHolder.getContext() - .getAuthentication(); - if (authentication == null) - throw new ArgeoException( - "Cannot change password without authentication"); - String username = authentication.getName(); - UserDetails userDetails = loadUserByUsername(username); - String currentPassword = userDetails.getPassword(); - if (currentPassword == null) - throw new ArgeoException("Cannot access current password"); - if (!passwordEncoder - .isPasswordValid(currentPassword, oldPassword, null)) - throw new ArgeoException("Old password invalid"); - // Spring Security LDAP 2.0 is buggy when used with OpenLDAP and called - // with oldPassword argument - super.changePassword(null, encodePassword(newPassword)); - } - - public void newRole(String role) { - userAdminDao.createRole(role, superUsername); - } - - public void synchronize() { - for (String username : userAdminDao.listUsers()) - loadUserByUsername(username); - // TODO: find a way to remove from JCR - } - - public void deleteRole(String role) { - userAdminDao.deleteRole(role); - } - - public Set listUsers() { - return userAdminDao.listUsers(); - } - - public Set listUsersInRole(String role) { - Set lst = new TreeSet( - userAdminDao.listUsersInRole(role)); - Iterator it = lst.iterator(); - while (it.hasNext()) { - if (it.next().equals(superUsername)) { - it.remove(); - break; - } - } - return lst; - } - - public List listUserRoles(String username) { - UserDetails userDetails = loadUserByUsername(username); - List roles = new ArrayList(); - for (GrantedAuthority ga : userDetails.getAuthorities()) { - roles.add(ga.getAuthority()); - } - return Collections.unmodifiableList(roles); - } - - public Set listEditableRoles() { - return userAdminDao.listEditableRoles(); - } - - protected String encodePassword(String password) { - if (!password.startsWith("{")) { - byte[] salt = new byte[16]; - random.nextBytes(salt); - return passwordEncoder.encodePassword(password, salt); - } else { - return password; - } - } - - public void setPasswordEncoder(PasswordEncoder passwordEncoder) { - this.passwordEncoder = passwordEncoder; - } - - public void setSuperUsername(String superUsername) { - this.superUsername = superUsername; - } - - public void setUserAdminDao(ArgeoUserAdminDaoLdap userAdminDao) { - this.userAdminDao = userAdminDao; - } - -} diff --git a/security/runtime/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/ArgeoUserAdminDaoLdap.java b/security/runtime/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/ArgeoUserAdminDaoLdap.java deleted file mode 100644 index 37d2a06a0..000000000 --- a/security/runtime/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/ArgeoUserAdminDaoLdap.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ldap; - -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.TreeSet; - -import javax.naming.Name; -import javax.naming.NamingException; -import javax.naming.directory.DirContext; - -import org.springframework.ldap.core.ContextExecutor; -import org.springframework.ldap.core.ContextMapper; -import org.springframework.ldap.core.DirContextAdapter; -import org.springframework.ldap.core.DistinguishedName; -import org.springframework.ldap.core.LdapTemplate; -import org.springframework.ldap.core.support.BaseLdapPathContextSource; -import org.springframework.security.ldap.LdapUsernameToDnMapper; -import org.springframework.security.ldap.LdapUtils; - -/** - * Wraps low-level LDAP operation on user and roles, used by - * {@link ArgeoLdapUserDetailsManager} - */ -public class ArgeoUserAdminDaoLdap { - private String userBase; - private String usernameAttribute; - private String groupBase; - private String[] groupClasses; - - private String groupRoleAttribute; - private String groupMemberAttribute; - private String defaultRole; - private String rolePrefix; - - private final LdapTemplate ldapTemplate; - private LdapUsernameToDnMapper usernameMapper; - - /** - * Standard constructor, using the LDAP context source shared with Spring - * Security components. - */ - public ArgeoUserAdminDaoLdap(BaseLdapPathContextSource contextSource) { - this.ldapTemplate = new LdapTemplate(contextSource); - } - - @SuppressWarnings("unchecked") - public synchronized Set listUsers() { - List usernames = (List) ldapTemplate.listBindings( - new DistinguishedName(userBase), new ContextMapper() { - public Object mapFromContext(Object ctxArg) { - DirContextAdapter ctx = (DirContextAdapter) ctxArg; - return ctx.getStringAttribute(usernameAttribute); - } - }); - - return Collections - .unmodifiableSortedSet(new TreeSet(usernames)); - } - - @SuppressWarnings("unchecked") - public Set listEditableRoles() { - return Collections.unmodifiableSortedSet(new TreeSet( - ldapTemplate.listBindings(groupBase, new ContextMapper() { - public Object mapFromContext(Object ctxArg) { - String groupName = ((DirContextAdapter) ctxArg) - .getStringAttribute(groupRoleAttribute); - String roleName = convertGroupToRole(groupName); - return roleName; - } - }))); - } - - @SuppressWarnings("unchecked") - public Set listUsersInRole(String role) { - return (Set) ldapTemplate.lookup( - buildGroupDn(convertRoleToGroup(role)), new ContextMapper() { - public Object mapFromContext(Object ctxArg) { - DirContextAdapter ctx = (DirContextAdapter) ctxArg; - String[] userDns = ctx - .getStringAttributes(groupMemberAttribute); - TreeSet set = new TreeSet(); - for (String userDn : userDns) { - DistinguishedName dn = new DistinguishedName(userDn); - String username = dn.getValue(usernameAttribute); - set.add(username); - } - return Collections.unmodifiableSortedSet(set); - } - }); - } - - public void createRole(String role, final String superuserName) { - String group = convertRoleToGroup(role); - DistinguishedName superuserDn = (DistinguishedName) ldapTemplate - .executeReadWrite(new ContextExecutor() { - public Object executeWithContext(DirContext ctx) - throws NamingException { - return LdapUtils.getFullDn( - usernameMapper.buildDn(superuserName), ctx); - } - }); - - Name groupDn = buildGroupDn(group); - DirContextAdapter context = new DirContextAdapter(); - context.setAttributeValues("objectClass", groupClasses); - context.setAttributeValue("cn", group); - // Add superuser because cannot create empty group - context.setAttributeValue(groupMemberAttribute, superuserDn.toString()); - ldapTemplate.bind(groupDn, context, null); - } - - public void deleteRole(String role) { - String group = convertRoleToGroup(role); - Name dn = buildGroupDn(group); - ldapTemplate.unbind(dn); - } - - /** Maps a role (ROLE_XXX) to the related LDAP group (xxx) */ - protected String convertRoleToGroup(String role) { - String group = role; - if (group.startsWith(rolePrefix)) { - group = group.substring(rolePrefix.length()); - group = group.toLowerCase(); - } - return group; - } - - /** Maps anLDAP group (xxx) to the related role (ROLE_XXX) */ - protected String convertGroupToRole(String groupName) { - groupName = groupName.toUpperCase(); - - return rolePrefix + groupName; - } - - protected Name buildGroupDn(String name) { - return new DistinguishedName(groupRoleAttribute + "=" + name + "," - + groupBase); - } - - public void setUserBase(String userBase) { - this.userBase = userBase; - } - - public void setUsernameAttribute(String usernameAttribute) { - this.usernameAttribute = usernameAttribute; - } - - public void setGroupBase(String groupBase) { - this.groupBase = groupBase; - } - - public void setGroupRoleAttribute(String groupRoleAttributeName) { - this.groupRoleAttribute = groupRoleAttributeName; - } - - public void setGroupMemberAttribute(String groupMemberAttributeName) { - this.groupMemberAttribute = groupMemberAttributeName; - } - - public void setDefaultRole(String defaultRole) { - this.defaultRole = defaultRole; - } - - public void setRolePrefix(String rolePrefix) { - this.rolePrefix = rolePrefix; - } - - public void setUsernameMapper(LdapUsernameToDnMapper usernameMapper) { - this.usernameMapper = usernameMapper; - } - - public String getDefaultRole() { - return defaultRole; - } - - public void setGroupClasses(String[] groupClasses) { - this.groupClasses = groupClasses; - } -} diff --git a/security/runtime/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/jcr/JcrLdapSynchronizer.java b/security/runtime/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/jcr/JcrLdapSynchronizer.java deleted file mode 100644 index 3e9e2cbfa..000000000 --- a/security/runtime/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/jcr/JcrLdapSynchronizer.java +++ /dev/null @@ -1,619 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ldap.jcr; - -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.SortedSet; -import java.util.UUID; - -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.query.Query; -import javax.jcr.version.VersionManager; -import javax.naming.Name; -import javax.naming.directory.BasicAttribute; -import javax.naming.directory.DirContext; -import javax.naming.directory.ModificationItem; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.ArgeoException; -import org.argeo.jcr.ArgeoNames; -import org.argeo.jcr.ArgeoTypes; -import org.argeo.jcr.JcrUtils; -import org.argeo.security.SecurityUtils; -import org.argeo.security.jcr.JcrSecurityModel; -import org.argeo.security.jcr.JcrUserDetails; -import org.argeo.security.jcr.SimpleJcrSecurityModel; -import org.springframework.ldap.core.ContextMapper; -import org.springframework.ldap.core.DirContextAdapter; -import org.springframework.ldap.core.DirContextOperations; -import org.springframework.ldap.core.DistinguishedName; -import org.springframework.ldap.core.LdapTemplate; -import org.springframework.security.GrantedAuthority; -import org.springframework.security.ldap.LdapUsernameToDnMapper; -import org.springframework.security.providers.encoding.PasswordEncoder; -import org.springframework.security.userdetails.UserDetails; -import org.springframework.security.userdetails.ldap.UserDetailsContextMapper; - -/** Makes sure that LDAP and JCR are in line. */ -public class JcrLdapSynchronizer implements UserDetailsContextMapper, - ArgeoNames { - private final static Log log = LogFactory.getLog(JcrLdapSynchronizer.class); - - // LDAP - private LdapTemplate ldapTemplate; - /** - * LDAP template whose context source has an object factory set to null. see - * this - */ - // private LdapTemplate rawLdapTemplate; - - private String userBase; - private String usernameAttribute; - private String passwordAttribute; - private String[] userClasses; - // private String defaultUserRole ="ROLE_USER"; - - // private NamingListener ldapUserListener; - // private SearchControls subTreeSearchControls; - private LdapUsernameToDnMapper usernameMapper; - - private PasswordEncoder passwordEncoder; - private final Random random; - - // JCR - /** Admin session on the main workspace */ - private Session nodeSession; - private Repository repository; - - // private JcrProfileListener jcrProfileListener; - private JcrSecurityModel jcrSecurityModel = new SimpleJcrSecurityModel(); - - // Mapping - private Map propertyToAttributes = new HashMap(); - - public JcrLdapSynchronizer() { - random = createRandom(); - } - - public void init() { - try { - nodeSession = repository.login(); - - // TODO put this in a different thread, and poll the LDAP server - // until it is up - try { - synchronize(); - - // LDAP - // subTreeSearchControls = new SearchControls(); - // subTreeSearchControls - // .setSearchScope(SearchControls.SUBTREE_SCOPE); - // LDAP listener - // ldapUserListener = new LdapUserListener(); - // rawLdapTemplate.executeReadOnly(new ContextExecutor() { - // public Object executeWithContext(DirContext ctx) - // throws NamingException { - // EventDirContext ectx = (EventDirContext) ctx.lookup(""); - // ectx.addNamingListener(userBase, "(" - // + usernameAttribute + "=*)", - // subTreeSearchControls, ldapUserListener); - // return null; - // } - // }); - } catch (Exception e) { - log.error("Could not synchronize and listen to LDAP," - + " probably because the LDAP server is not available." - + " Restart the system as soon as possible.", e); - } - - // JCR - // String[] nodeTypes = { ArgeoTypes.ARGEO_USER_PROFILE }; - // jcrProfileListener = new JcrProfileListener(); - // noLocal is used so that we are not notified when we modify JCR - // from LDAP - // nodeSession - // .getWorkspace() - // .getObservationManager() - // .addEventListener(jcrProfileListener, - // Event.PROPERTY_CHANGED | Event.NODE_ADDED, "/", - // true, null, nodeTypes, true); - } catch (Exception e) { - JcrUtils.logoutQuietly(nodeSession); - throw new ArgeoException("Cannot initialize LDAP/JCR synchronizer", - e); - } - } - - public void destroy() { - // JcrUtils.removeListenerQuietly(nodeSession, jcrProfileListener); - JcrUtils.logoutQuietly(nodeSession); - // try { - // rawLdapTemplate.executeReadOnly(new ContextExecutor() { - // public Object executeWithContext(DirContext ctx) - // throws NamingException { - // EventDirContext ectx = (EventDirContext) ctx.lookup(""); - // ectx.removeNamingListener(ldapUserListener); - // return null; - // } - // }); - // } catch (Exception e) { - // // silent (LDAP server may have been shutdown already) - // if (log.isTraceEnabled()) - // log.trace("Cannot remove LDAP listener", e); - // } - } - - /* - * LDAP TO JCR - */ - /** Full synchronization between LDAP and JCR. LDAP has priority. */ - protected void synchronize() { - try { - Name userBaseName = new DistinguishedName(userBase); - // TODO subtree search? - @SuppressWarnings("unchecked") - List userPaths = (List) ldapTemplate.listBindings( - userBaseName, new ContextMapper() { - public Object mapFromContext(Object ctxObj) { - try { - return mapLdapToJcr((DirContextAdapter) ctxObj); - } catch (Exception e) { - // do not break process because of error - log.error( - "Could not LDAP->JCR synchronize user " - + ctxObj, e); - return null; - } - } - }); - - // create accounts which are not in LDAP - Query query = nodeSession - .getWorkspace() - .getQueryManager() - .createQuery( - "select * from [" + ArgeoTypes.ARGEO_USER_PROFILE - + "]", Query.JCR_SQL2); - NodeIterator it = query.execute().getNodes(); - while (it.hasNext()) { - Node userProfile = it.nextNode(); - String path = userProfile.getPath(); - try { - if (!userPaths.contains(path)) { - String username = userProfile - .getProperty(ARGEO_USER_ID).getString(); - // GrantedAuthority[] authorities = {new - // GrantedAuthorityImpl(defaultUserRole)}; - GrantedAuthority[] authorities = {}; - JcrUserDetails userDetails = new JcrUserDetails( - userProfile, username, authorities); - String dn = createLdapUser(userDetails); - log.warn("Created ldap entry '" + dn + "' for user '" - + username + "'"); - - // if(!userProfile.getProperty(ARGEO_ENABLED).getBoolean()){ - // continue profiles; - // } - // - // log.warn("Path " - // + path - // + " not found in LDAP, disabling user " - // + userProfile.getProperty(ArgeoNames.ARGEO_USER_ID) - // .getString()); - - // Temporary hack to repair previous behaviour - if (!userProfile.getProperty(ARGEO_ENABLED) - .getBoolean()) { - VersionManager versionManager = nodeSession - .getWorkspace().getVersionManager(); - versionManager.checkout(userProfile.getPath()); - userProfile.setProperty(ArgeoNames.ARGEO_ENABLED, - true); - nodeSession.save(); - versionManager.checkin(userProfile.getPath()); - } - } - } catch (Exception e) { - log.error("Cannot process " + path, e); - } - } - } catch (Exception e) { - JcrUtils.discardQuietly(nodeSession); - log.error("Cannot synchronize LDAP and JCR", e); - // throw new ArgeoException("Cannot synchronize LDAP and JCR", e); - } - } - - private String createLdapUser(UserDetails user) { - DirContextAdapter ctx = new DirContextAdapter(); - mapUserToContext(user, ctx); - DistinguishedName dn = usernameMapper.buildDn(user.getUsername()); - ldapTemplate.bind(dn, ctx, null); - return dn.toString(); - } - - /** Called during authentication in order to retrieve user details */ - public UserDetails mapUserFromContext(final DirContextOperations ctx, - final String username, GrantedAuthority[] authorities) { - if (ctx == null) - throw new ArgeoException("No LDAP information for user " + username); - - String ldapUsername = ctx.getStringAttribute(usernameAttribute); - if (!ldapUsername.equals(username)) - throw new ArgeoException("Logged in with username " + username - + " but LDAP user is " + ldapUsername); - - Node userProfile = jcrSecurityModel.sync(nodeSession, username, - SecurityUtils.authoritiesToStringList(authorities)); - // JcrUserDetails.checkAccountStatus(userProfile); - - // password - SortedSet passwordAttributes = ctx - .getAttributeSortedStringSet(passwordAttribute); - String password; - if (passwordAttributes == null || passwordAttributes.size() == 0) { - //throw new ArgeoException("No password found for user " + username); - password = "NULL"; - } else { - byte[] arr = (byte[]) passwordAttributes.first(); - password = new String(arr); - // erase password - Arrays.fill(arr, (byte) 0); - } - - try { - return new JcrUserDetails(userProfile, password, authorities); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot retrieve user details for " - + username, e); - } - } - - /** - * Writes an LDAP context to the JCR user profile. - * - * @return path to user profile - */ - protected synchronized String mapLdapToJcr(DirContextAdapter ctx) { - Session session = nodeSession; - try { - // process - String username = ctx.getStringAttribute(usernameAttribute); - - Node userProfile = jcrSecurityModel.sync(session, username, null); - Map modifications = new HashMap(); - for (String jcrProperty : propertyToAttributes.keySet()) - ldapToJcr(userProfile, jcrProperty, ctx, modifications); - - int modifCount = modifications.size(); - if (modifCount > 0) { - session.getWorkspace().getVersionManager() - .checkout(userProfile.getPath()); - for (String prop : modifications.keySet()) - userProfile.setProperty(prop, modifications.get(prop)); - JcrUtils.updateLastModified(userProfile); - session.save(); - session.getWorkspace().getVersionManager() - .checkin(userProfile.getPath()); - if (log.isDebugEnabled()) - log.debug("Mapped " + modifCount + " LDAP modification" - + (modifCount == 1 ? "" : "s") + " from " - + ctx.getDn() + " to " + userProfile); - } - return userProfile.getPath(); - } catch (Exception e) { - JcrUtils.discardQuietly(session); - throw new ArgeoException("Cannot synchronize JCR and LDAP", e); - } - } - - /** Maps an LDAP property to a JCR property */ - protected void ldapToJcr(Node userProfile, String jcrProperty, - DirContextOperations ctx, Map modifications) { - // TODO do we really need DirContextOperations? - try { - String ldapAttribute; - if (propertyToAttributes.containsKey(jcrProperty)) - ldapAttribute = propertyToAttributes.get(jcrProperty); - else - throw new ArgeoException( - "No LDAP attribute mapped for JCR proprty " - + jcrProperty); - - String value = ctx.getStringAttribute(ldapAttribute); - String jcrValue = userProfile.hasProperty(jcrProperty) ? userProfile - .getProperty(jcrProperty).getString() : null; - if (value != null && jcrValue != null) { - if (!value.equals(jcrValue)) - modifications.put(jcrProperty, value); - } else if (value != null && jcrValue == null) { - modifications.put(jcrProperty, value); - } else if (value == null && jcrValue != null) { - modifications.put(jcrProperty, value); - } - } catch (Exception e) { - throw new ArgeoException("Cannot map JCR property " + jcrProperty - + " from LDAP", e); - } - } - - /* - * JCR to LDAP - */ - - public void mapUserToContext(UserDetails user, final DirContextAdapter ctx) { - if (!(user instanceof JcrUserDetails)) - throw new ArgeoException("Unsupported user details: " - + user.getClass()); - - ctx.setAttributeValues("objectClass", userClasses); - ctx.setAttributeValue(usernameAttribute, user.getUsername()); - ctx.setAttributeValue(passwordAttribute, - encodePassword(user.getPassword())); - - final JcrUserDetails jcrUserDetails = (JcrUserDetails) user; - try { - Node userProfile = nodeSession - .getNode(jcrUserDetails.getHomePath()).getNode( - ARGEO_PROFILE); - for (String jcrProperty : propertyToAttributes.keySet()) { - if (userProfile.hasProperty(jcrProperty)) { - ModificationItem mi = jcrToLdap(jcrProperty, userProfile - .getProperty(jcrProperty).getString()); - if (mi != null) - ctx.setAttribute(mi.getAttribute()); - } - } - if (log.isTraceEnabled()) - log.trace("Mapped " + userProfile + " to " + ctx.getDn()); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot synchronize JCR and LDAP", e); - } - - } - - /** Maps a JCR property to an LDAP property */ - protected ModificationItem jcrToLdap(String jcrProperty, String value) { - // TODO do we really need DirContextOperations? - try { - String ldapAttribute; - if (propertyToAttributes.containsKey(jcrProperty)) - ldapAttribute = propertyToAttributes.get(jcrProperty); - else - return null; - - // fix issue with empty 'sn' in LDAP - if (ldapAttribute.equals("sn") && (value.trim().equals(""))) - return null; - // fix issue with empty 'description' in LDAP - if (ldapAttribute.equals("description") && value.trim().equals("")) - return null; - BasicAttribute attr = new BasicAttribute( - propertyToAttributes.get(jcrProperty), value); - ModificationItem mi = new ModificationItem( - DirContext.REPLACE_ATTRIBUTE, attr); - return mi; - } catch (Exception e) { - throw new ArgeoException("Cannot map JCR property " + jcrProperty - + " from LDAP", e); - } - } - - /* - * UTILITIES - */ - protected String encodePassword(String password) { - if (!password.startsWith("{")) { - byte[] salt = new byte[16]; - random.nextBytes(salt); - return passwordEncoder.encodePassword(password, salt); - } else { - return password; - } - } - - private static Random createRandom() { - try { - return SecureRandom.getInstance("SHA1PRNG"); - } catch (NoSuchAlgorithmException e) { - return new Random(System.currentTimeMillis()); - } - } - - /* - * DEPENDENCY INJECTION - */ - - public void setLdapTemplate(LdapTemplate ldapTemplate) { - this.ldapTemplate = ldapTemplate; - } - - public void setRawLdapTemplate(LdapTemplate rawLdapTemplate) { - // this.rawLdapTemplate = rawLdapTemplate; - } - - public void setRepository(Repository repository) { - this.repository = repository; - } - - public void setUserBase(String userBase) { - this.userBase = userBase; - } - - public void setUsernameAttribute(String usernameAttribute) { - this.usernameAttribute = usernameAttribute; - } - - public void setPropertyToAttributes(Map propertyToAttributes) { - this.propertyToAttributes = propertyToAttributes; - } - - public void setUsernameMapper(LdapUsernameToDnMapper usernameMapper) { - this.usernameMapper = usernameMapper; - } - - public void setPasswordAttribute(String passwordAttribute) { - this.passwordAttribute = passwordAttribute; - } - - public void setUserClasses(String[] userClasses) { - this.userClasses = userClasses; - } - - public void setPasswordEncoder(PasswordEncoder passwordEncoder) { - this.passwordEncoder = passwordEncoder; - } - - public void setJcrSecurityModel(JcrSecurityModel jcrSecurityModel) { - this.jcrSecurityModel = jcrSecurityModel; - } - - /** Listen to LDAP */ - // class LdapUserListener implements ObjectChangeListener, - // NamespaceChangeListener, UnsolicitedNotificationListener { - // - // public void namingExceptionThrown(NamingExceptionEvent evt) { - // evt.getException().printStackTrace(); - // } - // - // public void objectChanged(NamingEvent evt) { - // Binding user = evt.getNewBinding(); - // // TODO find a way not to be called when JCR is the source of the - // // modification - // DirContextAdapter ctx = (DirContextAdapter) ldapTemplate - // .lookup(user.getName()); - // mapLdapToJcr(ctx); - // } - // - // public void objectAdded(NamingEvent evt) { - // Binding user = evt.getNewBinding(); - // DirContextAdapter ctx = (DirContextAdapter) ldapTemplate - // .lookup(user.getName()); - // mapLdapToJcr(ctx); - // } - // - // public void objectRemoved(NamingEvent evt) { - // if (log.isDebugEnabled()) - // log.debug(evt); - // } - // - // public void objectRenamed(NamingEvent evt) { - // if (log.isDebugEnabled()) - // log.debug(evt); - // } - // - // public void notificationReceived(UnsolicitedNotificationEvent evt) { - // UnsolicitedNotification notification = evt.getNotification(); - // NamingException ne = notification.getException(); - // String msg = "LDAP notification " + "ID=" + notification.getID() - // + ", referrals=" + notification.getReferrals(); - // if (ne != null) { - // if (log.isTraceEnabled()) - // log.trace(msg + ", exception= " + ne, ne); - // else - // log.warn(msg + ", exception= " + ne); - // } else if (log.isDebugEnabled()) { - // log.debug("Unsollicited LDAP notification " + msg); - // } - // } - // - // } - - /** Listen to JCR */ - // class JcrProfileListener implements EventListener { - // - // public void onEvent(EventIterator events) { - // try { - // final Map> modifications = new HashMap>(); - // while (events.hasNext()) { - // Event event = events.nextEvent(); - // try { - // if (Event.PROPERTY_CHANGED == event.getType()) { - // Property property = (Property) nodeSession - // .getItem(event.getPath()); - // String propertyName = property.getName(); - // Node userProfile = property.getParent(); - // String username = userProfile.getProperty( - // ARGEO_USER_ID).getString(); - // if (propertyToAttributes.containsKey(propertyName)) { - // Name name = usernameMapper.buildDn(username); - // if (!modifications.containsKey(name)) - // modifications.put(name, - // new ArrayList()); - // String value = property.getString(); - // ModificationItem mi = jcrToLdap(propertyName, - // value); - // if (mi != null) - // modifications.get(name).add(mi); - // } - // } else if (Event.NODE_ADDED == event.getType()) { - // Node userProfile = nodeSession.getNode(event - // .getPath()); - // String username = userProfile.getProperty( - // ARGEO_USER_ID).getString(); - // Name name = usernameMapper.buildDn(username); - // for (String propertyName : propertyToAttributes - // .keySet()) { - // if (!modifications.containsKey(name)) - // modifications.put(name, - // new ArrayList()); - // String value = userProfile.getProperty( - // propertyName).getString(); - // ModificationItem mi = jcrToLdap(propertyName, - // value); - // if (mi != null) - // modifications.get(name).add(mi); - // } - // } - // } catch (RepositoryException e) { - // throw new ArgeoException("Cannot process event " - // + event, e); - // } - // } - // - // for (Name name : modifications.keySet()) { - // List userModifs = modifications.get(name); - // int modifCount = userModifs.size(); - // ldapTemplate.modifyAttributes(name, userModifs - // .toArray(new ModificationItem[modifCount])); - // if (log.isDebugEnabled()) - // log.debug("Mapped " + modifCount + " JCR modification" - // + (modifCount == 1 ? "" : "s") + " to " + name); - // } - // } catch (Exception e) { - // // if (log.isDebugEnabled()) - // // e.printStackTrace(); - // throw new ArgeoException("Cannot process JCR events (" - // + e.getMessage() + ")", e); - // } - // } - // - // } -} diff --git a/security/runtime/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/jcr/JcrUserDetailsContextMapper.java b/security/runtime/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/jcr/JcrUserDetailsContextMapper.java deleted file mode 100644 index 87973d9bd..000000000 --- a/security/runtime/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/jcr/JcrUserDetailsContextMapper.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ldap.jcr; - -import java.util.UUID; - -import javax.jcr.Node; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.argeo.ArgeoException; -import org.argeo.jcr.ArgeoNames; -import org.argeo.jcr.JcrUtils; -import org.argeo.jcr.UserJcrUtils; -import org.argeo.security.jcr.JcrUserDetails; -import org.springframework.ldap.core.DirContextAdapter; -import org.springframework.ldap.core.DirContextOperations; -import org.springframework.security.GrantedAuthority; -import org.springframework.security.userdetails.UserDetails; -import org.springframework.security.userdetails.ldap.UserDetailsContextMapper; - -/** @deprecated Read only mapping from LDAP to user details */ -@Deprecated -public class JcrUserDetailsContextMapper implements UserDetailsContextMapper, - ArgeoNames { - /** Admin session on the security workspace */ - private Session securitySession; - private Repository repository; - private String securityWorkspace = "security"; - - public void init() { - try { - securitySession = repository.login(securityWorkspace); - } catch (RepositoryException e) { - JcrUtils.logoutQuietly(securitySession); - throw new ArgeoException( - "Cannot initialize LDAP/JCR user details context mapper", e); - } - } - - public void destroy() { - JcrUtils.logoutQuietly(securitySession); - } - - /** Called during authentication in order to retrieve user details */ - public UserDetails mapUserFromContext(final DirContextOperations ctx, - final String username, GrantedAuthority[] authorities) { - if (ctx == null) - throw new ArgeoException("No LDAP information for user " + username); - Node userHome = UserJcrUtils.getUserHome(securitySession, username); - if (userHome == null) - throw new ArgeoException("No JCR information for user " + username); - - // password - // SortedSet passwordAttributes = ctx - // .getAttributeSortedStringSet(passwordAttribute); - // String password; - // if (passwordAttributes == null || passwordAttributes.size() == 0) { - // throw new ArgeoException("No password found for user " + username); - // } else { - // byte[] arr = (byte[]) passwordAttributes.first(); - // password = new String(arr); - // // erase password - // Arrays.fill(arr, (byte) 0); - // } - - try { - // we don't have access to password, so let's not pretend - String password = UUID.randomUUID().toString(); - return new JcrUserDetails(userHome.getNode(ARGEO_PROFILE), - password, authorities); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot retrieve user details for " - + username, e); - } - } - - public void mapUserToContext(UserDetails user, final DirContextAdapter ctx) { - throw new UnsupportedOperationException("LDAP access is read-only"); - } - -} diff --git a/security/runtime/org.argeo.security.mvc/.classpath b/security/runtime/org.argeo.security.mvc/.classpath deleted file mode 100644 index ff41fbb4d..000000000 --- a/security/runtime/org.argeo.security.mvc/.classpath +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/security/runtime/org.argeo.security.mvc/.project b/security/runtime/org.argeo.security.mvc/.project deleted file mode 100644 index b287d0835..000000000 --- a/security/runtime/org.argeo.security.mvc/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - org.argeo.security.mvc - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.jdt.core.javanature - org.eclipse.pde.PluginNature - - diff --git a/security/runtime/org.argeo.security.mvc/.settings/org.eclipse.jdt.core.prefs b/security/runtime/org.argeo.security.mvc/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index d2110d0b1..000000000 --- a/security/runtime/org.argeo.security.mvc/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,5 +0,0 @@ -#Tue Sep 15 11:35:07 CEST 2009 -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 -org.eclipse.jdt.core.compiler.compliance=1.5 -org.eclipse.jdt.core.compiler.source=1.5 diff --git a/security/runtime/org.argeo.security.mvc/.settings/org.maven.ide.eclipse.prefs b/security/runtime/org.argeo.security.mvc/.settings/org.maven.ide.eclipse.prefs deleted file mode 100644 index 2169c4308..000000000 --- a/security/runtime/org.argeo.security.mvc/.settings/org.maven.ide.eclipse.prefs +++ /dev/null @@ -1,9 +0,0 @@ -#Tue Sep 15 11:35:01 CEST 2009 -activeProfiles= -eclipse.preferences.version=1 -fullBuildGoals=process-test-resources -includeModules=false -resolveWorkspaceProjects=true -resourceFilterGoals=process-resources resources\:testResources -skipCompilerPlugin=true -version=1 diff --git a/security/runtime/org.argeo.security.mvc/build.properties b/security/runtime/org.argeo.security.mvc/build.properties deleted file mode 100644 index a740a346d..000000000 --- a/security/runtime/org.argeo.security.mvc/build.properties +++ /dev/null @@ -1,2 +0,0 @@ -additional.bundles = org.springframework.beans -source.. = src/main/java/ diff --git a/security/runtime/org.argeo.security.mvc/pom.xml b/security/runtime/org.argeo.security.mvc/pom.xml deleted file mode 100644 index e2a0c08d6..000000000 --- a/security/runtime/org.argeo.security.mvc/pom.xml +++ /dev/null @@ -1,72 +0,0 @@ - - 4.0.0 - - org.argeo.commons.security - runtime - 2.1.12-SNAPSHOT - .. - - org.argeo.security.mvc - Commons Security MVC - - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-source-plugin - - - org.apache.maven.plugins - maven-jar-plugin - - - org.apache.felix - maven-bundle-plugin - - - - - org.argeo.security.mvc.* - - *,javax.servlet - - - - - - - - - org.argeo.commons.server - org.argeo.server.core - 2.1.12-SNAPSHOT - - - - - org.argeo.commons.security - org.argeo.security.core - 2.1.12-SNAPSHOT - - - - - org.argeo.tp - org.springframework.web.servlet - - - org.argeo.tp - org.springframework.aop - - - - - org.argeo.tp - javax.servlet - - - - \ No newline at end of file diff --git a/security/runtime/org.argeo.security.mvc/src/main/java/org/argeo/security/mvc/ArgeoRememberMeServices.java b/security/runtime/org.argeo.security.mvc/src/main/java/org/argeo/security/mvc/ArgeoRememberMeServices.java deleted file mode 100644 index fde9f3034..000000000 --- a/security/runtime/org.argeo.security.mvc/src/main/java/org/argeo/security/mvc/ArgeoRememberMeServices.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2007-2012 Mathieu Baudier - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.mvc; - -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.springframework.security.ui.rememberme.TokenBasedRememberMeServices; - -public class ArgeoRememberMeServices extends TokenBasedRememberMeServices { - public final static String DEFAULT_COOKIE_NAME = "ARGEO_SECURITY"; - - public ArgeoRememberMeServices() { - setCookieName(DEFAULT_COOKIE_NAME); - } - - /** - * Sets a "cancel cookie" (with maxAge = 0) on the response to disable - * persistent logins. - * - * @param request - * @param response - */ - protected void cancelCookie(HttpServletRequest request, - HttpServletResponse response) { - Cookie cookie = new Cookie(getCookieName(), null); - cookie.setMaxAge(0); - cookie.setPath("/"); - - response.addCookie(cookie); - } - - /** - * Sets the cookie on the response - * - * @param tokens - * the tokens which will be encoded to make the cookie value. - * @param maxAge - * the value passed to {@link Cookie#setMaxAge(int)} - * @param request - * the request - * @param response - * the response to add the cookie to. - */ - protected void setCookie(String[] tokens, int maxAge, - HttpServletRequest request, HttpServletResponse response) { - String cookieValue = encodeCookie(tokens); - Cookie cookie = new Cookie(getCookieName(), cookieValue); - cookie.setMaxAge(maxAge); - cookie.setPath("/"); - response.addCookie(cookie); - } - -} diff --git a/security/runtime/org.argeo.security.mvc/src/main/java/org/argeo/security/mvc/ArgeoUserInterceptor.java b/security/runtime/org.argeo.security.mvc/src/main/java/org/argeo/security/mvc/ArgeoUserInterceptor.java deleted file mode 100644 index fd83e9f73..000000000 --- a/security/runtime/org.argeo.security.mvc/src/main/java/org/argeo/security/mvc/ArgeoUserInterceptor.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2007-2012 Mathieu Baudier - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.mvc; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.argeo.security.UserAdminService; -import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; - -/** Add the current argeo user as an attribute to the request. */ -public class ArgeoUserInterceptor extends HandlerInterceptorAdapter { - private UserAdminService securityService; - - @Override - public boolean preHandle(HttpServletRequest request, - HttpServletResponse response, Object handler) throws Exception { - //request.setAttribute("argeoUser", securityService.getCurrentUser()); - return super.preHandle(request, response, handler); - } - - public void setSecurityService(UserAdminService securityService) { - this.securityService = securityService; - } - -} diff --git a/security/runtime/org.argeo.security.mvc/src/main/java/org/argeo/security/mvc/UsersRolesController.java b/security/runtime/org.argeo.security.mvc/src/main/java/org/argeo/security/mvc/UsersRolesController.java deleted file mode 100644 index 185d376a6..000000000 --- a/security/runtime/org.argeo.security.mvc/src/main/java/org/argeo/security/mvc/UsersRolesController.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2007-2012 Mathieu Baudier - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.mvc; - -import org.argeo.server.mvc.MvcConstants; -import org.springframework.stereotype.Controller; - -@Controller -public class UsersRolesController implements MvcConstants { -// private ArgeoSecurityService securityService; -// private Deserializer userDeserializer = null; - - /* USER */ - -// @RequestMapping("/getCredentials.*") -// @ModelAttribute("user") -// public ArgeoUser getCredentials() { -// ArgeoUser argeoUser = securityService.getCurrentUser(); -// if (argeoUser == null) -// return new SimpleArgeoUser(); -// else -// return argeoUser; -// } -// -// @RequestMapping("/getUsersList.*") -// @ModelAttribute("users") -// public Set getUsersList() { -// return securityService.listUsers(); -// } -// -// @RequestMapping("/userExists.*") -// public BooleanAnswer userExists(@RequestParam("username") String username) { -// return new BooleanAnswer(securityService.userExists(username)); -// } -// -// @RequestMapping("/createUser.*") -// @ModelAttribute("user") -// public ArgeoUser createUser(Reader reader) { -// ArgeoUser user = userDeserializer.deserialize(reader, -// SimpleArgeoUser.class); -// securityService.newUser(user); -// return securityService.getUser(user.getUsername()); -// } -// -// @RequestMapping("/updateUser.*") -// @ModelAttribute("user") -// public ArgeoUser updateUser(Reader reader) { -// ArgeoUser user = userDeserializer.deserialize(reader, -// SimpleArgeoUser.class); -// securityService.updateUser(user); -// return securityService.getUser(user.getUsername()); -// } -// -// @RequestMapping("/updateUserSelf.*") -// @ModelAttribute("user") -// /** Will only update the user natures.*/ -// public ArgeoUser updateUserSelf(Reader reader) { -// ArgeoUser user = securityService.getCurrentUser(); -// ArgeoUser userForNatures = userDeserializer.deserialize(reader, -// SimpleArgeoUser.class); -// user.updateUserNatures(userForNatures.getUserNatures()); -// securityService.updateUser(user); -// return securityService.getUser(user.getUsername()); -// } -// -// @RequestMapping("/deleteUser.*") -// public ServerAnswer deleteUser(@RequestParam("username") String username) { -// securityService.deleteUser(username); -// return ServerAnswer.ok("User " + username + " deleted"); -// } -// -// @RequestMapping("/getUserDetails.*") -// @ModelAttribute("user") -// public ArgeoUser getUserDetails(@RequestParam("username") String username) { -// return securityService.getUser(username); -// } - - /* ROLE */ -// @RequestMapping("/getRolesList.*") -// @ModelAttribute("roles") -// public Set getEditableRolesList() { -// return securityService.listEditableRoles(); -// } -// -// @RequestMapping("/createRole.*") -// public ServerAnswer createRole(@RequestParam("role") String role) { -// securityService.newRole(role); -// return ServerAnswer.ok("Role " + role + " created"); -// } -// -// @RequestMapping("/deleteRole.*") -// public ServerAnswer deleteRole(@RequestParam("role") String role) { -// securityService.deleteRole(role); -// return ServerAnswer.ok("Role " + role + " deleted"); -// } -// -// @RequestMapping("/updateUserPassword.*") -// public ServerAnswer updateUserPassword( -// @RequestParam("username") String username, -// @RequestParam("password") String password) { -// securityService.updateUserPassword(username, password); -// return ServerAnswer.ok("Password updated for user " + username); -// } -// -// @RequestMapping("/updatePassword.*") -// public ServerAnswer updatePassword( -// @RequestParam("oldPassword") String oldPassword, -// @RequestParam("password") String password) { -// securityService.updateCurrentUserPassword(oldPassword, password); -// return ServerAnswer.ok("Password updated"); -// } -// -// public void setUserDeserializer(Deserializer userDeserializer) { -// this.userDeserializer = userDeserializer; -// } -// -// public void setSecurityService(ArgeoSecurityService securityService) { -// this.securityService = securityService; -// } - -} diff --git a/security/runtime/pom.xml b/security/runtime/pom.xml index 7f0516f60..c3fa23e44 100644 --- a/security/runtime/pom.xml +++ b/security/runtime/pom.xml @@ -7,8 +7,8 @@ security .. - org.argeo.commons.security - runtime + org.argeo.commons + argeo-commons Commons Security Runtime pom diff --git a/server/dep/org.argeo.server.dep.activemq/pom.xml b/server/dep/org.argeo.server.dep.activemq/pom.xml index 0907ec653..e9272c4fe 100644 --- a/server/dep/org.argeo.server.dep.activemq/pom.xml +++ b/server/dep/org.argeo.server.dep.activemq/pom.xml @@ -1,7 +1,7 @@ 4.0.0 - org.argeo.commons.server + org.argeo.commons 2.1.12-SNAPSHOT dep .. @@ -12,7 +12,7 @@ - org.argeo.commons.base + org.argeo.commons org.argeo.dep.log4j 2.1.12-SNAPSHOT pom @@ -52,7 +52,7 @@ - + diff --git a/server/dep/org.argeo.server.dep.ads/pom.xml b/server/dep/org.argeo.server.dep.ads/pom.xml deleted file mode 100644 index 2de5b8313..000000000 --- a/server/dep/org.argeo.server.dep.ads/pom.xml +++ /dev/null @@ -1,54 +0,0 @@ - - 4.0.0 - - org.argeo.commons.server - 2.1.12-SNAPSHOT - dep - .. - - org.argeo.server.dep.ads - pom - Commons Apache Directory Server Dependencies - - - - org.argeo.commons.base - org.argeo.dep.log4j - 2.1.12-SNAPSHOT - pom - - - - - org.argeo.tp - org.apache.directory.server.core - - - org.argeo.tp - org.apache.directory.shared.asn.codec - - - org.argeo.tp - org.apache.mina.filter.ssl - - - org.argeo.tp - org.apache.directory.server.jndi - - - org.argeo.tp - jdbm - - - org.argeo.commons.server - org.argeo.ext.jdbm - 2.1.12-SNAPSHOT - - - - org.argeo.tp - org.apache.commons.lang - - - \ No newline at end of file diff --git a/server/dep/org.argeo.server.dep.hibernate/pom.xml b/server/dep/org.argeo.server.dep.hibernate/pom.xml index b493709b0..0f2e047a8 100644 --- a/server/dep/org.argeo.server.dep.hibernate/pom.xml +++ b/server/dep/org.argeo.server.dep.hibernate/pom.xml @@ -1,7 +1,7 @@ 4.0.0 - org.argeo.commons.server + org.argeo.commons 2.1.12-SNAPSHOT dep .. @@ -12,7 +12,7 @@ - org.argeo.commons.base + org.argeo.commons org.argeo.dep.log4j 2.1.12-SNAPSHOT pom diff --git a/server/dep/org.argeo.server.dep.jackrabbit.server/pom.xml b/server/dep/org.argeo.server.dep.jackrabbit.server/pom.xml deleted file mode 100644 index 6fd745180..000000000 --- a/server/dep/org.argeo.server.dep.jackrabbit.server/pom.xml +++ /dev/null @@ -1,79 +0,0 @@ - - 4.0.0 - - org.argeo.commons.server - 2.1.12-SNAPSHOT - dep - .. - - org.argeo.server.dep.jackrabbit.server - pom - Commons Jackrabbit Dependencies - - - org.argeo.commons.base - org.argeo.dep.jackrabbit - pom - 2.1.12-SNAPSHOT - - - - - org.argeo.tp - bcprov - - - org.argeo.tp - bcmail - - - - - - - - org.argeo.tp - org.apache.xmlbeans - - - org.argeo.tp - org.apache.xmlcommons - - - org.argeo.tp - org.apache.pdfbox - - - org.argeo.tp - org.apache.poi - - - org.argeo.tp - com.sun.syndication - - - org.argeo.tp - org.cyberneko.html - - - org.argeo.tp - de.l3s.boilerpipe - - - org.argeo.tp - javax.mail - - - org.argeo.tp - com.drewnoakes.metadata_extractor - - - org.argeo.tp - edu.ucar.unidata.netcdf - - - org.argeo.tp - org.ccil.cowan.tagsoup - - - \ No newline at end of file diff --git a/server/dep/org.argeo.server.dep.tomcat/pom.xml b/server/dep/org.argeo.server.dep.tomcat/pom.xml index 1188a0626..6f0ae7e84 100644 --- a/server/dep/org.argeo.server.dep.tomcat/pom.xml +++ b/server/dep/org.argeo.server.dep.tomcat/pom.xml @@ -2,7 +2,7 @@ 4.0.0 - org.argeo.commons.server + org.argeo.commons 2.1.12-SNAPSHOT dep .. @@ -13,7 +13,7 @@ - org.argeo.commons.base + org.argeo.commons org.argeo.dep.log4j 2.1.12-SNAPSHOT pom @@ -21,12 +21,12 @@ - org.argeo.commons.server + org.argeo.commons org.argeo.server.catalina 2.1.12-SNAPSHOT - org.argeo.commons.server + org.argeo.commons org.argeo.server.catalina.start 2.1.12-SNAPSHOT @@ -98,7 +98,7 @@ - org.argeo.commons.base + org.argeo.commons org.argeo.osgi.boot 2.1.12-SNAPSHOT test diff --git a/server/dep/pom.xml b/server/dep/pom.xml index 244df7fd1..008fc2f47 100644 --- a/server/dep/pom.xml +++ b/server/dep/pom.xml @@ -7,7 +7,7 @@ server .. - org.argeo.commons.server + org.argeo.commons dep Commons Server Dependencies pom @@ -44,7 +44,7 @@ - org.argeo.commons.base + org.argeo.commons org.argeo.osgi.boot 2.1.12-SNAPSHOT test diff --git a/server/modules/org.argeo.ext.bsf/pom.xml b/server/modules/org.argeo.ext.bsf/pom.xml index 47e4d3cca..d5907912e 100644 --- a/server/modules/org.argeo.ext.bsf/pom.xml +++ b/server/modules/org.argeo.ext.bsf/pom.xml @@ -1,8 +1,8 @@ 4.0.0 - org.argeo.commons.server - modules + org.argeo.commons + argeo-commons 2.1.12-SNAPSHOT .. diff --git a/server/modules/org.argeo.ext.jackrabbit.sybase/pom.xml b/server/modules/org.argeo.ext.jackrabbit.sybase/pom.xml index d5ee376ed..14cff8f4f 100644 --- a/server/modules/org.argeo.ext.jackrabbit.sybase/pom.xml +++ b/server/modules/org.argeo.ext.jackrabbit.sybase/pom.xml @@ -1,9 +1,9 @@ 4.0.0 - org.argeo.commons.server + org.argeo.commons 2.1.12-SNAPSHOT - modules + argeo-commons .. org.argeo.ext.jackrabbit.sybase diff --git a/server/modules/org.argeo.ext.jdbm/.project b/server/modules/org.argeo.ext.jdbm/.project deleted file mode 100644 index b1d7029b9..000000000 --- a/server/modules/org.argeo.ext.jdbm/.project +++ /dev/null @@ -1,22 +0,0 @@ - - - org.argeo.ext.jdbm - - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - - diff --git a/server/modules/org.argeo.ext.jdbm/build.properties b/server/modules/org.argeo.ext.jdbm/build.properties deleted file mode 100644 index 5f22cdd44..000000000 --- a/server/modules/org.argeo.ext.jdbm/build.properties +++ /dev/null @@ -1 +0,0 @@ -bin.includes = META-INF/ diff --git a/server/modules/org.argeo.ext.jdbm/pom.xml b/server/modules/org.argeo.ext.jdbm/pom.xml deleted file mode 100644 index 876568ea7..000000000 --- a/server/modules/org.argeo.ext.jdbm/pom.xml +++ /dev/null @@ -1,32 +0,0 @@ - - 4.0.0 - - org.argeo.commons.server - 2.1.12-SNAPSHOT - modules - .. - - org.argeo.ext.jdbm - Commons Server JDBM Extension - Add Apache Directory Server support to JDBM - - - - org.apache.felix - maven-bundle-plugin - - - jdbm - - org.apache.directory.server.core.partition.impl.btree.jdbm;resolution:=optional, - org.apache.directory.server.core.schema;resolution:=optional, - org.apache.directory.server.core.partition.impl;resolution:=optional, - org.apache.directory.server.core.partition.impl.btree;resolution:=optional, - org.apache.directory.shared.ldap.message;resolution:=optional, - - - - - - - \ No newline at end of file diff --git a/server/modules/org.argeo.jackrabbit.webapp/.project b/server/modules/org.argeo.jackrabbit.webapp/.project deleted file mode 100644 index 37eed0584..000000000 --- a/server/modules/org.argeo.jackrabbit.webapp/.project +++ /dev/null @@ -1,22 +0,0 @@ - - - org.argeo.jackrabbit.webapp - - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - - diff --git a/server/modules/org.argeo.jackrabbit.webapp/.settings/org.eclipse.pde.core.prefs b/server/modules/org.argeo.jackrabbit.webapp/.settings/org.eclipse.pde.core.prefs deleted file mode 100644 index ee0c8b2c0..000000000 --- a/server/modules/org.argeo.jackrabbit.webapp/.settings/org.eclipse.pde.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -#Tue Feb 22 17:15:24 CET 2011 -eclipse.preferences.version=1 -pluginProject.extensions=false -resolve.requirebundle=false diff --git a/server/modules/org.argeo.jackrabbit.webapp/WEB-INF/applicationContext.xml b/server/modules/org.argeo.jackrabbit.webapp/WEB-INF/applicationContext.xml deleted file mode 100644 index 723e6c70f..000000000 --- a/server/modules/org.argeo.jackrabbit.webapp/WEB-INF/applicationContext.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - osgibundle:jackrabbit-webapp.properties - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/server/modules/org.argeo.jackrabbit.webapp/WEB-INF/osgi.xml b/server/modules/org.argeo.jackrabbit.webapp/WEB-INF/osgi.xml deleted file mode 100644 index b4a3c48df..000000000 --- a/server/modules/org.argeo.jackrabbit.webapp/WEB-INF/osgi.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/server/modules/org.argeo.jackrabbit.webapp/WEB-INF/remoting-servlet.xml b/server/modules/org.argeo.jackrabbit.webapp/WEB-INF/remoting-servlet.xml deleted file mode 100644 index f5cd4d609..000000000 --- a/server/modules/org.argeo.jackrabbit.webapp/WEB-INF/remoting-servlet.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/server/modules/org.argeo.jackrabbit.webapp/WEB-INF/security-filters.xml b/server/modules/org.argeo.jackrabbit.webapp/WEB-INF/security-filters.xml deleted file mode 100644 index 52238a7de..000000000 --- a/server/modules/org.argeo.jackrabbit.webapp/WEB-INF/security-filters.xml +++ /dev/null @@ -1,147 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - PATTERN_TYPE_APACHE_ANT - /**=ROLE_USER,ROLE_ADMIN - - - - - - - PATTERN_TYPE_APACHE_ANT - /**=IS_AUTHENTICATED_ANONYMOUSLY - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ${argeo.server.realmName} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/server/modules/org.argeo.jackrabbit.webapp/WEB-INF/web.xml b/server/modules/org.argeo.jackrabbit.webapp/WEB-INF/web.xml deleted file mode 100644 index a1876b306..000000000 --- a/server/modules/org.argeo.jackrabbit.webapp/WEB-INF/web.xml +++ /dev/null @@ -1,111 +0,0 @@ - - - - Argeo Jackrabbit Webapp - - - - 5 - - - - - contextConfigLocation - /WEB-INF/applicationContext.xml - - - - Spring Context - org.springframework.web.context.ContextLoaderListener - - - contextClass - org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext - - - - - remoting - org.argeo.jackrabbit.remote.ExtendedDispatcherServlet - - contextClass - org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext - - - dispatchOptionsRequest - true - - 1 - - - - remoting - /jcr/* - - - - remoting - /pub/* - - - - - webdav - org.argeo.jackrabbit.remote.ExtendedDispatcherServlet - - contextClass - org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext - - - dispatchOptionsRequest - true - - 1 - - - - webdav - /files/* - - - - webdav - /public/* - - - - - filterChain.davex - org.springframework.web.filter.DelegatingFilterProxy - - - filterChain.davex - /jcr/* - - - - filterChain.private - org.springframework.web.filter.DelegatingFilterProxy - - - filterChain.private - /files/* - - - - filterChain.public - org.springframework.web.filter.DelegatingFilterProxy - - - filterChain.public - /pub/* - - - filterChain.public - /public/* - - - diff --git a/server/modules/org.argeo.jackrabbit.webapp/WEB-INF/webdav-config.xml b/server/modules/org.argeo.jackrabbit.webapp/WEB-INF/webdav-config.xml deleted file mode 100644 index da4e18b11..000000000 --- a/server/modules/org.argeo.jackrabbit.webapp/WEB-INF/webdav-config.xml +++ /dev/null @@ -1,197 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - nt:file - nt:resource - - - - - - - - - - - - - rep - jcr - - - - - - - diff --git a/server/modules/org.argeo.jackrabbit.webapp/WEB-INF/webdav-servlet.xml b/server/modules/org.argeo.jackrabbit.webapp/WEB-INF/webdav-servlet.xml deleted file mode 100644 index 561d20c03..000000000 --- a/server/modules/org.argeo.jackrabbit.webapp/WEB-INF/webdav-servlet.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/server/modules/org.argeo.jackrabbit.webapp/build.properties b/server/modules/org.argeo.jackrabbit.webapp/build.properties deleted file mode 100644 index 5f22cdd44..000000000 --- a/server/modules/org.argeo.jackrabbit.webapp/build.properties +++ /dev/null @@ -1 +0,0 @@ -bin.includes = META-INF/ diff --git a/server/modules/org.argeo.jackrabbit.webapp/jackrabbit-webapp.properties b/server/modules/org.argeo.jackrabbit.webapp/jackrabbit-webapp.properties deleted file mode 100644 index 47f47b93b..000000000 --- a/server/modules/org.argeo.jackrabbit.webapp/jackrabbit-webapp.properties +++ /dev/null @@ -1,3 +0,0 @@ -argeo.security.systemKey=argeo -argeo.server.realmName=Argeo -argeo.jcr.webapp.rememberMeValidity=3600 \ No newline at end of file diff --git a/server/modules/org.argeo.jackrabbit.webapp/pom.xml b/server/modules/org.argeo.jackrabbit.webapp/pom.xml deleted file mode 100644 index 3d70d939b..000000000 --- a/server/modules/org.argeo.jackrabbit.webapp/pom.xml +++ /dev/null @@ -1,61 +0,0 @@ - - 4.0.0 - - org.argeo.commons.server - 2.1.12-SNAPSHOT - modules - .. - - org.argeo.jackrabbit.webapp - Commons Server Jackrabbit Webapp - JCR remoting, WebDav - - - - org.apache.felix - maven-bundle-plugin - - - data - - - *, - javax.jcr, - javax.servlet, - javax.servlet.http, - javax.servlet.resources, - org.aopalliance.aop, - org.argeo.jackrabbit.remote, - org.argeo.jcr, - org.argeo.jcr.mvc, - org.springframework.aop, - org.springframework.aop.framework, - org.springframework.aop.scope, - org.springframework.beans.factory.config, - org.springframework.osgi.web.context.support, - org.springframework.security, - org.springframework.security.providers.anonymous, - org.springframework.security.ui, - org.springframework.security.ui.webapp, - org.springframework.security.ui.preauth.x509, - org.springframework.security.userdetails, - org.springframework.web.context, - org.springframework.web.filter, - org.springframework.web.servlet, - org.springframework.web.servlet.handler, - org.springframework.web.servlet.view, - org.springframework.security.util, - org.springframework.security.context, - org.springframework.security.ui.basicauth, - org.springframework.security.intercept.web, - org.springframework.security.vote, - org.springframework.security.ui.logout, - org.apache.jackrabbit.server, - - - - - - - \ No newline at end of file diff --git a/server/modules/org.argeo.node.repo.jackrabbit/.project b/server/modules/org.argeo.node.repo.jackrabbit/.project deleted file mode 100644 index 648ec17d9..000000000 --- a/server/modules/org.argeo.node.repo.jackrabbit/.project +++ /dev/null @@ -1,22 +0,0 @@ - - - org.argeo.node.repo.jackrabbit - - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - - diff --git a/server/modules/org.argeo.node.repo.jackrabbit/.settings/org.eclipse.pde.core.prefs b/server/modules/org.argeo.node.repo.jackrabbit/.settings/org.eclipse.pde.core.prefs deleted file mode 100644 index aae24717e..000000000 --- a/server/modules/org.argeo.node.repo.jackrabbit/.settings/org.eclipse.pde.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -#Wed Feb 23 10:53:42 CET 2011 -eclipse.preferences.version=1 -pluginProject.extensions=false -resolve.requirebundle=false diff --git a/server/modules/org.argeo.node.repo.jackrabbit/META-INF/spring/noderepo-osgi.xml b/server/modules/org.argeo.node.repo.jackrabbit/META-INF/spring/noderepo-osgi.xml deleted file mode 100644 index 957dda144..000000000 --- a/server/modules/org.argeo.node.repo.jackrabbit/META-INF/spring/noderepo-osgi.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - javax.jcr.Repository - org.argeo.jcr.MaintainedRepository - - - - - - - - \ No newline at end of file diff --git a/server/modules/org.argeo.node.repo.jackrabbit/META-INF/spring/noderepo.xml b/server/modules/org.argeo.node.repo.jackrabbit/META-INF/spring/noderepo.xml deleted file mode 100644 index 6648c1550..000000000 --- a/server/modules/org.argeo.node.repo.jackrabbit/META-INF/spring/noderepo.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - osgibundle:noderepo.properties - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/server/modules/org.argeo.node.repo.jackrabbit/build.properties b/server/modules/org.argeo.node.repo.jackrabbit/build.properties deleted file mode 100644 index a275ae638..000000000 --- a/server/modules/org.argeo.node.repo.jackrabbit/build.properties +++ /dev/null @@ -1,4 +0,0 @@ -bin.includes = META-INF/,\ - noderepo.properties,\ - repository-h2.xml,\ - repository-postgresql.xml diff --git a/server/modules/org.argeo.node.repo.jackrabbit/noderepo.properties b/server/modules/org.argeo.node.repo.jackrabbit/noderepo.properties deleted file mode 100644 index c91d51d08..000000000 --- a/server/modules/org.argeo.node.repo.jackrabbit/noderepo.properties +++ /dev/null @@ -1,16 +0,0 @@ -# Workspace used by the node session -argeo.node.repo.defaultWorkspace=main -#argeo.node.repo.securityWorkspace=security -argeo.node.repo.forceCndImport=true - -# Repository base directory -argeo.node.repo.home=${osgi.instance.area}/node - -## H2 Embedded (DEFAULT) -argeo.node.repo.configuration=osgibundle:repository-h2.xml -argeo.node.repo.dburl=jdbc:h2:${osgi.instance.area}/node/h2/repository -argeo.node.repo.dbuser=sa -argeo.node.repo.dbpassword= - -# ADVANCED -argeo.node.repo.maxPoolSize=10 \ No newline at end of file diff --git a/server/modules/org.argeo.node.repo.jackrabbit/pom.xml b/server/modules/org.argeo.node.repo.jackrabbit/pom.xml deleted file mode 100644 index 0ac05cc8f..000000000 --- a/server/modules/org.argeo.node.repo.jackrabbit/pom.xml +++ /dev/null @@ -1,40 +0,0 @@ - - 4.0.0 - - org.argeo.commons.server - 2.1.12-SNAPSHOT - modules - .. - - org.argeo.node.repo.jackrabbit - Commons Server Node Repository Jackrabbit - Default Node Repository Based on Jackrabbit - - - - org.apache.felix - maven-bundle-plugin - - - ${project.artifactId};singleton:=true - - META-INF/spring/*.xml;create-asynchronously:=false - - *, - com.mysql.jdbc;resolution:=optional, - org.h2;resolution:=optional, - org.postgresql;resolution:=optional, - javax.jcr, - org.apache.jackrabbit.core, - org.apache.jackrabbit.core.config, - org.argeo.jackrabbit, - org.argeo.jcr, - org.springframework.beans.factory.config, - - - - - - - \ No newline at end of file diff --git a/server/modules/org.argeo.node.repo.jackrabbit/repository-h2.xml b/server/modules/org.argeo.node.repo.jackrabbit/repository-h2.xml deleted file mode 100644 index 583bf4c1c..000000000 --- a/server/modules/org.argeo.node.repo.jackrabbit/repository-h2.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/server/modules/org.argeo.node.repo.jackrabbit/repository-memory.xml b/server/modules/org.argeo.node.repo.jackrabbit/repository-memory.xml deleted file mode 100644 index b41cfad6d..000000000 --- a/server/modules/org.argeo.node.repo.jackrabbit/repository-memory.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/server/modules/org.argeo.node.repo.jackrabbit/repository-mysql.xml b/server/modules/org.argeo.node.repo.jackrabbit/repository-mysql.xml deleted file mode 100644 index 208cd1de1..000000000 --- a/server/modules/org.argeo.node.repo.jackrabbit/repository-mysql.xml +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/server/modules/org.argeo.node.repo.jackrabbit/repository-postgresql.xml b/server/modules/org.argeo.node.repo.jackrabbit/repository-postgresql.xml deleted file mode 100644 index 811f0c6bc..000000000 --- a/server/modules/org.argeo.node.repo.jackrabbit/repository-postgresql.xml +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/server/modules/org.argeo.server.activemq.broker/pom.xml b/server/modules/org.argeo.server.activemq.broker/pom.xml index 3fef5ad4a..f62ae2505 100644 --- a/server/modules/org.argeo.server.activemq.broker/pom.xml +++ b/server/modules/org.argeo.server.activemq.broker/pom.xml @@ -1,9 +1,9 @@ 4.0.0 - org.argeo.commons.server + org.argeo.commons 2.1.12-SNAPSHOT - modules + argeo-commons .. org.argeo.server.activemq.broker diff --git a/server/modules/org.argeo.server.ads.server/.project b/server/modules/org.argeo.server.ads.server/.project deleted file mode 100644 index a191480d8..000000000 --- a/server/modules/org.argeo.server.ads.server/.project +++ /dev/null @@ -1,22 +0,0 @@ - - - org.argeo.server.ads.server - - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - - diff --git a/server/modules/org.argeo.server.ads.server/.settings/org.eclipse.pde.core.prefs b/server/modules/org.argeo.server.ads.server/.settings/org.eclipse.pde.core.prefs deleted file mode 100644 index 5733b3123..000000000 --- a/server/modules/org.argeo.server.ads.server/.settings/org.eclipse.pde.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -#Sun Jan 16 09:58:38 CET 2011 -eclipse.preferences.version=1 -pluginProject.extensions=false -resolve.requirebundle=false diff --git a/server/modules/org.argeo.server.ads.server/META-INF/spring/ads.xml b/server/modules/org.argeo.server.ads.server/META-INF/spring/ads.xml deleted file mode 100644 index 6fdf476cc..000000000 --- a/server/modules/org.argeo.server.ads.server/META-INF/spring/ads.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - osgibundle:ads.properties - - - - - - - - - - - ${argeo.ads.init.ldif} - - - - - - - - simple - ${argeo.ldap.manager.userdn} - ${argeo.ldap.manager.password} - - - - - - - - - - - - diff --git a/server/modules/org.argeo.server.ads.server/META-INF/spring/server.xml b/server/modules/org.argeo.server.ads.server/META-INF/spring/server.xml deleted file mode 100644 index 84407be13..000000000 --- a/server/modules/org.argeo.server.ads.server/META-INF/spring/server.xml +++ /dev/null @@ -1,363 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/server/modules/org.argeo.server.ads.server/ads.properties b/server/modules/org.argeo.server.ads.server/ads.properties deleted file mode 100644 index 4aa138d97..000000000 --- a/server/modules/org.argeo.server.ads.server/ads.properties +++ /dev/null @@ -1,5 +0,0 @@ -argeo.ldap.rootdn=dc=demo,dc=example,dc=org -argeo.ldap.port=10389 -argeo.ldap.manager.userdn=uid=admin,ou=system -argeo.ldap.manager.password=secret -argeo.ads.init.ldif=osgibundle:init.ldif \ No newline at end of file diff --git a/server/modules/org.argeo.server.ads.server/build.properties b/server/modules/org.argeo.server.ads.server/build.properties deleted file mode 100644 index 5f22cdd44..000000000 --- a/server/modules/org.argeo.server.ads.server/build.properties +++ /dev/null @@ -1 +0,0 @@ -bin.includes = META-INF/ diff --git a/server/modules/org.argeo.server.ads.server/init.ldif b/server/modules/org.argeo.server.ads.server/init.ldif deleted file mode 100644 index 0d2e8ba8f..000000000 --- a/server/modules/org.argeo.server.ads.server/init.ldif +++ /dev/null @@ -1,47 +0,0 @@ -dn: dc=demo,dc=example,dc=org -objectClass: domain -objectClass: extensibleObject -objectClass: top -dc: demo - -dn: ou=Roles,dc=demo,dc=example,dc=org -objectClass: organizationalUnit -objectClass: top -ou: Roles - -dn: ou=People,dc=demo,dc=example,dc=org -objectClass: organizationalUnit -objectClass: top -ou: People - -dn: uid=demo,ou=People,dc=demo,dc=example,dc=org -objectClass: organizationalPerson -objectClass: person -objectClass: inetOrgPerson -objectClass: top -cn: demo User -description: Demo user -givenname: Demo -mail: demo@localhost -sn: User -uid: demo -userpassword:: e1NIQX1pZVNWNTVRYytlUU9hWURSU2hhL0Fqek5USkU9 - -dn: uid=root,ou=People,dc=demo,dc=example,dc=org -objectClass: person -objectClass: inetOrgPerson -objectClass: organizationalPerson -objectClass: top -cn: demo User -description: Superuser -givenname: Root -mail: root@localhost -sn: Root -uid: root -userpassword:: e1NIQX1pZVNWNTVRYytlUU9hWURSU2hhL0Fqek5USkU9 - -dn: cn=admin,ou=Roles,dc=demo,dc=example,dc=org -objectClass: groupOfNames -objectClass: top -cn: admin -member: uid=root,ou=People,dc=demo,dc=example,dc=org diff --git a/server/modules/org.argeo.server.ads.server/pom.xml b/server/modules/org.argeo.server.ads.server/pom.xml deleted file mode 100644 index 0217736b4..000000000 --- a/server/modules/org.argeo.server.ads.server/pom.xml +++ /dev/null @@ -1,50 +0,0 @@ - - 4.0.0 - - org.argeo.commons.server - 2.1.12-SNAPSHOT - modules - .. - - org.argeo.server.ads.server - Commons Server Default ADS LDAP Server - - - - org.apache.felix - maven-bundle-plugin - - - - META-INF/spring/*.xml;create-asynchronously:=false - - *, - javax.naming.directory, - jdbm, - org.apache.directory.server.configuration, - org.apache.directory.server.core.authn, - org.apache.directory.server.core.authz, - org.apache.directory.server.core.collective, - org.apache.directory.server.core.configuration, - org.apache.directory.server.core.event, - org.apache.directory.server.core.exception, - org.apache.directory.server.core.normalization, - org.apache.directory.server.core.operational, - org.apache.directory.server.core.partition.impl.btree, - org.apache.directory.server.core.referral, - org.apache.directory.server.core.schema, - org.apache.directory.server.core.schema.bootstrap, - org.apache.directory.server.core.subtree, - org.apache.directory.server.jndi, - org.apache.directory.server.ldap.support.extended, - org.apache.directory.shared.asn1.codec, - org.argeo.server.ads, - org.springframework.beans.factory.config - - - - - - - \ No newline at end of file diff --git a/server/modules/org.argeo.server.catalina/pom.xml b/server/modules/org.argeo.server.catalina/pom.xml index 8a8c0e754..59fd5fefd 100644 --- a/server/modules/org.argeo.server.catalina/pom.xml +++ b/server/modules/org.argeo.server.catalina/pom.xml @@ -1,9 +1,9 @@ 4.0.0 - org.argeo.commons.server + org.argeo.commons 2.1.12-SNAPSHOT - modules + argeo-commons .. org.argeo.server.catalina diff --git a/server/modules/org.argeo.server.jdbc/pom.xml b/server/modules/org.argeo.server.jdbc/pom.xml index e8fddb17f..a5e5bf1ae 100644 --- a/server/modules/org.argeo.server.jdbc/pom.xml +++ b/server/modules/org.argeo.server.jdbc/pom.xml @@ -1,9 +1,9 @@ 4.0.0 - org.argeo.commons.server + org.argeo.commons 2.1.12-SNAPSHOT - modules + argeo-commons .. org.argeo.server.jdbc diff --git a/server/modules/org.argeo.server.rap.webapp/.project b/server/modules/org.argeo.server.rap.webapp/.project deleted file mode 100644 index 3ffaae189..000000000 --- a/server/modules/org.argeo.server.rap.webapp/.project +++ /dev/null @@ -1,22 +0,0 @@ - - - org.argeo.server.rap.webapp - - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - - diff --git a/server/modules/org.argeo.server.rap.webapp/.settings/org.eclipse.pde.core.prefs b/server/modules/org.argeo.server.rap.webapp/.settings/org.eclipse.pde.core.prefs deleted file mode 100644 index fd884c249..000000000 --- a/server/modules/org.argeo.server.rap.webapp/.settings/org.eclipse.pde.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -#Tue Mar 01 15:09:47 CET 2011 -eclipse.preferences.version=1 -pluginProject.extensions=false -resolve.requirebundle=false diff --git a/server/modules/org.argeo.server.rap.webapp/META-INF/context-template.xml b/server/modules/org.argeo.server.rap.webapp/META-INF/context-template.xml deleted file mode 100644 index eaf6e86cc..000000000 --- a/server/modules/org.argeo.server.rap.webapp/META-INF/context-template.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - \ No newline at end of file diff --git a/server/modules/org.argeo.server.rap.webapp/WEB-INF/applicationContext.xml b/server/modules/org.argeo.server.rap.webapp/WEB-INF/applicationContext.xml deleted file mode 100644 index 336862453..000000000 --- a/server/modules/org.argeo.server.rap.webapp/WEB-INF/applicationContext.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - osgibundle:rap-webapp.properties - - - - \ No newline at end of file diff --git a/server/modules/org.argeo.server.rap.webapp/WEB-INF/osgi.xml b/server/modules/org.argeo.server.rap.webapp/WEB-INF/osgi.xml deleted file mode 100644 index fec44339b..000000000 --- a/server/modules/org.argeo.server.rap.webapp/WEB-INF/osgi.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/server/modules/org.argeo.server.rap.webapp/WEB-INF/security-filters.xml b/server/modules/org.argeo.server.rap.webapp/WEB-INF/security-filters.xml deleted file mode 100644 index 4c7df6b06..000000000 --- a/server/modules/org.argeo.server.rap.webapp/WEB-INF/security-filters.xml +++ /dev/null @@ -1,144 +0,0 @@ - - - - - - - - - - - - - - - - - - - PATTERN_TYPE_APACHE_ANT - /**=ROLE_USER,ROLE_ADMIN - - - - - - - PATTERN_TYPE_APACHE_ANT - /**=IS_AUTHENTICATED_ANONYMOUSLY - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ${argeo.server.realmName} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/server/modules/org.argeo.server.rap.webapp/WEB-INF/service-servlet.xml b/server/modules/org.argeo.server.rap.webapp/WEB-INF/service-servlet.xml deleted file mode 100644 index 7a052199e..000000000 --- a/server/modules/org.argeo.server.rap.webapp/WEB-INF/service-servlet.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - osgiServiceController - - - - - - - org.eclipse.equinox.http.servlet.HttpServiceServlet - - - osgiService - - - \ No newline at end of file diff --git a/server/modules/org.argeo.server.rap.webapp/WEB-INF/web.xml b/server/modules/org.argeo.server.rap.webapp/WEB-INF/web.xml deleted file mode 100644 index 1b6e766e5..000000000 --- a/server/modules/org.argeo.server.rap.webapp/WEB-INF/web.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - Argeo OSGi Webapp - - - - contextConfigLocation - /WEB-INF/applicationContext.xml - - - - Spring Context - org.springframework.web.context.ContextLoaderListener - - - contextClass - org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext - - - - - service - org.springframework.web.servlet.DispatcherServlet - - contextClass - org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext - - 1 - - - - service - /* - - - - - springSecurityFilterChain - org.springframework.web.filter.DelegatingFilterProxy - - - - springSecurityFilterChain - /private - - - springSecurityFilterChain - /basicauth - - - springSecurityFilterChain - /clientauth - - - springSecurityFilterChain - /none - - - springSecurityFilterChain - /public - - - diff --git a/server/modules/org.argeo.server.rap.webapp/build.properties b/server/modules/org.argeo.server.rap.webapp/build.properties deleted file mode 100644 index 29dea25a4..000000000 --- a/server/modules/org.argeo.server.rap.webapp/build.properties +++ /dev/null @@ -1,2 +0,0 @@ -bin.includes = META-INF/,\ - WEB-INF/ diff --git a/server/modules/org.argeo.server.rap.webapp/pom.xml b/server/modules/org.argeo.server.rap.webapp/pom.xml deleted file mode 100644 index 365166b26..000000000 --- a/server/modules/org.argeo.server.rap.webapp/pom.xml +++ /dev/null @@ -1,54 +0,0 @@ - - 4.0.0 - - org.argeo.commons.server - 2.1.12-SNAPSHOT - modules - .. - - org.argeo.server.rap.webapp - Commons Server RAP Webapp - Integrates into OSGi HTTP registry - - - - org.apache.felix - maven-bundle-plugin - - - ui - - *, - - org.springframework.beans.factory.config, - - org.eclipse.equinox.http.servlet, - org.springframework.osgi.web.context.support, - org.springframework.security, - org.springframework.security.context, - org.springframework.security.intercept.web, - org.springframework.security.providers.anonymous, - org.springframework.security.ui, - org.springframework.security.ui.basicauth, - org.springframework.security.ui.logout, - org.springframework.security.ui.rememberme, - org.springframework.security.ui.webapp, - org.springframework.security.ui.preauth.x509, - org.springframework.security.userdetails, - org.springframework.security.util, - org.springframework.security.vote, - org.springframework.security.wrapper, - org.springframework.web.context, - org.springframework.web.filter, - org.springframework.web.servlet, - org.springframework.web.servlet.handler, - org.springframework.web.servlet.mvc, - - - - - - - - - \ No newline at end of file diff --git a/server/modules/org.argeo.server.rap.webapp/rap-webapp.properties b/server/modules/org.argeo.server.rap.webapp/rap-webapp.properties deleted file mode 100644 index 012255a15..000000000 --- a/server/modules/org.argeo.server.rap.webapp/rap-webapp.properties +++ /dev/null @@ -1,2 +0,0 @@ -argeo.security.systemKey=argeo -argeo.server.realmName=Argeo \ No newline at end of file diff --git a/server/modules/pom.xml b/server/modules/pom.xml index 384c8a27e..18652f2ed 100644 --- a/server/modules/pom.xml +++ b/server/modules/pom.xml @@ -6,8 +6,8 @@ server .. - org.argeo.commons.server - modules + org.argeo.commons + argeo-commons pom Commons Server Modules diff --git a/server/plugins/org.argeo.jcr.ui.explorer/.classpath b/server/plugins/org.argeo.jcr.ui.explorer/.classpath deleted file mode 100644 index 527d8abab..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/.classpath +++ /dev/null @@ -1,8 +0,0 @@ - - - - - >> - - - diff --git a/server/plugins/org.argeo.jcr.ui.explorer/.project b/server/plugins/org.argeo.jcr.ui.explorer/.project deleted file mode 100644 index 162cd6b8b..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - org.argeo.jcr.ui.explorer - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - - diff --git a/server/plugins/org.argeo.jcr.ui.explorer/.settings/org.eclipse.jdt.core.prefs b/server/plugins/org.argeo.jcr.ui.explorer/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 992c5d722..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,8 +0,0 @@ -#Thu Feb 24 08:49:06 CET 2011 -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 -org.eclipse.jdt.core.compiler.compliance=1.5 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.5 diff --git a/server/plugins/org.argeo.jcr.ui.explorer/META-INF/spring/commands.xml b/server/plugins/org.argeo.jcr.ui.explorer/META-INF/spring/commands.xml deleted file mode 100644 index ef9f3f1d4..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/META-INF/spring/commands.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/server/plugins/org.argeo.jcr.ui.explorer/META-INF/spring/editors.xml b/server/plugins/org.argeo.jcr.ui.explorer/META-INF/spring/editors.xml deleted file mode 100644 index fc86ceef7..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/META-INF/spring/editors.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - diff --git a/server/plugins/org.argeo.jcr.ui.explorer/META-INF/spring/jcr.xml b/server/plugins/org.argeo.jcr.ui.explorer/META-INF/spring/jcr.xml deleted file mode 100644 index e074154ed..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/META-INF/spring/jcr.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - diff --git a/server/plugins/org.argeo.jcr.ui.explorer/META-INF/spring/osgi.xml b/server/plugins/org.argeo.jcr.ui.explorer/META-INF/spring/osgi.xml deleted file mode 100644 index 255462be4..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/META-INF/spring/osgi.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/server/plugins/org.argeo.jcr.ui.explorer/META-INF/spring/views.xml b/server/plugins/org.argeo.jcr.ui.explorer/META-INF/spring/views.xml deleted file mode 100644 index 14f1943d7..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/META-INF/spring/views.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - diff --git a/server/plugins/org.argeo.jcr.ui.explorer/build.properties b/server/plugins/org.argeo.jcr.ui.explorer/build.properties deleted file mode 100644 index 9b0c715ca..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/build.properties +++ /dev/null @@ -1,7 +0,0 @@ -source.. = src/main/java/,\ - src/main/resources -output.. = target/classes/ -bin.includes = META-INF/,\ - .,\ - plugin.xml,\ - plugin.properties diff --git a/server/plugins/org.argeo.jcr.ui.explorer/icons/add.gif b/server/plugins/org.argeo.jcr.ui.explorer/icons/add.gif deleted file mode 100644 index 252d7ebcb..000000000 Binary files a/server/plugins/org.argeo.jcr.ui.explorer/icons/add.gif and /dev/null differ diff --git a/server/plugins/org.argeo.jcr.ui.explorer/icons/addFolder.gif b/server/plugins/org.argeo.jcr.ui.explorer/icons/addFolder.gif deleted file mode 100755 index d3f43d977..000000000 Binary files a/server/plugins/org.argeo.jcr.ui.explorer/icons/addFolder.gif and /dev/null differ diff --git a/server/plugins/org.argeo.jcr.ui.explorer/icons/addPrivileges.png b/server/plugins/org.argeo.jcr.ui.explorer/icons/addPrivileges.png deleted file mode 100644 index a6b251fc8..000000000 Binary files a/server/plugins/org.argeo.jcr.ui.explorer/icons/addPrivileges.png and /dev/null differ diff --git a/server/plugins/org.argeo.jcr.ui.explorer/icons/addRepo.gif b/server/plugins/org.argeo.jcr.ui.explorer/icons/addRepo.gif deleted file mode 100755 index 26d81c065..000000000 Binary files a/server/plugins/org.argeo.jcr.ui.explorer/icons/addRepo.gif and /dev/null differ diff --git a/server/plugins/org.argeo.jcr.ui.explorer/icons/addWorkspace.png b/server/plugins/org.argeo.jcr.ui.explorer/icons/addWorkspace.png deleted file mode 100644 index bbee7755f..000000000 Binary files a/server/plugins/org.argeo.jcr.ui.explorer/icons/addWorkspace.png and /dev/null differ diff --git a/server/plugins/org.argeo.jcr.ui.explorer/icons/browser.gif b/server/plugins/org.argeo.jcr.ui.explorer/icons/browser.gif deleted file mode 100644 index 6c7320c69..000000000 Binary files a/server/plugins/org.argeo.jcr.ui.explorer/icons/browser.gif and /dev/null differ diff --git a/server/plugins/org.argeo.jcr.ui.explorer/icons/dumpNode.gif b/server/plugins/org.argeo.jcr.ui.explorer/icons/dumpNode.gif deleted file mode 100644 index 14eb1be09..000000000 Binary files a/server/plugins/org.argeo.jcr.ui.explorer/icons/dumpNode.gif and /dev/null differ diff --git a/server/plugins/org.argeo.jcr.ui.explorer/icons/getSize.gif b/server/plugins/org.argeo.jcr.ui.explorer/icons/getSize.gif deleted file mode 100755 index b05bf3e3d..000000000 Binary files a/server/plugins/org.argeo.jcr.ui.explorer/icons/getSize.gif and /dev/null differ diff --git a/server/plugins/org.argeo.jcr.ui.explorer/icons/import_fs.png b/server/plugins/org.argeo.jcr.ui.explorer/icons/import_fs.png deleted file mode 100644 index d7c890c81..000000000 Binary files a/server/plugins/org.argeo.jcr.ui.explorer/icons/import_fs.png and /dev/null differ diff --git a/server/plugins/org.argeo.jcr.ui.explorer/icons/nodes.gif b/server/plugins/org.argeo.jcr.ui.explorer/icons/nodes.gif deleted file mode 100644 index bba3dbc69..000000000 Binary files a/server/plugins/org.argeo.jcr.ui.explorer/icons/nodes.gif and /dev/null differ diff --git a/server/plugins/org.argeo.jcr.ui.explorer/icons/query.png b/server/plugins/org.argeo.jcr.ui.explorer/icons/query.png deleted file mode 100644 index 54c089de1..000000000 Binary files a/server/plugins/org.argeo.jcr.ui.explorer/icons/query.png and /dev/null differ diff --git a/server/plugins/org.argeo.jcr.ui.explorer/icons/refresh.png b/server/plugins/org.argeo.jcr.ui.explorer/icons/refresh.png deleted file mode 100644 index a3884fb48..000000000 Binary files a/server/plugins/org.argeo.jcr.ui.explorer/icons/refresh.png and /dev/null differ diff --git a/server/plugins/org.argeo.jcr.ui.explorer/icons/remove.gif b/server/plugins/org.argeo.jcr.ui.explorer/icons/remove.gif deleted file mode 100644 index 0ae6decd0..000000000 Binary files a/server/plugins/org.argeo.jcr.ui.explorer/icons/remove.gif and /dev/null differ diff --git a/server/plugins/org.argeo.jcr.ui.explorer/icons/repositories.gif b/server/plugins/org.argeo.jcr.ui.explorer/icons/repositories.gif deleted file mode 100644 index c13bea1ca..000000000 Binary files a/server/plugins/org.argeo.jcr.ui.explorer/icons/repositories.gif and /dev/null differ diff --git a/server/plugins/org.argeo.jcr.ui.explorer/icons/sort.gif b/server/plugins/org.argeo.jcr.ui.explorer/icons/sort.gif deleted file mode 100644 index 23c5d0b11..000000000 Binary files a/server/plugins/org.argeo.jcr.ui.explorer/icons/sort.gif and /dev/null differ diff --git a/server/plugins/org.argeo.jcr.ui.explorer/plugin.properties b/server/plugins/org.argeo.jcr.ui.explorer/plugin.properties deleted file mode 100644 index 6dff863e6..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/plugin.properties +++ /dev/null @@ -1,2 +0,0 @@ -## commands label -addNewFolderCmdLbl=Add folder \ No newline at end of file diff --git a/server/plugins/org.argeo.jcr.ui.explorer/plugin.xml b/server/plugins/org.argeo.jcr.ui.explorer/plugin.xml deleted file mode 100644 index 67b87515f..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/plugin.xml +++ /dev/null @@ -1,360 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/server/plugins/org.argeo.jcr.ui.explorer/pom.xml b/server/plugins/org.argeo.jcr.ui.explorer/pom.xml deleted file mode 100644 index dfcc1a8d4..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/pom.xml +++ /dev/null @@ -1,61 +0,0 @@ - - 4.0.0 - - org.argeo.commons.server - 2.1.12-SNAPSHOT - plugins - .. - - org.argeo.jcr.ui.explorer - Commons JCR Explorer - - - - org.apache.felix - maven-bundle-plugin - - - lazy - plugin - org.argeo.jcr.ui.explorer.JcrExplorerPlugin - org.eclipse.ui;resolution:=optional, - org.eclipse.core.runtime;resolution:=optional, - org.eclipse.rap.ui;resolution:=optional, - org.eclipse.rap.ui.workbench;resolution:=optional - - *, - org.argeo.eclipse.spring, - - org.argeo.jcr.ui.explorer.* - - - - - - - - org.argeo.commons.base - org.argeo.util - 2.1.12-SNAPSHOT - - - org.argeo.commons.base - org.argeo.eclipse.ui.jcr - 2.1.12-SNAPSHOT - - - - - org.argeo.commons.base - org.argeo.eclipse.dep.rcp - 2.1.12-SNAPSHOT - provided - - - org.argeo.commons.base - org.argeo.eclipse.ui.rcp - 2.1.12-SNAPSHOT - provided - - - diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerConstants.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerConstants.java deleted file mode 100644 index a9cb25841..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerConstants.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer; - -/** Constants used across the application. */ -public interface JcrExplorerConstants { - /* - * MISCEALLENEOUS - */ - public final static String DATE_TIME_FORMAT = "dd/MM/yyyy, HH:mm"; - - public final static String PARAM_PATH = "org.argeo.jcr.ui.explorer.nodePath"; - -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerPerspective.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerPerspective.java deleted file mode 100644 index 2626415fc..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerPerspective.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer; - -import org.eclipse.ui.IFolderLayout; -import org.eclipse.ui.IPageLayout; -import org.eclipse.ui.IPerspectiveFactory; - -/** Base perspective for JcrExplorer browser */ -public class JcrExplorerPerspective implements IPerspectiveFactory { - public static String BROWSER_VIEW_ID = JcrExplorerPlugin.ID - + ".browserView"; - - public void createInitialLayout(IPageLayout layout) { - layout.setEditorAreaVisible(true); - - IFolderLayout upperLeft = layout.createFolder(JcrExplorerPlugin.ID - + ".upperLeft", IPageLayout.LEFT, 0.4f, layout.getEditorArea()); - upperLeft.addView(BROWSER_VIEW_ID); - -// String editorArea = layout.getEditorArea(); -// String logViewId = "org.argeo.security.ui.logView"; -// IFolderLayout bottom = layout.createFolder("bottom", -// IPageLayout.BOTTOM, 0.50f, editorArea); -// bottom.addView(logViewId); - } - -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerPlugin.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerPlugin.java deleted file mode 100644 index 3bf9e7f7d..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerPlugin.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer; - -import java.util.ResourceBundle; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.ui.plugin.AbstractUIPlugin; -import org.osgi.framework.BundleContext; - -/** - * The activator class controls the plug-in life cycle - */ -public class JcrExplorerPlugin extends AbstractUIPlugin { - private final static Log log = LogFactory.getLog(JcrExplorerPlugin.class); - private ResourceBundle messages; - - // The plug-in ID - public static final String ID = "org.argeo.jcr.ui.explorer"; //$NON-NLS-1$ - - // The shared instance - private static JcrExplorerPlugin plugin; - - /** - * The constructor - */ - public JcrExplorerPlugin() { - } - - /* - * (non-Javadoc) - * - * @see - * org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext - * ) - */ - public void start(BundleContext context) throws Exception { - super.start(context); - plugin = this; - messages = ResourceBundle - .getBundle("org.argeo.jcr.ui.explorer.messages"); - - } - - /* - * (non-Javadoc) - * - * @see - * org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext - * ) - */ - public void stop(BundleContext context) throws Exception { - plugin = null; - super.stop(context); - } - - /** - * Returns the shared instance - * - * @return the shared instance - */ - public static JcrExplorerPlugin getDefault() { - return plugin; - } - - public static ImageDescriptor getImageDescriptor(String path) { - return imageDescriptorFromPlugin(ID, path); - } - - /** Returns the internationalized label for the given key */ - public static String getMessage(String key) { - try { - return getDefault().messages.getString(key); - } catch (NullPointerException npe) { - log.warn(key + " not found."); - return key; - } - } - - /** - * Gives access to the internationalization message bundle. Returns null in - * case the ClientUiPlugin is not started (for JUnit tests, by instance) - */ - public static ResourceBundle getMessagesBundle() { - if (getDefault() != null) - // To avoid NPE - return getDefault().messages; - else - return null; - } - -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerView.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerView.java deleted file mode 100644 index 01a957a96..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerView.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer; - -import org.argeo.jcr.ui.explorer.views.GenericJcrBrowser; - -public class JcrExplorerView extends GenericJcrBrowser { - -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/browser/NodeContentProvider.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/browser/NodeContentProvider.java deleted file mode 100644 index fb6bd1a15..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/browser/NodeContentProvider.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.browser; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.List; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.RepositoryFactory; -import javax.jcr.Session; -import javax.jcr.nodetype.NodeType; - -import org.argeo.eclipse.ui.TreeParent; -import org.argeo.jcr.ArgeoJcrConstants; -import org.argeo.jcr.RepositoryRegister; -import org.argeo.jcr.UserJcrUtils; -import org.argeo.jcr.ui.explorer.model.RepositoriesElem; -import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem; -import org.argeo.util.security.Keyring; -import org.eclipse.jface.viewers.ITreeContentProvider; -import org.eclipse.jface.viewers.Viewer; - -/** - * Implementation of the {@code ITreeContentProvider} to display multiple - * repository environment in a tree like structure - * - */ -public class NodeContentProvider implements ITreeContentProvider { - final private RepositoryRegister repositoryRegister; - final private RepositoryFactory repositoryFactory; - /** - * A session of the logged in user on the default workspace of the node - * repository. - */ - final private Session userSession; - final private Keyring keyring; - private boolean sortChildren; - - // reference for cleaning - private SingleJcrNodeElem homeNode = null; - private RepositoriesElem repositoriesNode = null; - - // Utils - private TreeBrowserComparator itemComparator = new TreeBrowserComparator(); - - public NodeContentProvider(Session userSession, Keyring keyring, - RepositoryRegister repositoryRegister, - RepositoryFactory repositoryFactory, Boolean sortChildren) { - this.userSession = userSession; - this.keyring = keyring; - this.repositoryRegister = repositoryRegister; - this.repositoryFactory = repositoryFactory; - this.sortChildren = sortChildren; - } - - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - if (newInput == null)// dispose - return; - - if (userSession != null) { - Node userHome = UserJcrUtils.getUserHome(userSession); - if (userHome != null) { - // TODO : find a way to dynamically get alias for the node - if (homeNode != null) - homeNode.dispose(); - homeNode = new SingleJcrNodeElem(null, userHome, - userSession.getUserID(), ArgeoJcrConstants.ALIAS_NODE); - } - } - if (repositoryRegister != null) { - if (repositoriesNode != null) - repositoriesNode.dispose(); - repositoriesNode = new RepositoriesElem("Repositories", - repositoryRegister, repositoryFactory, null, userSession, - keyring); - } - } - - /** - * Sends back the first level of the Tree. Independent from inputElement - * that can be null - */ - public Object[] getElements(Object inputElement) { - List objs = new ArrayList(); - if (homeNode != null) - objs.add(homeNode); - if (repositoriesNode != null) - objs.add(repositoriesNode); - return objs.toArray(); - } - - public Object[] getChildren(Object parentElement) { - if (parentElement instanceof TreeParent) { - if (sortChildren) { - // TreeParent[] arr = (TreeParent[]) ((TreeParent) - // parentElement) - // .getChildren(); - Object[] tmpArr = ((TreeParent) parentElement).getChildren(); - TreeParent[] arr = new TreeParent[tmpArr.length]; - for (int i = 0; i < tmpArr.length; i++) - arr[i] = (TreeParent) tmpArr[i]; - - Arrays.sort(arr, itemComparator); - return arr; - } else - return ((TreeParent) parentElement).getChildren(); - - } else { - return new Object[0]; - } - } - - /** - * Sets whether the content provider should order the children nodes or not. - * It is user duty to call a full refresh of the tree after changing this - * parameter. - */ - public void setSortChildren(boolean sortChildren) { - this.sortChildren = sortChildren; - } - - public Object getParent(Object element) { - if (element instanceof TreeParent) { - return ((TreeParent) element).getParent(); - } else - return null; - } - - public boolean hasChildren(Object element) { - if (element instanceof RepositoriesElem) { - RepositoryRegister rr = ((RepositoriesElem) element) - .getRepositoryRegister(); - return rr.getRepositories().size() > 0; - } else if (element instanceof TreeParent) { - TreeParent tp = (TreeParent) element; - return tp.hasChildren(); - } - return false; - } - - public void dispose() { - if (homeNode != null) - homeNode.dispose(); - if (repositoriesNode != null) { - // logs out open sessions - // see https://bugzilla.argeo.org/show_bug.cgi?id=23 - repositoriesNode.dispose(); - } - } - - /** - * Specific comparator for this view. See spec in BUG : - * https://www.argeo.org/bugzilla/show_bug.cgi?id=139 - */ - private class TreeBrowserComparator implements Comparator { - - public int category(TreeParent element) { - if (element instanceof SingleJcrNodeElem) { - Node node = ((SingleJcrNodeElem) element).getNode(); - try { - if (node.isNodeType(NodeType.NT_FOLDER)) - return 5; - } catch (RepositoryException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - return 10; - } - - public int compare(TreeParent o1, TreeParent o2) { - int cat1 = category(o1); - int cat2 = category(o2); - - if (cat1 != cat2) { - return cat1 - cat2; - } - return o1.getName().compareTo(o2.getName()); - } - } -} \ No newline at end of file diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/browser/NodeLabelProvider.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/browser/NodeLabelProvider.java deleted file mode 100644 index d6d593ce8..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/browser/NodeLabelProvider.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.browser; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.nodetype.NodeType; - -import org.argeo.ArgeoException; -import org.argeo.eclipse.ui.jcr.DefaultNodeLabelProvider; -import org.argeo.eclipse.ui.jcr.JcrImages; -import org.argeo.jcr.ui.explorer.model.RemoteRepositoryElem; -import org.argeo.jcr.ui.explorer.model.RepositoriesElem; -import org.argeo.jcr.ui.explorer.model.RepositoryElem; -import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem; -import org.argeo.jcr.ui.explorer.model.WorkspaceElem; -import org.eclipse.swt.graphics.Image; - -public class NodeLabelProvider extends DefaultNodeLabelProvider { - // Images - - public String getText(Object element) { - try { - if (element instanceof SingleJcrNodeElem) { - SingleJcrNodeElem sjn = (SingleJcrNodeElem) element; - return getText(sjn.getNode()); - } else - return super.getText(element); - } catch (RepositoryException e) { - throw new ArgeoException( - "Unexpected JCR error while getting node name."); - } - } - - protected String getText(Node node) throws RepositoryException { - String label = node.getName(); - StringBuffer mixins = new StringBuffer(""); - for (NodeType type : node.getMixinNodeTypes()) - mixins.append(' ').append(type.getName()); - - return label + " [" + node.getPrimaryNodeType().getName() + mixins - + "]"; - } - - @Override - public Image getImage(Object element) { - if (element instanceof RemoteRepositoryElem) { - if (((RemoteRepositoryElem) element).isConnected()) - return JcrImages.REMOTE_CONNECTED; - else - return JcrImages.REMOTE_DISCONNECTED; - } else if (element instanceof RepositoryElem) { - if (((RepositoryElem) element).isConnected()) - return JcrImages.REPOSITORY_CONNECTED; - else - return JcrImages.REPOSITORY_DISCONNECTED; - } else if (element instanceof WorkspaceElem) { - if (((WorkspaceElem) element).isConnected()) - return JcrImages.WORKSPACE_CONNECTED; - else - return JcrImages.WORKSPACE_DISCONNECTED; - } else if (element instanceof RepositoriesElem) { - return JcrImages.REPOSITORIES; - } else if (element instanceof SingleJcrNodeElem) - try { - return super.getImage(((SingleJcrNodeElem) element).getNode()); - } catch (RepositoryException e) { - return null; - } - return super.getImage(element); - } - -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/browser/PropertiesContentProvider.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/browser/PropertiesContentProvider.java deleted file mode 100644 index d39f3195e..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/browser/PropertiesContentProvider.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.browser; - -import java.util.Set; -import java.util.TreeSet; - -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.PropertyIterator; -import javax.jcr.RepositoryException; - -import org.argeo.ArgeoException; -import org.argeo.eclipse.ui.jcr.utils.JcrItemsComparator; -import org.eclipse.jface.viewers.IStructuredContentProvider; -import org.eclipse.jface.viewers.Viewer; - -public class PropertiesContentProvider implements IStructuredContentProvider { - private JcrItemsComparator itemComparator = new JcrItemsComparator(); - - public void dispose() { - } - - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - } - - public Object[] getElements(Object inputElement) { - try { - if (inputElement instanceof Node) { - Set props = new TreeSet(itemComparator); - PropertyIterator pit = ((Node) inputElement).getProperties(); - while (pit.hasNext()) - props.add(pit.nextProperty()); - return props.toArray(); - } - return new Object[] {}; - } catch (RepositoryException e) { - throw new ArgeoException("Cannot get element for " + inputElement, - e); - } - } - -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/AddFolderNode.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/AddFolderNode.java deleted file mode 100644 index 0389aeec0..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/AddFolderNode.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.commands; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.nodetype.NodeType; - -import org.argeo.eclipse.ui.ErrorFeedback; -import org.argeo.eclipse.ui.TreeParent; -import org.argeo.eclipse.ui.dialogs.SingleValue; -import org.argeo.eclipse.ui.jcr.JcrUiPlugin; -import org.argeo.jcr.ui.explorer.JcrExplorerPlugin; -import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem; -import org.argeo.jcr.ui.explorer.model.WorkspaceElem; -import org.argeo.jcr.ui.explorer.views.GenericJcrBrowser; -import org.eclipse.core.commands.AbstractHandler; -import org.eclipse.core.commands.ExecutionEvent; -import org.eclipse.core.commands.ExecutionException; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.ui.handlers.HandlerUtil; - -/** - * Adds a node of type nt:folder, only on {@link SingleJcrNodeElem} and - * {@link WorkspaceElem} TreeObject types. - * - * - * This handler assumes that a selection provider is available and picks only - * first selected item. It is UI's job to enable the command only when the - * selection contains one and only one element. Thus no parameter is passed - * through the command. - * - * This handler is still 'hard linked' to a GenericJcrBrowser view to enable - * correct tree refresh when a node is added. This must be corrected in future - * versions. - */ -public class AddFolderNode extends AbstractHandler { - - public final static String ID = JcrExplorerPlugin.ID + ".addFolderNode"; - - // public final static String DEFAULT_LABEL = JcrExplorerPlugin - // .getMessage("addFolderNodeCmdLbl"); - // public final static String DEFAULT_ICON_REL_PATH = "icons/addRepo.gif"; - - public Object execute(ExecutionEvent event) throws ExecutionException { - - ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event) - .getActivePage().getSelection(); - - GenericJcrBrowser view = (GenericJcrBrowser) HandlerUtil - .getActiveWorkbenchWindow(event).getActivePage() - .findView(HandlerUtil.getActivePartId(event)); - - if (selection != null && !selection.isEmpty() - && selection instanceof IStructuredSelection) { - Object obj = ((IStructuredSelection) selection).getFirstElement(); - TreeParent treeParentNode = null; - Node jcrParentNode = null; - - if (obj instanceof SingleJcrNodeElem) { - treeParentNode = (TreeParent) obj; - jcrParentNode = ((SingleJcrNodeElem) treeParentNode).getNode(); - } else if (obj instanceof WorkspaceElem) { - treeParentNode = (TreeParent) obj; - jcrParentNode = ((WorkspaceElem) treeParentNode).getRootNode(); - } else - return null; - - String folderName = SingleValue.ask("Folder name", - "Enter folder name"); - if (folderName != null) { - try { - jcrParentNode.addNode(folderName, NodeType.NT_FOLDER); - jcrParentNode.getSession().save(); - view.nodeAdded(treeParentNode); - } catch (RepositoryException e) { - ErrorFeedback.show("Cannot create folder " + folderName - + " under " + treeParentNode, e); - } - } - } else { - ErrorFeedback.show(JcrUiPlugin - .getMessage("errorUnvalidNtFolderNodeType")); - } - return null; - } -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/AddPrivileges.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/AddPrivileges.java deleted file mode 100644 index 829290ebe..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/AddPrivileges.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.commands; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.argeo.ArgeoException; -import org.argeo.eclipse.ui.ErrorFeedback; -import org.argeo.eclipse.ui.TreeParent; -import org.argeo.jcr.ui.explorer.JcrExplorerPlugin; -import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem; -import org.argeo.jcr.ui.explorer.model.WorkspaceElem; -import org.argeo.jcr.ui.explorer.wizards.ChangeRightsWizard; -import org.eclipse.core.commands.AbstractHandler; -import org.eclipse.core.commands.ExecutionEvent; -import org.eclipse.core.commands.ExecutionException; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.wizard.WizardDialog; -import org.eclipse.ui.handlers.HandlerUtil; - -/** - * Open a dialog to change rights on the selected node. - */ - -public class AddPrivileges extends AbstractHandler { - public final static String ID = JcrExplorerPlugin.ID + ".addPrivileges"; - - public Object execute(ExecutionEvent event) throws ExecutionException { - - ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event) - .getActivePage().getSelection(); - if (selection != null && !selection.isEmpty() - && selection instanceof IStructuredSelection) { - Object obj = ((IStructuredSelection) selection).getFirstElement(); - TreeParent treeParentNode = null; - Node jcrParentNode = null; - - if (obj instanceof SingleJcrNodeElem) { - treeParentNode = (TreeParent) obj; - jcrParentNode = ((SingleJcrNodeElem) treeParentNode).getNode(); - } else if (obj instanceof WorkspaceElem) { - treeParentNode = (TreeParent) obj; - jcrParentNode = ((WorkspaceElem) treeParentNode).getRootNode(); - } else - return null; - - try { - ChangeRightsWizard wizard = new ChangeRightsWizard( - jcrParentNode.getSession(), jcrParentNode.getPath()); - WizardDialog dialog = new WizardDialog( - HandlerUtil.getActiveShell(event), wizard); - dialog.open(); - return null; - } catch (RepositoryException re) { - throw new ArgeoException( - "Unexpected error while creating the new workspace.", - re); - } - } else { - ErrorFeedback.show("Cannot add privileges"); - } - return null; - } -} \ No newline at end of file diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/AddRemoteRepository.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/AddRemoteRepository.java deleted file mode 100644 index e41edfca8..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/AddRemoteRepository.java +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.commands; - -import java.net.URI; -import java.util.Hashtable; - -import javax.jcr.Node; -import javax.jcr.Repository; -import javax.jcr.RepositoryFactory; -import javax.jcr.Session; -import javax.jcr.SimpleCredentials; - -import org.argeo.ArgeoException; -import org.argeo.eclipse.ui.ErrorFeedback; -import org.argeo.eclipse.ui.utils.CommandUtils; -import org.argeo.jcr.ArgeoJcrConstants; -import org.argeo.jcr.ArgeoNames; -import org.argeo.jcr.ArgeoTypes; -import org.argeo.jcr.JcrUtils; -import org.argeo.jcr.UserJcrUtils; -import org.argeo.jcr.ui.explorer.JcrExplorerConstants; -import org.argeo.util.security.Keyring; -import org.eclipse.core.commands.AbstractHandler; -import org.eclipse.core.commands.ExecutionEvent; -import org.eclipse.core.commands.ExecutionException; -import org.eclipse.jface.dialogs.Dialog; -import org.eclipse.jface.dialogs.IMessageProvider; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.dialogs.TitleAreaDialog; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Text; - -/** - * Connect to a remote repository and, if successful publish it as an OSGi - * service. - */ -public class AddRemoteRepository extends AbstractHandler implements - JcrExplorerConstants, ArgeoNames { - - private RepositoryFactory repositoryFactory; - private Repository nodeRepository; - private Keyring keyring; - - public Object execute(ExecutionEvent event) throws ExecutionException { - RemoteRepositoryLoginDialog dlg = new RemoteRepositoryLoginDialog( - Display.getDefault().getActiveShell()); - if (dlg.open() == Dialog.OK) { - CommandUtils.callCommand(Refresh.ID); - } - return null; - } - - public void setRepositoryFactory(RepositoryFactory repositoryFactory) { - this.repositoryFactory = repositoryFactory; - } - - public void setKeyring(Keyring keyring) { - this.keyring = keyring; - } - - public void setNodeRepository(Repository nodeRepository) { - this.nodeRepository = nodeRepository; - } - - class RemoteRepositoryLoginDialog extends TitleAreaDialog { - private Text name; - private Text uri; - private Text username; - private Text password; - private Button saveInKeyring; - - public RemoteRepositoryLoginDialog(Shell parentShell) { - super(parentShell); - } - - protected Point getInitialSize() { - return new Point(600, 400); - } - - protected Control createDialogArea(Composite parent) { - Composite dialogarea = (Composite) super.createDialogArea(parent); - dialogarea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, - true)); - Composite composite = new Composite(dialogarea, SWT.NONE); - composite.setLayout(new GridLayout(2, false)); - composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, - false)); - setMessage("Login to remote repository", IMessageProvider.NONE); - name = createLT(composite, "Name", "remoteRepository"); - uri = createLT(composite, "URI", - "http://localhost:7070/data/jcr/node"); - username = createLT(composite, "User", ""); - password = createLP(composite, "Password"); - - saveInKeyring = createLC(composite, "Remember password", false); - parent.pack(); - return composite; - } - - @Override - protected void createButtonsForButtonBar(Composite parent) { - super.createButtonsForButtonBar(parent); - Button test = createButton(parent, 2, "Test", false); - test.addSelectionListener(new SelectionAdapter() { - public void widgetSelected(SelectionEvent arg0) { - testConnection(); - } - }); - } - - void testConnection() { - Session session = null; - try { - URI checkedUri = new URI(uri.getText()); - String checkedUriStr = checkedUri.toString(); - - Hashtable params = new Hashtable(); - params.put(ArgeoJcrConstants.JCR_REPOSITORY_URI, checkedUriStr); - Repository repository = repositoryFactory.getRepository(params); - if (username.getText().trim().equals("")) {// anonymous - session = repository.login(); - } else { - // FIXME use getTextChars() when upgrading to 3.7 - // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=297412 - char[] pwd = password.getText().toCharArray(); - SimpleCredentials sc = new SimpleCredentials( - username.getText(), pwd); - session = repository.login(sc); - MessageDialog.openInformation(getParentShell(), "Success", - "Connection to '" + uri.getText() + "' successful"); - } - } catch (Exception e) { - ErrorFeedback.show( - "Connection test failed for " + uri.getText(), e); - } finally { - JcrUtils.logoutQuietly(session); - } - } - - @Override - protected void okPressed() { - Session nodeSession = null; - try { - nodeSession = nodeRepository.login(); - Node home = UserJcrUtils.getUserHome(nodeSession); - - Node remote = home.hasNode(ARGEO_REMOTE) ? home - .getNode(ARGEO_REMOTE) : home.addNode(ARGEO_REMOTE); - if (remote.hasNode(name.getText())) - throw new ArgeoException( - "There is already a remote repository named " - + name.getText()); - Node remoteRepository = remote.addNode(name.getText(), - ArgeoTypes.ARGEO_REMOTE_REPOSITORY); - remoteRepository.setProperty(ARGEO_URI, uri.getText()); - remoteRepository.setProperty(ARGEO_USER_ID, username.getText()); - nodeSession.save(); - if (saveInKeyring.getSelection()) { - String pwdPath = remoteRepository.getPath() + '/' - + ARGEO_PASSWORD; - keyring.set(pwdPath, password.getText().toCharArray()); - } - nodeSession.save(); - MessageDialog.openInformation( - getParentShell(), - "Repository Added", - "Remote repository '" + username.getText() + "@" - + uri.getText() + "' added"); - - super.okPressed(); - } catch (Exception e) { - ErrorFeedback.show("Cannot add remote repository", e); - } finally { - JcrUtils.logoutQuietly(nodeSession); - } - } - - /** Creates label and text. */ - protected Text createLT(Composite parent, String label, String initial) { - new Label(parent, SWT.NONE).setText(label); - Text text = new Text(parent, SWT.SINGLE | SWT.LEAD | SWT.BORDER); - text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - text.setText(initial); - return text; - } - - /** Creates label and check. */ - protected Button createLC(Composite parent, String label, - Boolean initial) { - new Label(parent, SWT.NONE).setText(label); - Button check = new Button(parent, SWT.CHECK); - check.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - check.setSelection(initial); - return check; - } - - protected Text createLP(Composite parent, String label) { - new Label(parent, SWT.NONE).setText(label); - Text text = new Text(parent, SWT.SINGLE | SWT.LEAD | SWT.BORDER - | SWT.PASSWORD); - text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - return text; - } - } -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/CreateWorkspace.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/CreateWorkspace.java deleted file mode 100644 index e579630ce..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/CreateWorkspace.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.commands; - -import java.util.Arrays; - -import org.argeo.eclipse.ui.ErrorFeedback; -import org.argeo.eclipse.ui.dialogs.SingleValue; -import org.argeo.jcr.ui.explorer.JcrExplorerPlugin; -import org.argeo.jcr.ui.explorer.model.RepositoryElem; -import org.argeo.jcr.ui.explorer.views.GenericJcrBrowser; -import org.eclipse.core.commands.AbstractHandler; -import org.eclipse.core.commands.ExecutionEvent; -import org.eclipse.core.commands.ExecutionException; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.ui.handlers.HandlerUtil; - -/** Creates a new JCR workspace */ -public class CreateWorkspace extends AbstractHandler { - - public final static String ID = JcrExplorerPlugin.ID + ".addFolderNode"; - - public Object execute(ExecutionEvent event) throws ExecutionException { - - ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event) - .getActivePage().getSelection(); - - GenericJcrBrowser view = (GenericJcrBrowser) HandlerUtil - .getActiveWorkbenchWindow(event).getActivePage() - .findView(HandlerUtil.getActivePartId(event)); - - if (selection != null && !selection.isEmpty() - && selection instanceof IStructuredSelection) { - Object obj = ((IStructuredSelection) selection).getFirstElement(); - if (!(obj instanceof RepositoryElem)) - return null; - - RepositoryElem repositoryNode = (RepositoryElem) obj; - String workspaceName = SingleValue.ask("Workspace name", - "Enter workspace name"); - if (workspaceName != null) { - if (Arrays.asList(repositoryNode.getAccessibleWorkspaceNames()) - .contains(workspaceName)) { - ErrorFeedback.show("Workspace " + workspaceName - + " already exists."); - } else { - repositoryNode.createWorkspace(workspaceName); - view.nodeAdded(repositoryNode); - } - } - } else { - ErrorFeedback.show("Cannot create workspace"); - } - return null; - } -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/DeleteNodes.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/DeleteNodes.java deleted file mode 100644 index 26d4cdd43..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/DeleteNodes.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.commands; - -import java.util.Iterator; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.argeo.ArgeoException; -import org.argeo.eclipse.ui.ErrorFeedback; -import org.argeo.eclipse.ui.TreeParent; -import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem; -import org.argeo.jcr.ui.explorer.model.WorkspaceElem; -import org.argeo.jcr.ui.explorer.views.GenericJcrBrowser; -import org.eclipse.core.commands.AbstractHandler; -import org.eclipse.core.commands.ExecutionEvent; -import org.eclipse.core.commands.ExecutionException; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.ui.handlers.HandlerUtil; - -/** - * Deletes the selected nodes: both in the JCR repository and in the UI view. - * Warning no check is done, except implementation dependent native checks, - * handle with care. - * - * This handler is still 'hard linked' to a GenericJcrBrowser view to enable - * correct tree refresh when a node is added. This must be corrected in future - * versions. - */ -public class DeleteNodes extends AbstractHandler { - public Object execute(ExecutionEvent event) throws ExecutionException { - ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event) - .getActivePage().getSelection(); - if (selection == null || !(selection instanceof IStructuredSelection)) - return null; - - GenericJcrBrowser view = (GenericJcrBrowser) HandlerUtil - .getActiveWorkbenchWindow(event).getActivePage() - .findView(HandlerUtil.getActivePartId(event)); - - // confirmation - StringBuffer buf = new StringBuffer(""); - Iterator lst = ((IStructuredSelection) selection).iterator(); - while (lst.hasNext()) { - SingleJcrNodeElem sjn = ((SingleJcrNodeElem) lst.next()); - buf.append(sjn.getName()).append(' '); - } - Boolean ok = MessageDialog.openConfirm( - HandlerUtil.getActiveShell(event), "Confirm deletion", - "Do you want to delete " + buf + "?"); - - // operation - if (ok) { - Iterator it = ((IStructuredSelection) selection).iterator(); - Object obj = null; - SingleJcrNodeElem ancestor = null; - WorkspaceElem rootAncestor = null; - try { - while (it.hasNext()) { - obj = it.next(); - if (obj instanceof SingleJcrNodeElem) { - // Cache objects - SingleJcrNodeElem sjn = (SingleJcrNodeElem) obj; - TreeParent tp = (TreeParent) sjn.getParent(); - Node node = sjn.getNode(); - - // Jcr Remove - node.remove(); - node.getSession().save(); - // UI remove - tp.removeChild(sjn); - - // Check if the parent is the root node - if (tp instanceof WorkspaceElem) - rootAncestor = (WorkspaceElem) tp; - else - ancestor = getOlder(ancestor, (SingleJcrNodeElem) tp); - } - } - if (rootAncestor != null) - view.nodeRemoved(rootAncestor); - else if (ancestor != null) - view.nodeRemoved(ancestor); - } catch (Exception e) { - ErrorFeedback.show("Cannot delete selected node ", e); - } - } - return null; - } - - private SingleJcrNodeElem getOlder(SingleJcrNodeElem A, SingleJcrNodeElem B) { - try { - if (A == null) - return B == null ? null : B; - // Todo enhanced this method - else - return A.getNode().getDepth() <= B.getNode().getDepth() ? A : B; - } catch (RepositoryException re) { - throw new ArgeoException("Cannot find ancestor", re); - } - } -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/DumpNode.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/DumpNode.java deleted file mode 100644 index c8a235d73..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/DumpNode.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.commands; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.GregorianCalendar; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.argeo.ArgeoException; -import org.argeo.eclipse.ui.specific.OpenFile; -import org.argeo.eclipse.ui.utils.CommandUtils; -import org.argeo.jcr.JcrUtils; -import org.argeo.jcr.ui.explorer.JcrExplorerPlugin; -import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem; -import org.eclipse.core.commands.AbstractHandler; -import org.eclipse.core.commands.ExecutionEvent; -import org.eclipse.core.commands.ExecutionException; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.ui.handlers.HandlerUtil; - -/** - * If the method - * HandlerUtil.getActiveWorkbenchWindow(event).getActivePage().getSelection() - * exits and has a SingleJcrNodeElem as first element, it canonically calls the - * JCR Session.exportSystemView() method on the underlying node with both - * skipBinary & noRecurse boolean flags set to false. - * - * Resulting stream is saved in a tmp file and opened via the "open file" - * single-sourced command. - */ -public class DumpNode extends AbstractHandler { - public final static String ID = JcrExplorerPlugin.ID + ".dumpNode"; - - private final static DateFormat df = new SimpleDateFormat( - "yyyy-MM-dd_HH-mm"); - - public Object execute(ExecutionEvent event) throws ExecutionException { - ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event) - .getActivePage().getSelection(); - if (selection == null || !(selection instanceof IStructuredSelection)) - return null; - - Iterator lst = ((IStructuredSelection) selection).iterator(); - if (lst.hasNext()) { - Object element = lst.next(); - if (element instanceof SingleJcrNodeElem) { - SingleJcrNodeElem sjn = (SingleJcrNodeElem) element; - Node node = sjn.getNode(); - - // TODO add a dialog to configure the export and ask for - // confirmation - // Boolean ok = MessageDialog.openConfirm( - // HandlerUtil.getActiveShell(event), "Confirm deletion", - // "Do you want to delete " + buf + "?"); - - File tmpFile; - FileOutputStream fos; - try { - tmpFile = File.createTempFile("JcrExport", ".xml"); - tmpFile.deleteOnExit(); - fos = new FileOutputStream(tmpFile); - String dateVal = df.format(new GregorianCalendar() - .getTime()); - node.getSession().exportSystemView(node.getPath(), fos, - true, false); - openGeneratedFile(tmpFile.getAbsolutePath(), - "Dump-" + JcrUtils.replaceInvalidChars(node.getName())+ "-" + dateVal + ".xml"); - } catch (RepositoryException e) { - throw new ArgeoException( - "Unable to perform SystemExport on " + node, e); - } catch (IOException e) { - throw new ArgeoException("Unable to SystemExport " + node, - e); - } - } - } - return null; - } - - private synchronized void openGeneratedFile(String path, String fileName) { - Map params = new HashMap(); - params.put(OpenFile.PARAM_FILE_NAME, fileName); - params.put(OpenFile.PARAM_FILE_URI, "file://" + path); - CommandUtils.callCommand("org.argeo.security.ui.specific.openFile", - params); - } -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/EditNode.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/EditNode.java deleted file mode 100644 index e98973e47..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/EditNode.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.commands; - -import java.util.HashMap; -import java.util.Map; - -import javax.jcr.Property; -import javax.jcr.nodetype.NodeType; - -import org.argeo.eclipse.ui.ErrorFeedback; -import org.argeo.eclipse.ui.jcr.editors.NodeEditorInput; -import org.eclipse.core.commands.AbstractHandler; -import org.eclipse.core.commands.ExecutionEvent; -import org.eclipse.core.commands.ExecutionException; -import org.eclipse.ui.PartInitException; -import org.eclipse.ui.handlers.HandlerUtil; - -/** Generic command to open a path in an editor. */ -public class EditNode extends AbstractHandler { - public final static String EDITOR_PARAM = "editor"; - - private String defaultEditorId; - - private Map nodeTypeToEditor = new HashMap(); - - public Object execute(ExecutionEvent event) throws ExecutionException { - String path = event.getParameter(Property.JCR_PATH); - - String type = event.getParameter(NodeType.NT_NODE_TYPE); - if (type == null) - type = NodeType.NT_UNSTRUCTURED; - - String editorId = event.getParameter(NodeType.NT_NODE_TYPE); - if (editorId == null) - editorId = nodeTypeToEditor.containsKey(type) ? nodeTypeToEditor - .get(type) : defaultEditorId; - - NodeEditorInput nei = new NodeEditorInput(path); - - try { - HandlerUtil.getActiveWorkbenchWindow(event).getActivePage() - .openEditor(nei, editorId); - } catch (PartInitException e) { - ErrorFeedback.show("Cannot open " + editorId + " with " + path - + " of type " + type, e); - } - // TODO Auto-generated method stub - return null; - } - - public void setDefaultEditorId(String defaultEditorId) { - this.defaultEditorId = defaultEditorId; - } - -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/GetNodeSize.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/GetNodeSize.java deleted file mode 100644 index cfcac1354..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/GetNodeSize.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.commands; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import javax.jcr.Node; - -import org.argeo.eclipse.ui.ErrorFeedback; -import org.argeo.jcr.JcrUtils; -import org.argeo.jcr.ui.explorer.JcrExplorerPlugin; -import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem; -import org.argeo.jcr.ui.explorer.model.WorkspaceElem; -import org.eclipse.core.commands.AbstractHandler; -import org.eclipse.core.commands.ExecutionEvent; -import org.eclipse.core.commands.ExecutionException; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.ui.handlers.HandlerUtil; - -/** Opens the generic node editor. */ -public class GetNodeSize extends AbstractHandler { - // private final static Log log = LogFactory.getLog(GetNodeSize.class); - - public final static String ID = JcrExplorerPlugin.ID + ".getNodeSize"; - - // public final static String DEFAULT_ICON_REL_PATH = "icons/getSize.gif"; - // public final static String DEFAULT_LABEL = JcrExplorerPlugin - // .getMessage("getNodeSizeCmdLbl"); - - public Object execute(ExecutionEvent event) throws ExecutionException { - // JcrUtils.getRepositoryByAlias(repositoryRegister, - // ArgeoJcrConstants.ALIAS_NODE); - - ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event) - .getActivePage().getSelection(); - - if (selection != null && !selection.isEmpty() - && selection instanceof IStructuredSelection) { - - // IStructuredSelection iss = (IStructuredSelection) selection; - // if (iss.size() > 1) - // ErrorFeedback.show(JcrExplorerPlugin - // .getMessage("warningInvalidMultipleSelection"), null); - - long size = 0; - - Iterator it = ((IStructuredSelection) selection).iterator(); - - // as the size method is recursive, we keep track of nodes for which - // we already have computed size so that we don't count them twice. - // In a first approximation, we assume that the structure selection - // keep the nodes ordered. - // TODO : enhance that. - List importedPathes = new ArrayList(); - try { - nodesIt: while (it.hasNext()) { - Object obj = it.next(); - String curPath; - Node node; - if (obj instanceof SingleJcrNodeElem) { - node = ((SingleJcrNodeElem) obj).getNode(); - curPath = node.getSession().getWorkspace().getName(); - curPath += "/" + node.getPath(); - } else if (obj instanceof WorkspaceElem) { - node = ((WorkspaceElem) obj).getRootNode(); - curPath = node.getSession().getWorkspace().getName(); - } else - // unvalid object type - continue nodesIt; - - Iterator itPath = importedPathes.iterator(); - while (itPath.hasNext()) { - String refPath = itPath.next(); - if (curPath.startsWith(refPath)) - // Already done : skip node - continue nodesIt; - } - size += JcrUtils.getNodeApproxSize(node); - importedPathes.add(curPath); - } - } catch (Exception e) { - ErrorFeedback.show("Cannot Get size of selected node ", e); - } - - String[] labels = { "OK" }; - Shell shell = HandlerUtil.getActiveWorkbenchWindow(event) - .getShell(); - MessageDialog md = new MessageDialog(shell, "Node size", null, - "Node size is: " + size / 1024 + " KB", - MessageDialog.INFORMATION, labels, 0); - md.open(); - } - return null; - } -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/ImportFileSystem.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/ImportFileSystem.java deleted file mode 100644 index 5c4bf7e6b..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/ImportFileSystem.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.commands; - -import javax.jcr.Node; - -import org.argeo.eclipse.ui.ErrorFeedback; -import org.argeo.eclipse.ui.TreeParent; -import org.argeo.jcr.ui.explorer.JcrExplorerPlugin; -import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem; -import org.argeo.jcr.ui.explorer.model.WorkspaceElem; -import org.argeo.jcr.ui.explorer.views.GenericJcrBrowser; -import org.argeo.jcr.ui.explorer.wizards.ImportFileSystemWizard; -import org.eclipse.core.commands.AbstractHandler; -import org.eclipse.core.commands.ExecutionEvent; -import org.eclipse.core.commands.ExecutionException; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.wizard.WizardDialog; -import org.eclipse.ui.handlers.HandlerUtil; - -/** Import a local file system directory tree. */ -public class ImportFileSystem extends AbstractHandler { - public Object execute(ExecutionEvent event) throws ExecutionException { - ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event) - .getActivePage().getSelection(); - GenericJcrBrowser view = (GenericJcrBrowser) HandlerUtil - .getActiveWorkbenchWindow(event).getActivePage() - .findView(HandlerUtil.getActivePartId(event)); - if (selection != null && !selection.isEmpty() - && selection instanceof IStructuredSelection) { - Object obj = ((IStructuredSelection) selection).getFirstElement(); - try { - Node folder = null; - if (obj instanceof SingleJcrNodeElem) { - folder = ((SingleJcrNodeElem) obj).getNode(); - } else if (obj instanceof WorkspaceElem) { - folder = ((WorkspaceElem) obj).getRootNode(); - } else { - ErrorFeedback.show(JcrExplorerPlugin - .getMessage("warningInvalidNodeToImport")); - } - if (folder != null) { - ImportFileSystemWizard wizard = new ImportFileSystemWizard( - folder); - WizardDialog dialog = new WizardDialog( - HandlerUtil.getActiveShell(event), wizard); - dialog.open(); - view.nodeAdded((TreeParent) obj); - } - } catch (Exception e) { - ErrorFeedback.show("Cannot import files to " + obj, e); - } - } - return null; - } -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/OpenGenericNodeEditor.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/OpenGenericNodeEditor.java deleted file mode 100644 index 6799d1706..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/OpenGenericNodeEditor.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.commands; - -import org.argeo.ArgeoException; -import org.argeo.eclipse.ui.jcr.editors.NodeEditorInput; -import org.argeo.jcr.ui.explorer.JcrExplorerConstants; -import org.argeo.jcr.ui.explorer.JcrExplorerPlugin; -import org.argeo.jcr.ui.explorer.editors.GenericNodeEditor; -import org.eclipse.core.commands.AbstractHandler; -import org.eclipse.core.commands.ExecutionEvent; -import org.eclipse.core.commands.ExecutionException; -import org.eclipse.ui.handlers.HandlerUtil; - -/** Opens the generic node editor. */ -public class OpenGenericNodeEditor extends AbstractHandler { - public final static String ID = JcrExplorerPlugin.ID + ".openGenericNodeEditor"; - - public Object execute(ExecutionEvent event) throws ExecutionException { - String path = event.getParameter(JcrExplorerConstants.PARAM_PATH); - try { - NodeEditorInput nei = new NodeEditorInput(path); - HandlerUtil.getActiveWorkbenchWindow(event).getActivePage() - .openEditor(nei, GenericNodeEditor.ID); - } catch (Exception e) { - throw new ArgeoException("Cannot open editor", e); - } - return null; - } - -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/Refresh.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/Refresh.java deleted file mode 100644 index 21ce25658..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/Refresh.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.commands; - -import java.util.Iterator; - -import org.argeo.eclipse.ui.TreeParent; -import org.argeo.eclipse.ui.jcr.views.AbstractJcrBrowser; -import org.argeo.jcr.ui.explorer.JcrExplorerPlugin; -import org.argeo.jcr.ui.explorer.utils.JcrUiUtils; -import org.argeo.jcr.ui.explorer.views.GenericJcrBrowser; -import org.eclipse.core.commands.AbstractHandler; -import org.eclipse.core.commands.ExecutionEvent; -import org.eclipse.core.commands.ExecutionException; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.IStructuredSelection; - -/** - * Force the selected objects of the active view to be refreshed doing the - * following: - *
    - *
  1. The model objects are recomputed
  2. - *
  3. the view is refreshed
  4. - *
- */ -public class Refresh extends AbstractHandler { - - public final static String ID = JcrExplorerPlugin.ID + ".refresh"; - - public Object execute(ExecutionEvent event) throws ExecutionException { - - AbstractJcrBrowser view = (AbstractJcrBrowser) JcrExplorerPlugin - .getDefault().getWorkbench().getActiveWorkbenchWindow() - .getActivePage().getActivePart();// - - ISelection selection = JcrExplorerPlugin.getDefault().getWorkbench() - .getActiveWorkbenchWindow().getActivePage().getSelection(); - - if (selection != null && selection instanceof IStructuredSelection - && !selection.isEmpty()) { - Iterator it = ((IStructuredSelection) selection).iterator(); - while (it.hasNext()) { - Object obj = it.next(); - if (obj instanceof TreeParent) { - TreeParent tp = (TreeParent) obj; - JcrUiUtils.forceRefreshIfNeeded(tp); - view.refresh(obj); - } - } - } else if (view instanceof GenericJcrBrowser) - ((GenericJcrBrowser) view).refresh(null); // force full refresh - - return null; - } -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/RemoveRemoteRepository.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/RemoveRemoteRepository.java deleted file mode 100644 index ec23dd08c..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/RemoveRemoteRepository.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.commands; - -import org.argeo.jcr.ui.explorer.model.RemoteRepositoryElem; -import org.argeo.jcr.ui.explorer.views.GenericJcrBrowser; -import org.eclipse.core.commands.AbstractHandler; -import org.eclipse.core.commands.ExecutionEvent; -import org.eclipse.core.commands.ExecutionException; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.ui.handlers.HandlerUtil; - -/** Remove a registered remote repository */ -public class RemoveRemoteRepository extends AbstractHandler { - - public Object execute(ExecutionEvent event) throws ExecutionException { - - ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event) - .getActivePage().getSelection(); - - GenericJcrBrowser view = (GenericJcrBrowser) HandlerUtil - .getActiveWorkbenchWindow(event).getActivePage() - .findView(HandlerUtil.getActivePartId(event)); - - if (selection != null && !selection.isEmpty() - && selection instanceof IStructuredSelection) { - Object obj = ((IStructuredSelection) selection).getFirstElement(); - - if (obj instanceof RemoteRepositoryElem) { - ((RemoteRepositoryElem) obj).remove(); - view.refresh(null); - } - } - return null; - } - -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/SortChildNodes.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/SortChildNodes.java deleted file mode 100644 index 2961529d8..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/SortChildNodes.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.commands; - -import org.argeo.jcr.ui.explorer.JcrExplorerPlugin; -import org.argeo.jcr.ui.explorer.views.GenericJcrBrowser; -import org.eclipse.core.commands.AbstractHandler; -import org.eclipse.core.commands.Command; -import org.eclipse.core.commands.ExecutionEvent; -import org.eclipse.core.commands.ExecutionException; -import org.eclipse.core.commands.State; -import org.eclipse.ui.PlatformUI; -import org.eclipse.ui.commands.ICommandService; -import org.eclipse.ui.handlers.HandlerUtil; - -/** - * Change isSorted state of the JcrExplorer Browser - */ -public class SortChildNodes extends AbstractHandler { - public final static String ID = JcrExplorerPlugin.ID + ".sortChildNodes"; - - public Object execute(ExecutionEvent event) throws ExecutionException { - GenericJcrBrowser view = (GenericJcrBrowser) HandlerUtil - .getActiveWorkbenchWindow(event).getActivePage() - .findView(GenericJcrBrowser.ID); - - ICommandService service = (ICommandService) PlatformUI.getWorkbench() - .getService(ICommandService.class); - Command command = service.getCommand(ID); - State state = command.getState(ID + ".toggleState"); - - boolean wasSorted = (Boolean) state.getValue(); - view.setSortChildNodes(!wasSorted); - state.setValue(!wasSorted); - return null; - } -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/dialogs/ChooseNameDialog.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/dialogs/ChooseNameDialog.java deleted file mode 100644 index d4a5cc757..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/dialogs/ChooseNameDialog.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.dialogs; - -import org.eclipse.jface.dialogs.IMessageProvider; -import org.eclipse.jface.dialogs.TitleAreaDialog; -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Text; - -/** Dialog to change the current user password */ -public class ChooseNameDialog extends TitleAreaDialog { - private Text nameT; - - public ChooseNameDialog(Shell parentShell) { - super(parentShell); - setTitle("Choose name"); - } - - protected Point getInitialSize() { - return new Point(300, 250); - } - - protected Control createDialogArea(Composite parent) { - Composite dialogarea = (Composite) super.createDialogArea(parent); - dialogarea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - Composite composite = new Composite(dialogarea, SWT.NONE); - composite.setLayout(new GridLayout(2, false)); - composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); - nameT = createLT(composite, "Name"); - - setMessage("Choose name", IMessageProvider.INFORMATION); - parent.pack(); - return composite; - } - - /** Creates label and text. */ - protected Text createLT(Composite parent, String label) { - new Label(parent, SWT.NONE).setText(label); - Text text = new Text(parent, SWT.SINGLE | SWT.LEAD | SWT.BORDER); - text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); - return text; - } - - public String getName() { - return nameT.getText(); - } -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/ChildNodesPage.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/ChildNodesPage.java deleted file mode 100644 index 682254a48..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/ChildNodesPage.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.editors; - -import javax.jcr.Node; - -import org.argeo.ArgeoException; -import org.argeo.jcr.ui.explorer.JcrExplorerPlugin; -import org.argeo.jcr.ui.explorer.browser.NodeLabelProvider; -import org.argeo.jcr.ui.explorer.providers.SingleNodeAsTreeContentProvider; -import org.argeo.jcr.ui.explorer.utils.GenericNodeDoubleClickListener; -import org.eclipse.jface.viewers.ITreeContentProvider; -import org.eclipse.jface.viewers.TreeViewer; -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.ui.forms.IManagedForm; -import org.eclipse.ui.forms.editor.FormEditor; -import org.eclipse.ui.forms.editor.FormPage; -import org.eclipse.ui.forms.widgets.ScrolledForm; - -/** - * List all childs of the current node and brings some browsing capabilities - * accross the repository - */ -public class ChildNodesPage extends FormPage { - // private final static Log log = LogFactory.getLog(ChildNodesPage.class); - - // business objects - private Node currentNode; - - // this page UI components - private SingleNodeAsTreeContentProvider nodeContentProvider; - private TreeViewer nodesViewer; - - public ChildNodesPage(FormEditor editor, String title, Node currentNode) { - super(editor, "ChildNodesPage", title); - this.currentNode = currentNode; - } - - protected void createFormContent(IManagedForm managedForm) { - try { - ScrolledForm form = managedForm.getForm(); - form.setText(JcrExplorerPlugin.getMessage("childNodesPageTitle")); - Composite body = form.getBody(); - GridLayout twt = new GridLayout(1, false); - twt.marginWidth = twt.marginHeight = 5; - body.setLayout(twt); - if (!currentNode.hasNodes()) { - managedForm.getToolkit().createLabel(body, - JcrExplorerPlugin.getMessage("warningNoChildNode")); - } else { - - nodeContentProvider = new SingleNodeAsTreeContentProvider(); - nodesViewer = createNodeViewer(body, nodeContentProvider); - nodesViewer.setInput(currentNode); - } - } catch (Exception e) { - throw new ArgeoException( - "Unexpected error while creating child node page", e); - } - } - - protected TreeViewer createNodeViewer(Composite parent, - final ITreeContentProvider nodeContentProvider) { - - final TreeViewer tmpNodeViewer = new TreeViewer(parent, SWT.MULTI); - - tmpNodeViewer.getTree().setLayoutData( - new GridData(SWT.FILL, SWT.FILL, true, true)); - - tmpNodeViewer.setContentProvider(nodeContentProvider); - tmpNodeViewer.setLabelProvider(new NodeLabelProvider()); - tmpNodeViewer - .addDoubleClickListener(new GenericNodeDoubleClickListener( - tmpNodeViewer)); - return tmpNodeViewer; - } -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/EmptyNodePage.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/EmptyNodePage.java deleted file mode 100644 index 322c7ebd2..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/EmptyNodePage.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.editors; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Label; -import org.eclipse.ui.forms.IManagedForm; -import org.eclipse.ui.forms.editor.FormEditor; -import org.eclipse.ui.forms.editor.FormPage; -import org.eclipse.ui.forms.widgets.ScrolledForm; - -/** - * This page is only used at editor's creation time when current node has not - * yet been set - */ -public class EmptyNodePage extends FormPage { - // private final static Log log = LogFactory.getLog(EmptyNodePage.class); - - public EmptyNodePage(FormEditor editor, String title) { - super(editor, "Empty Page", title); - } - - protected void createFormContent(IManagedForm managedForm) { - try { - ScrolledForm form = managedForm.getForm(); - GridLayout twt = new GridLayout(1, false); - twt.marginWidth = twt.marginHeight = 0; - form.getBody().setLayout(twt); - Label lbl = new Label(form.getBody(), SWT.NONE); - lbl.setText("Empty page"); - } catch (Exception e) { - e.printStackTrace(); - } - } -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericJcrQueryEditor.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericJcrQueryEditor.java deleted file mode 100644 index 3b98ed137..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericJcrQueryEditor.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.editors; - -import org.argeo.eclipse.ui.jcr.editors.AbstractJcrQueryEditor; -import org.argeo.jcr.ui.explorer.JcrExplorerPlugin; -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Listener; -import org.eclipse.swt.widgets.Text; - -/** Enables end user to type and execute any JCR query. */ -public class GenericJcrQueryEditor extends AbstractJcrQueryEditor { - public final static String ID = JcrExplorerPlugin.ID + ".genericJcrQueryEditor"; - - private Text queryField; - - @Override - public void createQueryForm(Composite parent) { - parent.setLayout(new GridLayout(1, false)); - - queryField = new Text(parent, SWT.BORDER | SWT.MULTI | SWT.WRAP); - queryField.setText(initialQuery); - queryField.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - - Button execute = new Button(parent, SWT.PUSH); - execute.setText("Execute"); - - Listener executeListener = new Listener() { - public void handleEvent(Event event) { - executeQuery(queryField.getText()); - } - }; - - execute.addListener(SWT.Selection, executeListener); - // queryField.addListener(SWT.DefaultSelection, executeListener); - } - - @Override - public void setFocus() { - queryField.setFocus(); - } -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericNodeEditor.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericNodeEditor.java deleted file mode 100644 index 57f3aa236..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericNodeEditor.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.editors; - -import javax.jcr.Node; - -import org.argeo.ArgeoException; -import org.argeo.jcr.JcrUtils; -import org.argeo.jcr.ui.explorer.JcrExplorerPlugin; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.IEditorSite; -import org.eclipse.ui.PartInitException; -import org.eclipse.ui.forms.editor.FormEditor; - -/** - * Container for the node editor page. At creation time, it takes a JCR Node - * that cannot be changed afterwards. - */ -public class GenericNodeEditor extends FormEditor { - - // private final static Log log = - // LogFactory.getLog(GenericNodeEditor.class); - public final static String ID = JcrExplorerPlugin.ID + ".genericNodeEditor"; - - private Node currentNode; - - private GenericPropertyPage genericPropertyPage; - private ChildNodesPage childNodesPage; - private NodeRightsManagementPage nodeRightsManagementPage; - private NodeVersionHistoryPage nodeVersionHistoryPage; - - public void init(IEditorSite site, IEditorInput input) - throws PartInitException { - super.init(site, input); - GenericNodeEditorInput nei = (GenericNodeEditorInput) getEditorInput(); - currentNode = nei.getCurrentNode(); - this.setPartName(JcrUtils.lastPathElement(nei.getPath())); - } - - @Override - protected void addPages() { - try { - // genericNodePage = new GenericNodePage(this, - // JcrExplorerPlugin.getMessage("genericNodePageTitle"), - // currentNode); - // addPage(genericNodePage); - - genericPropertyPage = new GenericPropertyPage(this, - JcrExplorerPlugin.getMessage("genericNodePageTitle"), - currentNode); - addPage(genericPropertyPage); - - childNodesPage = new ChildNodesPage(this, - JcrExplorerPlugin.getMessage("childNodesPageTitle"), - currentNode); - addPage(childNodesPage); - - nodeRightsManagementPage = new NodeRightsManagementPage(this, - JcrExplorerPlugin - .getMessage("nodeRightsManagementPageTitle"), - currentNode); - addPage(nodeRightsManagementPage); - - nodeVersionHistoryPage = new NodeVersionHistoryPage( - this, - JcrExplorerPlugin.getMessage("nodeVersionHistoryPageTitle"), - currentNode); - addPage(nodeVersionHistoryPage); - } catch (PartInitException e) { - throw new ArgeoException("Not able to add an empty page ", e); - } - } - - @Override - public void doSaveAs() { - // unused compulsory method - } - - @Override - public void doSave(IProgressMonitor monitor) { - try { - // Automatically commit all pages of the editor - commitPages(true); - firePropertyChange(PROP_DIRTY); - } catch (Exception e) { - throw new ArgeoException("Error while saving node", e); - } - - } - - @Override - public boolean isSaveAsAllowed() { - return true; - } - - Node getCurrentNode() { - return currentNode; - } -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericNodeEditorInput.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericNodeEditorInput.java deleted file mode 100644 index 45e337e5d..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericNodeEditorInput.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.editors; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.argeo.ArgeoException; -import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.IPersistableElement; - -/** - * An editor input based the JCR node object. - * */ - -public class GenericNodeEditorInput implements IEditorInput { - private final Node currentNode; - - // cache key properties at creation time to avoid Exception at recoring time - // when the session has been closed - private String path; - private String uid; - private String name; - - public GenericNodeEditorInput(Node currentNode) { - this.currentNode = currentNode; - try { - name = currentNode.getName(); - uid = currentNode.getIdentifier(); - path = currentNode.getPath(); - } catch (RepositoryException re) { - throw new ArgeoException( - "unexpected error while getting node key values at creation time", - re); - } - } - - public Node getCurrentNode() { - return currentNode; - } - - public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) { - return null; - } - - public boolean exists() { - return true; - } - - public ImageDescriptor getImageDescriptor() { - return null; - } - - public String getName() { - return name; - } - - public String getUid() { - return uid; - } - - public String getToolTipText() { - return path; - } - - public String getPath() { - return path; - } - - public IPersistableElement getPersistable() { - return null; - } - - /** - * equals method based on UID that is unique within a workspace and path of - * the node, thus 2 shared node that have same UID as defined in the spec - * but 2 different pathes will open two distinct editors. - * - * TODO enhance this method to support multirepository and multiworkspace - * environments - */ - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - - GenericNodeEditorInput other = (GenericNodeEditorInput) obj; - if (!getUid().equals(other.getUid())) - return false; - if (!getPath().equals(other.getPath())) - return false; - return true; - } -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericNodePage.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericNodePage.java deleted file mode 100644 index fd4dafe76..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericNodePage.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.editors; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.ListIterator; - -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.PropertyIterator; -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; - -import org.argeo.ArgeoException; -import org.argeo.jcr.JcrUtils; -import org.argeo.jcr.ui.explorer.JcrExplorerConstants; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Text; -import org.eclipse.ui.forms.AbstractFormPart; -import org.eclipse.ui.forms.IManagedForm; -import org.eclipse.ui.forms.editor.FormEditor; -import org.eclipse.ui.forms.editor.FormPage; -import org.eclipse.ui.forms.widgets.FormToolkit; -import org.eclipse.ui.forms.widgets.ScrolledForm; - -/** - * Main node editor page. Lists all properties of the current node and enable - * access and editing for some of them. - */ - -public class GenericNodePage extends FormPage implements JcrExplorerConstants { - // private final static Log log = LogFactory.getLog(GenericNodePage.class); - - // local constants - private final static String JCR_PROPERTY_NAME = "jcr:name"; - - // Utils - protected DateFormat timeFormatter = new SimpleDateFormat(DATE_TIME_FORMAT); - - // Main business Objects - private Node currentNode; - - // This page widgets - private FormToolkit tk; - private List modifyableProperties = new ArrayList(); - - public GenericNodePage(FormEditor editor, String title, Node currentNode) { - super(editor, "id", title); - this.currentNode = currentNode; - } - - protected void createFormContent(IManagedForm managedForm) { - tk = managedForm.getToolkit(); - ScrolledForm form = managedForm.getForm(); - GridLayout twt = new GridLayout(3, false); - twt.marginWidth = twt.marginHeight = 5; - - form.getBody().setLayout(twt); - createPropertiesPart(form.getBody()); - } - - private void createPropertiesPart(Composite parent) { - try { - - PropertyIterator pi = currentNode.getProperties(); - - // Initializes form part - AbstractFormPart part = new AbstractFormPart() { - public void commit(boolean onSave) { - try { - if (onSave) { - ListIterator it = modifyableProperties - .listIterator(); - while (it.hasNext()) { - // we only support Text controls for the time - // being - Text curControl = (Text) it.next(); - String value = curControl.getText(); - currentNode.setProperty((String) curControl - .getData(JCR_PROPERTY_NAME), value); - } - - // We only commit when onSave = true, - // thus it is still possible to save after a tab - // change. - super.commit(onSave); - } - } catch (RepositoryException re) { - throw new ArgeoException( - "Unexpected error while saving properties", re); - } - } - }; - - while (pi.hasNext()) { - Property prop = pi.nextProperty(); - addPropertyLine(parent, part, prop); - } - - getManagedForm().addPart(part); - } catch (RepositoryException re) { - throw new ArgeoException( - "Error during creation of network details section", re); - } - - } - - private void addPropertyLine(Composite parent, AbstractFormPart part, - Property prop) { - try { - tk.createLabel(parent, prop.getName()); - tk.createLabel(parent, - "[" + JcrUtils.getPropertyDefinitionAsString(prop) + "]"); - - if (prop.getDefinition().isProtected()) { - tk.createLabel(parent, formatReadOnlyPropertyValue(prop)); - } else - addModifyableValueWidget(parent, part, prop); - } catch (RepositoryException re) { - throw new ArgeoException("Cannot get property " + prop, re); - } - } - - private String formatReadOnlyPropertyValue(Property prop) { - try { - String strValue; - - if (prop.getType() == PropertyType.BINARY) - strValue = ""; - else if (prop.isMultiple()) - strValue = Arrays.asList(prop.getValues()).toString(); - else if (prop.getType() == PropertyType.DATE) - strValue = timeFormatter.format(prop.getValue().getDate() - .getTime()); - else - strValue = prop.getValue().getString(); - - return strValue; - } catch (RepositoryException re) { - throw new ArgeoException( - "Unexpected error while formatting read only property value", - re); - } - } - - private Control addModifyableValueWidget(Composite parent, - AbstractFormPart part, Property prop) { - GridData gd; - try { - if (prop.getType() == PropertyType.STRING) { - Text txt = tk.createText(parent, prop.getString()); - gd = new GridData(GridData.FILL_HORIZONTAL); - txt.setLayoutData(gd); - txt.addModifyListener(new ModifiedFieldListener(part)); - txt.setData(JCR_PROPERTY_NAME, prop.getName()); - modifyableProperties.add(txt); - } else { - // unsupported property type for editing, we create a read only - // label. - return tk - .createLabel(parent, formatReadOnlyPropertyValue(prop)); - } - return null; - } catch (RepositoryException re) { - throw new ArgeoException( - "Unexpected error while formatting read only property value", - re); - } - - } - - // - // LISTENERS - // - - private class ModifiedFieldListener implements ModifyListener { - - private AbstractFormPart formPart; - - public ModifiedFieldListener(AbstractFormPart generalPart) { - this.formPart = generalPart; - } - - public void modifyText(ModifyEvent e) { - formPart.markDirty(); - } - } - -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericPropertyPage.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericPropertyPage.java deleted file mode 100644 index 3aec4538c..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericPropertyPage.java +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.editors; - -import java.util.ArrayList; -import java.util.List; - -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.PropertyIterator; -import javax.jcr.RepositoryException; -import javax.jcr.Value; - -import org.argeo.ArgeoException; -import org.argeo.jcr.ui.explorer.JcrExplorerConstants; -import org.argeo.jcr.ui.explorer.JcrExplorerPlugin; -import org.argeo.jcr.ui.explorer.providers.PropertyLabelProvider; -import org.eclipse.jface.viewers.ITreeContentProvider; -import org.eclipse.jface.viewers.TreeViewer; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.FillLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Tree; -import org.eclipse.swt.widgets.TreeColumn; -import org.eclipse.ui.forms.IManagedForm; -import org.eclipse.ui.forms.editor.FormEditor; -import org.eclipse.ui.forms.editor.FormPage; -import org.eclipse.ui.forms.widgets.ScrolledForm; - -/** - * Generic editor property page. Lists all properties of current node as a - * complex tree. TODO: enable editing - */ - -public class GenericPropertyPage extends FormPage implements - JcrExplorerConstants { - // private final static Log log = - // LogFactory.getLog(GenericPropertyPage.class); - - // Main business Objects - private Node currentNode; - - public GenericPropertyPage(FormEditor editor, String title, Node currentNode) { - super(editor, "id", title); - this.currentNode = currentNode; - } - - protected void createFormContent(IManagedForm managedForm) { - ScrolledForm form = managedForm.getForm(); - form.setText(JcrExplorerPlugin.getMessage("genericNodePageTitle")); - FillLayout layout = new FillLayout(); - layout.marginHeight = 5; - layout.marginWidth = 5; - form.getBody().setLayout(layout); - - createComplexTree(form.getBody()); - - // TODO remove following - // createPropertiesPart(form.getBody()); - } - - private TreeViewer createComplexTree(Composite parent) { - int style = SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION; - Tree tree = new Tree(parent, style); - createColumn(tree, "Property", SWT.LEFT, 200); - createColumn(tree, "Value(s)", SWT.LEFT, 300); - createColumn(tree, "Attributes", SWT.LEFT, 65); - tree.setLinesVisible(true); - tree.setHeaderVisible(true); - - TreeViewer result = new TreeViewer(tree); - result.setContentProvider(new TreeContentProvider()); - result.setLabelProvider(new PropertyLabelProvider()); - result.setInput(currentNode); - result.expandAll(); - return result; - } - - private static TreeColumn createColumn(Tree parent, String name, int style, - int width) { - TreeColumn result = new TreeColumn(parent, style); - result.setText(name); - result.setWidth(width); - result.setMoveable(true); - result.setResizable(true); - return result; - } - - // - // private void createPropertiesPart(Composite parent) { - // try { - // - // PropertyIterator pi = currentNode.getProperties(); - // - // // Initializes form part - // AbstractFormPart part = new AbstractFormPart() { - // public void commit(boolean onSave) { - // try { - // if (onSave) { - // ListIterator it = modifyableProperties - // .listIterator(); - // while (it.hasNext()) { - // // we only support Text controls for the time - // // being - // Text curControl = (Text) it.next(); - // String value = curControl.getText(); - // currentNode.setProperty((String) curControl - // .getData(JCR_PROPERTY_NAME), value); - // } - // - // // We only commit when onSave = true, - // // thus it is still possible to save after a tab - // // change. - // super.commit(onSave); - // } - // } catch (RepositoryException re) { - // throw new ArgeoException( - // "Unexpected error while saving properties", re); - // } - // } - // }; - // - // while (pi.hasNext()) { - // Property prop = pi.nextProperty(); - // addPropertyLine(parent, part, prop); - // } - // - // getManagedForm().addPart(part); - // } catch (RepositoryException re) { - // throw new ArgeoException( - // "Error during creation of network details section", re); - // } - // - // } - // - // private void addPropertyLine(Composite parent, AbstractFormPart part, - // Property prop) { - // try { - // tk.createLabel(parent, prop.getName()); - // tk.createLabel(parent, - // "[" + JcrUtils.getPropertyDefinitionAsString(prop) + "]"); - // - // if (prop.getDefinition().isProtected()) { - // tk.createLabel(parent, formatReadOnlyPropertyValue(prop)); - // } else - // addModifyableValueWidget(parent, part, prop); - // } catch (RepositoryException re) { - // throw new ArgeoException("Cannot get property " + prop, re); - // } - // } - // - // private String formatReadOnlyPropertyValue(Property prop) { - // try { - // String strValue; - // - // if (prop.getType() == PropertyType.BINARY) - // strValue = ""; - // else if (prop.isMultiple()) - // strValue = Arrays.asList(prop.getValues()).toString(); - // else if (prop.getType() == PropertyType.DATE) - // strValue = timeFormatter.format(prop.getValue().getDate() - // .getTime()); - // else - // strValue = prop.getValue().getString(); - // - // return strValue; - // } catch (RepositoryException re) { - // throw new ArgeoException( - // "Unexpected error while formatting read only property value", - // re); - // } - // } - // - // private Control addModifyableValueWidget(Composite parent, - // AbstractFormPart part, Property prop) { - // GridData gd; - // try { - // if (prop.getType() == PropertyType.STRING) { - // Text txt = tk.createText(parent, prop.getString()); - // gd = new GridData(GridData.FILL_HORIZONTAL); - // txt.setLayoutData(gd); - // txt.addModifyListener(new ModifiedFieldListener(part)); - // txt.setData(JCR_PROPERTY_NAME, prop.getName()); - // modifyableProperties.add(txt); - // } else { - // // unsupported property type for editing, we create a read only - // // label. - // return tk - // .createLabel(parent, formatReadOnlyPropertyValue(prop)); - // } - // return null; - // } catch (RepositoryException re) { - // throw new ArgeoException( - // "Unexpected error while formatting read only property value", - // re); - // } - // - // } - - // Multiple Value Model - // protected class MultipleValueItem { - // private int index; - // private Value value; - // - // public MultipleValueItem(int index, Value value) { - // this.index = index; - // this.value = value; - // } - // - // public int getIndex() { - // return index; - // } - // - // public Object getValue() { - // return value; - // } - // } - - private class TreeContentProvider implements ITreeContentProvider { - public Object[] getElements(Object parent) { - Object[] props = null; - try { - - if (parent instanceof Node) { - Node node = (Node) parent; - PropertyIterator pi; - pi = node.getProperties(); - List propList = new ArrayList(); - while (pi.hasNext()) { - propList.add(pi.nextProperty()); - } - props = propList.toArray(); - } - } catch (RepositoryException e) { - throw new ArgeoException( - "Unexpected exception while listing node properties", e); - } - return props; - } - - public Object getParent(Object child) { - return null; - } - - public Object[] getChildren(Object parent) { - Object[] result = null; - if (parent instanceof Property) { - Property prop = (Property) parent; - try { - - if (prop.isMultiple()) { - Value[] values = prop.getValues(); - // List list = new - // ArrayList(); - // for (int i = 0; i < values.length; i++) { - // MultipleValueItem mvi = new MultipleValueItem(i, - // values[i]); - // list.add(mvi); - // } - - return values; - } - } catch (RepositoryException e) { - throw new ArgeoException( - "Unexpected error getting multiple values property.", - e); - } - } - return result; - } - - public boolean hasChildren(Object parent) { - try { - if (parent instanceof Property - && ((Property) parent).isMultiple()) { - return true; - } - } catch (RepositoryException e) { - throw new ArgeoException( - "Unexpected exception while checking if property is multiple", - e); - } - return false; - } - - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - } - - public void dispose() { - } - } -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/NodeRightsManagementPage.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/NodeRightsManagementPage.java deleted file mode 100644 index cc5efb5f9..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/NodeRightsManagementPage.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.editors; - -import javax.jcr.Node; -import javax.jcr.security.AccessControlManager; -import javax.jcr.security.Privilege; - -import org.argeo.ArgeoException; -import org.argeo.jcr.ui.explorer.JcrExplorerPlugin; -import org.eclipse.jface.viewers.ColumnLabelProvider; -import org.eclipse.jface.viewers.IStructuredContentProvider; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.jface.viewers.TableViewerColumn; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.layout.FillLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Table; -import org.eclipse.swt.widgets.TableColumn; -import org.eclipse.ui.forms.IManagedForm; -import org.eclipse.ui.forms.editor.FormEditor; -import org.eclipse.ui.forms.editor.FormPage; -import org.eclipse.ui.forms.widgets.ScrolledForm; - -/** - * This comments will be nicely fill by mbaudier in. - */ -public class NodeRightsManagementPage extends FormPage { - // private final static Log log = - // LogFactory.getLog(NodeRightsManagementPage.class); - - private Node currentNode; - - private TableViewer viewer; - - public NodeRightsManagementPage(FormEditor editor, String title, - Node currentNode) { - super(editor, "NodeRightsManagementPage", title); - this.currentNode = currentNode; - } - - protected void createFormContent(IManagedForm managedForm) { - ScrolledForm form = managedForm.getForm(); - form.setText(JcrExplorerPlugin - .getMessage("nodeRightsManagementPageTitle")); - FillLayout layout = new FillLayout(); - layout.marginHeight = 5; - layout.marginWidth = 5; - form.getBody().setLayout(layout); - createRightsPart(form.getBody()); - } - - /** Creates the rights part */ - protected void createRightsPart(Composite parent) { - Table table = new Table(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); - table.setLinesVisible(true); - table.setHeaderVisible(true); - viewer = new TableViewer(table); - - // check column - TableViewerColumn column = createTableViewerColumn(viewer, "checked", - 20); - column.setLabelProvider(new ColumnLabelProvider() { - public String getText(Object element) { - return null; - } - - public Image getImage(Object element) { - return null; - } - }); - // column.setEditingSupport(new RoleEditingSupport(rolesViewer, part)); - - // role column - column = createTableViewerColumn(viewer, "Role", 200); - column.setLabelProvider(new ColumnLabelProvider() { - public String getText(Object element) { - Privilege p = (Privilege) element; - return p.getName(); - } - - public Image getImage(Object element) { - return null; - } - }); - viewer.setContentProvider(new RightsContentProvider()); - viewer.setInput(getEditorSite()); - } - - protected TableViewerColumn createTableViewerColumn(TableViewer viewer, - String title, int bound) { - final TableViewerColumn viewerColumn = new TableViewerColumn(viewer, - SWT.NONE); - final TableColumn column = viewerColumn.getColumn(); - column.setText(title); - column.setWidth(bound); - column.setResizable(true); - column.setMoveable(true); - return viewerColumn; - } - - private class RightsContentProvider implements IStructuredContentProvider { - - public void dispose() { - } - - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - } - - public Object[] getElements(Object inputElement) { - try { - AccessControlManager accessControlManager = currentNode - .getSession().getAccessControlManager(); - Privilege[] privileges = accessControlManager - .getPrivileges(currentNode.getPath()); - return privileges; - } catch (Exception e) { - throw new ArgeoException("Cannot retrieve rights", e); - } - } - - } -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/NodeVersionHistoryPage.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/NodeVersionHistoryPage.java deleted file mode 100644 index 59fff5e59..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/NodeVersionHistoryPage.java +++ /dev/null @@ -1,319 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.editors; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.List; -import java.util.Map; - -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; -import javax.jcr.Value; -import javax.jcr.nodetype.NodeType; -import javax.jcr.version.Version; -import javax.jcr.version.VersionHistory; -import javax.jcr.version.VersionIterator; -import javax.jcr.version.VersionManager; - -import org.argeo.ArgeoException; -import org.argeo.jcr.JcrUtils; -import org.argeo.jcr.PropertyDiff; -import org.argeo.jcr.VersionDiff; -import org.argeo.jcr.ui.explorer.JcrExplorerConstants; -import org.argeo.jcr.ui.explorer.JcrExplorerPlugin; -import org.argeo.jcr.ui.explorer.providers.FullVersioningTreeContentProvider; -import org.argeo.jcr.ui.explorer.providers.VersionLabelProvider; -import org.argeo.jcr.ui.explorer.utils.GenericNodeDoubleClickListener; -import org.eclipse.jface.viewers.ITreeContentProvider; -import org.eclipse.jface.viewers.TreeViewer; -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Text; -import org.eclipse.ui.forms.AbstractFormPart; -import org.eclipse.ui.forms.IManagedForm; -import org.eclipse.ui.forms.editor.FormEditor; -import org.eclipse.ui.forms.editor.FormPage; -import org.eclipse.ui.forms.widgets.FormToolkit; -import org.eclipse.ui.forms.widgets.ScrolledForm; -import org.eclipse.ui.forms.widgets.Section; -import org.eclipse.ui.forms.widgets.TableWrapData; -import org.eclipse.ui.forms.widgets.TableWrapLayout; - -/** - * Offers two main sections : one to display a text area with a summary of all - * variations between a version and its predecessor and one tree view that - * enable browsing - * */ -public class NodeVersionHistoryPage extends FormPage implements - JcrExplorerConstants { - // private final static Log log = LogFactory - // .getLog(NodeVersionHistoryPage.class); - - // Utils - protected DateFormat timeFormatter = new SimpleDateFormat(DATE_TIME_FORMAT); - - // business objects - private Node currentNode; - - // this page UI components - private FullVersioningTreeContentProvider nodeContentProvider; - private TreeViewer nodesViewer; - private FormToolkit tk; - - public NodeVersionHistoryPage(FormEditor editor, String title, - Node currentNode) { - super(editor, "NodeVersionHistoryPage", title); - this.currentNode = currentNode; - } - - protected void createFormContent(IManagedForm managedForm) { - ScrolledForm form = managedForm.getForm(); - form.setText(JcrExplorerPlugin - .getMessage("nodeVersionHistoryPageTitle")); - tk = managedForm.getToolkit(); - GridLayout twt = new GridLayout(1, false); - twt.marginWidth = twt.marginHeight = 5; - Composite body = form.getBody(); - body.setLayout(twt); - - try { - if (!currentNode.isNodeType(NodeType.MIX_VERSIONABLE)) { - tk.createLabel(body, JcrExplorerPlugin - .getMessage("warningUnversionableNode")); - } else { - createHistorySection(form.getBody()); - createTreeSection(form.getBody()); - } - } catch (RepositoryException e) { - throw new ArgeoException( - "Unexpected error while checking if node is versionable", e); - } - } - - protected void createTreeSection(Composite parent) { - // Section Layout & MetaData - Section section = tk.createSection(parent, Section.TWISTIE); - section.setLayoutData(new GridData(GridData.FILL_BOTH)); - section.setText(JcrExplorerPlugin.getMessage("versionTreeSectionTitle")); - - // Section Body - Composite body = tk.createComposite(section, SWT.FILL); - // WARNING : 2 following lines are compulsory or body won't be - // displayed. - body.setLayout(new GridLayout()); - section.setClient(body); - - body.setLayoutData(new GridData(GridData.FILL_BOTH)); - section.setExpanded(true); - - nodeContentProvider = new FullVersioningTreeContentProvider(); - nodesViewer = createNodeViewer(body, nodeContentProvider); - nodesViewer.setInput(currentNode); - } - - protected TreeViewer createNodeViewer(Composite parent, - final ITreeContentProvider nodeContentProvider) { - - final TreeViewer tmpNodeViewer = new TreeViewer(parent, SWT.MULTI); - - tmpNodeViewer.getTree().setLayoutData( - new GridData(SWT.FILL, SWT.FILL, true, true)); - - tmpNodeViewer.setContentProvider(nodeContentProvider); - tmpNodeViewer.setLabelProvider(new VersionLabelProvider()); - tmpNodeViewer - .addDoubleClickListener(new GenericNodeDoubleClickListener( - tmpNodeViewer)); - return tmpNodeViewer; - } - - protected void createHistorySection(Composite parent) { - - // Section Layout - Section section = tk.createSection(parent, Section.TWISTIE); - section.setLayoutData(new GridData(TableWrapData.FILL_GRAB)); - TableWrapLayout twt = new TableWrapLayout(); - section.setLayout(twt); - - // Set title of the section - section.setText(JcrExplorerPlugin - .getMessage("versionHistorySectionTitle")); - - final Text styledText = tk.createText(section, "", SWT.FULL_SELECTION - | SWT.BORDER | SWT.MULTI | SWT.WRAP | SWT.V_SCROLL); - styledText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - section.setClient(styledText); - refreshHistory(styledText); - styledText.setEditable(false); - section.setExpanded(false); - - AbstractFormPart part = new AbstractFormPart() { - public void commit(boolean onSave) { - } - - public void refresh() { - super.refresh(); - refreshHistory(styledText); - } - }; - getManagedForm().addPart(part); - } - - protected void refreshHistory(Text styledText) { - try { - List lst = listHistoryDiff(); - StringBuffer main = new StringBuffer(""); - - for (int i = lst.size() - 1; i >= 0; i--) { - if (i == 0) - main.append("Creation ("); - else - main.append("Update " + i + " ("); - - if (lst.get(i).getUserId() != null) - main.append("UserId : " + lst.get(i).getUserId()); - - if (lst.get(i).getUserId() != null - && lst.get(i).getUpdateTime() != null) - main.append(", "); - - if (lst.get(i).getUpdateTime() != null) - main.append("Date : " - + timeFormatter.format(lst.get(i).getUpdateTime() - .getTime()) + ")\n"); - - StringBuffer buf = new StringBuffer(""); - Map diffs = lst.get(i).getDiffs(); - for (String prop : diffs.keySet()) { - PropertyDiff pd = diffs.get(prop); - // String propName = pd.getRelPath(); - Value refValue = pd.getReferenceValue(); - Value newValue = pd.getNewValue(); - String refValueStr = ""; - String newValueStr = ""; - - if (refValue != null) { - if (refValue.getType() == PropertyType.DATE) { - refValueStr = timeFormatter.format(refValue - .getDate().getTime()); - } else - refValueStr = refValue.getString(); - } - if (newValue != null) { - if (newValue.getType() == PropertyType.DATE) { - newValueStr = timeFormatter.format(newValue - .getDate().getTime()); - } else - newValueStr = newValue.getString(); - } - - if (pd.getType() == PropertyDiff.MODIFIED) { - buf.append(prop).append(": "); - buf.append(refValueStr); - buf.append(" > "); - buf.append(newValueStr); - buf.append("\n"); - } else if (pd.getType() == PropertyDiff.ADDED - && !"".equals(newValueStr)) { - // we don't list property that have been added with an - // empty string as value - buf.append(prop).append(": "); - buf.append(" + "); - buf.append(newValueStr); - buf.append("\n"); - } else if (pd.getType() == PropertyDiff.REMOVED) { - buf.append(prop).append(": "); - buf.append(" - "); - buf.append(refValueStr); - buf.append("\n"); - } - } - buf.append("\n"); - main.append(buf); - } - styledText.setText(main.toString()); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot generate history for node", e); - } - - } - - public List listHistoryDiff() { - try { - List res = new ArrayList(); - VersionManager versionManager = currentNode.getSession() - .getWorkspace().getVersionManager(); - VersionHistory versionHistory = versionManager - .getVersionHistory(currentNode.getPath()); - - VersionIterator vit = versionHistory.getAllLinearVersions(); - while (vit.hasNext()) { - Version version = vit.nextVersion(); - Node node = version.getFrozenNode(); - Version predecessor = null; - try { - predecessor = version.getLinearPredecessor(); - } catch (Exception e) { - // no predecessor seems to throw an exception even if it - // shouldn't... - } - if (predecessor == null) {// original - } else { - Map diffs = JcrUtils.diffProperties( - predecessor.getFrozenNode(), node); - if (!diffs.isEmpty()) { - String lastUserName = null; - Calendar lastUpdate = null; - try { - if (currentNode - .isNodeType(NodeType.MIX_LAST_MODIFIED)) { - lastUserName = node.getProperty( - Property.JCR_LAST_MODIFIED_BY) - .getString(); - lastUpdate = node.getProperty( - Property.JCR_LAST_MODIFIED).getDate(); - } else - lastUpdate = version.getProperty( - Property.JCR_CREATED).getDate(); - - } catch (Exception e) { - // Silent that info is optional - } - VersionDiff vd = new VersionDiff(lastUserName, - lastUpdate, diffs); - res.add(vd); - } - } - } - return res; - } catch (RepositoryException e) { - throw new ArgeoException("Cannot generate history for node "); - } - - } - - @Override - public void setActive(boolean active) { - super.setActive(active); - } -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/StringNodeEditorInput.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/StringNodeEditorInput.java deleted file mode 100644 index 654b2aeea..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/StringNodeEditorInput.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.editors; - -import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.IPersistableElement; - -/** - * An editor input based on three strings define a node : - *
    - *
  • complete path to the node
  • - *
  • the workspace name
  • - *
  • the repository alias
  • - *
- * In a single workspace and/or repository environment, name and alias can be - * null. - * - * Note : unused for the time being. - */ - -public class StringNodeEditorInput implements IEditorInput { - private final String path; - private final String repositoryAlias; - private final String workspaceName; - - /** - * In order to implement a generic explorer that supports remote and multi - * workspaces repositories, node path can be detailed by these strings. - * - * @param repositoryAlias - * : can be null - * @param workspaceName - * : can be null - * @param path - */ - public StringNodeEditorInput(String repositoryAlias, String workspaceName, - String path) { - this.path = path; - this.repositoryAlias = repositoryAlias; - this.workspaceName = workspaceName; - } - - public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) { - return null; - } - - public boolean exists() { - return true; - } - - public ImageDescriptor getImageDescriptor() { - return null; - } - - public String getName() { - return path; - } - - public String getRepositoryAlias() { - return repositoryAlias; - } - - public String getWorkspaceName() { - return workspaceName; - } - - public IPersistableElement getPersistable() { - return null; - } - - public String getToolTipText() { - return path; - } - - public String getPath() { - return path; - } - - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - - StringNodeEditorInput other = (StringNodeEditorInput) obj; - - if (!path.equals(other.getPath())) - return false; - - String own = other.getWorkspaceName(); - if ((workspaceName == null && own != null) - || (workspaceName != null && (own == null || !workspaceName - .equals(own)))) - return false; - - String ora = other.getRepositoryAlias(); - if ((repositoryAlias == null && ora != null) - || (repositoryAlias != null && (ora == null || !repositoryAlias - .equals(ora)))) - return false; - - return true; - } -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/MaintainedRepositoryElem.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/MaintainedRepositoryElem.java deleted file mode 100644 index abb97a9e8..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/MaintainedRepositoryElem.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.argeo.jcr.ui.explorer.model; - -import javax.jcr.Repository; - -import org.argeo.ArgeoException; -import org.argeo.eclipse.ui.TreeParent; -import org.argeo.jcr.MaintainedRepository; - -/** Wraps a {@link MaintainedRepository} */ -public class MaintainedRepositoryElem extends RepositoryElem { - - public MaintainedRepositoryElem(String alias, Repository repository, - TreeParent parent) { - super(alias, repository, parent); - if (!(repository instanceof MaintainedRepository)) { - throw new ArgeoException("Repository " + alias - + " is not amiantained repository"); - } - } - - protected MaintainedRepository getMaintainedRepository() { - return (MaintainedRepository) getRepository(); - } -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/RemoteRepositoryElem.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/RemoteRepositoryElem.java deleted file mode 100644 index 0be69781c..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/RemoteRepositoryElem.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.model; - -import java.util.Arrays; - -import javax.jcr.Node; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.RepositoryFactory; -import javax.jcr.Session; -import javax.jcr.SimpleCredentials; - -import org.argeo.ArgeoException; -import org.argeo.eclipse.ui.TreeParent; -import org.argeo.jcr.ArgeoJcrUtils; -import org.argeo.jcr.ArgeoNames; -import org.argeo.util.security.Keyring; - -/** Root of a remote repository */ -public class RemoteRepositoryElem extends RepositoryElem { - private final Keyring keyring; - /** - * A session of the logged in user on the default workspace of the node - * repository. - */ - private final Session userSession; - private final String remoteNodePath; - - private final RepositoryFactory repositoryFactory; - private final String uri; - - public RemoteRepositoryElem(String alias, - RepositoryFactory repositoryFactory, String uri, TreeParent parent, - Session userSession, Keyring keyring, String remoteNodePath) { - super(alias, null, parent); - this.repositoryFactory = repositoryFactory; - this.uri = uri; - this.keyring = keyring; - this.userSession = userSession; - this.remoteNodePath = remoteNodePath; - } - - @Override - protected Session repositoryLogin(String workspaceName) - throws RepositoryException { - Node remoteRepository = userSession.getNode(remoteNodePath); - String userID = remoteRepository.getProperty(ArgeoNames.ARGEO_USER_ID) - .getString(); - String pwdPath = remoteRepository.getPath() + '/' - + ArgeoNames.ARGEO_PASSWORD; - char[] password = keyring.getAsChars(pwdPath); - - try { - SimpleCredentials credentials = new SimpleCredentials(userID, - password); - return getRepository().login(credentials, workspaceName); - } finally { - Arrays.fill(password, 0, password.length, ' '); - } - } - - @Override - public Repository getRepository() { - if (repository == null) - repository = ArgeoJcrUtils.getRepositoryByUri(repositoryFactory, - uri); - return super.getRepository(); - } - - public void remove() { - try { - Node remoteNode = userSession.getNode(remoteNodePath); - remoteNode.remove(); - remoteNode.getSession().save(); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot remove " + remoteNodePath, e); - } - } - -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/RepositoriesElem.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/RepositoriesElem.java deleted file mode 100644 index b123727bc..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/RepositoriesElem.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.model; - -import java.util.Map; - -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.RepositoryFactory; -import javax.jcr.Session; - -import org.argeo.ArgeoException; -import org.argeo.eclipse.ui.ErrorFeedback; -import org.argeo.eclipse.ui.TreeParent; -import org.argeo.jcr.ArgeoNames; -import org.argeo.jcr.MaintainedRepository; -import org.argeo.jcr.RepositoryRegister; -import org.argeo.jcr.UserJcrUtils; -import org.argeo.util.security.Keyring; - -/** - * UI Tree component. Implements the Argeo abstraction of a - * {@link RepositoryFactory} that enable a user to "mount" various repositories - * in a single Tree like View. It is usually meant to be at the root of the UI - * Tree and thus {@link getParent()} method will return null. - * - * The {@link RepositoryFactory} is injected at instantiation time and must be - * use get or register new {@link Repository} objects upon which a reference is - * kept here. - */ - -public class RepositoriesElem extends TreeParent implements ArgeoNames { - private final RepositoryRegister repositoryRegister; - private final RepositoryFactory repositoryFactory; - - /** - * A session of the logged in user on the default workspace of the node - * repository. - */ - private final Session userSession; - private final Keyring keyring; - - public RepositoriesElem(String name, RepositoryRegister repositoryRegister, - RepositoryFactory repositoryFactory, TreeParent parent, - Session userSession, Keyring keyring) { - super(name); - this.repositoryRegister = repositoryRegister; - this.repositoryFactory = repositoryFactory; - this.userSession = userSession; - this.keyring = keyring; - } - - /** - * Override normal behavior to initialize the various repositories only at - * request time - */ - @Override - public synchronized Object[] getChildren() { - if (isLoaded()) { - return super.getChildren(); - } else { - // initialize current object - Map refRepos = repositoryRegister - .getRepositories(); - for (String name : refRepos.keySet()) { - Repository repository = refRepos.get(name); - if (repository instanceof MaintainedRepository) - super.addChild(new MaintainedRepositoryElem(name, - repository, this)); - else - super.addChild(new RepositoryElem(name, repository, this)); - } - - // remote - if (keyring != null) { - try { - addRemoteRepositories(keyring); - } catch (RepositoryException e) { - throw new ArgeoException( - "Cannot browse remote repositories", e); - } - } - return super.getChildren(); - } - } - - protected void addRemoteRepositories(Keyring jcrKeyring) - throws RepositoryException { - Node userHome = UserJcrUtils.getUserHome(userSession); - if (userHome != null && userHome.hasNode(ARGEO_REMOTE)) { - NodeIterator it = userHome.getNode(ARGEO_REMOTE).getNodes(); - while (it.hasNext()) { - Node remoteNode = it.nextNode(); - String uri = remoteNode.getProperty(ARGEO_URI).getString(); - try { - RemoteRepositoryElem remoteRepositoryNode = new RemoteRepositoryElem( - remoteNode.getName(), repositoryFactory, uri, this, - userSession, jcrKeyring, remoteNode.getPath()); - super.addChild(remoteRepositoryNode); - } catch (Exception e) { - ErrorFeedback.show("Cannot add remote repository " - + remoteNode, e); - } - } - } - } - - public void registerNewRepository(String alias, Repository repository) { - // TODO: implement this - // Create a new RepositoryNode Object - // add it - // super.addChild(new RepositoriesNode(...)); - } - - /** Returns the {@link RepositoryRegister} wrapped by this object. */ - public RepositoryRegister getRepositoryRegister() { - return repositoryRegister; - } -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/RepositoryElem.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/RepositoryElem.java deleted file mode 100644 index 935bac12b..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/RepositoryElem.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.model; - -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.argeo.ArgeoException; -import org.argeo.eclipse.ui.TreeParent; - -/** - * UI Tree component. Wraps a JCR {@link Repository}. It also keeps a reference - * to its parent Tree Ui component; typically the unique {@link Repositories} - * object of the current view to enable bi-directionnal browsing in the tree. - */ - -public class RepositoryElem extends TreeParent { - private String alias; - protected Repository repository; - private Session defaultSession = null; - - /** Create a new repository with distinct name & alias */ - public RepositoryElem(String alias, Repository repository, TreeParent parent) { - super(alias); - this.repository = repository; - setParent(parent); - this.alias = alias; - } - - public void login() { - try { - defaultSession = repositoryLogin(null); - String[] wkpNames = defaultSession.getWorkspace() - .getAccessibleWorkspaceNames(); - for (String wkpName : wkpNames) { - if (wkpName.equals(defaultSession.getWorkspace().getName())) - addChild(new WorkspaceElem(this, wkpName, defaultSession)); - else - addChild(new WorkspaceElem(this, wkpName)); - } - } catch (RepositoryException e) { - throw new ArgeoException("Cannot connect to repository " + alias, e); - } - } - - /** - * Actual call to the - * {@link Repository#login(javax.jcr.Credentials, String)} method. To be - * overridden. - */ - protected Session repositoryLogin(String workspaceName) - throws RepositoryException { - return repository.login(workspaceName); - } - - public String[] getAccessibleWorkspaceNames() { - try { - return defaultSession.getWorkspace().getAccessibleWorkspaceNames(); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot retrieve workspace names", e); - } - } - - public void createWorkspace(String workspaceName) { - if (!isConnected()) - login(); - try { - defaultSession.getWorkspace().createWorkspace(workspaceName); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot create workspace", e); - } - } - - /** returns the {@link Repository} referenced by the current UI Node */ - public Repository getRepository() { - return repository; - } - - public String getAlias() { - return alias; - } - - public Boolean isConnected() { - if (defaultSession != null && defaultSession.isLive()) - return true; - else - return false; - } -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/SingleJcrNodeElem.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/SingleJcrNodeElem.java deleted file mode 100644 index 7b588f83b..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/SingleJcrNodeElem.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.model; - -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.RepositoryException; -import javax.jcr.Workspace; - -import org.argeo.ArgeoException; -import org.argeo.eclipse.ui.TreeParent; - -/** - * UI Tree component. Wraps a node of a JCR {@link Workspace}. It also keeps a - * reference to its parent node that can either be a {@link WorkspaceElem}, a - * {@link SingleJcrNodeElem} or null if the node is "mounted" as the root of the UI - * tree. - */ - -public class SingleJcrNodeElem extends TreeParent { - - private final Node node; - private String alias = null; - - // keeps a local reference to the node's name to avoid exception when the - // session is lost - // private final String name; - - /** Creates a new UiNode in the UI Tree */ - public SingleJcrNodeElem(TreeParent parent, Node node, String name) { - super(name); - setParent(parent); - this.node = node; - } - - /** - * Creates a new UiNode in the UI Tree, keeping a reference to the alias of - * the corresponding repository in the current UI environment. It is useful - * to be able to mount nodes as roots of the UI tree. - */ - public SingleJcrNodeElem(TreeParent parent, Node node, String name, String alias) { - super(name); - setParent(parent); - this.node = node; - this.alias = alias; - } - - /** returns the node wrapped by the current Ui object */ - public Node getNode() { - return node; - } - - protected String getRepositoryAlias() { - return alias; - } - - /** - * Override normal behavior to initialize children only when first requested - */ - @Override - public synchronized Object[] getChildren() { - if (isLoaded()) { - return super.getChildren(); - } else { - // initialize current object - try { - NodeIterator ni = node.getNodes(); - while (ni.hasNext()) { - Node curNode = ni.nextNode(); - addChild(new SingleJcrNodeElem(this, curNode, curNode.getName())); - } - return super.getChildren(); - } catch (RepositoryException re) { - throw new ArgeoException( - "Unexcpected error while initializing children SingleJcrNode", - re); - } - } - } - - @Override - public boolean hasChildren() { - try { - if (node.getSession().isLive()) - return node.hasNodes(); - else - return false; - } catch (RepositoryException re) { - throw new ArgeoException( - "Unexpected error while checking children node existence", - re); - } - } - -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/WorkspaceElem.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/WorkspaceElem.java deleted file mode 100644 index bb9b69caf..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/WorkspaceElem.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.model; - -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.Workspace; - -import org.argeo.ArgeoException; -import org.argeo.eclipse.ui.TreeParent; -import org.argeo.jcr.JcrUtils; - -/** - * UI Tree component. Wraps the root node of a JCR {@link Workspace}. It also - * keeps a reference to its parent {@link RepositoryElem}, to be able to - * retrieve alias of the current used repository - */ -public class WorkspaceElem extends TreeParent { - private Session session = null; - - public WorkspaceElem(RepositoryElem parent, String name) { - this(parent, name, null); - } - - public WorkspaceElem(RepositoryElem parent, String name, Session session) { - super(name); - this.session = session; - setParent(parent); - } - - public Session getSession() { - return session; - } - - public Node getRootNode() { - try { - if (session != null) - return session.getRootNode(); - else - return null; - } catch (RepositoryException e) { - throw new ArgeoException("Cannot get root node of workspace " - + getName(), e); - } - } - - public void login() { - try { - session = ((RepositoryElem) getParent()).repositoryLogin(getName()); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot connect to repository " - + getName(), e); - } - } - - public Boolean isConnected() { - if (session != null && session.isLive()) - return true; - else - return false; - } - - @Override - public synchronized void dispose() { - logout(); - super.dispose(); - } - - /** Logouts the session, does not nothing if there is no live session. */ - public void logout() { - clearChildren(); - JcrUtils.logoutQuietly(session); - } - - @Override - public boolean hasChildren() { - try { - if (isConnected()) - return session.getRootNode().hasNodes(); - else - return false; - } catch (RepositoryException re) { - throw new ArgeoException( - "Unexpected error while checking children node existence", - re); - } - } - - /** Override normal behaviour to initialize display of the workspace */ - @Override - public synchronized Object[] getChildren() { - if (isLoaded()) { - return super.getChildren(); - } else { - // initialize current object - try { - Node rootNode; - if (session == null) - return null; - else - rootNode = session.getRootNode(); - NodeIterator ni = rootNode.getNodes(); - while (ni.hasNext()) { - Node node = ni.nextNode(); - addChild(new SingleJcrNodeElem(this, node, node.getName())); - } - return super.getChildren(); - } catch (RepositoryException e) { - throw new ArgeoException( - "Cannot initialize WorkspaceNode UI object." - + getName(), e); - } - } - } -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/providers/FullVersioningTreeContentProvider.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/providers/FullVersioningTreeContentProvider.java deleted file mode 100644 index 736a5aa2f..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/providers/FullVersioningTreeContentProvider.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.providers; - -import java.util.ArrayList; -import java.util.List; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.nodetype.NodeType; -import javax.jcr.version.Version; -import javax.jcr.version.VersionHistory; -import javax.jcr.version.VersionIterator; -import javax.jcr.version.VersionManager; - -import org.argeo.ArgeoException; -import org.eclipse.jface.viewers.ITreeContentProvider; -import org.eclipse.jface.viewers.Viewer; - -/** - * Implementation of the {@code ITreeContentProvider} in order to display some - * version informations of a JCR full versionable node in a tree like structure - * - */ -public class FullVersioningTreeContentProvider implements ITreeContentProvider { - // private Node rootNode; - // private ItemComparator itemComparator = new ItemComparator(); - - /** - * Sends back the first level of the Tree. input element must be a single - * node object - */ - public Object[] getElements(Object inputElement) { - try { - Node rootNode = (Node) inputElement; - String curPath = rootNode.getPath(); - VersionManager vm = rootNode.getSession().getWorkspace() - .getVersionManager(); - - VersionHistory vh = vm.getVersionHistory(curPath); - List result = new ArrayList(); - VersionIterator vi = vh.getAllLinearVersions(); - - while (vi.hasNext()) { - result.add(vi.nextVersion()); - } - return result.toArray(); - } catch (RepositoryException re) { - throw new ArgeoException( - "Unexpected error while getting version elements", re); - } - } - - public Object[] getChildren(Object parentElement) { - try { - if (parentElement instanceof Version) { - List tmp = new ArrayList(); - tmp.add(((Version) parentElement).getFrozenNode()); - return tmp.toArray(); - } - } catch (RepositoryException re) { - throw new ArgeoException("Unexpected error while getting child " - + "node for version element", re); - } - return null; - } - - public Object getParent(Object element) { - try { - // this will not work in a simpleVersionning environment, parent is - // not a node. - if (element instanceof Node - && ((Node) element).isNodeType(NodeType.NT_FROZEN_NODE)) { - Node node = (Node) element; - return node.getParent(); - } else - return null; - } catch (RepositoryException e) { - return null; - } - } - - public boolean hasChildren(Object element) { - try { - if (element instanceof Version) - return true; - else if (element instanceof Node) - return ((Node) element).hasNodes(); - else - return false; - } catch (RepositoryException e) { - throw new ArgeoException("Cannot check children of " + element, e); - } - } - - public void dispose() { - } - - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - } - -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/providers/PropertyLabelProvider.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/providers/PropertyLabelProvider.java deleted file mode 100644 index decbe6338..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/providers/PropertyLabelProvider.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.providers; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; - -import javax.jcr.Property; -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; -import javax.jcr.Value; - -import org.argeo.ArgeoException; -import org.argeo.jcr.JcrUtils; -import org.argeo.jcr.ui.explorer.JcrExplorerConstants; -import org.eclipse.jface.viewers.ColumnLabelProvider; -import org.eclipse.jface.viewers.ViewerCell; - -public class PropertyLabelProvider extends ColumnLabelProvider implements - JcrExplorerConstants { - - // To be able to change column order easily - public static final int COLUMN_PROPERTY = 0; - public static final int COLUMN_VALUE = 1; - public static final int COLUMN_ATTRIBUTES = 2; - - // Utils - protected DateFormat timeFormatter = new SimpleDateFormat(DATE_TIME_FORMAT); - - public void update(ViewerCell cell) { - Object element = cell.getElement(); - cell.setText(getColumnText(element, cell.getColumnIndex())); - // Image image = getImage(element); - // cell.setImage(image); - // cell.setBackground(getBackground(element)); - // cell.setForeground(getForeground(element)); - // cell.setFont(getFont(element)); - } - - public String getColumnText(Object element, int columnIndex) { - try { - if (element instanceof Property) { - Property prop = (Property) element; - if (prop.isMultiple()) { - switch (columnIndex) { - case COLUMN_PROPERTY: - return prop.getName(); - case COLUMN_VALUE: - // Corresponding values are listed on children - return ""; - case COLUMN_ATTRIBUTES: - return JcrUtils.getPropertyDefinitionAsString(prop); - } - } else { - switch (columnIndex) { - case COLUMN_PROPERTY: - return prop.getName(); - case COLUMN_VALUE: - return formatValueAsString(prop.getValue()); - case COLUMN_ATTRIBUTES: - return JcrUtils.getPropertyDefinitionAsString(prop); - } - } - } else if (element instanceof Value) { - Value val = (Value) element; - - switch (columnIndex) { - case COLUMN_PROPERTY: - // Nothing to show - return ""; - case COLUMN_VALUE: - return formatValueAsString(val); - case COLUMN_ATTRIBUTES: - // Corresponding attributes are listed on the parent - return ""; - } - } - - } catch (RepositoryException re) { - throw new ArgeoException( - "Unexepected error while getting property values", re); - } - return null; - } - - private String formatValueAsString(Value value) { - // TODO enhance this method - try { - String strValue; - - if (value.getType() == PropertyType.BINARY) - strValue = ""; - else if (value.getType() == PropertyType.DATE) - strValue = timeFormatter.format(value.getDate().getTime()); - else - strValue = value.getString(); - return strValue; - } catch (RepositoryException e) { - throw new ArgeoException("unexpected error while formatting value", - e); - } - } -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/providers/SingleNodeAsTreeContentProvider.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/providers/SingleNodeAsTreeContentProvider.java deleted file mode 100644 index 8c69b6b9c..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/providers/SingleNodeAsTreeContentProvider.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.providers; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.RepositoryException; - -import org.argeo.ArgeoException; -import org.argeo.eclipse.ui.jcr.utils.JcrItemsComparator; -import org.eclipse.jface.viewers.ITreeContentProvider; -import org.eclipse.jface.viewers.Viewer; - -/** - * Implementation of the {@code ITreeContentProvider} in order to display a - * single JCR node and its children in a tree like structure - * - */ -public class SingleNodeAsTreeContentProvider implements ITreeContentProvider { - // private Node rootNode; - private JcrItemsComparator itemComparator = new JcrItemsComparator(); - - /** - * Sends back the first level of the Tree. input element must be a single - * node object - */ - public Object[] getElements(Object inputElement) { - try { - Node rootNode = (Node) inputElement; - List result = new ArrayList(); - NodeIterator ni = rootNode.getNodes(); - while (ni.hasNext()) { - result.add(ni.nextNode()); - } - - return result.toArray(); - } catch (RepositoryException re) { - throw new ArgeoException( - "Unexpected error while getting child nodes for children editor page ", - re); - } - } - - public Object[] getChildren(Object parentElement) { - return childrenNodes((Node) parentElement); - } - - public Object getParent(Object element) { - try { - Node node = (Node) element; - if (!node.getPath().equals("/")) - return node.getParent(); - else - return null; - } catch (RepositoryException e) { - return null; - } - } - - public boolean hasChildren(Object element) { - try { - return ((Node) element).hasNodes(); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot check children of " + element, e); - } - } - - public void dispose() { - } - - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - } - - protected Object[] childrenNodes(Node parentNode) { - try { - List children = new ArrayList(); - NodeIterator nit = parentNode.getNodes(); - while (nit.hasNext()) { - Node node = nit.nextNode(); - children.add(node); - } - Node[] arr = children.toArray(new Node[children.size()]); - Arrays.sort(arr, itemComparator); - return arr; - } catch (RepositoryException e) { - throw new ArgeoException("Cannot list children of " + parentNode, e); - } - } -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/providers/VersionLabelProvider.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/providers/VersionLabelProvider.java deleted file mode 100644 index 69b35ebb5..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/providers/VersionLabelProvider.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.providers; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.version.Version; - -import org.argeo.ArgeoException; -import org.eclipse.jface.viewers.ColumnLabelProvider; - -/** - * simple wrapping of the ColumnLabelProvider class to provide text display in - * order to build a tree for version. The Get text method does not assume that - * Version extends Node class to respect JCR 2.0 specification - * - */ -public class VersionLabelProvider extends ColumnLabelProvider { - - public String getText(Object element) { - try { - if (element instanceof Version) { - Version version = (Version) element; - return version.getName(); - } else if (element instanceof Node) { - return ((Node) element).getName(); - } - } catch (RepositoryException re) { - throw new ArgeoException( - "Unexpected error while getting element name", re); - } - return super.getText(element); - } -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/utils/GenericNodeDoubleClickListener.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/utils/GenericNodeDoubleClickListener.java deleted file mode 100644 index 0f93450eb..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/utils/GenericNodeDoubleClickListener.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.utils; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.nodetype.NodeType; - -import org.argeo.ArgeoException; -import org.argeo.eclipse.ui.jcr.utils.JcrFileProvider; -import org.argeo.eclipse.ui.specific.FileHandler; -import org.argeo.jcr.ui.explorer.JcrExplorerPlugin; -import org.argeo.jcr.ui.explorer.editors.GenericNodeEditor; -import org.argeo.jcr.ui.explorer.editors.GenericNodeEditorInput; -import org.argeo.jcr.ui.explorer.model.RepositoryElem; -import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem; -import org.argeo.jcr.ui.explorer.model.WorkspaceElem; -import org.eclipse.jface.viewers.DoubleClickEvent; -import org.eclipse.jface.viewers.IDoubleClickListener; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.viewers.TreeViewer; -import org.eclipse.ui.PartInitException; - -/** - * Centralizes the management of double click on a NodeTreeViewer - */ -public class GenericNodeDoubleClickListener implements IDoubleClickListener { - - // private final static Log log = LogFactory - // .getLog(GenericNodeDoubleClickListener.class); - - private TreeViewer nodeViewer; - private JcrFileProvider jfp; - private FileHandler fileHandler; - - public GenericNodeDoubleClickListener(TreeViewer nodeViewer) { - this.nodeViewer = nodeViewer; - jfp = new JcrFileProvider(); - // Commented out. see https://www.argeo.org/bugzilla/show_bug.cgi?id=188 - fileHandler = null; - // fileHandler = new FileHandler(jfp); - } - - public void doubleClick(DoubleClickEvent event) { - if (event.getSelection() == null || event.getSelection().isEmpty()) - return; - Object obj = ((IStructuredSelection) event.getSelection()) - .getFirstElement(); - if (obj instanceof RepositoryElem) { - RepositoryElem rpNode = (RepositoryElem) obj; - if (!rpNode.isConnected()) { - rpNode.login(); - nodeViewer.refresh(obj); - } - // else do nothing - } else if (obj instanceof WorkspaceElem) { - WorkspaceElem wn = (WorkspaceElem) obj; - if (wn.isConnected()) - wn.logout(); - else - wn.login(); - nodeViewer.refresh(obj); - } else if (obj instanceof SingleJcrNodeElem) { - SingleJcrNodeElem sjn = (SingleJcrNodeElem) obj; - Node node = sjn.getNode(); - try { - if (node.isNodeType(NodeType.NT_FILE)) { - // double click on a file node triggers its opening - String name = node.getName(); - String id = node.getIdentifier(); - - // For the file provider to be able to browse the - // various - // repository. - // TODO : enhanced that. - // ITreeContentProvider itcp = (ITreeContentProvider) - // nodeViewer - // .getContentProvider(); - jfp.setReferenceNode(node); - if (fileHandler != null) - fileHandler.openFile(name, id); - } - GenericNodeEditorInput gnei = new GenericNodeEditorInput(node); - JcrExplorerPlugin.getDefault().getWorkbench() - .getActiveWorkbenchWindow().getActivePage() - .openEditor(gnei, GenericNodeEditor.ID); - } catch (RepositoryException re) { - throw new ArgeoException( - "Repository error while getting node info", re); - } catch (PartInitException pie) { - throw new ArgeoException( - "Unexepected exception while opening node editor", pie); - } - } - } -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/utils/JcrUiUtils.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/utils/JcrUiUtils.java deleted file mode 100644 index ca32113ed..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/utils/JcrUiUtils.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.utils; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.argeo.ArgeoException; -import org.argeo.eclipse.ui.TreeParent; -import org.argeo.jcr.ui.explorer.model.RepositoriesElem; -import org.argeo.jcr.ui.explorer.model.RepositoryElem; -import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem; -import org.argeo.jcr.ui.explorer.model.WorkspaceElem; - -/** Centralizes some useful methods to build UIs with JCR */ -public class JcrUiUtils { - - /** Insure that the UI component is not stale, refresh if needed */ - public static void forceRefreshIfNeeded(TreeParent element) { - Node curNode = null; - - boolean doRefresh = false; - - try { - if (element instanceof SingleJcrNodeElem) { - curNode = ((SingleJcrNodeElem) element).getNode(); - } else if (element instanceof WorkspaceElem) { - curNode = ((WorkspaceElem) element).getRootNode(); - } - - if (curNode != null - && element.getChildren().length != curNode.getNodes() - .getSize()) - doRefresh = true; - else if (element instanceof RepositoryElem) { - RepositoryElem rn = (RepositoryElem) element; - if (rn.isConnected()) { - String[] wkpNames = rn.getAccessibleWorkspaceNames(); - if (element.getChildren().length != wkpNames.length) - doRefresh = true; - } - } else if (element instanceof RepositoriesElem) { - doRefresh = true; - // Always force refresh for RepositoriesElem : the condition - // below does not take remote repository into account and it is - // not trivial to do so. - - // RepositoriesElem rn = (RepositoriesElem) element; - // if (element.getChildren().length != - // rn.getRepositoryRegister() - // .getRepositories().size()) - // doRefresh = true; - } - if (doRefresh) { - element.clearChildren(); - element.getChildren(); - } - } catch (RepositoryException re) { - throw new ArgeoException( - "Unexpected error while synchronising the UI with the JCR repository", - re); - } - } - - /** - * Insure that a model element is inline with the underlying data by - * cleaning the corresponding subtree and building it again. - */ - public static void forceRebuild(TreeParent element) { - // TODO implement this method if needed. - } - /** - * Workaround to get the alias of the repository that contains the given - * element. As we cannot browse the UI tree upward we recursively browse it - * downward until we find the given element - * */ - // public static String getRepositoryAliasFromITreeElement( - // NodeContentProvider ncp, Object element) { - // RepositoryNode repositoryNode = null; - // if (element instanceof RepositoryNode) - // return ((RepositoryNode) element).getName(); - // else if (element instanceof RepositoryRegister) - // throw new ArgeoException( - // "Cannot get alias for a repository register"); - // - // // Get root elements - // Object[] elements = ncp.getElements(null); - // - // try { - // for (int i = 0; i < elements.length; i++) { - // if (elements[i] instanceof Node) { - // Node curNode = (Node) elements[i]; - // if (curNode.isNodeType(ArgeoTypes.ARGEO_USER_HOME)) { - // // Do nothing, we'll find the node in the "normal" tree - // // and - // // get corresponding alias this way round - // } else - // throw new ArgeoException( - // "Normal nodes should not be at the root of NodeTreeViewer"); - // } else if (elements[i] instanceof RepositoryRegister) { - // RepositoryRegister repositoryRegister = (RepositoryRegister) elements[i]; - // Map repositories = repositoryRegister - // .getRepositories(); - // - // for (String name : repositories.keySet()) { - // boolean found = isElementInCurrentTreePart( - // ncp, - // new RepositoryNode(name, repositories.get(name)), - // (Node) element); - // if (found) - // return name; - // } - // } else - // throw new ArgeoException( - // "Unexpected object class at the root of NodeTreeViewer"); - // } - // } catch (RepositoryException re) { - // throw new ArgeoException( - // "Unexpected error while retrieving Alias name", re); - // } - // return null; - // } - // - // /** implements the recursivity */ - // private static boolean isElementInCurrentTreePart(NodeContentProvider - // ncp, - // Object parentElement, NodParente searchedElement) { - // boolean found = false; - // if (parentElement instanceof WorkspaceNode) { - // WorkspaceNode wn = (WorkspaceNode) parentElement; - // Object[] children = wn.getChildren(); - // int i = children.length - 1; - // while (!found && i >= 0) { - // found = isElementInCurrentTreePart(ncp, children[i], - // searchedElement); - // } - // return found; - // } else if (parentElement instanceof RepositoryNode) { - // RepositoryNode rn = (RepositoryNode) parentElement; - // Object[] children = rn.getChildren(); - // int i = children.length - 1; - // while (!found && i >= 0) { - // found = isElementInCurrentTreePart(ncp, children[i], - // searchedElement); - // } - // return found; - // } else { - // Node node = (Node) parentElement; - // if (node.equals(searchedElement)) - // return true; - // NodeIterator ni; - // try { - // ni = node.getNodes(); - // while (!found && ni.hasNext()) { - // found = isElementInCurrentTreePart(ncp, ni.nextNode(), - // searchedElement); - // } - // } catch (RepositoryException e) { - // throw new ArgeoException("unexpected erreur while recursively" - // + " recovering RepositoryNode for selected object", e); - // } - // - // return found; - // } - // } -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/utils/TreeObjectsComparator.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/utils/TreeObjectsComparator.java deleted file mode 100644 index 02450d6ed..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/utils/TreeObjectsComparator.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.utils; - -import java.util.Comparator; - -import org.argeo.eclipse.ui.TreeParent; - -public class TreeObjectsComparator implements Comparator { - public int compare(TreeParent o1, TreeParent o2) { - return o1.getName().compareTo(o2.getName()); - } -} \ No newline at end of file diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/views/GenericJcrBrowser.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/views/GenericJcrBrowser.java deleted file mode 100644 index f401ae8fe..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/views/GenericJcrBrowser.java +++ /dev/null @@ -1,357 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.views; - -import java.util.List; - -import javax.jcr.Property; -import javax.jcr.PropertyType; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.RepositoryFactory; -import javax.jcr.Session; -import javax.jcr.Value; -import javax.jcr.observation.Event; -import javax.jcr.observation.EventListener; -import javax.jcr.observation.ObservationManager; - -import org.argeo.ArgeoException; -import org.argeo.eclipse.ui.TreeParent; -import org.argeo.eclipse.ui.jcr.AsyncUiEventListener; -import org.argeo.eclipse.ui.jcr.utils.NodeViewerComparer; -import org.argeo.eclipse.ui.jcr.views.AbstractJcrBrowser; -import org.argeo.jcr.RepositoryRegister; -import org.argeo.jcr.ui.explorer.JcrExplorerPlugin; -import org.argeo.jcr.ui.explorer.browser.NodeContentProvider; -import org.argeo.jcr.ui.explorer.browser.NodeLabelProvider; -import org.argeo.jcr.ui.explorer.browser.PropertiesContentProvider; -import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem; -import org.argeo.jcr.ui.explorer.utils.GenericNodeDoubleClickListener; -import org.argeo.jcr.ui.explorer.utils.JcrUiUtils; -import org.argeo.util.security.Keyring; -import org.eclipse.jface.action.MenuManager; -import org.eclipse.jface.viewers.ColumnLabelProvider; -import org.eclipse.jface.viewers.ISelectionChangedListener; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.viewers.ITreeContentProvider; -import org.eclipse.jface.viewers.SelectionChangedEvent; -import org.eclipse.jface.viewers.StructuredSelection; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.jface.viewers.TableViewerColumn; -import org.eclipse.jface.viewers.TreeViewer; -import org.eclipse.swt.SWT; -import org.eclipse.swt.custom.SashForm; -import org.eclipse.swt.layout.FillLayout; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Menu; - -/** - * Basic View to display a sash form to browse a JCR compliant multirepository - * environment - */ -public class GenericJcrBrowser extends AbstractJcrBrowser { - public final static String ID = JcrExplorerPlugin.ID + ".browserView"; - private boolean sortChildNodes = true; - - /* DEPENDENCY INJECTION */ - private Keyring keyring; - private RepositoryRegister repositoryRegister; - private RepositoryFactory repositoryFactory; - private Repository nodeRepository; - /** - * A session of the logged in user on the default workspace of the node - * repository. - */ - private Session userSession; - - // This page widgets - private TreeViewer nodesViewer; - private NodeContentProvider nodeContentProvider; - private TableViewer propertiesViewer; - private EventListener resultsObserver; - - @Override - public void createPartControl(Composite parent) { - parent.setLayout(new FillLayout()); - SashForm sashForm = new SashForm(parent, SWT.VERTICAL); - sashForm.setSashWidth(4); - sashForm.setLayout(new FillLayout()); - - // Create the tree on top of the view - Composite top = new Composite(sashForm, SWT.NONE); - GridLayout gl = new GridLayout(1, false); - top.setLayout(gl); - - try { - this.userSession = this.nodeRepository.login(); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot open user session", e); - } - - nodeContentProvider = new NodeContentProvider(userSession, keyring, - repositoryRegister, repositoryFactory, sortChildNodes); - - // nodes viewer - nodesViewer = createNodeViewer(top, nodeContentProvider); - - // context menu : it is completely defined in the plugin.xml file. - MenuManager menuManager = new MenuManager(); - Menu menu = menuManager.createContextMenu(nodesViewer.getTree()); - - nodesViewer.getTree().setMenu(menu); - getSite().registerContextMenu(menuManager, nodesViewer); - getSite().setSelectionProvider(nodesViewer); - - nodesViewer.setInput(getViewSite()); - - // Create the property viewer on the bottom - Composite bottom = new Composite(sashForm, SWT.NONE); - bottom.setLayout(new GridLayout(1, false)); - propertiesViewer = createPropertiesViewer(bottom); - - sashForm.setWeights(getWeights()); - nodesViewer.setComparer(new NodeViewerComparer()); - } - - @Override - public void refresh(Object obj) { - // Enable full refresh from a command when no element of the tree is - // selected - if (obj == null) { - Object[] elements = nodeContentProvider.getElements(null); - for (Object el : elements) { - if (el instanceof TreeParent) - JcrUiUtils.forceRefreshIfNeeded((TreeParent) el); - getNodeViewer().refresh(el); - } - } - super.refresh(obj); - } - - /** - * To be overridden to adapt size of form and result frames. - */ - protected int[] getWeights() { - return new int[] { 70, 30 }; - } - - protected TreeViewer createNodeViewer(Composite parent, - final ITreeContentProvider nodeContentProvider) { - - final TreeViewer tmpNodeViewer = new TreeViewer(parent, SWT.MULTI); - - tmpNodeViewer.getTree().setLayoutData( - new GridData(SWT.FILL, SWT.FILL, true, true)); - - tmpNodeViewer.setContentProvider(nodeContentProvider); - tmpNodeViewer.setLabelProvider(new NodeLabelProvider()); - tmpNodeViewer - .addSelectionChangedListener(new ISelectionChangedListener() { - public void selectionChanged(SelectionChangedEvent event) { - if (!event.getSelection().isEmpty()) { - IStructuredSelection sel = (IStructuredSelection) event - .getSelection(); - Object firstItem = sel.getFirstElement(); - if (firstItem instanceof SingleJcrNodeElem) - propertiesViewer - .setInput(((SingleJcrNodeElem) firstItem) - .getNode()); - } else { - propertiesViewer.setInput(getViewSite()); - } - } - }); - - resultsObserver = new TreeObserver(tmpNodeViewer.getTree().getDisplay()); - if (keyring != null) - try { - ObservationManager observationManager = userSession - .getWorkspace().getObservationManager(); - observationManager.addEventListener(resultsObserver, - Event.PROPERTY_ADDED | Event.PROPERTY_CHANGED, "/", - true, null, null, false); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot register listeners", e); - } - - tmpNodeViewer - .addDoubleClickListener(new GenericNodeDoubleClickListener( - tmpNodeViewer)); - return tmpNodeViewer; - } - - protected TableViewer createPropertiesViewer(Composite parent) { - propertiesViewer = new TableViewer(parent); - propertiesViewer.getTable().setLayoutData( - new GridData(SWT.FILL, SWT.FILL, true, true)); - propertiesViewer.getTable().setHeaderVisible(true); - propertiesViewer.setContentProvider(new PropertiesContentProvider()); - TableViewerColumn col = new TableViewerColumn(propertiesViewer, - SWT.NONE); - col.getColumn().setText("Name"); - col.getColumn().setWidth(200); - col.setLabelProvider(new ColumnLabelProvider() { - public String getText(Object element) { - try { - return ((Property) element).getName(); - } catch (RepositoryException e) { - throw new ArgeoException( - "Unexpected exception in label provider", e); - } - } - }); - col = new TableViewerColumn(propertiesViewer, SWT.NONE); - col.getColumn().setText("Value"); - col.getColumn().setWidth(400); - col.setLabelProvider(new ColumnLabelProvider() { - public String getText(Object element) { - try { - Property property = (Property) element; - if (property.getType() == PropertyType.BINARY) - return ""; - else if (property.isMultiple()) { - StringBuffer buf = new StringBuffer("["); - Value[] values = property.getValues(); - for (int i = 0; i < values.length; i++) { - if (i != 0) - buf.append(", "); - buf.append(values[i].getString()); - } - buf.append(']'); - return buf.toString(); - } else - return property.getValue().getString(); - } catch (RepositoryException e) { - throw new ArgeoException( - "Unexpected exception in label provider", e); - } - } - }); - col = new TableViewerColumn(propertiesViewer, SWT.NONE); - col.getColumn().setText("Type"); - col.getColumn().setWidth(200); - col.setLabelProvider(new ColumnLabelProvider() { - public String getText(Object element) { - try { - return PropertyType.nameFromValue(((Property) element) - .getType()); - } catch (RepositoryException e) { - throw new ArgeoException( - "Unexpected exception in label provider", e); - } - } - }); - propertiesViewer.setInput(getViewSite()); - return propertiesViewer; - } - - @Override - public void dispose() { - super.dispose(); - } - - @Override - protected TreeViewer getNodeViewer() { - return nodesViewer; - } - - /** - * Resets the tree content provider - * - * @param sortChildNodes - * if true the content provider will use a comparer to sort nodes - * that might slow down the display - * */ - public void setSortChildNodes(boolean sortChildNodes) { - this.sortChildNodes = sortChildNodes; - ((NodeContentProvider) nodesViewer.getContentProvider()) - .setSortChildren(sortChildNodes); - nodesViewer.setInput(getViewSite()); - } - - /** Notifies the current view that a node has been added */ - public void nodeAdded(TreeParent parentNode) { - // insure that Ui objects have been correctly created: - JcrUiUtils.forceRefreshIfNeeded(parentNode); - getNodeViewer().refresh(parentNode); - getNodeViewer().expandToLevel(parentNode, 1); - } - - /** Notifies the current view that a node has been removed */ - public void nodeRemoved(TreeParent parentNode) { - IStructuredSelection newSel = new StructuredSelection(parentNode); - getNodeViewer().setSelection(newSel, true); - // Force refresh - IStructuredSelection tmpSel = (IStructuredSelection) getNodeViewer() - .getSelection(); - getNodeViewer().refresh(tmpSel.getFirstElement()); - } - - class TreeObserver extends AsyncUiEventListener { - - public TreeObserver(Display display) { - super(display); - } - - @Override - protected Boolean willProcessInUiThread(List events) - throws RepositoryException { - for (Event event : events) { - if (getLog().isTraceEnabled()) - getLog().debug("Received event " + event); - String path = event.getPath(); - int index = path.lastIndexOf('/'); - String propertyName = path.substring(index + 1); - if (getLog().isTraceEnabled()) - getLog().debug("Concerned property " + propertyName); - } - return false; - } - - protected void onEventInUiThread(List events) - throws RepositoryException { - if (getLog().isTraceEnabled()) - getLog().trace("Refresh result list"); - nodesViewer.refresh(); - } - - } - - public boolean getSortChildNodes() { - return sortChildNodes; - } - - /* DEPENDENCY INJECTION */ - public void setRepositoryRegister(RepositoryRegister repositoryRegister) { - this.repositoryRegister = repositoryRegister; - } - - public void setKeyring(Keyring keyring) { - this.keyring = keyring; - } - - public void setRepositoryFactory(RepositoryFactory repositoryFactory) { - this.repositoryFactory = repositoryFactory; - } - - public void setNodeRepository(Repository nodeRepository) { - this.nodeRepository = nodeRepository; - } - -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/wizards/ChangeRightsWizard.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/wizards/ChangeRightsWizard.java deleted file mode 100644 index 4381837e4..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/wizards/ChangeRightsWizard.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.wizards; - -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.argeo.ArgeoException; -import org.argeo.jcr.JcrUtils; -import org.eclipse.jface.wizard.Wizard; - -/** - * Small wizard to manage authorizations on the root node of the current - * workspace - */ -public class ChangeRightsWizard extends Wizard { - - private Session currentSession; - private String path; - - // This page widget - private ChooseRightsPage page; - - public ChangeRightsWizard(Session currentSession, String path) { - super(); - this.currentSession = currentSession; - this.path = path; - } - - @Override - public void addPages() { - try { - page = new ChooseRightsPage(path); - addPage(page); - } catch (Exception e) { - throw new ArgeoException("Cannot add page to wizard ", e); - } - } - - @Override - public boolean performFinish() { - if (!canFinish()) - return false; - try { - JcrUtils.addPrivilege(currentSession, path, page.getGroupName(), - page.getAuthTypeStr()); - } catch (RepositoryException re) { - throw new ArgeoException( - "Unexpected error while setting privileges", re); - } - return true; - } -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/wizards/ChooseRightsPage.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/wizards/ChooseRightsPage.java deleted file mode 100644 index 69948ce83..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/wizards/ChooseRightsPage.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.wizards; - -import javax.jcr.security.Privilege; - -import org.eclipse.jface.wizard.WizardPage; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Combo; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Text; - -public class ChooseRightsPage extends WizardPage implements ModifyListener { - - // This page widget - private Text groupNameTxt; - private Combo authorizationCmb; - - // USABLE SHORTCUTS - protected final static String[] validAuthType = { Privilege.JCR_READ, - Privilege.JCR_WRITE, Privilege.JCR_ALL }; - - public ChooseRightsPage(String path) { - super("Main"); - setTitle("Add privilege to " + path); - } - - public void createControl(Composite parent) { - // specify subject - Composite composite = new Composite(parent, SWT.NONE); - composite.setLayout(new GridLayout(2, false)); - Label lbl = new Label(composite, SWT.LEAD); - lbl.setText("Group or user name (no blank, no special chars)"); - lbl.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false)); - groupNameTxt = new Text(composite, SWT.LEAD | SWT.BORDER); - groupNameTxt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, - false)); - if (groupNameTxt != null) - groupNameTxt.addModifyListener(this); - - // Choose rigths - new Label(composite, SWT.NONE).setText("Choose corresponding rights"); - authorizationCmb = new Combo(composite, SWT.BORDER | SWT.V_SCROLL); - authorizationCmb.setItems(validAuthType); - GridData gd = new GridData(GridData.FILL_HORIZONTAL); - authorizationCmb.setLayoutData(gd); - - authorizationCmb.select(0); - - // Compulsory - setControl(composite); - } - - protected String getGroupName() { - return groupNameTxt.getText(); - } - - protected String getAuthTypeStr() { - return authorizationCmb.getItem(authorizationCmb.getSelectionIndex()); - } - - public void modifyText(ModifyEvent event) { - String message = checkComplete(); - if (message != null) - setMessage(message, WizardPage.ERROR); - else { - setMessage("Complete", WizardPage.INFORMATION); - setPageComplete(true); - } - } - - /** @return error message or null if complete */ - protected String checkComplete() { - String groupStr = groupNameTxt.getText(); - if (groupStr == null || "".equals(groupStr)) - return "Please enter the name of the corresponding group."; - // Remove regexp check for the time being. - // else if (!match(groupStr)) - // return - // "Please use only alphanumerical chars for the short technical name."; - return null; - } -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/wizards/ImportFileSystemWizard.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/wizards/ImportFileSystemWizard.java deleted file mode 100644 index 127c2cd54..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/wizards/ImportFileSystemWizard.java +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.ui.explorer.wizards; - -import java.io.File; -import java.io.FileInputStream; - -import javax.jcr.Binary; -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.nodetype.NodeType; - -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.ArgeoException; -import org.argeo.eclipse.ui.ErrorFeedback; -import org.argeo.eclipse.ui.specific.ImportToServerWizardPage; -import org.argeo.eclipse.ui.specific.UploadFileWizardPage; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.operation.IRunnableWithProgress; -import org.eclipse.jface.wizard.Wizard; - -public class ImportFileSystemWizard extends Wizard { - private final static Log log = LogFactory - .getLog(ImportFileSystemWizard.class); - - private UploadFileWizardPage importPage; - private final Node folder; - - public ImportFileSystemWizard(Node folder) { - this.folder = folder; - setWindowTitle("Import from file system"); - } - - @Override - public void addPages() { - importPage = new UploadFileWizardPage(); - addPage(importPage); - setNeedsProgressMonitor(importPage.getNeedsProgressMonitor()); - } - - /** - * Called when the user click on 'Finish' in the wizard. The real upload to - * the JCR repository is done here. - */ - @Override - public boolean performFinish() { - - // Initialization - final String objectType = importPage.getObjectType(); - final String objectPath = importPage.getObjectPath(); - - // We do not display a progress bar for one file only - if (ImportToServerWizardPage.FILE_ITEM_TYPE.equals(objectType)) { - // In Rap we must force the "real" upload of the file - importPage.performFinish(); - try { - Node fileNode = folder.addNode(importPage.getObjectName(), - NodeType.NT_FILE); - Node resNode = fileNode.addNode(Property.JCR_CONTENT, - NodeType.NT_RESOURCE); - Binary binary = null; - try { - binary = folder.getSession().getValueFactory() - .createBinary(importPage.getFileInputStream()); - resNode.setProperty(Property.JCR_DATA, binary); - } finally { - if (binary != null) - binary.dispose(); - IOUtils.closeQuietly(importPage.getFileInputStream()); - } - folder.getSession().save(); - } catch (Exception e) { - e.printStackTrace(); - return false; - } - return true; - } else if (ImportToServerWizardPage.FOLDER_ITEM_TYPE.equals(objectType)) { - if (objectPath == null || !new File(objectPath).exists()) { - ErrorFeedback.show("Directory " + objectPath - + " does not exist"); - return false; - } - - Boolean failed = false; - final File dir = new File(objectPath).getAbsoluteFile(); - final Long sizeB = directorySize(dir, 0l); - final Stats stats = new Stats(); - Long begin = System.currentTimeMillis(); - try { - getContainer().run(true, true, new IRunnableWithProgress() { - public void run(IProgressMonitor monitor) { - try { - Integer sizeKB = (int) (sizeB / FileUtils.ONE_KB); - monitor.beginTask("", sizeKB); - importDirectory(folder, dir, monitor, stats); - monitor.done(); - } catch (Exception e) { - if (e instanceof RuntimeException) - throw (RuntimeException) e; - else - throw new ArgeoException("Cannot import " - + objectPath, e); - } - } - }); - } catch (Exception e) { - ErrorFeedback.show("Cannot import " + objectPath, e); - failed = true; - } - - Long duration = System.currentTimeMillis() - begin; - Long durationS = duration / 1000l; - String durationStr = (durationS / 60) + " min " + (durationS % 60) - + " s"; - StringBuffer message = new StringBuffer("Imported\n"); - message.append(stats.fileCount).append(" files\n"); - message.append(stats.dirCount).append(" directories\n"); - message.append(FileUtils.byteCountToDisplaySize(stats.sizeB)); - if (failed) - message.append(" of planned ").append( - FileUtils.byteCountToDisplaySize(sizeB)); - message.append("\n"); - message.append("in ").append(durationStr).append("\n"); - if (failed) - MessageDialog.openError(getShell(), "Import failed", - message.toString()); - else - MessageDialog.openInformation(getShell(), "Import successful", - message.toString()); - - return true; - } - return false; - - } - - /** Recursively computes the size of the directory in bytes. */ - protected Long directorySize(File dir, Long currentSize) { - Long size = currentSize; - File[] files = dir.listFiles(); - for (File file : files) { - if (file.isDirectory()) { - size = directorySize(file, size); - } else { - size = size + file.length(); - } - } - return size; - } - - /** - * Import recursively a directory and its content to the repository. - */ - protected void importDirectory(Node folder, File dir, - IProgressMonitor monitor, Stats stats) { - try { - File[] files = dir.listFiles(); - for (File file : files) { - if (file.isDirectory()) { - Node childFolder = folder.addNode(file.getName(), - NodeType.NT_FOLDER); - importDirectory(childFolder, file, monitor, stats); - folder.getSession().save(); - stats.dirCount++; - } else { - Long fileSize = file.length(); - - // we skip tempory files that are created by apps when a - // file is being edited. - // TODO : make this configurable. - if (file.getName().lastIndexOf('~') != file.getName() - .length() - 1) { - - monitor.subTask(file.getName() + " (" - + FileUtils.byteCountToDisplaySize(fileSize) - + ") " + file.getCanonicalPath()); - try { - Node fileNode = folder.addNode(file.getName(), - NodeType.NT_FILE); - Node resNode = fileNode.addNode( - Property.JCR_CONTENT, NodeType.NT_RESOURCE); - Binary binary = null; - try { - binary = folder - .getSession() - .getValueFactory() - .createBinary(new FileInputStream(file)); - resNode.setProperty(Property.JCR_DATA, binary); - } finally { - if (binary != null) - binary.dispose(); - } - folder.getSession().save(); - stats.fileCount++; - stats.sizeB = stats.sizeB + fileSize; - } catch (Exception e) { - log.warn("Import of " - + file - + " (" - + FileUtils - .byteCountToDisplaySize(fileSize) - + ") failed: " + e); - folder.getSession().refresh(false); - } - monitor.worked((int) (fileSize / FileUtils.ONE_KB)); - } - } - } - } catch (Exception e) { - throw new ArgeoException("Cannot import " + dir + " to " + folder, - e); - } - } - - static class Stats { - public Long fileCount = 0l; - public Long dirCount = 0l; - public Long sizeB = 0l; - } -} diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/resources/org/argeo/jcr/ui/explorer/messages.properties b/server/plugins/org.argeo.jcr.ui.explorer/src/main/resources/org/argeo/jcr/ui/explorer/messages.properties deleted file mode 100644 index 3023c523f..000000000 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/resources/org/argeo/jcr/ui/explorer/messages.properties +++ /dev/null @@ -1,28 +0,0 @@ -## English labels for Agreo JCR UI application - -## Generic labels - -## Errors & warnings -errorUnvalidNtFolderNodeType= Error: folder can only be created on a Jcr Node -warningInvalidNodeToImport=Can only import to a node -warningInvalidMultipleSelection=This functionality is implemented only on a single node for the time being. -warningUnversionableNode= Current node is not versionable. -warningNoChildNode= Current node has no child. - -## Commands -getNodeSizeCmdLbl= Get approx. size -addFolderNodeCmdLbl= Add Folder - -## GenericNodeEditor -nodeEditorLbl=Generic node editor -genericNodePageTitle=Properties -childNodesPageTitle=Children -nodeRightsManagementPageTitle=Rights -nodeVersionHistoryPageTitle=History - -# History -versionTreeSectionTitle=Version list -versionHistorySectionTitle=History - -## Dummy ones -testLbl=Internationalizations of messages seems to work properly. diff --git a/server/plugins/pom.xml b/server/plugins/pom.xml index fc08789c7..bc96b87e7 100644 --- a/server/plugins/pom.xml +++ b/server/plugins/pom.xml @@ -6,8 +6,8 @@ server .. - org.argeo.commons.server - plugins + org.argeo.commons + argeo-commons Commons Server Eclipse Plugins pom diff --git a/server/runtime/org.argeo.server.ads/.classpath b/server/runtime/org.argeo.server.ads/.classpath deleted file mode 100644 index ff41fbb4d..000000000 --- a/server/runtime/org.argeo.server.ads/.classpath +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/server/runtime/org.argeo.server.ads/.project b/server/runtime/org.argeo.server.ads/.project deleted file mode 100644 index 448ef0483..000000000 --- a/server/runtime/org.argeo.server.ads/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - org.argeo.server.ads - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.jdt.core.javanature - org.eclipse.pde.PluginNature - - diff --git a/server/runtime/org.argeo.server.ads/.settings/org.eclipse.jdt.core.prefs b/server/runtime/org.argeo.server.ads/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 34d3d6088..000000000 --- a/server/runtime/org.argeo.server.ads/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,67 +0,0 @@ -#Sun Feb 21 11:17:20 CET 2010 -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 -org.eclipse.jdt.core.compiler.compliance=1.5 -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.5 diff --git a/server/runtime/org.argeo.server.ads/.settings/org.maven.ide.eclipse.prefs b/server/runtime/org.argeo.server.ads/.settings/org.maven.ide.eclipse.prefs deleted file mode 100644 index 8a80a771a..000000000 --- a/server/runtime/org.argeo.server.ads/.settings/org.maven.ide.eclipse.prefs +++ /dev/null @@ -1,9 +0,0 @@ -#Mon Nov 23 13:34:22 CET 2009 -activeProfiles= -eclipse.preferences.version=1 -fullBuildGoals=process-test-resources -includeModules=false -resolveWorkspaceProjects=true -resourceFilterGoals=process-resources resources\:testResources -skipCompilerPlugin=true -version=1 diff --git a/server/runtime/org.argeo.server.ads/build.properties b/server/runtime/org.argeo.server.ads/build.properties deleted file mode 100644 index f883dc49f..000000000 --- a/server/runtime/org.argeo.server.ads/build.properties +++ /dev/null @@ -1,2 +0,0 @@ -additional.bundles = org.apache.directory.server.core -source.. = src/main/java/ diff --git a/server/runtime/org.argeo.server.ads/pom.xml b/server/runtime/org.argeo.server.ads/pom.xml deleted file mode 100644 index 76a4a1319..000000000 --- a/server/runtime/org.argeo.server.ads/pom.xml +++ /dev/null @@ -1,88 +0,0 @@ - - 4.0.0 - - org.argeo.commons.server - runtime - 2.1.12-SNAPSHOT - .. - - org.argeo.server.ads - Commons Server Apache Directory Server - - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-source-plugin - - - org.apache.maven.plugins - maven-jar-plugin - - - org.apache.felix - maven-bundle-plugin - - - - - org.argeo.server.ads.* - - - - - - - - - org.argeo.commons.base - org.argeo.util - 2.1.12-SNAPSHOT - - - - - org.argeo.tp - org.apache.directory.server.jndi - - - - org.slf4j - com.springsource.slf4j.api - - - - - - - org.argeo.tp - org.apache.commons.io - - - - - org.argeo.tp - org.springframework.core - - - org.argeo.tp - org.springframework.beans - - - - - org.argeo.tp - slf4j.org.apache.commons.logging - - - org.argeo.tp - slf4j.api - - - \ No newline at end of file diff --git a/server/runtime/org.argeo.server.ads/src/main/java/org/argeo/server/ads/AdsContainer.java b/server/runtime/org.argeo.server.ads/src/main/java/org/argeo/server/ads/AdsContainer.java deleted file mode 100644 index e95cd8f5a..000000000 --- a/server/runtime/org.argeo.server.ads/src/main/java/org/argeo/server/ads/AdsContainer.java +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.server.ads; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.Writer; -import java.util.ArrayList; -import java.util.List; -import java.util.Properties; - -import javax.naming.Context; -import javax.naming.InitialContext; -import javax.naming.NamingException; -import javax.naming.directory.InitialDirContext; - -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.directory.server.configuration.MutableServerStartupConfiguration; -import org.apache.directory.server.core.configuration.ShutdownConfiguration; -import org.apache.directory.server.jndi.ServerContextFactory; -import org.argeo.ArgeoException; -import org.springframework.beans.factory.DisposableBean; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.core.io.Resource; -import org.springframework.util.Assert; - -/** Wraps an Apache Directory Server instance. */ -@SuppressWarnings("restriction") -public class AdsContainer implements InitializingBean, DisposableBean { - private final static Log log = LogFactory.getLog(AdsContainer.class); - - private MutableServerStartupConfiguration configuration; - private Properties environment = null; - private File workingDirectory = new File( - System.getProperty("java.io.tmpdir") + File.separator - + "argeo-apacheDirectoryServer"); - private Boolean deleteWorkingDirOnExit = false; - - // LDIF - private List ldifs = new ArrayList(); - private List ignoredLdifAttributes = new ArrayList(); - /** default is 'demo' */ - private String ldifPassword = "e1NIQX1pZVNWNTVRYytlUU9hWURSU2hhL0Fqek5USkU9"; - private String ldifPasswordAttribute = "userPassword"; - private File ldifDirectory; - - @SuppressWarnings("unchecked") - public void afterPropertiesSet() throws Exception { - - log.info("Starting directory server with id '" - + configuration.getInstanceId() + "' in directory " - + workingDirectory.getAbsolutePath()); - - if (deleteWorkingDirOnExit && workingDirectory.exists()) { - log.warn("Found existing directory " + workingDirectory - + " deleting it..."); - FileUtils.deleteDirectory(workingDirectory); - } - configuration.setWorkingDirectory(workingDirectory); - workingDirectory.mkdirs(); - - if (ldifDirectory != null) - configuration.setLdifDirectory(ldifDirectory); - else - configuration.setLdifDirectory(new File(workingDirectory - .getAbsolutePath() + File.separator + "ldif")); - - if (ignoredLdifAttributes.size() == 0) { - ignoredLdifAttributes.add("entryUUID"); - ignoredLdifAttributes.add("structuralObjectClass"); - ignoredLdifAttributes.add("creatorsName"); - ignoredLdifAttributes.add("createTimestamp"); - ignoredLdifAttributes.add("entryCSN"); - ignoredLdifAttributes.add("modifiersName"); - ignoredLdifAttributes.add("modifyTimestamp"); - } - - // Process provided LDIF files - if (ldifs.size() > 0) - configuration.getLdifDirectory().mkdirs(); - for (Resource ldif : ldifs) { - File targetFile = new File(configuration.getLdifDirectory() - .getAbsolutePath() - + File.separator - + ldif.getFilename().replace(':', '_')); - processLdif(ldif, targetFile); - } - - Properties env = new Properties(); - env.setProperty(Context.INITIAL_CONTEXT_FACTORY, - ServerContextFactory.class.getName()); - Assert.notNull(environment); - env.putAll(environment); - env.putAll(configuration.toJndiEnvironment()); - - try { - new InitialDirContext(env); - } catch (NamingException e) { - throw new ArgeoException("Failed to start Apache Directory server", - e); - } - } - - /** - * Processes an LDIF resource, filtering out attributes that cannot be - * imported in ADS and forcing a password. - */ - protected void processLdif(Resource ldif, File targetFile) { - BufferedReader reader = null; - Writer writer = null; - try { - reader = new BufferedReader(new InputStreamReader( - ldif.getInputStream())); - writer = new FileWriter(targetFile); - String line = null; - lines: while ((line = reader.readLine()) != null) { - // comment and empty lines - if (line.trim().equals("") || line.startsWith("#")) { - writer.write(line); - writer.write('\n'); - continue lines; - } - - String[] tokens = line.split(":"); - String attribute = null; - if (tokens != null && tokens.length > 1) { - attribute = tokens[0].trim(); - if (ignoredLdifAttributes.contains(attribute)) - continue lines;// ignore - - if (attribute.equals("bdb_db_open")) { - log.warn("Ignored OpenLDAP output\n" + line); - continue lines; - } - - if (ldifPassword != null - && attribute.equals(ldifPasswordAttribute)) { - line = ldifPasswordAttribute + ":: " + ldifPassword; - } - - writer.write(line); - writer.write('\n'); - } else { - log.warn("Ignored LDIF line\n" + line); - } - } - if (log.isDebugEnabled()) - log.debug("Processed " + ldif + " to LDIF directory " - + configuration.getLdifDirectory()); - } catch (IOException e) { - throw new ArgeoException("Cannot process LDIF " + ldif, e); - } finally { - IOUtils.closeQuietly(reader); - IOUtils.closeQuietly(writer); - } - } - - @SuppressWarnings("unchecked") - public void destroy() throws Exception { - ShutdownConfiguration shutdown = new ShutdownConfiguration( - configuration.getInstanceId()); - - Properties env = new Properties(); - env.setProperty(Context.INITIAL_CONTEXT_FACTORY, - ServerContextFactory.class.getName()); - Assert.notNull(environment); - env.putAll(environment); - env.putAll(shutdown.toJndiEnvironment()); - - log.info("Shutting down directory server with id '" - + configuration.getInstanceId() + "'"); - - try { - new InitialContext(env); - } catch (NamingException e) { - throw new ArgeoException("Failed to stop Apache Directory server", - e); - } - - if (workingDirectory.exists() && deleteWorkingDirOnExit) { - if (log.isDebugEnabled()) - log.debug("Delete Apache DS working dir " + workingDirectory); - FileUtils.deleteDirectory(workingDirectory); - } - - } - - public void setConfiguration(MutableServerStartupConfiguration configuration) { - this.configuration = configuration; - } - - public void setWorkingDirectory(File workingDirectory) { - this.workingDirectory = workingDirectory; - } - - public void setEnvironment(Properties environment) { - this.environment = environment; - } - - public void setLdifs(List ldifs) { - this.ldifs = ldifs; - } - - public void setLdifDirectory(File ldifDirectory) { - this.ldifDirectory = ldifDirectory; - } - - public void setDeleteWorkingDirOnExit(Boolean deleteWorkingDirOnExit) { - this.deleteWorkingDirOnExit = deleteWorkingDirOnExit; - } - - public void setIgnoredLdifAttributes(List ignoredLdifAttributes) { - this.ignoredLdifAttributes = ignoredLdifAttributes; - } - - public void setLdifPassword(String ldifPassword) { - this.ldifPassword = ldifPassword; - } - - public void setLdifPasswordAttribute(String ldifPasswordAttribute) { - this.ldifPasswordAttribute = ldifPasswordAttribute; - } - -} diff --git a/server/runtime/org.argeo.server.catalina.start/pom.xml b/server/runtime/org.argeo.server.catalina.start/pom.xml index 85e9fe145..ce9d40597 100644 --- a/server/runtime/org.argeo.server.catalina.start/pom.xml +++ b/server/runtime/org.argeo.server.catalina.start/pom.xml @@ -1,9 +1,9 @@ 4.0.0 - org.argeo.commons.server + org.argeo.commons 2.1.12-SNAPSHOT - runtime + argeo-commons .. org.argeo.server.catalina.start diff --git a/server/runtime/org.argeo.server.core/.classpath b/server/runtime/org.argeo.server.core/.classpath deleted file mode 100644 index 3bf3adef5..000000000 --- a/server/runtime/org.argeo.server.core/.classpath +++ /dev/null @@ -1,7 +0,0 @@ - - - - >> - - - diff --git a/server/runtime/org.argeo.server.core/.project b/server/runtime/org.argeo.server.core/.project deleted file mode 100644 index b28214ba7..000000000 --- a/server/runtime/org.argeo.server.core/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - org.argeo.server.core - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.jdt.core.javanature - org.eclipse.pde.PluginNature - - diff --git a/server/runtime/org.argeo.server.core/build.properties b/server/runtime/org.argeo.server.core/build.properties deleted file mode 100644 index 92847ec08..000000000 --- a/server/runtime/org.argeo.server.core/build.properties +++ /dev/null @@ -1,7 +0,0 @@ -source.. = src/main/java/ -additional.bundles = slf4j.api,\ - slf4j.org.apache.commons.logging,\ - slf4j.log4j,\ - org.apache.log4j,\ - com.jcraft.jsch - \ No newline at end of file diff --git a/server/runtime/org.argeo.server.core/pom.xml b/server/runtime/org.argeo.server.core/pom.xml deleted file mode 100644 index 0a5634eb0..000000000 --- a/server/runtime/org.argeo.server.core/pom.xml +++ /dev/null @@ -1,114 +0,0 @@ - - - 4.0.0 - - org.argeo.commons.server - runtime - 2.1.12-SNAPSHOT - .. - - org.argeo.server.core - Commons Server Core - - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-source-plugin - - - org.apache.maven.plugins - maven-jar-plugin - - - org.apache.felix - maven-bundle-plugin - - - - - org.argeo.server.* - - - javax.servlet, - org.springframework.web.context, - * - - - - - - - - - org.argeo.commons.base - org.argeo.util - 2.1.12-SNAPSHOT - - - - - org.argeo.tp - org.apache.commons.io - - - org.argeo.tp - org.apache.commons.vfs - - - org.argeo.tp - org.apache.commons.exec - - - org.argeo.tp - com.jcraft.jsch - - - - org.argeo.tp - org.joda.time - - - - - org.argeo.tp - org.springframework.web - - - org.argeo.tp - org.springframework.beans - - - org.argeo.tp - org.springframework.context - - - org.argeo.tp - org.springframework.core - - - org.argeo.tp - org.springframework.web.servlet - - - - - org.argeo.tp - javax.servlet - - - - - org.argeo.tp - slf4j.org.apache.commons.logging - - - - org.argeo.tp - org.apache.commons.fileupload - - - \ No newline at end of file diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/BooleanAnswer.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/BooleanAnswer.java deleted file mode 100644 index 2b7ffb2fc..000000000 --- a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/BooleanAnswer.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.server; - - -/** Answer to an execution of a remote service which performed changes. */ -public class BooleanAnswer { - private Boolean value = Boolean.TRUE; - - /** Canonical constructor */ - public BooleanAnswer(Boolean status) { - this.value = status; - } - - /** Empty constructor */ - public BooleanAnswer() { - } - - public Boolean getValue() { - return value; - } - -} diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/Deserializer.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/Deserializer.java deleted file mode 100644 index 4d7faf966..000000000 --- a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/Deserializer.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.server; - -import java.io.Reader; - -public interface Deserializer { - public T deserialize(Reader reader, Class clss); -} diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/DeserializingEditor.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/DeserializingEditor.java deleted file mode 100644 index 915b71cfe..000000000 --- a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/DeserializingEditor.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.server; - -import java.beans.PropertyEditorSupport; -import java.io.StringReader; - -import org.apache.commons.io.IOUtils; - -public class DeserializingEditor extends PropertyEditorSupport { - private final Deserializer deserializer; - private final Class targetClass; - - public DeserializingEditor(Deserializer deserializer, Class targetClass) { - super(); - this.deserializer = deserializer; - this.targetClass = targetClass; - } - - @Override - public void setAsText(String text) throws IllegalArgumentException { - StringReader reader = new StringReader(text); - try { - setValue(deserializer.deserialize(reader, targetClass)); - } finally { - IOUtils.closeQuietly(reader); - } - } - -} diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/PrimitiveAnswer.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/PrimitiveAnswer.java deleted file mode 100644 index c69ffedb8..000000000 --- a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/PrimitiveAnswer.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.server; - -/** - * Answer to a request to a remote service that sends back only one primitive - */ -public class PrimitiveAnswer { - - private Object primitive; - - /** Canonical constructor */ - public PrimitiveAnswer(Object primitive) { - this.primitive = primitive; - } - - public Object getValue() { - return primitive; - } - -} diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/Serializer.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/Serializer.java deleted file mode 100644 index 890b17cd4..000000000 --- a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/Serializer.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.server; - -import java.io.Writer; - -public interface Serializer { - /** Will be removed soon. Use {@link #serialize(Object, Writer)} instead. */ - @Deprecated - public void serialize(Writer writer, Object obj); - - public void serialize(Object obj, Writer writer); -} diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/ServerAnswer.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/ServerAnswer.java deleted file mode 100644 index 2f9cbee1d..000000000 --- a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/ServerAnswer.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.server; - -import java.io.PrintWriter; -import java.io.StringWriter; - -import org.apache.commons.io.IOUtils; -import org.argeo.ArgeoException; - -/** Answer to an execution of a remote service which performed changes. */ -public class ServerAnswer { - public final static String OK = "OK"; - public final static String ERROR = "ERROR"; - - private String status = OK; - private String message = ""; - - // TODO: add an exception field - - /** Canonical constructor */ - public ServerAnswer(String status, String message) { - setStatus(status); - if (message == null) - throw new ArgeoException("Message cannot be null"); - this.message = message; - } - - /** Empty constructor */ - public ServerAnswer() { - } - - public String getStatus() { - return status; - } - - public void setStatus(String status) { - if (status == null || (!status.equals(OK) && !status.equals(ERROR))) - throw new ArgeoException("Bad status format: " + status); - this.status = status; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - public Boolean isOk() { - return status.equals(OK); - } - - public Boolean isError() { - return status.equals(ERROR); - } - - public static ServerAnswer error(String message) { - return new ServerAnswer(ERROR, message); - } - - public static ServerAnswer error(Throwable e) { - StringWriter writer = new StringWriter(); - try { - e.printStackTrace(new PrintWriter(writer)); - return new ServerAnswer(ERROR, writer.toString()); - } finally { - IOUtils.closeQuietly(writer); - } - } - - public static ServerAnswer ok(String message) { - return new ServerAnswer(OK, message); - } - - @Override - public String toString() { - return "ServerAnswer{status:" + status + ", message:" + message + "}"; - } - -} diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/ServerSerializer.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/ServerSerializer.java deleted file mode 100644 index cdb163214..000000000 --- a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/ServerSerializer.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.server; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -public interface ServerSerializer { - public void serialize(Object obj, HttpServletRequest request, - HttpServletResponse response); -} diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/AbstractAtomicBackup.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/AbstractAtomicBackup.java deleted file mode 100644 index 53972e503..000000000 --- a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/AbstractAtomicBackup.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.server.backup; - -import org.apache.commons.vfs.FileObject; -import org.apache.commons.vfs.FileSystemManager; -import org.apache.commons.vfs.FileSystemOptions; -import org.apache.commons.vfs.provider.sftp.SftpFileSystemConfigBuilder; -import org.argeo.ArgeoException; - -/** - * Simplify atomic backups implementation, especially by managing VFS. - */ -public abstract class AbstractAtomicBackup implements AtomicBackup { - private String name; - private String compression = "bz2"; - - protected abstract void writeBackup(FileObject targetFo); - - public AbstractAtomicBackup() { - } - - public AbstractAtomicBackup(String name) { - this.name = name; - } - - public void init() { - if (name == null) - throw new ArgeoException("Atomic backup name must be set"); - } - - public void destroy() { - - } - - @Override - public String backup(FileSystemManager fileSystemManager, - String backupsBase, BackupContext backupContext, - FileSystemOptions opts) { - if (name == null) - throw new ArgeoException("Atomic backup name must be set"); - - FileObject targetFo = null; - try { - if (backupsBase.startsWith("sftp:")) - SftpFileSystemConfigBuilder.getInstance() - .setStrictHostKeyChecking(opts, "no"); - if (compression == null || compression.equals("none")) - targetFo = fileSystemManager.resolveFile(backupsBase + '/' - + backupContext.getRelativeFolder() + '/' + name, opts); - else if (compression.equals("bz2")) - targetFo = fileSystemManager.resolveFile("bz2:" + backupsBase - + '/' + backupContext.getRelativeFolder() + '/' + name - + ".bz2" + "!" + name, opts); - else if (compression.equals("gz")) - targetFo = fileSystemManager.resolveFile("gz:" + backupsBase - + '/' + backupContext.getRelativeFolder() + '/' + name - + ".gz" + "!" + name, opts); - else - throw new ArgeoException("Unsupported compression " - + compression); - - writeBackup(targetFo); - - return targetFo.toString(); - } catch (Exception e) { - throw new ArgeoException("Cannot backup " + name + " to " - + targetFo, e); - } finally { - BackupUtils.closeFOQuietly(targetFo); - } - } - - public void setName(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - public void setCompression(String compression) { - this.compression = compression; - } -} diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/AtomicBackup.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/AtomicBackup.java deleted file mode 100644 index 3ebe4b5d2..000000000 --- a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/AtomicBackup.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.server.backup; - -import org.apache.commons.vfs.FileSystemManager; -import org.apache.commons.vfs.FileSystemOptions; - -/** Performs the backup of a single component, typically a database dump */ -public interface AtomicBackup { - /** Name identifiying this backup */ - public String getName(); - - /** - * Retrieves the data of the component in a format that allows to restore - * the component - * - * @param backupContext - * the context of this backup - * @return the VFS URI of the generated file or directory - */ - public String backup(FileSystemManager fileSystemManager, - String backupsBase, BackupContext backupContext, - FileSystemOptions opts); -} diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/BackupContext.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/BackupContext.java deleted file mode 100644 index 5f6442f04..000000000 --- a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/BackupContext.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.server.backup; - -import java.text.DateFormat; -import java.util.Date; - -/** - * Transient information of a given backup, centralizing common information such - * as timestamp and location. - */ -public interface BackupContext { - /** Backup date */ - public Date getTimestamp(); - - /** Formatted backup date */ - public String getTimestampAsString(); - - /** System name */ - public String getSystemName(); - - /** Local base */ - public String getRelativeFolder(); - - /** Date format */ - public DateFormat getDateFormat(); -} diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/BackupFileSystemManager.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/BackupFileSystemManager.java deleted file mode 100644 index 9a0549c5a..000000000 --- a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/BackupFileSystemManager.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.server.backup; - -import org.apache.commons.vfs.FileSystemException; -import org.apache.commons.vfs.impl.DefaultFileSystemManager; -import org.apache.commons.vfs.provider.bzip2.Bzip2FileProvider; -import org.apache.commons.vfs.provider.ftp.FtpFileProvider; -import org.apache.commons.vfs.provider.gzip.GzipFileProvider; -import org.apache.commons.vfs.provider.local.DefaultLocalFileProvider; -import org.apache.commons.vfs.provider.ram.RamFileProvider; -import org.apache.commons.vfs.provider.sftp.SftpFileProvider; -import org.apache.commons.vfs.provider.url.UrlFileProvider; -import org.argeo.ArgeoException; - -/** - * Programatically configured VFS file system manager which can be declared as a - * bean and associated with a life cycle (methods - * {@link DefaultFileSystemManager#init()} and - * {@link DefaultFileSystemManager#closet()}). Supports bz2, file, ram, gzip, - * ftp, sftp - */ -public class BackupFileSystemManager extends DefaultFileSystemManager { - - public BackupFileSystemManager() { - super(); - try { - addProvider("file", new DefaultLocalFileProvider()); - addProvider("bz2", new Bzip2FileProvider()); - addProvider("ftp", new FtpFileProvider()); - addProvider("sftp", new SftpFileProvider()); - addProvider("gzip", new GzipFileProvider()); - addProvider("ram", new RamFileProvider()); - setDefaultProvider(new UrlFileProvider()); - } catch (FileSystemException e) { - throw new ArgeoException("Cannot configure backup file provider", e); - } - } -} diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/BackupPurge.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/BackupPurge.java deleted file mode 100644 index 37eecd674..000000000 --- a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/BackupPurge.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.server.backup; - -import java.text.DateFormat; - -import org.apache.commons.vfs.FileSystemManager; -import org.apache.commons.vfs.FileSystemOptions; - -/** Purges previous backups */ -public interface BackupPurge { - /** - * Purge the backups identified by these arguments. Although these are the - * same fields as a {@link BackupContext} we don't pass it as argument since - * we want to use this interface to purge remote backups as well (that is, - * with a different base), or outside the scope of a running backup. - */ - public void purge(FileSystemManager fileSystemManager, String base, - String name, DateFormat dateFormat, FileSystemOptions opts); -} diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/BackupUtils.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/BackupUtils.java deleted file mode 100644 index e949b0ccf..000000000 --- a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/BackupUtils.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.server.backup; - -import org.apache.commons.vfs.FileObject; - -/** Backup utilities */ -public class BackupUtils { - /** Close a file object quietly even if it is null or throws an exception. */ - public static void closeFOQuietly(FileObject fo) { - if (fo != null) { - try { - fo.close(); - } catch (Exception e) { - // silent - } - } - } - - /** Prevents instantiation */ - private BackupUtils() { - } -} diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/MySqlBackup.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/MySqlBackup.java deleted file mode 100644 index 8d3377143..000000000 --- a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/MySqlBackup.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.server.backup; - -import org.apache.commons.vfs.FileObject; - -/** Backups a MySQL database using mysqldump. */ -public class MySqlBackup extends OsCallBackup { - private String mysqldumpLocation = "/usr/bin/mysqldump"; - - private String dbUser; - private String dbPassword; - private String dbName; - - public MySqlBackup() { - } - - public MySqlBackup(String dbUser, String dbPassword, String dbName) { - this.dbUser = dbUser; - this.dbPassword = dbPassword; - this.dbName = dbName; - init(); - } - - @Override - public void init() { - if (getName() == null) - setName(dbName + ".mysql"); - super.init(); - } - - @Override - public void writeBackup(FileObject targetFo) { - if (getCommand() == null) - setCommand(mysqldumpLocation - + " --lock-tables --add-locks --add-drop-table" - + " -u ${dbUser} --password=${dbPassword} --databases ${dbName}"); - getVariables().put("dbUser", dbUser); - getVariables().put("dbPassword", dbPassword); - getVariables().put("dbName", dbName); - - super.writeBackup(targetFo); - } - - public void setDbUser(String dbUser) { - this.dbUser = dbUser; - } - - public void setDbPassword(String dbPassword) { - this.dbPassword = dbPassword; - } - - public void setDbName(String dbName) { - this.dbName = dbName; - } - - public void setMysqldumpLocation(String mysqldumpLocation) { - this.mysqldumpLocation = mysqldumpLocation; - } - -} diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/OpenLdapBackup.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/OpenLdapBackup.java deleted file mode 100644 index eb5ce2d96..000000000 --- a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/OpenLdapBackup.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.server.backup; - -import org.apache.commons.vfs.FileObject; -import org.argeo.ArgeoException; - -/** Backups an OpenLDAP server using slapcat */ -public class OpenLdapBackup extends OsCallBackup { - private String slapcatLocation = "/usr/sbin/slapcat"; - private String slapdConfLocation = "/etc/openldap/slapd.conf"; - private String baseDn; - - public OpenLdapBackup() { - super(); - } - - public OpenLdapBackup(String baseDn) { - super(); - this.baseDn = baseDn; - } - - @Override - public void writeBackup(FileObject targetFo) { - if (baseDn == null) - throw new ArgeoException("Base DN must be set"); - - if (getCommand() == null) - setCommand(slapcatLocation - + " -f ${slapdConfLocation} -b '${baseDn}'"); - getVariables().put("slapdConfLocation", slapdConfLocation); - getVariables().put("baseDn", baseDn); - - super.writeBackup(targetFo); - } - - public void setSlapcatLocation(String slapcatLocation) { - this.slapcatLocation = slapcatLocation; - } - - public void setSlapdConfLocation(String slapdConfLocation) { - this.slapdConfLocation = slapdConfLocation; - } - - public void setBaseDn(String baseDn) { - this.baseDn = baseDn; - } - -} diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/OsCallBackup.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/OsCallBackup.java deleted file mode 100644 index 816157cfd..000000000 --- a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/OsCallBackup.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.server.backup; - -import java.io.ByteArrayOutputStream; -import java.util.HashMap; -import java.util.Map; - -import org.apache.commons.exec.CommandLine; -import org.apache.commons.exec.DefaultExecutor; -import org.apache.commons.exec.ExecuteException; -import org.apache.commons.exec.ExecuteStreamHandler; -import org.apache.commons.exec.Executor; -import org.apache.commons.exec.PumpStreamHandler; -import org.apache.commons.io.IOUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.commons.vfs.FileContent; -import org.apache.commons.vfs.FileObject; -import org.argeo.ArgeoException; - -/** - * Runs an OS command and save its standard output as a file. Typically used for - * MySQL or OpenLDAP dumps. - */ -public class OsCallBackup extends AbstractAtomicBackup { - private final static Log log = LogFactory.getLog(OsCallBackup.class); - - private String command; - private Map variables = new HashMap(); - private Executor executor = new DefaultExecutor(); - - private Map environment = new HashMap(); - - /** Name of the sudo user, root if "", not sudo if null */ - private String sudo = null; - - public OsCallBackup() { - } - - public OsCallBackup(String name) { - super(name); - } - - public OsCallBackup(String name, String command) { - super(name); - this.command = command; - } - - @Override - public void writeBackup(FileObject targetFo) { - String commandToUse = command; - - // sudo - if (sudo != null) { - if (sudo.equals("")) - commandToUse = "sudo " + commandToUse; - else - commandToUse = "sudo -u " + sudo + " " + commandToUse; - } - - CommandLine commandLine = CommandLine.parse(commandToUse, variables); - ByteArrayOutputStream errBos = new ByteArrayOutputStream(); - if (log.isTraceEnabled()) - log.trace(commandLine.toString()); - - try { - // stdout - FileContent targetContent = targetFo.getContent(); - // stderr - ExecuteStreamHandler streamHandler = new PumpStreamHandler( - targetContent.getOutputStream(), errBos); - executor.setStreamHandler(streamHandler); - executor.execute(commandLine, environment); - } catch (ExecuteException e) { - byte[] err = errBos.toByteArray(); - String errStr = new String(err); - throw new ArgeoException("Process " + commandLine + " failed (" - + e.getExitValue() + "): " + errStr, e); - } catch (Exception e) { - byte[] err = errBos.toByteArray(); - String errStr = new String(err); - throw new ArgeoException("Process " + commandLine + " failed: " - + errStr, e); - } finally { - IOUtils.closeQuietly(errBos); - } - } - - public void setCommand(String command) { - this.command = command; - } - - protected String getCommand() { - return command; - } - - /** - * A reference to the environment variables that will be passed to the - * process. Empty by default. - */ - protected Map getEnvironment() { - return environment; - } - - protected Map getVariables() { - return variables; - } - - public void setVariables(Map variables) { - this.variables = variables; - } - - public void setExecutor(Executor executor) { - this.executor = executor; - } - - public void setSudo(String sudo) { - this.sudo = sudo; - } - -} diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/PostgreSqlBackup.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/PostgreSqlBackup.java deleted file mode 100644 index 37716bb79..000000000 --- a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/PostgreSqlBackup.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.server.backup; - -import org.apache.commons.vfs.FileObject; - -/** Backups a PostgreSQL database using pg_dump. */ -public class PostgreSqlBackup extends OsCallBackup { - /** - * PostgreSQL password environment variable (see - * http://stackoverflow.com/questions - * /2893954/how-to-pass-in-password-to-pg-dump) - */ - protected final static String PGPASSWORD = "PGPASSWORD"; - - private String pgDumpLocation = "/usr/bin/pg_dump"; - - private String dbUser; - private String dbPassword; - private String dbName; - - public PostgreSqlBackup() { - super(); - } - - public PostgreSqlBackup(String dbUser, String dbPassword, String dbName) { - this.dbUser = dbUser; - this.dbPassword = dbPassword; - this.dbName = dbName; - init(); - } - - @Override - public void init() { - // disable compression since pg_dump is used with -Fc option - setCompression(null); - - if (getName() == null) - setName(dbName + ".pgdump"); - super.init(); - } - - @Override - public void writeBackup(FileObject targetFo) { - if (getCommand() == null) { - getEnvironment().put(PGPASSWORD, dbPassword); - setCommand(pgDumpLocation + " -Fc" + " -U ${dbUser} ${dbName}"); - } - getVariables().put("dbUser", dbUser); - getVariables().put("dbPassword", dbPassword); - getVariables().put("dbName", dbName); - - super.writeBackup(targetFo); - } - - public void setDbUser(String dbUser) { - this.dbUser = dbUser; - } - - public void setDbPassword(String dbPassword) { - this.dbPassword = dbPassword; - } - - public void setDbName(String dbName) { - this.dbName = dbName; - } - - public void setPgDumpLocation(String mysqldumpLocation) { - this.pgDumpLocation = mysqldumpLocation; - } - -} diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/SimpleBackupContext.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/SimpleBackupContext.java deleted file mode 100644 index 872f31cf3..000000000 --- a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/SimpleBackupContext.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.server.backup; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Date; - -import org.apache.commons.vfs.FileSystemManager; - -/** Simple implementation of a backup context */ -public class SimpleBackupContext implements BackupContext { - private DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmm"); - private final Date timestamp; - private final String name; - - private final FileSystemManager fileSystemManager; - - public SimpleBackupContext(FileSystemManager fileSystemManager, - String backupsBase, String name) { - this.name = name; - this.timestamp = new Date(); - this.fileSystemManager = fileSystemManager; - } - - public Date getTimestamp() { - return timestamp; - } - - public String getTimestampAsString() { - return dateFormat.format(timestamp); - } - - public String getSystemName() { - return name; - } - - public String getRelativeFolder() { - return name + '/' + getTimestampAsString(); - } - - public DateFormat getDateFormat() { - return dateFormat; - } - - public FileSystemManager getFileSystemManager() { - return fileSystemManager; - } - -} diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/SimpleBackupPurge.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/SimpleBackupPurge.java deleted file mode 100644 index 035c49c75..000000000 --- a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/SimpleBackupPurge.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.server.backup; - -import java.text.DateFormat; -import java.util.Date; -import java.util.SortedMap; -import java.util.TreeMap; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.commons.vfs.FileObject; -import org.apache.commons.vfs.FileSystemManager; -import org.apache.commons.vfs.FileSystemOptions; -import org.apache.commons.vfs.Selectors; -import org.argeo.ArgeoException; -import org.joda.time.DateTime; -import org.joda.time.Period; - -/** Simple backup purge which keeps backups only for a given number of days */ -public class SimpleBackupPurge implements BackupPurge { - private final static Log log = LogFactory.getLog(SimpleBackupPurge.class); - - private Integer daysKept = 30; - - @Override - public void purge(FileSystemManager fileSystemManager, String base, - String name, DateFormat dateFormat, FileSystemOptions opts) { - try { - DateTime nowDt = new DateTime(); - FileObject baseFo = fileSystemManager.resolveFile( - base + '/' + name, opts); - - SortedMap toDelete = new TreeMap(); - int backupCount = 0; - - // make sure base dir exists - baseFo.createFolder(); - - // scan backups and list those which should be deleted - for (FileObject backupFo : baseFo.getChildren()) { - String backupName = backupFo.getName().getBaseName(); - Date backupDate = dateFormat.parse(backupName); - backupCount++; - - DateTime backupDt = new DateTime(backupDate.getTime()); - Period sinceThen = new Period(backupDt, nowDt); - int days = sinceThen.getDays(); - // int days = sinceThen.getMinutes(); - if (days > daysKept) { - toDelete.put(backupDt, backupFo); - } - } - - if (toDelete.size() != 0 && toDelete.size() == backupCount) { - // all backups would be deleted - // but we want to keep at least one - DateTime lastBackupDt = toDelete.firstKey(); - FileObject keptFo = toDelete.remove(lastBackupDt); - log.warn("Backup " + keptFo - + " kept although it is older than " + daysKept - + " days."); - } - - // delete old backups - for (FileObject backupFo : toDelete.values()) { - backupFo.delete(Selectors.SELECT_ALL); - if (log.isDebugEnabled()) - log.debug("Deleted backup " + backupFo); - } - } catch (Exception e) { - throw new ArgeoException("Could not purge previous backups", e); - } - - } - -} diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/SvnBackup.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/SvnBackup.java deleted file mode 100644 index 636bbcaaa..000000000 --- a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/SvnBackup.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.server.backup; - -import java.io.File; - -import org.apache.commons.vfs.FileObject; - -/** Backups a Subversion repository using svnadmin. */ -public class SvnBackup extends OsCallBackup { - private String svnadminLocation = "/usr/bin/svnadmin"; - - private String repoLocation; - private String repoName; - - public SvnBackup() { - } - - public SvnBackup(String repoLocation) { - this.repoLocation = repoLocation; - init(); - } - - @Override - public void init() { - // use directory as repo name - if (repoName == null) - repoName = new File(repoLocation).getName(); - - if (getName() == null) - setName(repoName + ".svndump"); - super.init(); - } - - @Override - public void writeBackup(FileObject targetFo) { - if (getCommand() == null) { - setCommand(svnadminLocation + " dump " + " ${repoLocation}"); - } - getVariables().put("repoLocation", repoLocation); - - super.writeBackup(targetFo); - } - - public void setRepoLocation(String repoLocation) { - this.repoLocation = repoLocation; - } - - public void setRepoName(String repoName) { - this.repoName = repoName; - } - - public void setSvnadminLocation(String mysqldumpLocation) { - this.svnadminLocation = mysqldumpLocation; - } - -} diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/SystemBackup.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/SystemBackup.java deleted file mode 100644 index 92f73c7a6..000000000 --- a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/backup/SystemBackup.java +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.server.backup; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.commons.vfs.FileObject; -import org.apache.commons.vfs.FileSystemException; -import org.apache.commons.vfs.FileSystemManager; -import org.apache.commons.vfs.FileSystemOptions; -import org.apache.commons.vfs.Selectors; -import org.apache.commons.vfs.UserAuthenticator; -import org.apache.commons.vfs.auth.StaticUserAuthenticator; -import org.apache.commons.vfs.impl.DefaultFileSystemConfigBuilder; -import org.apache.commons.vfs.impl.StandardFileSystemManager; -import org.argeo.ArgeoException; - -/** - * Combines multiple backups and transfer them to a remote location. Purges - * remote and local data based on certain criteria. - */ -public class SystemBackup implements Runnable { - private final static Log log = LogFactory.getLog(SystemBackup.class); - - private FileSystemManager fileSystemManager; - private UserAuthenticator userAuthenticator = null; - - private String backupsBase; - private String systemName; - - private List atomicBackups = new ArrayList(); - private BackupPurge backupPurge = new SimpleBackupPurge(); - - private Map remoteBases = new HashMap(); - - @Override - public void run() { - if (atomicBackups.size() == 0) - throw new ArgeoException("No atomic backup listed"); - List failures = new ArrayList(); - - SimpleBackupContext backupContext = new SimpleBackupContext( - fileSystemManager, backupsBase, systemName); - - // purge older backups - FileSystemOptions opts = new FileSystemOptions(); - try { - DefaultFileSystemConfigBuilder.getInstance().setUserAuthenticator( - opts, userAuthenticator); - } catch (FileSystemException e) { - throw new ArgeoException("Cannot create authentication", e); - } - - try { - - backupPurge.purge(fileSystemManager, backupsBase, systemName, - backupContext.getDateFormat(), opts); - } catch (Exception e) { - failures.add("Purge " + backupsBase + " failed: " + e.getMessage()); - log.error("Purge of " + backupsBase + " failed", e); - } - - // perform backup - for (AtomicBackup atomickBackup : atomicBackups) { - try { - String target = atomickBackup.backup(fileSystemManager, - backupsBase, backupContext, opts); - if (log.isDebugEnabled()) - log.debug("Performed backup " + target); - } catch (Exception e) { - String msg = "Atomic backup " + atomickBackup.getName() - + " failed: " + ArgeoException.chainCausesMessages(e); - failures.add(msg); - log.error(msg); - if (log.isTraceEnabled()) - log.trace( - "Stacktrace of atomic backup " - + atomickBackup.getName() + " failure.", e); - } - } - - // dispatch to remote - for (String remoteBase : remoteBases.keySet()) { - FileObject localBaseFo = null; - FileObject remoteBaseFo = null; - UserAuthenticator auth = remoteBases.get(remoteBase); - - // authentication - FileSystemOptions remoteOpts = new FileSystemOptions(); - try { - DefaultFileSystemConfigBuilder.getInstance() - .setUserAuthenticator(remoteOpts, auth); - backupPurge.purge(fileSystemManager, remoteBase, systemName, - backupContext.getDateFormat(), remoteOpts); - } catch (Exception e) { - failures.add("Purge " + remoteBase + " failed: " - + e.getMessage()); - log.error("Cannot purge " + remoteBase, e); - } - - try { - localBaseFo = fileSystemManager.resolveFile(backupsBase + '/' - + backupContext.getRelativeFolder(), opts); - remoteBaseFo = fileSystemManager.resolveFile(remoteBase + '/' - + backupContext.getRelativeFolder(), remoteOpts); - remoteBaseFo.copyFrom(localBaseFo, Selectors.SELECT_ALL); - if (log.isDebugEnabled()) - log.debug("Copied backup to " + remoteBaseFo + " from " - + localBaseFo); - // } - } catch (Exception e) { - failures.add("Dispatch to " + remoteBase + " failed: " - + e.getMessage()); - log.error( - "Cannot dispatch backups from " - + backupContext.getRelativeFolder() + " to " - + remoteBase, e); - } - BackupUtils.closeFOQuietly(localBaseFo); - BackupUtils.closeFOQuietly(remoteBaseFo); - } - - int failureCount = 0; - if (failures.size() > 0) { - StringBuffer buf = new StringBuffer(); - for (String failure : failures) { - buf.append('\n').append(failureCount).append(" - ") - .append(failure); - failureCount++; - } - throw new ArgeoException(failureCount - + " error(s) when running the backup," - + " check the logs and the backups as soon as possible." - + buf); - } - } - - public void setFileSystemManager(FileSystemManager fileSystemManager) { - this.fileSystemManager = fileSystemManager; - } - - public void setBackupsBase(String backupsBase) { - this.backupsBase = backupsBase; - } - - public void setSystemName(String name) { - this.systemName = name; - } - - public void setAtomicBackups(List atomicBackups) { - this.atomicBackups = atomicBackups; - } - - public void setBackupPurge(BackupPurge backupPurge) { - this.backupPurge = backupPurge; - } - - public void setUserAuthenticator(UserAuthenticator userAuthenticator) { - this.userAuthenticator = userAuthenticator; - } - - public void setRemoteBases(Map remoteBases) { - this.remoteBases = remoteBases; - } - - public static void main(String args[]) { - while (true) { - try { - StandardFileSystemManager fsm = new StandardFileSystemManager(); - fsm.init(); - - SystemBackup systemBackup = new SystemBackup(); - systemBackup.setSystemName("mySystem"); - systemBackup - .setBackupsBase("/home/mbaudier/dev/src/commons/server/runtime/org.argeo.server.core/target"); - systemBackup.setFileSystemManager(fsm); - - List atomicBackups = new ArrayList(); - - MySqlBackup mySqlBackup = new MySqlBackup("root", "", "test"); - atomicBackups.add(mySqlBackup); - PostgreSqlBackup postgreSqlBackup = new PostgreSqlBackup( - "argeo", "argeo", "gis_template"); - atomicBackups.add(postgreSqlBackup); - SvnBackup svnBackup = new SvnBackup( - "/home/mbaudier/tmp/testsvnrepo"); - atomicBackups.add(svnBackup); - - systemBackup.setAtomicBackups(atomicBackups); - - Map remoteBases = new HashMap(); - StaticUserAuthenticator userAuthenticator = new StaticUserAuthenticator( - null, "demo", "demo"); - remoteBases.put("sftp://localhost/home/mbaudier/test", - userAuthenticator); - systemBackup.setRemoteBases(remoteBases); - - systemBackup.run(); - - fsm.close(); - } catch (FileSystemException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - System.exit(1); - } - - // wait - try { - Thread.sleep(120 * 1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } -} diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/dao/AbstractMemoryDaoSupport.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/dao/AbstractMemoryDaoSupport.java deleted file mode 100644 index f9af51bcf..000000000 --- a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/dao/AbstractMemoryDaoSupport.java +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.server.dao; - -import java.beans.PropertyEditor; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; - -import org.apache.commons.io.IOUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.ArgeoException; -import org.springframework.beans.BeanWrapper; -import org.springframework.beans.BeanWrapperImpl; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.core.io.Resource; - -public abstract class AbstractMemoryDaoSupport implements LightDaoSupport, - ApplicationContextAware, InitializingBean { - private final static Log log = LogFactory - .getLog(AbstractMemoryDaoSupport.class); - - private ClassLoader classLoader = getClass().getClassLoader(); - private ApplicationContext applicationContext; - private List> additionalClasses = new ArrayList>(); - - private Map, Map> model = new HashMap, Map>(); - - private Map externalRefs = new HashMap(); - - private List scannedPackages = new ArrayList(); - - private List resources = new ArrayList(); - - private Map, PropertyEditor> customEditors = new HashMap, PropertyEditor>();; - - protected abstract void load(InputStream in, List references); - - protected abstract Object findInternalRef(Reference reference); - - public void afterPropertiesSet() throws Exception { - init(); - } - - public void init() { - for (PropertyEditor propertyEditor : customEditors.values()) - if (propertyEditor instanceof LightDaoAware) { - ((LightDaoAware) propertyEditor).setLightDaoSupport(this); - } - - // Load data - List references = new ArrayList(); - - for (Resource res : resources) { - InputStream in = null; - try { - in = res.getInputStream(); - load(in, references); - } catch (Exception e) { - throw new ArgeoException("Cannot load stream", e); - } finally { - IOUtils.closeQuietly(in); - } - } - - // Inject references - for (Reference ref : references) { - injectReference(ref); - } - if (log.isDebugEnabled()) - log.debug(references.size() + " references linked"); - } - - public List> getSupportedClasses() { - List> res = new ArrayList>(); - res.addAll(additionalClasses); - res.addAll(model.keySet()); - return res; - } - - protected void injectReference(Reference reference) { - BeanWrapper bw = new BeanWrapperImpl(reference.object); - Object targetObject; - if (reference.getExternalRef() != null) { - String ref = reference.getExternalRef(); - if (externalRefs.containsKey(ref)) - targetObject = externalRefs.get(ref); - else if (applicationContext != null) - targetObject = applicationContext.getBean(ref); - else { - targetObject = null; - log.warn("Ref " + ref + " not found"); - } - } else { - targetObject = findInternalRef(reference); - } - bw.setPropertyValue(reference.property, targetObject); - - } - - protected BeanWrapper newBeanWrapper(Class targetClass) { - BeanWrapperImpl bw = new BeanWrapperImpl(targetClass); - for (Class clss : customEditors.keySet()) - bw.registerCustomEditor(clss, customEditors.get(clss)); - return bw; - } - - @SuppressWarnings("unchecked") - public T getByKey(Class clss, Object key) { - if (key == null) - throw new ArgeoException("Key is null for " + clss); - return (T) model.get(findClass(clss)).get(key); - } - - /** - * Slow. - * - * @return the first found - */ - public T getByField(Class clss, String field, Object value) { - List all = list(clss, null); - T res = null; - for (T obj : all) { - if (new BeanWrapperImpl(obj).getPropertyValue(field).equals(value)) { - res = obj; - break; - } - } - return res; - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - public List list(Class clss, Object filter) { - List res = new ArrayList(); - - Class classToUse = findClass(clss); - if (classToUse != null) - res.addAll((Collection) model.get(classToUse).values()); - - if (applicationContext != null) - res.addAll(applicationContext.getBeansOfType(clss).values()); - - return res; - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - protected Class findClass(Class parent) { - if (model.containsKey(parent)) - return parent; - - for (Class clss : model.keySet()) { - if (parent.isAssignableFrom(clss)) - return clss;// return the first found - } - if (log.isDebugEnabled()) - log.warn("No class found for " + parent.getName()); - return null; - } - - public void setApplicationContext(ApplicationContext applicationContext) - throws BeansException { - this.applicationContext = applicationContext; - } - - /** - * When it should be stored under a different class (e.g. super class or - * interface) - */ - public void saveOrUpdate(Object key, Object value, Class clss) { - if (!model.containsKey(clss)) - model.put(clss, new TreeMap()); - model.get(clss).put(key, value); - } - - protected ClassLoader getClassLoader() { - return classLoader; - } - - public void setExternalRefs(Map externalRefs) { - this.externalRefs = externalRefs; - } - - public Map getExternalRefs() { - return externalRefs; - } - - public void setScannedPackages(List scannedPackages) { - this.scannedPackages = scannedPackages; - } - - public List getScannedPackages() { - return scannedPackages; - } - - public void setResources(List workbooks) { - this.resources = workbooks; - } - - public List getResources() { - return resources; - } - - public void setClassLoader(ClassLoader classLoader) { - this.classLoader = classLoader; - } - - public List> getAdditionalClasses() { - return additionalClasses; - } - - public void setAdditionalClasses(List> additionalClasses) { - this.additionalClasses = additionalClasses; - } - - public void setCustomEditors(Map, PropertyEditor> propertyEditors) { - this.customEditors = propertyEditors; - } - - protected static class Reference { - private Object object; - private String property; - private String externalRef; - - public Reference(Object object, String property, String externalRef) { - this.object = object; - this.property = property; - this.externalRef = externalRef; - } - - public Object getObject() { - return object; - } - - public String getProperty() { - return property; - } - - public String getExternalRef() { - return externalRef; - } - - } -} diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/dao/AbstractTabularDaoSupport.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/dao/AbstractTabularDaoSupport.java deleted file mode 100644 index 1ca5a100c..000000000 --- a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/dao/AbstractTabularDaoSupport.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.server.dao; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.ArgeoException; - -public abstract class AbstractTabularDaoSupport extends - AbstractMemoryDaoSupport { - private final static Log log = LogFactory - .getLog(AbstractTabularDaoSupport.class); - - private Map> tabularView = new HashMap>(); - - @Override - protected Object findInternalRef(Reference reference) { - TabularInternalReference tabReference = (TabularInternalReference) reference; - return getFromTabularView(tabReference.getTargetTableName(), - tabReference.getTargetRow()); - } - - protected Object getFromTabularView(String tableName, Integer row) { - return tabularView.get(tableName).get(row - 2); - } - - protected void registerInTabularView(String tableName, Object object) { - if (!tabularView.containsKey(tableName)) - tabularView.put(tableName, new ArrayList()); - tabularView.get(tableName).add(object); - } - - protected Class findClassToInstantiate(String tableName) { - // TODO: ability to map sheet names and class names - String className = tableName; - Class clss = null; - try { - clss = getClassLoader().loadClass(className); - return clss; - } catch (ClassNotFoundException e) { - // silent - } - - scannedPkgs: for (String pkg : getScannedPackages()) { - try { - clss = getClassLoader().loadClass(pkg.trim() + "." + className); - break scannedPkgs; - } catch (ClassNotFoundException e) { - // silent - if (log.isTraceEnabled()) - log.trace(e.getMessage()); - } - } - - if (clss == null) - throw new ArgeoException("Cannot find a class for table " - + tableName); - - return clss; - } - - protected static class TabularInternalReference extends Reference { - private String targetTableName; - private Integer targetRow; - - public TabularInternalReference(Object object, String property, - String targetSheet, Integer targetRow) { - super(object, property, null); - this.targetTableName = targetSheet; - this.targetRow = targetRow; - } - - public String getTargetTableName() { - return targetTableName; - } - - public Integer getTargetRow() { - return targetRow; - } - - } -} diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/dao/LightDaoAware.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/dao/LightDaoAware.java deleted file mode 100644 index 5ae7bea1e..000000000 --- a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/dao/LightDaoAware.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.server.dao; - -public interface LightDaoAware { - public void setLightDaoSupport(LightDaoSupport lightDaoSupport); -} diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/dao/LightDaoPropertyEditor.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/dao/LightDaoPropertyEditor.java deleted file mode 100644 index de6ba7084..000000000 --- a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/dao/LightDaoPropertyEditor.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.server.dao; - -import java.beans.PropertyEditorSupport; - -import org.argeo.ArgeoException; - -public class LightDaoPropertyEditor extends PropertyEditorSupport implements - LightDaoAware { - private LightDaoSupport lightDaoSupport; - - private Class targetClass; - /** Can be null */ - private String businessIdField; - - @Override - public String getAsText() { - return getValue().toString(); - } - - @Override - public void setAsText(String text) throws IllegalArgumentException { - if (targetClass == null) - throw new ArgeoException("Target class cannot be null"); - - if (businessIdField != null) - setValue(lightDaoSupport.getByField(targetClass, businessIdField, - text)); - else - setValue(lightDaoSupport.getByKey(targetClass, text)); - } - - public void setLightDaoSupport(LightDaoSupport lightDaoSupport) { - this.lightDaoSupport = lightDaoSupport; - } - - public void setTargetClass(Class targetClass) { - this.targetClass = targetClass; - } - - public void setBusinessIdField(String businessIdField) { - this.businessIdField = businessIdField; - } - -} diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/dao/LightDaoSupport.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/dao/LightDaoSupport.java deleted file mode 100644 index 6ea1b754d..000000000 --- a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/dao/LightDaoSupport.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.server.dao; - -import java.util.List; - -/** Minimal generic DAO for easy to implements objects <-> storage mapping. */ -public interface LightDaoSupport { - /** Retrieve an object of a given type by its unique key. */ - public T getByKey(Class clss, Object key); - - /** Retrieve an object of a given type by the value of one of its fields. */ - public T getByField(Class clss, String field, Object value); - - /** List all objects, optionally filtering them (implementation dependent) */ - public List list(Class clss, Object filter); - - /** Lis all supported object types. */ - public List> getSupportedClasses(); - - /** Save or update an object */ - public void saveOrUpdate(Object key, Object value, Class clss); -} diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/mvc/DefaultHandlerExceptionResolver.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/mvc/DefaultHandlerExceptionResolver.java deleted file mode 100644 index 6269bd007..000000000 --- a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/mvc/DefaultHandlerExceptionResolver.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.server.mvc; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.server.ServerAnswer; -import org.springframework.web.servlet.HandlerExceptionResolver; -import org.springframework.web.servlet.ModelAndView; - -public class DefaultHandlerExceptionResolver implements - HandlerExceptionResolver { - private final static Log log = LogFactory - .getLog(DefaultHandlerExceptionResolver.class); - - public ModelAndView resolveException(HttpServletRequest request, - HttpServletResponse response, Object handler, Exception ex) { - ModelAndView mv = new ModelAndView(); - ServerAnswer serverAnswer = ServerAnswer.error(ex); - mv.addObject(serverAnswer); - - if (log.isDebugEnabled()) - log.error(serverAnswer); - - mv.setViewName("500"); - // response.setStatus(500); - return mv; - } - -} diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/mvc/EmptyViewController.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/mvc/EmptyViewController.java deleted file mode 100644 index c83d4aeba..000000000 --- a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/mvc/EmptyViewController.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.server.mvc; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.ParameterizableViewController; - -/** Dummy controller which simply redirects to a view (typically a JSP)*/ -public class EmptyViewController extends ParameterizableViewController { - - protected ModelAndView handleRequestInternal(HttpServletRequest request, - HttpServletResponse response) throws Exception { - ModelAndView modelAndView = new ModelAndView(); - modelAndView.setViewName(getViewName()); - return modelAndView; - - } -} diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/mvc/MvcConstants.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/mvc/MvcConstants.java deleted file mode 100644 index d5c32dc89..000000000 --- a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/mvc/MvcConstants.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.server.mvc; - -public interface MvcConstants { - public final static String ANSWER_MODEL_KEY = "org.argeo.server.mvc.ANSWER"; - public final static String ANSWER_MODEL_KEY_AS_HTML = "org.argeo.server.mvc.ANSWER_AS_HTML"; -} diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/mvc/SerializingView.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/mvc/SerializingView.java deleted file mode 100644 index b42a9a0d2..000000000 --- a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/mvc/SerializingView.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.server.mvc; - -import java.util.Locale; -import java.util.Map; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.argeo.ArgeoException; -import org.argeo.server.ServerAnswer; -import org.argeo.server.ServerSerializer; -import org.springframework.validation.BindingResult; -import org.springframework.web.servlet.View; -import org.springframework.web.servlet.view.AbstractView; - -/** - * Can be used as a standalone {@link View} or using - * {@link SerializingViewResolver} - */ -public class SerializingView extends AbstractView implements MvcConstants { - private final String viewName; - private final Locale locale; - - private ServerSerializer serializer; - - public SerializingView() { - this.viewName = null; - this.locale = Locale.getDefault(); - } - - public SerializingView(String viewName, Locale locale, - ServerSerializer serializer) { - this.viewName = viewName; - this.locale = locale; - this.serializer = serializer; - } - - @SuppressWarnings({ "rawtypes" }) - @Override - protected void renderMergedOutputModel(Map model, - HttpServletRequest request, HttpServletResponse response) - throws Exception { - Boolean serverAnswersAsHtml = model - .containsKey(ANSWER_MODEL_KEY_AS_HTML); - - final Object answer = findAnswerInModel(model); - - if ((answer instanceof ServerAnswer) && serverAnswersAsHtml) { - response.setContentType("text/html"); - ServerAnswer serverAnswer = (ServerAnswer) answer; - response.getWriter().append("
");
-			response.getWriter().append(serverAnswer.getMessage());
-			response.getWriter().append("
"); - } else { - serializer.serialize(answer, request, response); - } - } - - @SuppressWarnings("rawtypes") - protected Object findAnswerInModel(Map model) { - if (model.size() == 1) { - return model.values().iterator().next(); - } else if (model.size() == 2) { - boolean otherIsBindingResult = false; - Object answerValue = null; - for (Object value : model.values()) { - if (value instanceof BindingResult) - otherIsBindingResult = true; - else - answerValue = value; - } - - if (otherIsBindingResult) - return answerValue; - } - - if (model.containsKey(ANSWER_MODEL_KEY)) { - return model.get(ANSWER_MODEL_KEY); - } else if (model.containsKey(ANSWER_MODEL_KEY_AS_HTML)) { - return model.get(ANSWER_MODEL_KEY_AS_HTML); - } else if (viewName != null && model.containsKey(viewName)) { - return model.get(viewName); - } else { - if (model.size() == 0) - throw new ArgeoException("Model is empty."); - else - throw new ArgeoException( - "Model has a size different from 1. Specify a modelKey."); - } - } - - public String getViewName() { - return viewName; - } - - public Locale getLocale() { - return locale; - } - - public void setSerializer(ServerSerializer serializer) { - this.serializer = serializer; - } - -} diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/mvc/SerializingViewResolver.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/mvc/SerializingViewResolver.java deleted file mode 100644 index 93315438f..000000000 --- a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/mvc/SerializingViewResolver.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.server.mvc; - -import java.util.Locale; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.server.ServerSerializer; -import org.springframework.web.servlet.View; -import org.springframework.web.servlet.view.AbstractCachingViewResolver; - -/** - * Returns a {@link SerializingView} based on the underlying. - */ -public class SerializingViewResolver extends AbstractCachingViewResolver { - private final static Log log = LogFactory - .getLog(SerializingViewResolver.class); - - private ServerSerializer serializer; - - @Override - protected View loadView(String viewName, Locale locale) throws Exception { - if (log.isTraceEnabled()) - log.trace("viewName=" + viewName); - return new SerializingView(viewName, locale, serializer); - } - - public void setSerializer(ServerSerializer serializer) { - this.serializer = serializer; - } - -} diff --git a/server/runtime/org.argeo.server.hibernate/pom.xml b/server/runtime/org.argeo.server.hibernate/pom.xml index 0cb8e2782..adbd42779 100644 --- a/server/runtime/org.argeo.server.hibernate/pom.xml +++ b/server/runtime/org.argeo.server.hibernate/pom.xml @@ -1,8 +1,8 @@ 4.0.0 - org.argeo.commons.server - runtime + org.argeo.commons + argeo-commons 2.1.12-SNAPSHOT .. @@ -38,14 +38,14 @@ - org.argeo.commons.server + org.argeo.commons org.argeo.server.core 2.1.12-SNAPSHOT - org.argeo.commons.server + org.argeo.commons org.argeo.server.dep.hibernate 2.1.12-SNAPSHOT pom diff --git a/server/runtime/org.argeo.server.jackrabbit/.classpath b/server/runtime/org.argeo.server.jackrabbit/.classpath deleted file mode 100644 index e9c521af6..000000000 --- a/server/runtime/org.argeo.server.jackrabbit/.classpath +++ /dev/null @@ -1,8 +0,0 @@ - - - - - >> - - - diff --git a/server/runtime/org.argeo.server.jackrabbit/.project b/server/runtime/org.argeo.server.jackrabbit/.project deleted file mode 100644 index a381d35e0..000000000 --- a/server/runtime/org.argeo.server.jackrabbit/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - org.argeo.server.jackrabbit - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.jdt.core.javanature - org.eclipse.pde.PluginNature - - diff --git a/server/runtime/org.argeo.server.jackrabbit/build.properties b/server/runtime/org.argeo.server.jackrabbit/build.properties deleted file mode 100644 index 722c27c73..000000000 --- a/server/runtime/org.argeo.server.jackrabbit/build.properties +++ /dev/null @@ -1,10 +0,0 @@ -additional.bundles = slf4j.api,\ - slf4j.log4j,\ - org.apache.log4j,\ - org.apache.commons.collections,\ - edu.oswego.cs.dl.util.concurrent,\ - org.h2,\ - org.apache.lucene,\ - org.springframework.context -source.. = src/main/java/,\ - src/main/resources/ diff --git a/server/runtime/org.argeo.server.jackrabbit/pom.xml b/server/runtime/org.argeo.server.jackrabbit/pom.xml deleted file mode 100644 index 9f2f585af..000000000 --- a/server/runtime/org.argeo.server.jackrabbit/pom.xml +++ /dev/null @@ -1,103 +0,0 @@ - - 4.0.0 - - org.argeo.commons.server - runtime - 2.1.12-SNAPSHOT - .. - - org.argeo.server.jackrabbit - Commons Server Jackrabbit - - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-source-plugin - - - org.apache.maven.plugins - maven-jar-plugin - - - org.apache.felix - maven-bundle-plugin - - - - org.argeo.jackrabbit.*, - - - javax.servlet, - org.apache.jackrabbit.webdav.server, - org.springframework.web.context, - org.xml.sax;version="0.0.0", - org.apache.jackrabbit.webdav.jcr, - org.springframework.beans, - * - - - - - - - - - org.argeo.commons.base - org.argeo.util - 2.1.12-SNAPSHOT - - - org.argeo.commons.server - org.argeo.server.jcr.mvc - 2.1.12-SNAPSHOT - - - - - org.argeo.commons.base - org.argeo.dep.jackrabbit - pom - 2.1.12-SNAPSHOT - - - - - org.argeo.tp.rap.platform - org.eclipse.osgi - provided - - - - - org.argeo.tp - org.springframework.beans - - - org.argeo.tp - org.springframework.web.servlet - - - org.argeo.tp - org.springframework.security.core - - - - - org.argeo.commons.base - org.argeo.support.junit - 2.1.12-SNAPSHOT - test - - - org.argeo.commons.base - org.argeo.dep.log4j - 2.1.12-SNAPSHOT - pom - test - - - \ No newline at end of file diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitAuthorizations.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitAuthorizations.java deleted file mode 100644 index e880b6700..000000000 --- a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitAuthorizations.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jackrabbit; - -import java.security.Principal; -import java.util.Arrays; -import java.util.List; - -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.jackrabbit.api.JackrabbitSession; -import org.apache.jackrabbit.api.security.user.Authorizable; -import org.apache.jackrabbit.api.security.user.UserManager; -import org.argeo.ArgeoException; -import org.argeo.jcr.security.JcrAuthorizations; - -/** Apply authorizations to a Jackrabbit repository. */ -public class JackrabbitAuthorizations extends JcrAuthorizations { - private final static Log log = LogFactory - .getLog(JackrabbitAuthorizations.class); - - private List groupPrefixes = Arrays - .asList(new String[] { "ROLE_" });// new ArrayList(); - - @Override - protected Principal getOrCreatePrincipal(Session session, - String principalName) throws RepositoryException { - UserManager um = ((JackrabbitSession) session).getUserManager(); - synchronized (um) { - Authorizable authorizable = um.getAuthorizable(principalName); - if (authorizable == null) { - groupPrefixes: for (String groupPrefix : groupPrefixes) { - if (principalName.startsWith(groupPrefix)) { - authorizable = um.createGroup(principalName); - log.info("Created group " + principalName); - break groupPrefixes; - } - } - if (authorizable == null) - throw new ArgeoException("Authorizable " + principalName - + " not found"); - } - return authorizable.getPrincipal(); - } - } - - public void setGroupPrefixes(List groupsToCreate) { - this.groupPrefixes = groupsToCreate; - } -} diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitContainer.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitContainer.java deleted file mode 100644 index 9060b585a..000000000 --- a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitContainer.java +++ /dev/null @@ -1,352 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jackrabbit; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.HashSet; -import java.util.Map; -import java.util.Properties; -import java.util.Set; -import java.util.TreeSet; -import java.util.UUID; - -import javax.jcr.Node; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.jackrabbit.api.JackrabbitRepository; -import org.apache.jackrabbit.core.RepositoryImpl; -import org.apache.jackrabbit.core.config.RepositoryConfig; -import org.apache.jackrabbit.core.config.RepositoryConfigurationParser; -import org.argeo.ArgeoException; -import org.argeo.jcr.ArgeoNames; -import org.argeo.jcr.JcrUtils; -import org.argeo.jcr.MaintainedRepository; -import org.springframework.core.io.Resource; -import org.springframework.util.SystemPropertyUtils; -import org.xml.sax.InputSource; - -/** - * Wrapper around a Jackrabbit repository which allows to configure it in Spring - * and expose it as a {@link Repository}. - */ -public class JackrabbitContainer extends JackrabbitWrapper implements - MaintainedRepository { - private final static Log log = LogFactory.getLog(JackrabbitContainer.class); - - // local - private Resource configuration; - private Resource variables; - private RepositoryConfig repositoryConfig; - private File homeDirectory; - private Boolean inMemory = false; - - /** Migrations to execute (if not already done) */ - private Set dataModelMigrations = new HashSet(); - - /** - * Empty constructor, {@link #init()} should be called after properties have - * been set - */ - public JackrabbitContainer() { - } - - public void init() { - long begin = System.currentTimeMillis(); - - if (getRepository() != null) - throw new ArgeoException( - "Cannot be used to wrap another repository"); - Repository repository = createJackrabbitRepository(); - super.setRepository(repository); - - // migrate if needed - migrate(); - - // apply new CND files after migration - prepareDataModel(); - - double duration = ((double) (System.currentTimeMillis() - begin)) / 1000; - if (log.isDebugEnabled()) - log.debug("Initialized JCR repository wrapper in " + duration - + " s"); - } - - /** Actually creates the new repository. */ - protected Repository createJackrabbitRepository() { - long begin = System.currentTimeMillis(); - InputStream configurationIn = null; - Repository repository; - try { - // temporary - if (inMemory && getHomeDirectory().exists()) { - FileUtils.deleteDirectory(getHomeDirectory()); - log.warn("Deleted Jackrabbit home directory " - + getHomeDirectory()); - } - - // process configuration file - Properties vars = getConfigurationProperties(); - configurationIn = readConfiguration(); - vars.put(RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE, - getHomeDirectory().getCanonicalPath()); - repositoryConfig = RepositoryConfig.create(new InputSource( - configurationIn), vars); - - // - // Actual repository creation - // - repository = RepositoryImpl.create(repositoryConfig); - - double duration = ((double) (System.currentTimeMillis() - begin)) / 1000; - if (log.isTraceEnabled()) - log.trace("Created Jackrabbit repository in " + duration - + " s, home: " + getHomeDirectory()); - - return repository; - } catch (Exception e) { - throw new ArgeoException("Cannot create Jackrabbit repository " - + getHomeDirectory(), e); - } finally { - IOUtils.closeQuietly(configurationIn); - } - } - - /** Lazy init. */ - protected File getHomeDirectory() { - try { - if (homeDirectory == null) { - if (inMemory) { - homeDirectory = new File( - System.getProperty("java.io.tmpdir") - + File.separator - + System.getProperty("user.name") - + File.separator + "jackrabbit-" - + UUID.randomUUID()); - homeDirectory.mkdirs(); - // will it work if directory is not empty?? - homeDirectory.deleteOnExit(); - } - } - - return homeDirectory.getCanonicalFile(); - } catch (IOException e) { - throw new ArgeoException("Cannot get canonical file for " - + homeDirectory, e); - } - } - - /** Executes migrations, if needed. */ - protected void migrate() { - // No migration to perform - if (dataModelMigrations.size() == 0) - return; - - Boolean restartAndClearCaches = false; - - // migrate data - Session session = null; - try { - session = login(); - for (JackrabbitDataModelMigration dataModelMigration : new TreeSet( - dataModelMigrations)) { - if (dataModelMigration.migrate(session)) { - restartAndClearCaches = true; - } - } - } catch (ArgeoException e) { - throw e; - } catch (Exception e) { - throw new ArgeoException("Cannot migrate", e); - } finally { - JcrUtils.logoutQuietly(session); - } - - // restart repository - if (restartAndClearCaches) { - Repository repository = getRepository(); - if (repository instanceof RepositoryImpl) { - JackrabbitDataModelMigration - .clearRepositoryCaches(((RepositoryImpl) repository) - .getConfig()); - } - ((JackrabbitRepository) repository).shutdown(); - createJackrabbitRepository(); - } - - // set data model version - try { - session = login(); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot login to migrated repository", e); - } - - for (JackrabbitDataModelMigration dataModelMigration : new TreeSet( - dataModelMigrations)) { - try { - if (session.itemExists(dataModelMigration - .getDataModelNodePath())) { - Node dataModelNode = session.getNode(dataModelMigration - .getDataModelNodePath()); - dataModelNode.setProperty( - ArgeoNames.ARGEO_DATA_MODEL_VERSION, - dataModelMigration.getTargetVersion()); - session.save(); - } - } catch (Exception e) { - log.error("Cannot set model version", e); - } - } - JcrUtils.logoutQuietly(session); - - } - - /** Shutdown the repository */ - public void destroy() throws Exception { - Repository repository = getRepository(); - if (repository != null && repository instanceof RepositoryImpl) { - long begin = System.currentTimeMillis(); - ((RepositoryImpl) repository).shutdown(); - if (inMemory) - if (getHomeDirectory().exists()) { - FileUtils.deleteDirectory(getHomeDirectory()); - if (log.isDebugEnabled()) - log.debug("Deleted Jackrabbit home directory " - + getHomeDirectory()); - } - double duration = ((double) (System.currentTimeMillis() - begin)) / 1000; - log.info("Destroyed Jackrabbit repository in " + duration - + " s, home: " + getHomeDirectory()); - } - repository = null; - } - - public void dispose() { - throw new IllegalArgumentException( - "Call destroy() method instead of dispose()"); - } - - /* - * UTILITIES - */ - /** - * Reads the configuration which will initialize a {@link RepositoryConfig}. - */ - protected InputStream readConfiguration() { - try { - return configuration != null ? configuration.getInputStream() - : null; - } catch (IOException e) { - throw new ArgeoException("Cannot read Jackrabbit configuration " - + configuration, e); - } - } - - /** - * Reads the variables which will initialize a {@link Properties}. Returns - * null by default, to be overridden. - * - * @return a new stream or null if no variables available - */ - protected InputStream readVariables() { - try { - return variables != null ? variables.getInputStream() : null; - } catch (IOException e) { - throw new ArgeoException("Cannot read Jackrabbit variables " - + variables, e); - } - } - - /** - * Resolves ${} placeholders in the provided string. Based on system - * properties if no map is provided. - */ - protected String resolvePlaceholders(String string, - Map variables) { - return SystemPropertyUtils.resolvePlaceholders(string); - } - - /** Generates the properties to use in the configuration. */ - protected Properties getConfigurationProperties() { - InputStream propsIn = null; - Properties vars; - try { - vars = new Properties(); - propsIn = readVariables(); - if (propsIn != null) { - vars.load(propsIn); - } - // resolve system properties - for (Object key : vars.keySet()) { - // TODO: implement a smarter mechanism to resolve nested ${} - String newValue = resolvePlaceholders( - vars.getProperty(key.toString()), null); - vars.put(key, newValue); - } - // override with system properties - vars.putAll(System.getProperties()); - - if (log.isTraceEnabled()) { - log.trace("Jackrabbit config variables:"); - for (Object key : new TreeSet(vars.keySet())) - log.trace(key + "=" + vars.getProperty(key.toString())); - } - - } catch (IOException e) { - throw new ArgeoException("Cannot read configuration properties", e); - } finally { - IOUtils.closeQuietly(propsIn); - } - return vars; - } - - /* - * FIELDS ACCESS - */ - - public void setHomeDirectory(File homeDirectory) { - this.homeDirectory = homeDirectory; - } - - public void setInMemory(Boolean inMemory) { - this.inMemory = inMemory; - } - - public void setRepository(Repository repository) { - throw new ArgeoException("Cannot be used to wrap another repository"); - } - - public void setDataModelMigrations( - Set dataModelMigrations) { - this.dataModelMigrations = dataModelMigrations; - } - - public void setVariables(Resource variables) { - this.variables = variables; - } - - public void setConfiguration(Resource configuration) { - this.configuration = configuration; - } - -} diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitDataModelMigration.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitDataModelMigration.java deleted file mode 100644 index 401b34df6..000000000 --- a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitDataModelMigration.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jackrabbit; - -import java.io.InputStreamReader; -import java.io.Reader; - -import javax.jcr.Node; -import javax.jcr.Session; - -import org.apache.commons.io.IOUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.jackrabbit.commons.cnd.CndImporter; -import org.apache.jackrabbit.core.config.RepositoryConfig; -import org.argeo.ArgeoException; -import org.argeo.jcr.ArgeoNames; -import org.argeo.jcr.JcrCallback; -import org.argeo.jcr.JcrUtils; -import org.springframework.core.io.Resource; - -/** Migrate the data in a Jackrabbit repository. */ -public class JackrabbitDataModelMigration implements - Comparable { - private final static Log log = LogFactory - .getLog(JackrabbitDataModelMigration.class); - - private String dataModelNodePath; - private String targetVersion; - private Resource migrationCnd; - private JcrCallback dataModification; - - /** - * Expects an already started repository with the old data model to migrate. - * Expects to be run with admin rights (Repository.login() will be used). - * - * @return true if a migration was performed and the repository needs to be - * restarted and its caches cleared. - */ - public Boolean migrate(Session session) { - long begin = System.currentTimeMillis(); - Reader reader = null; - try { - // check if already migrated - if (!session.itemExists(dataModelNodePath)) { - log.warn("Node " + dataModelNodePath - + " does not exist: nothing to migrate."); - return false; - } - Node dataModelNode = session.getNode(dataModelNodePath); - if (dataModelNode.hasProperty(ArgeoNames.ARGEO_DATA_MODEL_VERSION)) { - String currentVersion = dataModelNode.getProperty( - ArgeoNames.ARGEO_DATA_MODEL_VERSION).getString(); - if (compareVersions(currentVersion, targetVersion) >= 0) { - log.info("Data model at version " + currentVersion - + ", no need to migrate."); - return false; - } - } - - // apply transitional CND - if (migrationCnd != null) { - reader = new InputStreamReader(migrationCnd.getInputStream()); - CndImporter.registerNodeTypes(reader, session, true); - session.save(); - log.info("Registered migration node types from " + migrationCnd); - } - - // modify data - dataModification.execute(session); - - // apply changes - session.save(); - - long duration = System.currentTimeMillis() - begin; - log.info("Migration of data model " + dataModelNodePath + " to " - + targetVersion + " performed in " + duration + "ms"); - return true; - } catch (Exception e) { - JcrUtils.discardQuietly(session); - throw new ArgeoException("Migration of data model " - + dataModelNodePath + " to " + targetVersion + " failed.", - e); - } finally { - JcrUtils.logoutQuietly(session); - IOUtils.closeQuietly(reader); - } - } - - protected static int compareVersions(String version1, String version2) { - // TODO do a proper version analysis and comparison - return version1.compareTo(version2); - } - - /** To be called on a stopped repository. */ - public static void clearRepositoryCaches(RepositoryConfig repositoryConfig) { - try { - String customeNodeTypesPath = "/nodetypes/custom_nodetypes.xml"; - repositoryConfig.getFileSystem().deleteFile(customeNodeTypesPath); - if (log.isDebugEnabled()) - log.debug("Cleared " + customeNodeTypesPath); - } catch (Exception e) { - throw new ArgeoException("Cannot clear caches", e); - } - - // File customNodeTypes = new File(home.getPath() - // + "/repository/nodetypes/custom_nodetypes.xml"); - // if (customNodeTypes.exists()) { - // customNodeTypes.delete(); - // if (log.isDebugEnabled()) - // log.debug("Cleared " + customNodeTypes); - // } else { - // log.warn("File " + customNodeTypes + " not found."); - // } - } - - /* - * FOR USE IN (SORTED) SETS - */ - - public int compareTo(JackrabbitDataModelMigration dataModelMigration) { - // TODO make ordering smarter - if (dataModelNodePath.equals(dataModelMigration.dataModelNodePath)) - return compareVersions(targetVersion, - dataModelMigration.targetVersion); - else - return dataModelNodePath - .compareTo(dataModelMigration.dataModelNodePath); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof JackrabbitDataModelMigration)) - return false; - JackrabbitDataModelMigration dataModelMigration = (JackrabbitDataModelMigration) obj; - return dataModelNodePath.equals(dataModelMigration.dataModelNodePath) - && targetVersion.equals(dataModelMigration.targetVersion); - } - - @Override - public int hashCode() { - return targetVersion.hashCode(); - } - - public void setDataModelNodePath(String dataModelNodePath) { - this.dataModelNodePath = dataModelNodePath; - } - - public void setTargetVersion(String targetVersion) { - this.targetVersion = targetVersion; - } - - public void setMigrationCnd(Resource migrationCnd) { - this.migrationCnd = migrationCnd; - } - - public void setDataModification(JcrCallback dataModification) { - this.dataModification = dataModification; - } - - public String getDataModelNodePath() { - return dataModelNodePath; - } - - public String getTargetVersion() { - return targetVersion; - } - -} diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitRepositoryFactory.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitRepositoryFactory.java deleted file mode 100644 index d64bb5e68..000000000 --- a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitRepositoryFactory.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jackrabbit; - -import java.io.File; -import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; - -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.RepositoryFactory; -import javax.jcr.Session; - -import org.apache.commons.io.IOUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.jackrabbit.commons.JcrUtils; -import org.apache.jackrabbit.core.RepositoryImpl; -import org.apache.jackrabbit.core.config.RepositoryConfig; -import org.apache.jackrabbit.core.config.RepositoryConfigurationParser; -import org.apache.jackrabbit.jcr2dav.Jcr2davRepositoryFactory; -import org.argeo.ArgeoException; -import org.argeo.jcr.ArgeoJcrConstants; -import org.argeo.jcr.DefaultRepositoryFactory; -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.Resource; -import org.xml.sax.InputSource; - -/** - * Repository factory which can create new repositories and access remote - * Jackrabbit repositories - */ -public class JackrabbitRepositoryFactory extends DefaultRepositoryFactory - implements RepositoryFactory, ArgeoJcrConstants { - - private final static Log log = LogFactory - .getLog(JackrabbitRepositoryFactory.class); - - private Resource fileRepositoryConfiguration = new ClassPathResource( - "/org/argeo/jackrabbit/repository-h2.xml"); - - @SuppressWarnings({ "rawtypes", "unchecked" }) - public Repository getRepository(Map parameters) throws RepositoryException { - // check if can be found by alias - Repository repository = super.getRepository(parameters); - if (repository != null) - return repository; - - // check if remote - String uri = null; - if (parameters.containsKey(JCR_REPOSITORY_URI)) - uri = parameters.get(JCR_REPOSITORY_URI).toString(); - else if (parameters.containsKey(JcrUtils.REPOSITORY_URI)) - uri = parameters.get(JcrUtils.REPOSITORY_URI).toString(); - - if (uri != null) { - if (uri.startsWith("http"))// http, https - repository = createRemoteRepository(uri); - else if (uri.startsWith("file"))// http, https - repository = createFileRepository(uri, parameters); - else if (uri.startsWith("vm")) { - log.warn("URI " - + uri - + " should have been managed by generic JCR repository factory"); - repository = getRepositoryByAlias(getAliasFromURI(uri)); - } - } - - // publish under alias - if (parameters.containsKey(JCR_REPOSITORY_ALIAS)) { - Properties properties = new Properties(); - properties.putAll(parameters); - String alias = parameters.get(JCR_REPOSITORY_ALIAS).toString(); - publish(alias, repository, properties); - log.info("Registered JCR repository under alias '" + alias - + "' with properties " + properties); - } - - return repository; - } - - protected Repository createRemoteRepository(String uri) - throws RepositoryException { - Map params = new HashMap(); - params.put(JcrUtils.REPOSITORY_URI, uri); - Repository repository = new Jcr2davRepositoryFactory() - .getRepository(params); - if (repository == null) - throw new ArgeoException("Remote Davex repository " + uri - + " not found"); - log.info("Initialized remote Jackrabbit repository from uri " + uri); - return repository; - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - protected Repository createFileRepository(final String uri, Map parameters) - throws RepositoryException { - InputStream configurationIn = null; - try { - Properties vars = new Properties(); - vars.putAll(parameters); - String dirPath = uri.substring("file:".length()); - File homeDir = new File(dirPath); - if (homeDir.exists() && !homeDir.isDirectory()) - throw new ArgeoException("Repository home " + dirPath - + " is not a directory"); - if (!homeDir.exists()) - homeDir.mkdirs(); - configurationIn = fileRepositoryConfiguration.getInputStream(); - vars.put(RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE, - homeDir.getCanonicalPath()); - RepositoryConfig repositoryConfig = RepositoryConfig.create( - new InputSource(configurationIn), vars); - - // TransientRepository repository = new - // TransientRepository(repositoryConfig); - final RepositoryImpl repository = RepositoryImpl - .create(repositoryConfig); - Session session = repository.login(); - // FIXME make it generic - org.argeo.jcr.JcrUtils.addPrivilege(session, "/", "ROLE_ADMIN", - "jcr:all"); - org.argeo.jcr.JcrUtils.logoutQuietly(session); - Runtime.getRuntime().addShutdownHook( - new Thread("Clean JCR repository " + uri) { - public void run() { - repository.shutdown(); - log.info("Destroyed repository " + uri); - } - }); - log.info("Initialized file Jackrabbit repository from uri " + uri); - return repository; - } catch (Exception e) { - throw new ArgeoException("Cannot create repository " + uri, e); - } finally { - IOUtils.closeQuietly(configurationIn); - } - } - - /** - * Called after the repository has been initialised. Does nothing by - * default. - */ - @SuppressWarnings("rawtypes") - protected void postInitialization(Repository repository, Map parameters) { - - } - - public void setFileRepositoryConfiguration( - Resource fileRepositoryConfiguration) { - this.fileRepositoryConfiguration = fileRepositoryConfiguration; - } - -} diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitWrapper.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitWrapper.java deleted file mode 100644 index f9f04c4cb..000000000 --- a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitWrapper.java +++ /dev/null @@ -1,375 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jackrabbit; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.net.URL; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.jcr.Credentials; -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.Repository; -import javax.jcr.Session; -import javax.jcr.nodetype.NodeType; - -import org.apache.commons.io.FilenameUtils; -import org.apache.commons.io.IOUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.jackrabbit.commons.NamespaceHelper; -import org.apache.jackrabbit.commons.cnd.CndImporter; -import org.argeo.ArgeoException; -import org.argeo.jcr.ArgeoJcrConstants; -import org.argeo.jcr.ArgeoNames; -import org.argeo.jcr.ArgeoTypes; -import org.argeo.jcr.JcrRepositoryWrapper; -import org.argeo.jcr.JcrUtils; -import org.argeo.util.security.DigestUtils; -import org.osgi.framework.Bundle; -import org.osgi.framework.BundleContext; -import org.osgi.framework.ServiceReference; -import org.osgi.service.packageadmin.ExportedPackage; -import org.osgi.service.packageadmin.PackageAdmin; -import org.springframework.context.ResourceLoaderAware; -import org.springframework.core.io.Resource; -import org.springframework.core.io.ResourceLoader; - -/** - * Wrapper around a Jackrabbit repository which allows to simplify configuration - * and intercept some actions. It exposes itself as a {@link Repository}. - */ -public class JackrabbitWrapper extends JcrRepositoryWrapper implements - ResourceLoaderAware { - private final static Log log = LogFactory.getLog(JackrabbitWrapper.class); - private final static String DIGEST_ALGORITHM = "MD5"; - - // local - private ResourceLoader resourceLoader; - - // data model - /** Node type definitions in CND format */ - private List cndFiles = new ArrayList(); - /** - * Always import CNDs. Useful during development of new data models. In - * production, explicit migration processes should be used. - */ - private Boolean forceCndImport = true; - - /** Namespaces to register: key is prefix, value namespace */ - private Map namespaces = new HashMap(); - - private BundleContext bundleContext; - - /** - * Explicitly set admin credentials used in initialization. Useful for - * testing, in real applications authentication is rather dealt with - * externally - */ - private Credentials adminCredentials = null; - - /** - * Empty constructor, {@link #init()} should be called after properties have - * been set - */ - public JackrabbitWrapper() { - } - - @Override - public void init() { - prepareDataModel(); - } - - /* - * DATA MODEL - */ - - /** - * Import declared node type definitions and register namespaces. Tries to - * update the node definitions if they have changed. In case of failures an - * error will be logged but no exception will be thrown. - */ - protected void prepareDataModel() { - if ((cndFiles == null || cndFiles.size() == 0) - && (namespaces == null || namespaces.size() == 0)) - return; - - Session session = null; - try { - session = login(adminCredentials); - // register namespaces - if (namespaces.size() > 0) { - NamespaceHelper namespaceHelper = new NamespaceHelper(session); - namespaceHelper.registerNamespaces(namespaces); - } - - // load CND files from classpath or as URL - for (String resUrl : cndFiles) { - processCndFile(session, resUrl); - } - } catch (Exception e) { - JcrUtils.discardQuietly(session); - throw new ArgeoException("Cannot import node type definitions " - + cndFiles, e); - } finally { - JcrUtils.logoutQuietly(session); - } - - } - - protected void processCndFile(Session session, String resUrl) { - Reader reader = null; - try { - // check existing data model nodes - new NamespaceHelper(session).registerNamespace(ArgeoNames.ARGEO, - ArgeoNames.ARGEO_NAMESPACE); - if (!session.itemExists(ArgeoJcrConstants.DATA_MODELS_BASE_PATH)) - JcrUtils.mkdirs(session, - ArgeoJcrConstants.DATA_MODELS_BASE_PATH); - Node dataModels = session - .getNode(ArgeoJcrConstants.DATA_MODELS_BASE_PATH); - NodeIterator it = dataModels.getNodes(); - Node dataModel = null; - while (it.hasNext()) { - Node node = it.nextNode(); - if (node.getProperty(ArgeoNames.ARGEO_URI).getString() - .equals(resUrl)) { - dataModel = node; - break; - } - } - - byte[] cndContent = readCndContent(resUrl); - String newDigest = DigestUtils.digest(DIGEST_ALGORITHM, cndContent); - Bundle bundle = findDataModelBundle(resUrl); - - String currentVersion = null; - if (dataModel != null) { - currentVersion = dataModel.getProperty( - ArgeoNames.ARGEO_DATA_MODEL_VERSION).getString(); - if (dataModel.hasNode(Node.JCR_CONTENT)) { - String oldDigest = JcrUtils.checksumFile(dataModel, - DIGEST_ALGORITHM); - if (oldDigest.equals(newDigest)) { - if (log.isDebugEnabled()) - log.debug("Data model " + resUrl - + " hasn't changed, keeping version " - + currentVersion); - return; - } - } - } - - if (dataModel != null && !forceCndImport) { - log.info("Data model " - + resUrl - + " has changed since version " - + currentVersion - + (bundle != null ? ": version " + bundle.getVersion() - + ", bundle " + bundle.getSymbolicName() : "")); - return; - } - - reader = new InputStreamReader(new ByteArrayInputStream(cndContent)); - // actually imports the CND - try { - CndImporter.registerNodeTypes(reader, session, true); - } catch (Exception e) { - log.error("Cannot import data model " + resUrl, e); - return; - } - - if (dataModel != null && !dataModel.isNodeType(NodeType.NT_FILE)) { - dataModel.remove(); - dataModel = null; - } - - // FIXME: what if argeo.cnd would not be the first called on - // a new repo? argeo:dataModel would not be found - String fileName = FilenameUtils.getName(resUrl); - if (dataModel == null) { - dataModel = dataModels.addNode(fileName, NodeType.NT_FILE); - dataModel.addNode(Node.JCR_CONTENT, NodeType.NT_RESOURCE); - dataModel.addMixin(ArgeoTypes.ARGEO_DATA_MODEL); - dataModel.setProperty(ArgeoNames.ARGEO_URI, resUrl); - } else { - session.getWorkspace().getVersionManager() - .checkout(dataModel.getPath()); - } - if (bundle != null) - dataModel.setProperty(ArgeoNames.ARGEO_DATA_MODEL_VERSION, - bundle.getVersion().toString()); - else - dataModel.setProperty(ArgeoNames.ARGEO_DATA_MODEL_VERSION, - "0.0.0"); - JcrUtils.copyBytesAsFile(dataModel.getParent(), fileName, - cndContent); - JcrUtils.updateLastModified(dataModel); - session.save(); - session.getWorkspace().getVersionManager() - .checkin(dataModel.getPath()); - - if (currentVersion == null) - log.info("Data model " - + resUrl - + (bundle != null ? ", version " + bundle.getVersion() - + ", bundle " + bundle.getSymbolicName() : "")); - else - log.info("Data model " - + resUrl - + " updated from version " - + currentVersion - + (bundle != null ? ", version " + bundle.getVersion() - + ", bundle " + bundle.getSymbolicName() : "")); - } catch (Exception e) { - throw new ArgeoException("Cannot process data model " + resUrl, e); - } finally { - IOUtils.closeQuietly(reader); - } - } - - protected byte[] readCndContent(String resUrl) { - InputStream in = null; - try { - boolean classpath; - // normalize URL - if (bundleContext != null && resUrl.startsWith("classpath:")) { - resUrl = resUrl.substring("classpath:".length()); - classpath = true; - } else if (resUrl.indexOf(':') < 0) { - if (!resUrl.startsWith("/")) { - resUrl = "/" + resUrl; - log.warn("Classpath should start with '/'"); - } - classpath = true; - } else { - classpath = false; - } - - URL url = null; - if (classpath) { - if (bundleContext != null) { - Bundle currentBundle = bundleContext.getBundle(); - url = currentBundle.getResource(resUrl); - } else { - resUrl = "classpath:" + resUrl; - url = null; - } - } else if (!resUrl.startsWith("classpath:")) { - url = new URL(resUrl); - } - - if (url != null) { - in = url.openStream(); - } else if (resourceLoader != null) { - Resource res = resourceLoader.getResource(resUrl); - in = res.getInputStream(); - url = res.getURL(); - } else { - throw new ArgeoException("No " + resUrl + " in the classpath," - + " make sure the containing" + " package is visible."); - } - - return IOUtils.toByteArray(in); - } catch (Exception e) { - throw new ArgeoException("Cannot read CND from " + resUrl, e); - } finally { - IOUtils.closeQuietly(in); - } - } - - /* - * REPOSITORY INTERCEPTOR - */ - - /* - * UTILITIES - */ - /** Find which OSGi bundle provided the data model resource */ - protected Bundle findDataModelBundle(String resUrl) { - if (bundleContext == null) - return null; - - if (resUrl.startsWith("/")) - resUrl = resUrl.substring(1); - String pkg = resUrl.substring(0, resUrl.lastIndexOf('/')).replace('/', - '.'); - ServiceReference paSr = bundleContext - .getServiceReference(PackageAdmin.class.getName()); - PackageAdmin packageAdmin = (PackageAdmin) bundleContext - .getService(paSr); - - // find exported package - ExportedPackage exportedPackage = null; - ExportedPackage[] exportedPackages = packageAdmin - .getExportedPackages(pkg); - if (exportedPackages == null) - throw new ArgeoException("No exported package found for " + pkg); - for (ExportedPackage ep : exportedPackages) { - for (Bundle b : ep.getImportingBundles()) { - if (b.getBundleId() == bundleContext.getBundle().getBundleId()) { - exportedPackage = ep; - break; - } - } - } - - Bundle exportingBundle = null; - if (exportedPackage != null) { - exportingBundle = exportedPackage.getExportingBundle(); - } else { - // assume this is in the same bundle - exportingBundle = bundleContext.getBundle(); -// throw new ArgeoException("No OSGi exporting package found for " -// + resUrl); - } - return exportingBundle; - } - - /* - * FIELDS ACCESS - */ - public void setNamespaces(Map namespaces) { - this.namespaces = namespaces; - } - - public void setCndFiles(List cndFiles) { - this.cndFiles = cndFiles; - } - - public void setBundleContext(BundleContext bundleContext) { - this.bundleContext = bundleContext; - } - - public void setForceCndImport(Boolean forceCndUpdate) { - this.forceCndImport = forceCndUpdate; - } - - public void setResourceLoader(ResourceLoader resourceLoader) { - this.resourceLoader = resourceLoader; - } - - public void setAdminCredentials(Credentials adminCredentials) { - this.adminCredentials = adminCredentials; - } - -} diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/OsgiJackrabbitRepositoryFactory.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/OsgiJackrabbitRepositoryFactory.java deleted file mode 100644 index b28699e60..000000000 --- a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/OsgiJackrabbitRepositoryFactory.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jackrabbit; - -import java.util.Hashtable; -import java.util.Properties; - -import javax.jcr.Repository; - -import org.osgi.framework.BundleContext; - -/** - * OSGi-aware Jackrabbit repository factory which can retrieve/publish - * {@link Repository} as OSGi services. - */ -public class OsgiJackrabbitRepositoryFactory extends - JackrabbitRepositoryFactory { - private BundleContext bundleContext; - - protected void publish(String alias, Repository repository, - Properties properties) { - if (bundleContext != null) { - // do not modify reference - Hashtable props = new Hashtable(); - props.putAll(props); - props.put(JCR_REPOSITORY_ALIAS, alias); - bundleContext.registerService(Repository.class.getName(), - repository, props); - } - } - - public void setBundleContext(BundleContext bundleContext) { - this.bundleContext = bundleContext; - } - -} diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/AbstractJackrabbitHandlerMapping.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/AbstractJackrabbitHandlerMapping.java deleted file mode 100644 index 99bfab4e8..000000000 --- a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/AbstractJackrabbitHandlerMapping.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jackrabbit.remote; - -import org.apache.jackrabbit.server.SessionProvider; -import org.argeo.jcr.mvc.MultipleRepositoryHandlerMapping; - -/** Base class for Jackrabbit handler mappings. */ -public abstract class AbstractJackrabbitHandlerMapping extends - MultipleRepositoryHandlerMapping { - private SessionProvider sessionProvider; - - protected SessionProvider getSessionProvider() { - return sessionProvider; - } - - public void setSessionProvider(SessionProvider sessionProvider) { - this.sessionProvider = sessionProvider; - } - -} diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/ExtendedDispatcherServlet.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/ExtendedDispatcherServlet.java deleted file mode 100644 index 14b6e9989..000000000 --- a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/ExtendedDispatcherServlet.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jackrabbit.remote; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.ArgeoException; -import org.springframework.web.servlet.DispatcherServlet; - -/** - * Overrides Spring {@link DispatcherServlet}, see - * http://forum.springsource.org/showthread.php?t=53472. - */ -public class ExtendedDispatcherServlet extends DispatcherServlet { - private static final long serialVersionUID = -5584673209855752009L; - - private final static Log log = LogFactory - .getLog(ExtendedDispatcherServlet.class); - - protected void service(HttpServletRequest request, - HttpServletResponse response) throws ServletException, - java.io.IOException { - try { - if (log.isTraceEnabled()) { - log.trace("SessionID = " + request.getSession().getId()); - log.trace(" ContextPath = " + request.getContextPath()); - log.trace(" ServletPath = " + request.getServletPath()); - log.trace(" PathInfo = " + request.getPathInfo()); - log.trace(" Method = " + request.getMethod()); - log.trace(" User-Agent = " + request.getHeader("User-Agent")); - } - doService(request, response); - } catch (Exception e) { - throw new ArgeoException("Cannot process request", e); - } - } - -} diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/IOHandlerWrapper.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/IOHandlerWrapper.java deleted file mode 100644 index daf2ecb2b..000000000 --- a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/IOHandlerWrapper.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jackrabbit.remote; - -import java.io.IOException; - -import org.apache.jackrabbit.server.io.ExportContext; -import org.apache.jackrabbit.server.io.IOHandler; -import org.apache.jackrabbit.server.io.IOManager; -import org.apache.jackrabbit.server.io.ImportContext; -import org.apache.jackrabbit.webdav.DavResource; -import org.argeo.ArgeoException; - -/** Wraps an IOHandler so that it can be injected a posteriori */ -public class IOHandlerWrapper implements IOHandler { - private IOManager ioManager = null; - private IOHandler ioHandler = null; - - public void setIOHandler(IOHandler ioHandler) { - if ((this.ioHandler != null) && (ioHandler != null)) - throw new ArgeoException( - "There is already an IO Handler registered"); - this.ioHandler = ioHandler; - if (ioManager != null && this.ioHandler != null) - ioHandler.setIOManager(ioManager); - } - - public IOHandler getIOHandler() { - return ioHandler; - } - - public IOManager getIOManager() { - return ioManager; - } - - public void setIOManager(IOManager ioManager) { - this.ioManager = ioManager; - if (ioHandler != null) - ioHandler.setIOManager(ioManager); - } - - public String getName() { - if (ioHandler != null) - return ioHandler.getName(); - else - return "Empty IOHandler Wrapper"; - } - - public boolean canImport(ImportContext context, boolean isCollection) { - if (ioHandler != null) - return ioHandler.canImport(context, isCollection); - return false; - } - - public boolean canImport(ImportContext context, DavResource resource) { - if (ioHandler != null) - return ioHandler.canImport(context, resource); - return false; - } - - public boolean importContent(ImportContext context, boolean isCollection) - throws IOException { - if (ioHandler != null) - ioHandler.importContent(context, isCollection); - return false; - } - - public boolean importContent(ImportContext context, DavResource resource) - throws IOException { - if (ioHandler != null) - ioHandler.importContent(context, resource); - return false; - } - - public boolean canExport(ExportContext context, boolean isCollection) { - if (ioHandler != null) - ioHandler.canExport(context, isCollection); - return false; - } - - public boolean canExport(ExportContext context, DavResource resource) { - if (ioHandler != null) - ioHandler.canExport(context, resource); - return false; - } - - public boolean exportContent(ExportContext context, boolean isCollection) - throws IOException { - if (ioHandler != null) - ioHandler.exportContent(context, isCollection); - return false; - } - - public boolean exportContent(ExportContext context, DavResource resource) - throws IOException { - if (ioHandler != null) - ioHandler.exportContent(context, resource); - return false; - } - -} diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/IOManagerBean.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/IOManagerBean.java deleted file mode 100644 index 82a76738b..000000000 --- a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/IOManagerBean.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jackrabbit.remote; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import org.apache.jackrabbit.server.io.ExportContext; -import org.apache.jackrabbit.server.io.IOHandler; -import org.apache.jackrabbit.server.io.IOManager; -import org.apache.jackrabbit.server.io.ImportContext; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.tika.detect.Detector; - -/** {@link IOManager} that can easily be configured as a bean. */ -public class IOManagerBean implements IOManager { - private Detector detector = null; - private List ioHandlers = new ArrayList(); - - public boolean importContent(ImportContext context, boolean isCollection) - throws IOException { - // TODO Auto-generated method stub - return false; - } - - public boolean importContent(ImportContext context, DavResource resource) - throws IOException { - // TODO Auto-generated method stub - return false; - } - - public boolean exportContent(ExportContext context, boolean isCollection) - throws IOException { - // TODO Auto-generated method stub - return false; - } - - public boolean exportContent(ExportContext context, DavResource resource) - throws IOException { - // TODO Auto-generated method stub - return false; - } - - public synchronized void addIOHandler(IOHandler ioHandler) { - ioHandlers.add(ioHandler); - } - - public synchronized IOHandler[] getIOHandlers() { - return ioHandlers.toArray(new IOHandler[ioHandlers.size()]); - } - - public Detector getDetector() { - return detector; - } - - public void setDetector(Detector detector) { - this.detector = detector; - } - - public synchronized List getIoHandlers() { - return ioHandlers; - } - - public synchronized void setIoHandlers(List ioHandlers) { - this.ioHandlers = ioHandlers; - } - -} diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/JcrRemotingHandlerMapping.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/JcrRemotingHandlerMapping.java deleted file mode 100644 index caea5fc8b..000000000 --- a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/JcrRemotingHandlerMapping.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jackrabbit.remote; - -import java.util.Properties; - -import javax.jcr.Repository; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; - -public class JcrRemotingHandlerMapping extends AbstractJackrabbitHandlerMapping { - - protected HttpServlet createServlet(Repository repository, String pathPrefix) - throws ServletException { - JcrRemotingServlet servlet = new JcrRemotingServlet(repository, - getSessionProvider()); - Properties initParameters = new Properties(); - initParameters.setProperty( - JcrRemotingServlet.INIT_PARAM_RESOURCE_PATH_PREFIX, pathPrefix); - servlet.init(new DelegatingServletConfig(pathPrefix.replace('/', '_'), - initParameters)); - return servlet; - } -} diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/JcrRemotingServlet.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/JcrRemotingServlet.java deleted file mode 100644 index b3f079745..000000000 --- a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/JcrRemotingServlet.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jackrabbit.remote; - -import javax.jcr.Repository; - -import org.apache.jackrabbit.server.SessionProvider; - -public class JcrRemotingServlet extends - org.apache.jackrabbit.server.remoting.davex.JcrRemotingServlet { - - private static final long serialVersionUID = 3131835511468341309L; - - private final Repository repository; - private final SessionProvider sessionProvider; - - public JcrRemotingServlet(Repository repository, - SessionProvider sessionProvider) { - this.repository = repository; - this.sessionProvider = sessionProvider; - } - - @Override - protected Repository getRepository() { - return repository; - } - - @Override - protected SessionProvider getSessionProvider() { - return sessionProvider; - } - -} diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/OpenInViewSessionProvider.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/OpenInViewSessionProvider.java deleted file mode 100644 index b4d1d6021..000000000 --- a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/OpenInViewSessionProvider.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jackrabbit.remote; - -import java.io.Serializable; - -import javax.jcr.LoginException; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.jackrabbit.server.SessionProvider; -import org.argeo.jcr.JcrUtils; - -/** - * Implements an open session in view patter: a new JCR session is created for - * each request - */ -public class OpenInViewSessionProvider implements SessionProvider, Serializable { - private static final long serialVersionUID = 2270957712453841368L; - - private final static Log log = LogFactory - .getLog(OpenInViewSessionProvider.class); - - public Session getSession(HttpServletRequest request, Repository rep, - String workspace) throws LoginException, ServletException, - RepositoryException { - return login(request, rep, workspace); - } - - protected Session login(HttpServletRequest request, Repository repository, - String workspace) throws RepositoryException { - if (log.isTraceEnabled()) - log.trace("Login to workspace " - + (workspace == null ? "" : workspace) - + " in web session " + request.getSession().getId()); - return repository.login(workspace); - } - - public void releaseSession(Session session) { - JcrUtils.logoutQuietly(session); - if (log.isTraceEnabled()) - log.trace("Logged out remote JCR session " + session); - } - - public void init() { - } - - public void destroy() { - } - -} diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/ScopedSessionProvider.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/ScopedSessionProvider.java deleted file mode 100644 index ffe6df9b1..000000000 --- a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/ScopedSessionProvider.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jackrabbit.remote; - -import java.io.Serializable; - -import javax.jcr.LoginException; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.jackrabbit.server.SessionProvider; -import org.argeo.ArgeoException; -import org.argeo.jcr.ArgeoJcrConstants; -import org.argeo.jcr.JcrUtils; -import org.springframework.security.Authentication; -import org.springframework.security.context.SecurityContextHolder; - -/** - * Session provider assuming a single workspace and a short life cycle, - * typically a Spring bean of scope (web) 'session'. - */ -public class ScopedSessionProvider implements SessionProvider, Serializable { - private static final long serialVersionUID = 6589775984177317058L; - private static final Log log = LogFactory - .getLog(ScopedSessionProvider.class); - private transient HttpSession httpSession = null; - private transient Session jcrSession = null; - - private transient String currentRepositoryName = null; - private transient String currentWorkspaceName = null; - private transient String currentJcrUser = null; - - // private transient String anonymousUserId = "anonymous"; - - public Session getSession(HttpServletRequest request, Repository rep, - String workspace) throws LoginException, ServletException, - RepositoryException { - - Authentication authentication = SecurityContextHolder.getContext() - .getAuthentication(); - if (authentication == null) - throw new ArgeoException( - "Request not authenticated by Spring Security"); - String springUser = authentication.getName(); - - // HTTP - String requestJcrRepository = (String) request - .getAttribute(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS); - - // HTTP session - if (httpSession != null - && !httpSession.getId().equals(request.getSession().getId())) - throw new ArgeoException( - "Only session scope is supported in this mode"); - if (httpSession == null) - httpSession = request.getSession(); - - // Initializes current values - if (currentRepositoryName == null) - currentRepositoryName = requestJcrRepository; - if (currentWorkspaceName == null) - currentWorkspaceName = workspace; - if (currentJcrUser == null) - currentJcrUser = springUser; - - // logout if there was a change in session coordinates - if (jcrSession != null) - if (!currentRepositoryName.equals(requestJcrRepository)) { - if (log.isDebugEnabled()) - log.debug(getHttpSessionId() + " Changed from repository '" - + currentRepositoryName + "' to '" - + requestJcrRepository - + "', logging out cached JCR session."); - logout(); - } else if (!currentWorkspaceName.equals(workspace)) { - if (log.isDebugEnabled()) - log.debug(getHttpSessionId() + " Changed from workspace '" - + currentWorkspaceName + "' to '" + workspace - + "', logging out cached JCR session."); - logout(); - } else if (!currentJcrUser.equals(springUser)) { - if (log.isDebugEnabled()) - log.debug(getHttpSessionId() + " Changed from user '" - + currentJcrUser + "' to '" + springUser - + "', logging out cached JCR session."); - logout(); - } - - // login if needed - if (jcrSession == null) - try { - Session session = login(rep, workspace); - if (!session.getUserID().equals(springUser)) { - JcrUtils.logoutQuietly(session); - throw new ArgeoException("Spring Security user '" - + springUser + "' not in line with JCR user '" - + session.getUserID() + "'"); - } - currentRepositoryName = requestJcrRepository; - // do not use workspace variable which may be null - currentWorkspaceName = session.getWorkspace().getName(); - currentJcrUser = session.getUserID(); - - jcrSession = session; - return jcrSession; - } catch (RepositoryException e) { - throw new ArgeoException("Cannot open session to workspace " - + workspace, e); - } - - // returns cached session - return jcrSession; - } - - protected Session login(Repository repository, String workspace) - throws RepositoryException { - Session session = repository.login(workspace); - if (log.isDebugEnabled()) - log.debug(getHttpSessionId() + " User '" + session.getUserID() - + "' logged in workspace '" - + session.getWorkspace().getName() + "' of repository '" - + currentRepositoryName + "'"); - return session; - } - - public void releaseSession(Session session) { - if (log.isTraceEnabled()) - log.trace(getHttpSessionId() + " Releasing JCR session " + session); - } - - protected void logout() { - JcrUtils.logoutQuietly(jcrSession); - jcrSession = null; - } - - protected final String getHttpSessionId() { - return httpSession != null ? httpSession.getId() : ""; - } - - public void init() { - } - - public void destroy() { - logout(); - if (getHttpSessionId() != null) - if (log.isDebugEnabled()) - log.debug(getHttpSessionId() - + " Cleaned up provider for web session "); - httpSession = null; - } - -} diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/SimpleSessionProvider.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/SimpleSessionProvider.java deleted file mode 100644 index 1d438d504..000000000 --- a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/SimpleSessionProvider.java +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jackrabbit.remote; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import javax.jcr.LoginException; -import javax.jcr.Node; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.Value; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.jackrabbit.api.JackrabbitSession; -import org.apache.jackrabbit.api.security.user.Group; -import org.apache.jackrabbit.api.security.user.User; -import org.apache.jackrabbit.api.security.user.UserManager; -import org.apache.jackrabbit.server.SessionProvider; -import org.argeo.ArgeoException; -import org.argeo.jcr.ArgeoNames; -import org.argeo.jcr.JcrUtils; -import org.argeo.jcr.UserJcrUtils; - -/** - * Implements an open session in view patter: a new JCR session is created for - * each request - * - * @deprecated use {@link ScopedSessionProvider} or - * {@link OpenInViewSessionProvider} - */ -@Deprecated -public class SimpleSessionProvider implements SessionProvider, Serializable { - private static final long serialVersionUID = 2270957712453841368L; - - private final static Log log = LogFactory - .getLog(SimpleSessionProvider.class); - - private transient Map sessions; - - private Boolean openSessionInView = true; - - private String defaultWorkspace = "default"; - - private String webSessionId = null; - - public Session getSession(HttpServletRequest request, Repository rep, - String workspace) throws LoginException, ServletException, - RepositoryException { - - if (openSessionInView) { - JackrabbitSession session = (JackrabbitSession) login(request, rep, - workspace); - if (session.getWorkspace().getName().equals(defaultWorkspace)) - writeRemoteRoles(session); - return session; - } else { - if (webSessionId != null - && !webSessionId.equals(request.getSession().getId())) - throw new ArgeoException( - "Only session scope is supported in this mode"); - webSessionId = request.getSession().getId(); - - // since sessions is transient it can't be restored from the session - if (sessions == null) - sessions = Collections - .synchronizedMap(new HashMap()); - - if (!sessions.containsKey(workspace)) { - try { - // JackrabbitSession session = (JackrabbitSession) - // rep.login( - // null, workspace); - JackrabbitSession session = (JackrabbitSession) login( - request, rep, workspace); - if (session.getWorkspace().getName() - .equals(defaultWorkspace)) - writeRemoteRoles(session); - if (log.isTraceEnabled()) - log.trace("User " + session.getUserID() - + " logged into " + request.getServletPath()); - sessions.put(workspace, session); - return session; - } catch (Exception e) { - throw new ArgeoException("Cannot open session", e); - } - } else { - Session session = sessions.get(workspace); - if (!session.isLive()) { - sessions.remove(workspace); - session = login(request, rep, workspace); - sessions.put(workspace, session); - } - return session; - } - } - } - - protected Session login(HttpServletRequest request, Repository repository, - String workspace) throws RepositoryException { - if (log.isDebugEnabled()) - log.debug("Login to workspace " - + (workspace == null ? "" : workspace) - + " in web session " + request.getSession().getId()); - return repository.login(workspace); - } - - protected void writeRemoteRoles(JackrabbitSession session) - throws RepositoryException { - // FIXME better deal w/ non node repo - - // retrieve roles - String userId = session.getUserID(); - UserManager userManager = session.getUserManager(); - User user = (User) userManager.getAuthorizable(userId); - if (user == null) { - // anonymous - return; - } - List userGroupIds = new ArrayList(); - if (user != null) - for (Iterator it = user.memberOf(); it.hasNext();) - userGroupIds.add(it.next().getID()); - - // write roles if needed - Node userHome = UserJcrUtils.getUserHome(session); - boolean writeRoles = false; - if (userHome.hasProperty(ArgeoNames.ARGEO_REMOTE_ROLES)) { - Value[] roles = userHome.getProperty(ArgeoNames.ARGEO_REMOTE_ROLES) - .getValues(); - if (roles.length != userGroupIds.size()) - writeRoles = true; - else - for (int i = 0; i < roles.length; i++) - if (!roles[i].getString().equals(userGroupIds.get(i))) - writeRoles = true; - } else - writeRoles = true; - - if (writeRoles) { - session.getWorkspace().getVersionManager() - .checkout(userHome.getPath()); - String[] roleIds = userGroupIds.toArray(new String[userGroupIds - .size()]); - userHome.setProperty(ArgeoNames.ARGEO_REMOTE_ROLES, roleIds); - JcrUtils.updateLastModified(userHome); - session.save(); - session.getWorkspace().getVersionManager() - .checkin(userHome.getPath()); - } - - } - - public void releaseSession(Session session) { - if (log.isTraceEnabled()) - log.trace("Releasing JCR session " + session); - if (openSessionInView) { - JcrUtils.logoutQuietly(session); - if (log.isDebugEnabled()) - log.debug("Logged out remote JCR session " + session); - } - } - - public void init() { - if (log.isDebugEnabled()) - log.debug("Init session provider for web session " + webSessionId); - } - - public void destroy() { - if (log.isDebugEnabled()) - log.debug("Destroy session provider for web session " - + webSessionId); - - if (sessions != null) - for (String workspace : sessions.keySet()) { - Session session = sessions.get(workspace); - JcrUtils.logoutQuietly(session); - } - } - - /** - * If set to true a new session will be created each time (the default), - * otherwise a single session is cached by workspace and the object should - * be of scope session (not supported) - */ - public void setOpenSessionInView(Boolean openSessionInView) { - this.openSessionInView = openSessionInView; - } - - public void setSecurityWorkspace(String securityWorkspace) { - this.defaultWorkspace = securityWorkspace; - } - -} diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/SimpleWebdavHandlerMapping.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/SimpleWebdavHandlerMapping.java deleted file mode 100644 index bd8d8041a..000000000 --- a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/SimpleWebdavHandlerMapping.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jackrabbit.remote; - -import java.util.Properties; - -import javax.jcr.Repository; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; - -/** Handler mapping for WebDav */ -public class SimpleWebdavHandlerMapping extends - AbstractJackrabbitHandlerMapping { - private String configuration; - - protected HttpServlet createServlet(Repository repository, String pathPrefix) - throws ServletException { - - SimpleWebdavServlet servlet = new SimpleWebdavServlet(repository, - getSessionProvider()); - Properties initParameters = new Properties(); - initParameters.setProperty( - SimpleWebdavServlet.INIT_PARAM_RESOURCE_CONFIG, configuration); - initParameters - .setProperty( - SimpleWebdavServlet.INIT_PARAM_RESOURCE_PATH_PREFIX, - pathPrefix); - servlet.init(new DelegatingServletConfig(pathPrefix.replace('/', '_'), - initParameters)); - return servlet; - } - - public void setConfiguration(String configuration) { - this.configuration = configuration; - } -} diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/SimpleWebdavServlet.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/SimpleWebdavServlet.java deleted file mode 100644 index f1ca0a9f2..000000000 --- a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/SimpleWebdavServlet.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jackrabbit.remote; - -import java.io.IOException; - -import javax.jcr.Repository; -import javax.servlet.ServletException; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.jackrabbit.server.SessionProvider; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.WebdavRequest; -import org.apache.jackrabbit.webdav.WebdavResponse; - -/** WebDav servlet whose repository is injected */ -public class SimpleWebdavServlet extends - org.apache.jackrabbit.webdav.simple.SimpleWebdavServlet { - private static final long serialVersionUID = -369787931175177080L; - - private final static Log log = LogFactory.getLog(SimpleWebdavServlet.class); - - private final Repository repository; - - public SimpleWebdavServlet(Repository repository, - SessionProvider sessionProvider) { - this.repository = repository; - setSessionProvider(sessionProvider); - } - - public Repository getRepository() { - return repository; - } - - @Override - protected boolean execute(WebdavRequest request, WebdavResponse response, - int method, DavResource resource) throws ServletException, - IOException, DavException { - if (log.isTraceEnabled()) - log.trace(request.getMethod() + "\t" + request.getPathInfo()); - boolean res = super.execute(request, response, method, resource); - return res; - } - -} diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/resources/org/argeo/jackrabbit/repository-fs.xml b/server/runtime/org.argeo.server.jackrabbit/src/main/resources/org/argeo/jackrabbit/repository-fs.xml deleted file mode 100644 index 609fc8b33..000000000 --- a/server/runtime/org.argeo.server.jackrabbit/src/main/resources/org/argeo/jackrabbit/repository-fs.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/resources/org/argeo/jackrabbit/repository-h2.xml b/server/runtime/org.argeo.server.jackrabbit/src/main/resources/org/argeo/jackrabbit/repository-h2.xml deleted file mode 100644 index b6a92528a..000000000 --- a/server/runtime/org.argeo.server.jackrabbit/src/main/resources/org/argeo/jackrabbit/repository-h2.xml +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/resources/org/argeo/jackrabbit/repository-memory.xml b/server/runtime/org.argeo.server.jackrabbit/src/main/resources/org/argeo/jackrabbit/repository-memory.xml deleted file mode 100644 index e552c33a7..000000000 --- a/server/runtime/org.argeo.server.jackrabbit/src/main/resources/org/argeo/jackrabbit/repository-memory.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/wikitext/design.mediawiki b/server/runtime/org.argeo.server.jackrabbit/src/main/wikitext/design.mediawiki deleted file mode 100644 index 1a273832c..000000000 --- a/server/runtime/org.argeo.server.jackrabbit/src/main/wikitext/design.mediawiki +++ /dev/null @@ -1,9 +0,0 @@ -= Titre = - - == Sous Titre == - -* point1 -* point2 - - Code (il suffit de mettre un espace en début de ligne - \ No newline at end of file diff --git a/server/runtime/org.argeo.server.jcr.mvc/.classpath b/server/runtime/org.argeo.server.jcr.mvc/.classpath deleted file mode 100644 index c5931a083..000000000 --- a/server/runtime/org.argeo.server.jcr.mvc/.classpath +++ /dev/null @@ -1,7 +0,0 @@ - - - >> - - - - diff --git a/server/runtime/org.argeo.server.jcr.mvc/.project b/server/runtime/org.argeo.server.jcr.mvc/.project deleted file mode 100644 index 73c19d5d2..000000000 --- a/server/runtime/org.argeo.server.jcr.mvc/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - org.argeo.server.jcr.mvc - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - - diff --git a/server/runtime/org.argeo.server.jcr.mvc/build.properties b/server/runtime/org.argeo.server.jcr.mvc/build.properties deleted file mode 100644 index 5fc538bc8..000000000 --- a/server/runtime/org.argeo.server.jcr.mvc/build.properties +++ /dev/null @@ -1,4 +0,0 @@ -source.. = src/main/java/ -output.. = target/classes/ -bin.includes = META-INF/,\ - . diff --git a/server/runtime/org.argeo.server.jcr.mvc/pom.xml b/server/runtime/org.argeo.server.jcr.mvc/pom.xml deleted file mode 100644 index b25208770..000000000 --- a/server/runtime/org.argeo.server.jcr.mvc/pom.xml +++ /dev/null @@ -1,84 +0,0 @@ - - - 4.0.0 - - org.argeo.commons.server - runtime - 2.1.12-SNAPSHOT - .. - - org.argeo.server.jcr.mvc - Commons Server JCR MVC - - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-source-plugin - - - org.apache.maven.plugins - maven-jar-plugin - - - org.apache.felix - maven-bundle-plugin - - - - - org.argeo.jcr.mvc.* - - - org.springframework.core, - org.springframework.beans.factory, - javax.xml.transform.*;version="0.0.0", - javax.xml.parsers.*;version="0.0.0", - org.w3c.dom.*;version="0.0.0", - org.xml.sax.*;version="0.0.0", - * - - - - - - - - - org.argeo.commons.server - org.argeo.server.jcr - 2.1.12-SNAPSHOT - - - - - org.argeo.tp - org.springframework.context - - - org.argeo.tp - org.springframework.core - - - org.argeo.tp - org.springframework.beans - - - org.argeo.tp - org.springframework.web - - - org.argeo.tp - org.springframework.web.servlet - - - - - org.argeo.tp - slf4j.org.apache.commons.logging - - - \ No newline at end of file diff --git a/server/runtime/org.argeo.server.jcr.mvc/src/main/java/org/argeo/jcr/mvc/MultipleRepositoryHandlerMapping.java b/server/runtime/org.argeo.server.jcr.mvc/src/main/java/org/argeo/jcr/mvc/MultipleRepositoryHandlerMapping.java deleted file mode 100644 index fb3f1ae65..000000000 --- a/server/runtime/org.argeo.server.jcr.mvc/src/main/java/org/argeo/jcr/mvc/MultipleRepositoryHandlerMapping.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.mvc; - -import java.util.Enumeration; -import java.util.Properties; -import java.util.StringTokenizer; - -import javax.jcr.Repository; -import javax.jcr.RepositoryFactory; -import javax.servlet.ServletConfig; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.jcr.ArgeoJcrConstants; -import org.argeo.jcr.ArgeoJcrUtils; -import org.springframework.beans.BeansException; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.web.context.ServletContextAware; -import org.springframework.web.servlet.HandlerExecutionChain; -import org.springframework.web.servlet.HandlerMapping; - -/** Handles multiple JCR servers with a single servlet. */ -public abstract class MultipleRepositoryHandlerMapping implements - HandlerMapping, ApplicationContextAware, ServletContextAware { - private final static Log log = LogFactory - .getLog(MultipleRepositoryHandlerMapping.class); - - private final static String MKCOL = "MKCOL"; - - private ConfigurableApplicationContext applicationContext; - private ServletContext servletContext; - - // private RepositoryRegister repositoryRegister; - private RepositoryFactory repositoryFactory; - - /** Actually creates the servlet to be registered. */ - protected abstract HttpServlet createServlet(Repository repository, - String pathPrefix) throws ServletException; - - public HandlerExecutionChain getHandler(HttpServletRequest request) - throws Exception { - if (log.isTraceEnabled()) { - log.trace("getContextPath=" + request.getContextPath()); - log.trace("getServletPath=" + request.getServletPath()); - log.trace("getPathInfo=" + request.getPathInfo()); - } - - String pathInfo = request.getPathInfo(); - String repositoryAlias = extractRepositoryAlias(pathInfo); - if (repositoryAlias.equals("")) - return null; - - // MKCOL on repository or root node doesn't make sense - // and causes issues - if (request.getMethod().equals(MKCOL)) { - StringTokenizer st = new StringTokenizer(pathInfo, "/"); - if (!st.hasMoreTokens()) - return null; - st.nextToken();// repository - if (!st.hasMoreTokens()) - return null; - st.nextToken();// workspace - if (!st.hasMoreTokens()) - return null; - } - - request.setAttribute(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS, - repositoryAlias); - String pathPrefix = request.getServletPath() + '/' + repositoryAlias; - String beanName = pathPrefix; - - if (!applicationContext.containsBean(beanName)) { - Repository repository = ArgeoJcrUtils.getRepositoryByAlias( - repositoryFactory, repositoryAlias); - // Repository repository = repositoryRegister.getRepositories().get( - // repositoryAlias); - HttpServlet servlet = createServlet(repository, pathPrefix); - applicationContext.getBeanFactory().registerSingleton(beanName, - servlet); - // TODO: unregister it as well - } - HttpServlet remotingServlet = (HttpServlet) applicationContext - .getBean(beanName); - HandlerExecutionChain hec = new HandlerExecutionChain(remotingServlet); - return hec; - } - - /** Returns the first two token of the path */ - // protected String[] extractPrefix(String pathInfo) { - // String[] res = new String[2]; - // StringTokenizer st = new StringTokenizer(pathInfo, "/"); - // if (st.hasMoreTokens()) - // res[0] = st.nextToken(); - // if (st.hasMoreTokens()) - // res[1] = st.nextToken(); - // return res; - // } - - /** Returns the first token of the path */ - protected String extractRepositoryAlias(String pathInfo) { - StringBuffer buf = new StringBuffer(); - for (int i = 1; i < pathInfo.length(); i++) { - char c = pathInfo.charAt(i); - if (c == '/') - break; - buf.append(c); - } - return buf.toString(); - } - - /** The repository name is the first part of the path info */ - // protected String extractRepositoryName(List pathTokens) { - // StringBuffer currName = new StringBuffer(""); - // for (String token : pathTokens) { - // currName.append(token); - // if (repositoryRegister.getRepositories().containsKey( - // currName.toString())) - // return currName.toString(); - // currName.append('/'); - // } - // throw new ArgeoException("No repository can be found for request " - // + pathTokens); - // } - - public void setApplicationContext(ApplicationContext applicationContext) - throws BeansException { - this.applicationContext = (ConfigurableApplicationContext) applicationContext; - } - - public void setServletContext(ServletContext servletContext) { - this.servletContext = servletContext; - } - - // public void setRepositoryRegister(RepositoryRegister repositoryRegister) - // { - // this.repositoryRegister = repositoryRegister; - // } - - public void setRepositoryFactory(RepositoryFactory repositoryFactory) { - this.repositoryFactory = repositoryFactory; - } - - protected class DelegatingServletConfig implements ServletConfig { - private String name; - private Properties initParameters; - - public DelegatingServletConfig(String name, Properties initParameters) { - super(); - this.name = name; - this.initParameters = initParameters; - } - - public String getServletName() { - return name; - } - - public ServletContext getServletContext() { - return servletContext; - } - - public String getInitParameter(String paramName) { - return initParameters.getProperty(paramName); - } - - @SuppressWarnings("rawtypes") - public Enumeration getInitParameterNames() { - return initParameters.keys(); - } - } -} diff --git a/server/runtime/org.argeo.server.jcr.mvc/src/main/java/org/argeo/jcr/mvc/ResourceProxyServlet.java b/server/runtime/org.argeo.server.jcr.mvc/src/main/java/org/argeo/jcr/mvc/ResourceProxyServlet.java deleted file mode 100644 index c821be054..000000000 --- a/server/runtime/org.argeo.server.jcr.mvc/src/main/java/org/argeo/jcr/mvc/ResourceProxyServlet.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.mvc; - -import java.io.IOException; -import java.io.InputStream; - -import javax.jcr.Binary; -import javax.jcr.Node; -import javax.jcr.PathNotFoundException; -import javax.jcr.Property; -import javax.jcr.RepositoryException; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.io.FilenameUtils; -import org.apache.commons.io.IOUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.ArgeoException; -import org.argeo.jcr.JcrUtils; -import org.argeo.jcr.proxy.ResourceProxy; - -/** Wraps a proxy via HTTP */ -public class ResourceProxyServlet extends HttpServlet { - private static final long serialVersionUID = -8886549549223155801L; - - private final static Log log = LogFactory - .getLog(ResourceProxyServlet.class); - - private ResourceProxy proxy; - - private String contentTypeCharset = "UTF-8"; - - @Override - protected void doGet(HttpServletRequest request, - HttpServletResponse response) throws ServletException, IOException { - String path = request.getPathInfo(); - - if (log.isTraceEnabled()) { - log.trace("path=" + path); - log.trace("UserPrincipal = " + request.getUserPrincipal().getName()); - log.trace("SessionID = " + request.getSession().getId()); - log.trace("ContextPath = " + request.getContextPath()); - log.trace("ServletPath = " + request.getServletPath()); - log.trace("PathInfo = " + request.getPathInfo()); - log.trace("Method = " + request.getMethod()); - log.trace("User-Agent = " + request.getHeader("User-Agent")); - } - - Node node = null; - try { - node = proxy.proxy(path); - if (node == null) - response.sendError(404); - else - processResponse(node, response); - } finally { - if (node != null) - try { - JcrUtils.logoutQuietly(node.getSession()); - } catch (RepositoryException e) { - // silent - } - } - - } - - /** Retrieve the content of the node. */ - protected void processResponse(Node node, HttpServletResponse response) { - Binary binary = null; - InputStream in = null; - try { - String fileName = node.getName(); - String ext = FilenameUtils.getExtension(fileName); - - // TODO use a more generic / standard approach - // see http://svn.apache.org/viewvc/tomcat/trunk/conf/web.xml - String contentType; - if ("xml".equals(ext)) - contentType = "text/xml;charset=" + contentTypeCharset; - else if ("jar".equals(ext)) - contentType = "application/java-archive"; - else if ("zip".equals(ext)) - contentType = "application/zip"; - else if ("gz".equals(ext)) - contentType = "application/x-gzip"; - else if ("bz2".equals(ext)) - contentType = "application/x-bzip2"; - else if ("tar".equals(ext)) - contentType = "application/x-tar"; - else if ("rpm".equals(ext)) - contentType = "application/x-redhat-package-manager"; - else - contentType = "application/octet-stream"; - contentType = contentType + ";name=\"" + fileName + "\""; - response.setHeader("Content-Disposition", "attachment; filename=\"" - + fileName + "\""); - response.setHeader("Expires", "0"); - response.setHeader("Cache-Control", "no-cache, must-revalidate"); - response.setHeader("Pragma", "no-cache"); - - response.setContentType(contentType); - - try { - binary = node.getNode(Property.JCR_CONTENT) - .getProperty(Property.JCR_DATA).getBinary(); - } catch (PathNotFoundException e) { - log.error("Node " + node + " as no data under content"); - throw e; - } - in = binary.getStream(); - IOUtils.copy(in, response.getOutputStream()); - } catch (Exception e) { - throw new ArgeoException("Cannot download " + node, e); - } finally { - IOUtils.closeQuietly(in); - JcrUtils.closeQuietly(binary); - } - } - - public void setProxy(ResourceProxy resourceProxy) { - this.proxy = resourceProxy; - } - -} diff --git a/server/runtime/org.argeo.server.jcr/.classpath b/server/runtime/org.argeo.server.jcr/.classpath deleted file mode 100644 index d40e15cbf..000000000 --- a/server/runtime/org.argeo.server.jcr/.classpath +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - >> - - - diff --git a/server/runtime/org.argeo.server.jcr/.project b/server/runtime/org.argeo.server.jcr/.project deleted file mode 100644 index 977218c59..000000000 --- a/server/runtime/org.argeo.server.jcr/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - org.argeo.server.jcr - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - - diff --git a/server/runtime/org.argeo.server.jcr/build.properties b/server/runtime/org.argeo.server.jcr/build.properties deleted file mode 100644 index d564e5792..000000000 --- a/server/runtime/org.argeo.server.jcr/build.properties +++ /dev/null @@ -1,22 +0,0 @@ -source.. = src/main/java/,\ - src/test/java/,\ - src/test/resources/,\ - src/main/resources/ -output.. = target/classes/,\ - target/test-classes/ -bin.includes = META-INF/,\ - . -additional.bundles = slf4j.api,\ - slf4j.log4j,\ - org.apache.log4j,\ - org.apache.commons.collections,\ - edu.oswego.cs.dl.util.concurrent,\ - org.apache.lucene,\ - junit,\ - org.apache.xml.serializer,\ - org.apache.commons.dbcp,\ - org.apache.commons.pool,\ - org.apache.jackrabbit,\ - org.h2,\ - org.apache.tika - diff --git a/server/runtime/org.argeo.server.jcr/pom.xml b/server/runtime/org.argeo.server.jcr/pom.xml deleted file mode 100644 index dd6742467..000000000 --- a/server/runtime/org.argeo.server.jcr/pom.xml +++ /dev/null @@ -1,136 +0,0 @@ - - 4.0.0 - - org.argeo.commons.server - runtime - 2.1.12-SNAPSHOT - .. - - org.argeo.server.jcr - Commons Server JCR - - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-source-plugin - - - org.apache.maven.plugins - maven-jar-plugin - - - org.apache.felix - maven-bundle-plugin - - - - org.argeo.jcr.* - - junit.framework;resolution:=optional, - org.xml.sax;version="0.0.0", - org.springframework.core;resolution:=optional, - org.springframework.core.io;resolution:=optional, - org.springframework.*;resolution:=optional, - * - - - - - org.argeo.maven.plugins - maven-argeo-osgi-plugin - - true - true - - -clean - - - - XXX - - - - - - - - org.argeo.commons.base - org.argeo.util - 2.1.12-SNAPSHOT - - - - - org.argeo.tp - javax.jcr - - - - org.argeo.tp - org.apache.commons.io - - - - - org.argeo.tp - org.springframework.core - provided - - - org.argeo.tp - org.springframework.beans - provided - - - - - org.argeo.tp - org.eclipse.osgi - provided - - - - - org.argeo.tp - slf4j.org.apache.commons.logging - - - - - - org.argeo.tp - junit - true - - - org.argeo.commons.base - org.argeo.dep.jackrabbit - 2.1.12-SNAPSHOT - pom - test - - - org.argeo.commons.base - org.argeo.support.junit - 2.1.12-SNAPSHOT - test - - - org.argeo.commons.base - org.argeo.dep.log4j - 2.1.12-SNAPSHOT - pom - test - - - org.argeo.commons.base - org.argeo.osgi.boot - 2.1.12-SNAPSHOT - test - - - \ No newline at end of file diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoJcrConstants.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoJcrConstants.java deleted file mode 100644 index b9b513a30..000000000 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoJcrConstants.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr; - -/** Argeo model specific constants */ -public interface ArgeoJcrConstants { - public final static String ARGEO_BASE_PATH = "/argeo:system"; - public final static String DATA_MODELS_BASE_PATH = ARGEO_BASE_PATH - + "/argeo:dataModels"; - public final static String PEOPLE_BASE_PATH = ARGEO_BASE_PATH - + "/argeo:people"; - - // parameters (typically for call to a RepositoryFactory) - public final static String JCR_REPOSITORY_ALIAS = "argeo.jcr.repository.alias"; - public final static String JCR_REPOSITORY_URI = "argeo.jcr.repository.uri"; - - // standard aliases - public final static String ALIAS_NODE = "node"; - -} diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoJcrUtils.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoJcrUtils.java deleted file mode 100644 index dccb06cf4..000000000 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoJcrUtils.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr; - -import java.util.HashMap; -import java.util.Map; - -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.RepositoryFactory; - -import org.argeo.ArgeoException; - -/** Utilities related to Argeo model in JCR */ -public class ArgeoJcrUtils implements ArgeoJcrConstants { - /** - * Wraps the call to the repository factory based on parameter - * {@link ArgeoJcrConstants#JCR_REPOSITORY_ALIAS} in order to simplify it - * and protect against future API changes. - */ - public static Repository getRepositoryByAlias( - RepositoryFactory repositoryFactory, String alias) { - try { - Map parameters = new HashMap(); - parameters.put(JCR_REPOSITORY_ALIAS, alias); - return repositoryFactory.getRepository(parameters); - } catch (RepositoryException e) { - throw new ArgeoException( - "Unexpected exception when trying to retrieve repository with alias " - + alias, e); - } - } - - /** - * Wraps the call to the repository factory based on parameter - * {@link ArgeoJcrConstants#JCR_REPOSITORY_URI} in order to simplify it and - * protect against future API changes. - */ - public static Repository getRepositoryByUri( - RepositoryFactory repositoryFactory, String uri) { - return getRepositoryByUri(repositoryFactory, uri, null); - } - - /** - * Wraps the call to the repository factory based on parameter - * {@link ArgeoJcrConstants#JCR_REPOSITORY_URI} in order to simplify it and - * protect against future API changes. - */ - public static Repository getRepositoryByUri( - RepositoryFactory repositoryFactory, String uri, String alias) { - try { - Map parameters = new HashMap(); - parameters.put(JCR_REPOSITORY_URI, uri); - if (alias != null) - parameters.put(JCR_REPOSITORY_ALIAS, alias); - return repositoryFactory.getRepository(parameters); - } catch (RepositoryException e) { - throw new ArgeoException( - "Unexpected exception when trying to retrieve repository with uri " - + uri, e); - } - } - - private ArgeoJcrUtils() { - } - -} diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoNames.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoNames.java deleted file mode 100644 index 6e3eca999..000000000 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoNames.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr; - -/** JCR names in the http://www.argeo.org/argeo namespace */ -public interface ArgeoNames { - public final static String ARGEO_NAMESPACE = "http://www.argeo.org/ns/argeo"; - public final static String ARGEO = "argeo"; - - public final static String ARGEO_URI = "argeo:uri"; - public final static String ARGEO_USER_ID = "argeo:userID"; - public final static String ARGEO_PREFERENCES = "argeo:preferences"; - public final static String ARGEO_DATA_MODEL_VERSION = "argeo:dataModelVersion"; - - public final static String ARGEO_REMOTE = "argeo:remote"; - public final static String ARGEO_PASSWORD = "argeo:password"; - public final static String ARGEO_REMOTE_ROLES = "argeo:remoteRoles"; - - // user profile - public final static String ARGEO_PROFILE = "argeo:profile"; - - // spring security - public final static String ARGEO_ENABLED = "argeo:enabled"; - public final static String ARGEO_ACCOUNT_NON_EXPIRED = "argeo:accountNonExpired"; - public final static String ARGEO_ACCOUNT_NON_LOCKED = "argeo:accountNonLocked"; - public final static String ARGEO_CREDENTIALS_NON_EXPIRED = "argeo:credentialsNonExpired"; - - // personal details - public final static String ARGEO_FIRST_NAME = "argeo:firstName"; - public final static String ARGEO_LAST_NAME = "argeo:lastName"; - public final static String ARGEO_PRIMARY_EMAIL = "argeo:primaryEmail"; - public final static String ARGEO_PRIMARY_ORGANIZATION = "argeo:primaryOrganization"; - - // tabular - public final static String ARGEO_IS_KEY = "argeo:isKey"; - - // crypto - public final static String ARGEO_IV = "argeo:iv"; - public final static String ARGEO_SECRET_KEY_FACTORY = "argeo:secretKeyFactory"; - public final static String ARGEO_SALT = "argeo:salt"; - public final static String ARGEO_ITERATION_COUNT = "argeo:iterationCount"; - public final static String ARGEO_KEY_LENGTH = "argeo:keyLength"; - public final static String ARGEO_SECRET_KEY_ENCRYPTION = "argeo:secretKeyEncryption"; - public final static String ARGEO_CIPHER = "argeo:cipher"; - public final static String ARGEO_KEYRING = "argeo:keyring"; -} diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoTypes.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoTypes.java deleted file mode 100644 index a11ead53f..000000000 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoTypes.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr; - -/** JCR types in the http://www.argeo.org/argeo namespace */ -public interface ArgeoTypes { - public final static String ARGEO_LINK = "argeo:link"; - public final static String ARGEO_USER_HOME = "argeo:userHome"; - public final static String ARGEO_USER_PROFILE = "argeo:userProfile"; - public final static String ARGEO_REMOTE_REPOSITORY = "argeo:remoteRepository"; - public final static String ARGEO_PREFERENCE_NODE = "argeo:preferenceNode"; - - // data model - public final static String ARGEO_DATA_MODEL = "argeo:dataModel"; - - // tabular - public final static String ARGEO_TABLE = "argeo:table"; - public final static String ARGEO_COLUMN = "argeo:column"; - public final static String ARGEO_CSV = "argeo:csv"; - - // crypto - public final static String ARGEO_ENCRYPTED = "argeo:encrypted"; - public final static String ARGEO_PBE_SPEC = "argeo:pbeSpec"; - -} diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/CollectionNodeIterator.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/CollectionNodeIterator.java deleted file mode 100644 index a65907a7a..000000000 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/CollectionNodeIterator.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr; - -import java.util.Collection; -import java.util.Iterator; -import java.util.NoSuchElementException; - -import javax.jcr.Node; -import javax.jcr.NodeIterator; - -/** Wraps a collection of nodes in order to read it as a {@link NodeIterator} */ -public class CollectionNodeIterator implements NodeIterator { - private final Long collectionSize; - private final Iterator iterator; - private Integer position = 0; - - public CollectionNodeIterator(Collection nodes) { - super(); - this.collectionSize = (long) nodes.size(); - this.iterator = nodes.iterator(); - } - - public void skip(long skipNum) { - if (skipNum < 0) - throw new IllegalArgumentException( - "Skip count has to be positive: " + skipNum); - - for (long i = 0; i < skipNum; i++) { - if (!hasNext()) - throw new NoSuchElementException("Last element past (position=" - + getPosition() + ")"); - nextNode(); - } - } - - public long getSize() { - return collectionSize; - } - - public long getPosition() { - return position; - } - - public boolean hasNext() { - return iterator.hasNext(); - } - - public Object next() { - return nextNode(); - } - - public void remove() { - iterator.remove(); - } - - public Node nextNode() { - Node node = iterator.next(); - position++; - return node; - } - -} diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/DefaultJcrListener.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/DefaultJcrListener.java deleted file mode 100644 index 253b3055d..000000000 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/DefaultJcrListener.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr; - -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.observation.Event; -import javax.jcr.observation.EventIterator; -import javax.jcr.observation.EventListener; -import javax.jcr.observation.ObservationManager; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.ArgeoException; - -/** To be overridden */ -public class DefaultJcrListener implements EventListener { - private final static Log log = LogFactory.getLog(DefaultJcrListener.class); - private Session session; - private String path = "/"; - private Boolean deep = true; - - public void start() { - try { - addEventListener(session().getWorkspace().getObservationManager()); - if (log.isDebugEnabled()) - log.debug("Registered JCR event listener on " + path); - } catch (Exception e) { - throw new ArgeoException("Cannot register event listener", e); - } - } - - public void stop() { - try { - session().getWorkspace().getObservationManager() - .removeEventListener(this); - if (log.isDebugEnabled()) - log.debug("Unregistered JCR event listener on " + path); - } catch (Exception e) { - throw new ArgeoException("Cannot unregister event listener", e); - } - } - - /** Default is listen to all events */ - protected Integer getEvents() { - return Event.NODE_ADDED | Event.NODE_REMOVED | Event.PROPERTY_ADDED - | Event.PROPERTY_CHANGED | Event.PROPERTY_REMOVED; - } - - /** To be overidden */ - public void onEvent(EventIterator events) { - while (events.hasNext()) { - Event event = events.nextEvent(); - log.debug(event); - } - } - - /** To be overidden */ - protected void addEventListener(ObservationManager observationManager) - throws RepositoryException { - observationManager.addEventListener(this, getEvents(), path, deep, - null, null, false); - } - - private Session session() { - return session; - } - - public void setPath(String path) { - this.path = path; - } - - public void setDeep(Boolean deep) { - this.deep = deep; - } - - public void setSession(Session session) { - this.session = session; - } - -} diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/DefaultRepositoryFactory.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/DefaultRepositoryFactory.java deleted file mode 100644 index a7b30e7be..000000000 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/DefaultRepositoryFactory.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr; - -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Map; -import java.util.Properties; - -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.RepositoryFactory; - -import org.argeo.ArgeoException; - -/** - * Simple implementation of {@link RepositoryFactory}, supporting OSGi aliases. - */ -public class DefaultRepositoryFactory extends DefaultRepositoryRegister - implements RepositoryFactory, ArgeoJcrConstants { - @SuppressWarnings("rawtypes") - public Repository getRepository(Map parameters) throws RepositoryException { - if (parameters.containsKey(JCR_REPOSITORY_ALIAS)) { - String alias = parameters.get(JCR_REPOSITORY_ALIAS).toString(); - return getRepositoryByAlias(alias); - } else if (parameters.containsKey(JCR_REPOSITORY_URI)) { - String uri = parameters.get(JCR_REPOSITORY_URI).toString(); - return getRepositoryByAlias(getAliasFromURI(uri)); - } - return null; - } - - protected String getAliasFromURI(String uri) { - try { - URI uriObj = new URI(uri); - String alias = uriObj.getPath(); - if (alias.charAt(0) == '/') - alias = alias.substring(1); - if (alias.charAt(alias.length() - 1) == '/') - alias = alias.substring(0, alias.length() - 1); - return alias; - } catch (URISyntaxException e) { - throw new ArgeoException("Cannot interpret URI " + uri, e); - } - } - - /** - * Retrieve a repository by alias - * - * @return the repository registered with alias or null if none - */ - protected Repository getRepositoryByAlias(String alias) { - if (getRepositories().containsKey(alias)) - return getRepositories().get(alias); - else - return null; - } - - protected void publish(String alias, Repository repository, - Properties properties) { - register(repository, properties); - } - -} diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/DefaultRepositoryRegister.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/DefaultRepositoryRegister.java deleted file mode 100644 index f13c84e3b..000000000 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/DefaultRepositoryRegister.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr; - -import java.util.Collections; -import java.util.Map; -import java.util.Observable; -import java.util.TreeMap; - -import javax.jcr.Repository; -import javax.jcr.RepositoryException; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -public class DefaultRepositoryRegister extends Observable implements - RepositoryRegister, ArgeoJcrConstants { - private final static Log log = LogFactory - .getLog(DefaultRepositoryRegister.class); - - /** Read only map which will be directly exposed. */ - private Map repositories = Collections - .unmodifiableMap(new TreeMap()); - - @SuppressWarnings("rawtypes") - public synchronized Repository getRepository(Map parameters) - throws RepositoryException { - if (!parameters.containsKey(JCR_REPOSITORY_ALIAS)) - throw new RepositoryException("Parameter " + JCR_REPOSITORY_ALIAS - + " has to be defined."); - String alias = parameters.get(JCR_REPOSITORY_ALIAS).toString(); - if (!repositories.containsKey(alias)) - throw new RepositoryException( - "No repository registered with alias " + alias); - - return repositories.get(alias); - } - - /** Access to the read-only map */ - public synchronized Map getRepositories() { - return repositories; - } - - /** Registers a service, typically called when OSGi services are bound. */ - @SuppressWarnings("rawtypes") - public synchronized void register(Repository repository, Map properties) { - // TODO: also check bean name? - String alias; - if (properties == null || !properties.containsKey(JCR_REPOSITORY_ALIAS)) { - log.warn("Cannot register a repository if no " - + JCR_REPOSITORY_ALIAS + " property is speecified."); - return; - } - alias = properties.get(JCR_REPOSITORY_ALIAS).toString(); - Map map = new TreeMap( - repositories); - map.put(alias, repository); - repositories = Collections.unmodifiableMap(map); - setChanged(); - notifyObservers(alias); - } - - /** Unregisters a service, typically called when OSGi services are unbound. */ - @SuppressWarnings("rawtypes") - public synchronized void unregister(Repository repository, Map properties) { - // TODO: also check bean name? - if (properties == null || !properties.containsKey(JCR_REPOSITORY_ALIAS)) { - log.warn("Cannot unregister a repository without property " - + JCR_REPOSITORY_ALIAS); - return; - } - - String alias = properties.get(JCR_REPOSITORY_ALIAS).toString(); - Map map = new TreeMap( - repositories); - map.put(alias, repository); - repositories = Collections.unmodifiableMap(map); - setChanged(); - notifyObservers(alias); - } -} diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrCallback.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrCallback.java deleted file mode 100644 index 0c4706f84..000000000 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrCallback.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr; - -import javax.jcr.Session; - -/** An arbitrary execution on a JCR session, optionally returning a result. */ -public interface JcrCallback { - public Object execute(Session session); -} diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrRepositoryWrapper.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrRepositoryWrapper.java deleted file mode 100644 index f993c2f58..000000000 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrRepositoryWrapper.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr; - -import javax.jcr.Credentials; -import javax.jcr.LoginException; -import javax.jcr.NoSuchWorkspaceException; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.Value; - -import org.argeo.ArgeoException; - -/** - * Wrapper around a JCR repository which allows to simplify configuration and - * intercept some actions. It exposes itself as a {@link Repository}. - */ -public abstract class JcrRepositoryWrapper implements Repository { - // private final static Log log = LogFactory - // .getLog(JcrRepositoryWrapper.class); - - // wrapped repository - private Repository repository; - - private Boolean autocreateWorkspaces = false; - - /** - * Empty constructor, {@link #init()} should be called after properties have - * been set - */ - public JcrRepositoryWrapper() { - } - - /** Initializes */ - public void init() { - } - - /** Shutdown the repository */ - public void destroy() throws Exception { - } - - /* - * DELEGATED JCR REPOSITORY METHODS - */ - - public String getDescriptor(String key) { - return getRepository().getDescriptor(key); - } - - public String[] getDescriptorKeys() { - return getRepository().getDescriptorKeys(); - } - - /** Central login method */ - public Session login(Credentials credentials, String workspaceName) - throws LoginException, NoSuchWorkspaceException, - RepositoryException { - Session session; - try { - session = getRepository().login(credentials, workspaceName); - } catch (NoSuchWorkspaceException e) { - if (autocreateWorkspaces && workspaceName != null) - session = createWorkspaceAndLogsIn(credentials, workspaceName); - else - throw e; - } - processNewSession(session); - return session; - } - - public Session login() throws LoginException, RepositoryException { - return login(null, null); - } - - public Session login(Credentials credentials) throws LoginException, - RepositoryException { - return login(credentials, null); - } - - public Session login(String workspaceName) throws LoginException, - NoSuchWorkspaceException, RepositoryException { - return login(null, workspaceName); - } - - /** Called after a session has been created, does nothing by default. */ - protected void processNewSession(Session session) { - } - - /** Wraps access to the repository, making sure it is available. */ - protected synchronized Repository getRepository() { -// if (repository == null) { -// throw new ArgeoException("No repository initialized." -// + " Was the init() method called?" -// + " The destroy() method should also" -// + " be called on shutdown."); -// } - return repository; - } - - /** - * Logs in to the default workspace, creates the required workspace, logs - * out, logs in to the required workspace. - */ - protected Session createWorkspaceAndLogsIn(Credentials credentials, - String workspaceName) throws RepositoryException { - if (workspaceName == null) - throw new ArgeoException("No workspace specified."); - Session session = getRepository().login(credentials); - session.getWorkspace().createWorkspace(workspaceName); - session.logout(); - return getRepository().login(credentials, workspaceName); - } - - public boolean isStandardDescriptor(String key) { - return getRepository().isStandardDescriptor(key); - } - - public boolean isSingleValueDescriptor(String key) { - return getRepository().isSingleValueDescriptor(key); - } - - public Value getDescriptorValue(String key) { - return getRepository().getDescriptorValue(key); - } - - public Value[] getDescriptorValues(String key) { - return getRepository().getDescriptorValues(key); - } - - public synchronized void setRepository(Repository repository) { - this.repository = repository; - } - - public void setAutocreateWorkspaces(Boolean autocreateWorkspaces) { - this.autocreateWorkspaces = autocreateWorkspaces; - } - -} diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrResourceAdapter.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrResourceAdapter.java deleted file mode 100644 index 0b1a98cf0..000000000 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrResourceAdapter.java +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr; - -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.List; - -import javax.jcr.Binary; -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.nodetype.NodeType; -import javax.jcr.version.Version; -import javax.jcr.version.VersionHistory; -import javax.jcr.version.VersionIterator; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.ArgeoException; - -/** - * Bridge Spring resources and JCR folder / files semantics (nt:folder / - * nt:file), supporting versioning as well. - */ -public class JcrResourceAdapter { - private final static Log log = LogFactory.getLog(JcrResourceAdapter.class); - - private Session session; - - private Boolean versioning = true; - private String defaultEncoding = "UTF-8"; - - // private String restoreBase = "/.restore"; - - public JcrResourceAdapter() { - } - - public JcrResourceAdapter(Session session) { - this.session = session; - } - - public void mkdirs(String path) { - JcrUtils.mkdirs(session(), path, NodeType.NT_FOLDER, - NodeType.NT_FOLDER, versioning); - } - - public void create(String path, InputStream in, String mimeType) { - try { - if (session().itemExists(path)) { - throw new ArgeoException("Node " + path + " already exists."); - } - - int index = path.lastIndexOf('/'); - String parentPath = path.substring(0, index); - if (parentPath.equals("")) - parentPath = "/"; - String fileName = path.substring(index + 1); - if (!session().itemExists(parentPath)) - throw new ArgeoException("Parent folder of node " + path - + " does not exist: " + parentPath); - - Node folderNode = (Node) session().getItem(parentPath); - Node fileNode = folderNode.addNode(fileName, "nt:file"); - - Node contentNode = fileNode.addNode(Property.JCR_CONTENT, - "nt:resource"); - if (mimeType != null) - contentNode.setProperty(Property.JCR_MIMETYPE, mimeType); - contentNode.setProperty(Property.JCR_ENCODING, defaultEncoding); - Binary binary = session().getValueFactory().createBinary(in); - contentNode.setProperty(Property.JCR_DATA, binary); - JcrUtils.closeQuietly(binary); - Calendar lastModified = Calendar.getInstance(); - // lastModified.setTimeInMillis(file.lastModified()); - contentNode.setProperty(Property.JCR_LAST_MODIFIED, lastModified); - // resNode.addMixin("mix:referenceable"); - - if (versioning) - fileNode.addMixin("mix:versionable"); - - session().save(); - - if (versioning) - session().getWorkspace().getVersionManager() - .checkin(fileNode.getPath()); - - if (log.isDebugEnabled()) - log.debug("Created " + path); - } catch (Exception e) { - throw new ArgeoException("Cannot create node for " + path, e); - } - - } - - public void update(String path, InputStream in) { - try { - - if (!session().itemExists(path)) { - String type = null; - // FIXME: using javax.activation leads to conflict between Java - // 1.5 and 1.6 (since javax.activation was included in Java 1.6) - // String type = new MimetypesFileTypeMap() - // .getContentType(FilenameUtils.getName(path)); - create(path, in, type); - return; - } - - Node fileNode = (Node) session().getItem(path); - Node contentNode = fileNode.getNode(Property.JCR_CONTENT); - if (versioning) - session().getWorkspace().getVersionManager() - .checkout(fileNode.getPath()); - Binary binary = session().getValueFactory().createBinary(in); - contentNode.setProperty(Property.JCR_DATA, binary); - JcrUtils.closeQuietly(binary); - Calendar lastModified = Calendar.getInstance(); - // lastModified.setTimeInMillis(file.lastModified()); - contentNode.setProperty(Property.JCR_LAST_MODIFIED, lastModified); - - session().save(); - if (versioning) - session().getWorkspace().getVersionManager() - .checkin(fileNode.getPath()); - - if (log.isDebugEnabled()) - log.debug("Updated " + path); - } catch (Exception e) { - throw new ArgeoException("Cannot update node " + path, e); - } - } - - public List listVersions(String path) { - if (!versioning) - throw new ArgeoException("Versioning is not activated"); - - try { - List versions = new ArrayList(); - Node fileNode = (Node) session().getItem(path); - VersionHistory history = session().getWorkspace() - .getVersionManager().getVersionHistory(fileNode.getPath()); - for (VersionIterator it = history.getAllVersions(); it.hasNext();) { - Version version = (Version) it.next(); - versions.add(version.getCreated()); - if (log.isTraceEnabled()) { - log.debug(version); - // debug(version); - } - } - return versions; - } catch (Exception e) { - throw new ArgeoException("Cannot list version of node " + path, e); - } - } - - public InputStream retrieve(String path) { - try { - Node node = (Node) session().getItem( - path + "/" + Property.JCR_CONTENT); - Property property = node.getProperty(Property.JCR_DATA); - return property.getBinary().getStream(); - } catch (Exception e) { - throw new ArgeoException("Cannot retrieve " + path, e); - } - } - - public synchronized InputStream retrieve(String path, Integer revision) { - if (!versioning) - throw new ArgeoException("Versioning is not activated"); - - try { - Node fileNode = (Node) session().getItem(path); - VersionHistory history = session().getWorkspace() - .getVersionManager().getVersionHistory(fileNode.getPath()); - int count = 0; - Version version = null; - for (VersionIterator it = history.getAllVersions(); it.hasNext();) { - version = (Version) it.next(); - if (count == revision + 1) { - InputStream in = fromVersion(version); - if (log.isDebugEnabled()) - log.debug("Retrieved " + path + " at revision " - + revision); - return in; - } - count++; - } - } catch (Exception e) { - throw new ArgeoException("Cannot retrieve version " + revision - + " of " + path, e); - } - - throw new ArgeoException("Version " + revision - + " does not exist for node " + path); - } - - protected InputStream fromVersion(Version version) - throws RepositoryException { - Node frozenNode = version.getNode("jcr:frozenNode"); - InputStream in = frozenNode.getNode(Property.JCR_CONTENT) - .getProperty(Property.JCR_DATA).getBinary().getStream(); - return in; - } - - protected Session session() { - return session; - } - - public void setVersioning(Boolean versioning) { - this.versioning = versioning; - } - - public void setDefaultEncoding(String defaultEncoding) { - this.defaultEncoding = defaultEncoding; - } - - protected String fill(Integer number) { - int size = 4; - String str = number.toString(); - for (int i = str.length(); i < size; i++) { - str = "0" + str; - } - return str; - } - - public void setSession(Session session) { - this.session = session; - } - -} diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrUrlStreamHandler.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrUrlStreamHandler.java deleted file mode 100644 index a77763937..000000000 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrUrlStreamHandler.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.net.URLConnection; -import java.net.URLStreamHandler; - -import javax.jcr.Item; -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.nodetype.NodeType; - -/** URL stream handler able to deal with nt:file node and properties. NOT FINISHED */ -public class JcrUrlStreamHandler extends URLStreamHandler { - private final Session session; - - public JcrUrlStreamHandler(Session session) { - this.session = session; - } - - @Override - protected URLConnection openConnection(final URL u) throws IOException { - // TODO Auto-generated method stub - return new URLConnection(u) { - - @Override - public void connect() throws IOException { - String itemPath = u.getPath(); - try { - if (!session.itemExists(itemPath)) - throw new IOException("No item under " + itemPath); - - Item item = session.getItem(u.getPath()); - if (item.isNode()) { - // this should be a nt:file node - Node node = (Node) item; - if (!node.getPrimaryNodeType().isNodeType( - NodeType.NT_FILE)) - throw new IOException("Node " + node + " is not a " - + NodeType.NT_FILE); - - } else { - Property property = (Property) item; - if(property.getType()==PropertyType.BINARY){ - //Binary binary = property.getBinary(); - - } - } - } catch (RepositoryException e) { - IOException ioe = new IOException( - "Unexpected JCR exception"); - ioe.initCause(e); - throw ioe; - } - } - - @Override - public InputStream getInputStream() throws IOException { - // TODO Auto-generated method stub - return super.getInputStream(); - } - - }; - } - -} diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrUtils.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrUtils.java deleted file mode 100644 index 2176e757c..000000000 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrUtils.java +++ /dev/null @@ -1,1590 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URL; -import java.security.Principal; -import java.text.DateFormat; -import java.text.ParseException; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Collections; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; - -import javax.jcr.Binary; -import javax.jcr.NamespaceRegistry; -import javax.jcr.NoSuchWorkspaceException; -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.Property; -import javax.jcr.PropertyIterator; -import javax.jcr.PropertyType; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.Value; -import javax.jcr.Workspace; -import javax.jcr.nodetype.NodeType; -import javax.jcr.observation.EventListener; -import javax.jcr.query.Query; -import javax.jcr.query.QueryResult; -import javax.jcr.security.AccessControlEntry; -import javax.jcr.security.AccessControlList; -import javax.jcr.security.AccessControlManager; -import javax.jcr.security.AccessControlPolicy; -import javax.jcr.security.AccessControlPolicyIterator; -import javax.jcr.security.Privilege; - -import org.apache.commons.io.IOUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.ArgeoException; -import org.argeo.ArgeoMonitor; -import org.argeo.util.security.DigestUtils; -import org.argeo.util.security.SimplePrincipal; - -/** Utility methods to simplify common JCR operations. */ -public class JcrUtils implements ArgeoJcrConstants { - - final private static Log log = LogFactory.getLog(JcrUtils.class); - - /** - * Not complete yet. See - * http://www.day.com/specs/jcr/2.0/3_Repository_Model.html#3.2.2%20Local - * %20Names - */ - public final static char[] INVALID_NAME_CHARACTERS = { '/', ':', '[', ']', - '|', '*', /* - * invalid XML chars : - */ - '<', '>', '&' }; - - /** Prevents instantiation */ - private JcrUtils() { - } - - /** - * Queries one single node. - * - * @return one single node or null if none was found - * @throws ArgeoException - * if more than one node was found - */ - public static Node querySingleNode(Query query) { - NodeIterator nodeIterator; - try { - QueryResult queryResult = query.execute(); - nodeIterator = queryResult.getNodes(); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot execute query " + query, e); - } - Node node; - if (nodeIterator.hasNext()) - node = nodeIterator.nextNode(); - else - return null; - - if (nodeIterator.hasNext()) - throw new ArgeoException("Query returned more than one node."); - return node; - } - - /** Retrieves the node name from the provided path */ - public static String nodeNameFromPath(String path) { - if (path.equals("/")) - return ""; - if (path.charAt(0) != '/') - throw new ArgeoException("Path " + path + " must start with a '/'"); - String pathT = path; - if (pathT.charAt(pathT.length() - 1) == '/') - pathT = pathT.substring(0, pathT.length() - 2); - - int index = pathT.lastIndexOf('/'); - return pathT.substring(index + 1); - } - - /** Retrieves the parent path of the provided path */ - public static String parentPath(String path) { - if (path.equals("/")) - throw new ArgeoException("Root path '/' has no parent path"); - if (path.charAt(0) != '/') - throw new ArgeoException("Path " + path + " must start with a '/'"); - String pathT = path; - if (pathT.charAt(pathT.length() - 1) == '/') - pathT = pathT.substring(0, pathT.length() - 2); - - int index = pathT.lastIndexOf('/'); - return pathT.substring(0, index); - } - - /** The provided data as a path ('/' at the end, not the beginning) */ - public static String dateAsPath(Calendar cal) { - return dateAsPath(cal, false); - } - - /** - * Creates a deep path based on a URL: - * http://subdomain.example.com/to/content?args => - * com/example/subdomain/to/content - */ - public static String urlAsPath(String url) { - try { - URL u = new URL(url); - StringBuffer path = new StringBuffer(url.length()); - // invert host - path.append(hostAsPath(u.getHost())); - // we don't put port since it may not always be there and may change - path.append(u.getPath()); - return path.toString(); - } catch (MalformedURLException e) { - throw new ArgeoException("Cannot generate URL path for " + url, e); - } - } - - /** Set the {@link NodeType#NT_ADDRESS} properties based on this URL. */ - public static void urlToAddressProperties(Node node, String url) { - try { - URL u = new URL(url); - node.setProperty(Property.JCR_PROTOCOL, u.getProtocol()); - node.setProperty(Property.JCR_HOST, u.getHost()); - node.setProperty(Property.JCR_PORT, Integer.toString(u.getPort())); - node.setProperty(Property.JCR_PATH, normalizePath(u.getPath())); - } catch (Exception e) { - throw new ArgeoException("Cannot set URL " + url - + " as nt:address properties", e); - } - } - - /** Build URL based on the {@link NodeType#NT_ADDRESS} properties. */ - public static String urlFromAddressProperties(Node node) { - try { - URL u = new URL( - node.getProperty(Property.JCR_PROTOCOL).getString(), node - .getProperty(Property.JCR_HOST).getString(), - (int) node.getProperty(Property.JCR_PORT).getLong(), node - .getProperty(Property.JCR_PATH).getString()); - return u.toString(); - } catch (Exception e) { - throw new ArgeoException( - "Cannot get URL from nt:address properties of " + node, e); - } - } - - /* - * PATH UTILITIES - */ - - /** Make sure that: starts with '/', do not end with '/', do not have '//' */ - public static String normalizePath(String path) { - List tokens = tokenize(path); - StringBuffer buf = new StringBuffer(path.length()); - for (String token : tokens) { - buf.append('/'); - buf.append(token); - } - return buf.toString(); - } - - /** - * Creates a path from a FQDN, inverting the order of the component: - * www.argeo.org => org.argeo.www - */ - public static String hostAsPath(String host) { - StringBuffer path = new StringBuffer(host.length()); - String[] hostTokens = host.split("\\."); - for (int i = hostTokens.length - 1; i >= 0; i--) { - path.append(hostTokens[i]); - if (i != 0) - path.append('/'); - } - return path.toString(); - } - - /** - * Creates a path from a UUID (e.g. 6ebda899-217d-4bf1-abe4-2839085c8f3c => - * 6ebda899-217d/4bf1/abe4/2839085c8f3c/). '/' at the end, not the beginning - */ - public static String uuidAsPath(String uuid) { - StringBuffer path = new StringBuffer(uuid.length()); - String[] tokens = uuid.split("-"); - for (int i = 0; i < tokens.length; i++) { - path.append(tokens[i]); - if (i != 0) - path.append('/'); - } - return path.toString(); - } - - /** - * The provided data as a path ('/' at the end, not the beginning) - * - * @param cal - * the date - * @param addHour - * whether to add hour as well - */ - public static String dateAsPath(Calendar cal, Boolean addHour) { - StringBuffer buf = new StringBuffer(14); - buf.append('Y'); - buf.append(cal.get(Calendar.YEAR)); - buf.append('/'); - - int month = cal.get(Calendar.MONTH) + 1; - buf.append('M'); - if (month < 10) - buf.append(0); - buf.append(month); - buf.append('/'); - - int day = cal.get(Calendar.DAY_OF_MONTH); - buf.append('D'); - if (day < 10) - buf.append(0); - buf.append(day); - buf.append('/'); - - if (addHour) { - int hour = cal.get(Calendar.HOUR_OF_DAY); - buf.append('H'); - if (hour < 10) - buf.append(0); - buf.append(hour); - buf.append('/'); - } - return buf.toString(); - - } - - /** Converts in one call a string into a gregorian calendar. */ - public static Calendar parseCalendar(DateFormat dateFormat, String value) { - try { - Date date = dateFormat.parse(value); - Calendar calendar = new GregorianCalendar(); - calendar.setTime(date); - return calendar; - } catch (ParseException e) { - throw new ArgeoException("Cannot parse " + value - + " with date format " + dateFormat, e); - } - - } - - /** The last element of a path. */ - public static String lastPathElement(String path) { - if (path.charAt(path.length() - 1) == '/') - throw new ArgeoException("Path " + path + " cannot end with '/'"); - int index = path.lastIndexOf('/'); - if (index < 0) - return path; - return path.substring(index + 1); - } - - /** - * Call {@link Node#getName()} without exceptions (useful in super - * constructors). - */ - public static String getNameQuietly(Node node) { - try { - return node.getName(); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot get name from " + node, e); - } - } - - /** - * Call {@link Node#getProperty(String)} without exceptions (useful in super - * constructors). - */ - public static String getStringPropertyQuietly(Node node, String propertyName) { - try { - return node.getProperty(propertyName).getString(); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot get name from " + node, e); - } - } - - /** - * Routine that get the child with this name, adding id it does not already - * exist - */ - public static Node getOrAdd(Node parent, String childName, - String childPrimaryNodeType) throws RepositoryException { - return parent.hasNode(childName) ? parent.getNode(childName) : parent - .addNode(childName, childPrimaryNodeType); - } - - /** - * Routine that get the child with this name, adding id it does not already - * exist - */ - public static Node getOrAdd(Node parent, String childName) - throws RepositoryException { - return parent.hasNode(childName) ? parent.getNode(childName) : parent - .addNode(childName); - } - - /** Convert a {@link NodeIterator} to a list of {@link Node} */ - public static List nodeIteratorToList(NodeIterator nodeIterator) { - List nodes = new ArrayList(); - while (nodeIterator.hasNext()) { - nodes.add(nodeIterator.nextNode()); - } - return nodes; - } - - /* - * PROPERTIES - */ - - /** - * Concisely get the string value of a property or null if this node doesn't - * have this property - */ - public static String get(Node node, String propertyName) { - try { - if (!node.hasProperty(propertyName)) - return null; - return node.getProperty(propertyName).getString(); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot get property " + propertyName - + " of " + node, e); - } - } - - /** Concisely get the boolean value of a property */ - public static Boolean check(Node node, String propertyName) { - try { - return node.getProperty(propertyName).getBoolean(); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot get property " + propertyName - + " of " + node, e); - } - } - - /** Concisely get the bytes array value of a property */ - public static byte[] getBytes(Node node, String propertyName) { - try { - return getBinaryAsBytes(node.getProperty(propertyName)); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot get property " + propertyName - + " of " + node, e); - } - } - - /** Creates the nodes making path, if they don't exist. */ - public static Node mkdirs(Session session, String path) { - return mkdirs(session, path, null, null, false); - } - - /** - * use {@link #mkdirs(Session, String, String, String, Boolean)} instead. - * - * @deprecated - */ - @Deprecated - public static Node mkdirs(Session session, String path, String type, - Boolean versioning) { - return mkdirs(session, path, type, type, false); - } - - /** - * @param type - * the type of the leaf node - */ - public static Node mkdirs(Session session, String path, String type) { - return mkdirs(session, path, type, null, false); - } - - /** - * Create sub nodes relative to a parent node - * - * @param nodeType - * the type of the leaf node - */ - public static Node mkdirs(Node parentNode, String relativePath, - String nodeType) { - return mkdirs(parentNode, relativePath, nodeType, null); - } - - /** - * Create sub nodes relative to a parent node - * - * @param nodeType - * the type of the leaf node - */ - public static Node mkdirs(Node parentNode, String relativePath, - String nodeType, String intermediaryNodeType) { - List tokens = tokenize(relativePath); - Node currParent = parentNode; - try { - for (int i = 0; i < tokens.size(); i++) { - String name = tokens.get(i); - if (currParent.hasNode(name)) { - currParent = currParent.getNode(name); - } else { - if (i != (tokens.size() - 1)) {// intermediary - currParent = currParent.addNode(name, - intermediaryNodeType); - } else {// leaf - currParent = currParent.addNode(name, nodeType); - } - } - } - return currParent; - } catch (RepositoryException e) { - throw new ArgeoException("Cannot mkdirs relative path " - + relativePath + " from " + parentNode, e); - } - } - - /** - * Synchronized and save is performed, to avoid race conditions in - * initializers leading to duplicate nodes. - */ - public synchronized static Node mkdirsSafe(Session session, String path, - String type) { - try { - if (session.hasPendingChanges()) - throw new ArgeoException( - "Session has pending changes, save them first."); - Node node = mkdirs(session, path, type); - session.save(); - return node; - } catch (RepositoryException e) { - discardQuietly(session); - throw new ArgeoException("Cannot safely make directories", e); - } - } - - public synchronized static Node mkdirsSafe(Session session, String path) { - return mkdirsSafe(session, path, null); - } - - /** - * Creates the nodes making path, if they don't exist. This is up to the - * caller to save the session. Use with caution since it can create - * duplicate nodes if used concurrently. - */ - public static Node mkdirs(Session session, String path, String type, - String intermediaryNodeType, Boolean versioning) { - try { - if (path.equals('/')) - return session.getRootNode(); - - if (session.itemExists(path)) { - Node node = session.getNode(path); - // check type - if (type != null && !node.isNodeType(type) - && !node.getPath().equals("/")) - throw new ArgeoException("Node " + node - + " exists but is of type " - + node.getPrimaryNodeType().getName() - + " not of type " + type); - // TODO: check versioning - return node; - } - - StringBuffer current = new StringBuffer("/"); - Node currentNode = session.getRootNode(); - Iterator it = tokenize(path).iterator(); - while (it.hasNext()) { - String part = it.next(); - current.append(part).append('/'); - if (!session.itemExists(current.toString())) { - if (!it.hasNext() && type != null) - currentNode = currentNode.addNode(part, type); - else if (it.hasNext() && intermediaryNodeType != null) - currentNode = currentNode.addNode(part, - intermediaryNodeType); - else - currentNode = currentNode.addNode(part); - if (versioning) - currentNode.addMixin(NodeType.MIX_VERSIONABLE); - if (log.isTraceEnabled()) - log.debug("Added folder " + part + " as " + current); - } else { - currentNode = (Node) session.getItem(current.toString()); - } - } - return currentNode; - } catch (RepositoryException e) { - discardQuietly(session); - throw new ArgeoException("Cannot mkdirs " + path, e); - } finally { - } - } - - /** Convert a path to the list of its tokens */ - public static List tokenize(String path) { - List tokens = new ArrayList(); - boolean optimized = false; - if (!optimized) { - String[] rawTokens = path.split("/"); - for (String token : rawTokens) { - if (!token.equals("")) - tokens.add(token); - } - } else { - StringBuffer curr = new StringBuffer(); - char[] arr = path.toCharArray(); - chars: for (int i = 0; i < arr.length; i++) { - char c = arr[i]; - if (c == '/') { - if (i == 0 || (i == arr.length - 1)) - continue chars; - if (curr.length() > 0) { - tokens.add(curr.toString()); - curr = new StringBuffer(); - } - } else - curr.append(c); - } - if (curr.length() > 0) { - tokens.add(curr.toString()); - curr = new StringBuffer(); - } - } - return Collections.unmodifiableList(tokens); - } - - /** - * Safe and repository implementation independent registration of a - * namespace. - */ - public static void registerNamespaceSafely(Session session, String prefix, - String uri) { - try { - registerNamespaceSafely(session.getWorkspace() - .getNamespaceRegistry(), prefix, uri); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot find namespace registry", e); - } - } - - /** - * Safe and repository implementation independent registration of a - * namespace. - */ - public static void registerNamespaceSafely(NamespaceRegistry nr, - String prefix, String uri) { - try { - String[] prefixes = nr.getPrefixes(); - for (String pref : prefixes) - if (pref.equals(prefix)) { - String registeredUri = nr.getURI(pref); - if (!registeredUri.equals(uri)) - throw new ArgeoException("Prefix " + pref - + " already registered for URI " - + registeredUri - + " which is different from provided URI " - + uri); - else - return;// skip - } - nr.registerNamespace(prefix, uri); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot register namespace " + uri - + " under prefix " + prefix, e); - } - } - - /** Recursively outputs the contents of the given node. */ - public static void debug(Node node) { - debug(node, log); - } - - /** Recursively outputs the contents of the given node. */ - public static void debug(Node node, Log log) { - try { - // First output the node path - log.debug(node.getPath()); - // Skip the virtual (and large!) jcr:system subtree - if (node.getName().equals("jcr:system")) { - return; - } - - // Then the children nodes (recursive) - NodeIterator it = node.getNodes(); - while (it.hasNext()) { - Node childNode = it.nextNode(); - debug(childNode, log); - } - - // Then output the properties - PropertyIterator properties = node.getProperties(); - // log.debug("Property are : "); - - properties: while (properties.hasNext()) { - Property property = properties.nextProperty(); - if (property.getType() == PropertyType.BINARY) - continue properties;// skip - if (property.getDefinition().isMultiple()) { - // A multi-valued property, print all values - Value[] values = property.getValues(); - for (int i = 0; i < values.length; i++) { - log.debug(property.getPath() + "=" - + values[i].getString()); - } - } else { - // A single-valued property - log.debug(property.getPath() + "=" + property.getString()); - } - } - } catch (Exception e) { - log.error("Could not debug " + node, e); - } - - } - - /** Logs the effective access control policies */ - public static void logEffectiveAccessPolicies(Node node) { - try { - logEffectiveAccessPolicies(node.getSession(), node.getPath()); - } catch (RepositoryException e) { - log.error("Cannot log effective access policies of " + node, e); - } - } - - /** Logs the effective access control policies */ - public static void logEffectiveAccessPolicies(Session session, String path) { - if (!log.isDebugEnabled()) - return; - - try { - AccessControlPolicy[] effectivePolicies = session - .getAccessControlManager().getEffectivePolicies(path); - if (effectivePolicies.length > 0) { - for (AccessControlPolicy policy : effectivePolicies) { - if (policy instanceof AccessControlList) { - AccessControlList acl = (AccessControlList) policy; - log.debug("Access control list for " + path + "\n" - + accessControlListSummary(acl)); - } - } - } else { - log.debug("No effective access control policy for " + path); - } - } catch (RepositoryException e) { - log.error("Cannot log effective access policies of " + path, e); - } - } - - /** Returns a human-readable summary of this access control list. */ - public static String accessControlListSummary(AccessControlList acl) { - StringBuffer buf = new StringBuffer(""); - try { - for (AccessControlEntry ace : acl.getAccessControlEntries()) { - buf.append('\t').append(ace.getPrincipal().getName()) - .append('\n'); - for (Privilege priv : ace.getPrivileges()) - buf.append("\t\t").append(priv.getName()).append('\n'); - } - return buf.toString(); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot write summary of " + acl, e); - } - } - - /** - * Copies recursively the content of a node to another one. Do NOT copy the - * property values of {@link NodeType#MIX_CREATED} and - * {@link NodeType#MIX_LAST_MODIFIED}, but update the - * {@link Property#JCR_LAST_MODIFIED} and - * {@link Property#JCR_LAST_MODIFIED_BY} properties if the target node has - * the {@link NodeType#MIX_LAST_MODIFIED} mixin. - */ - public static void copy(Node fromNode, Node toNode) { - try { - if (toNode.getDefinition().isProtected()) - return; - - // process properties - PropertyIterator pit = fromNode.getProperties(); - properties: while (pit.hasNext()) { - Property fromProperty = pit.nextProperty(); - String propertyName = fromProperty.getName(); - if (toNode.hasProperty(propertyName) - && toNode.getProperty(propertyName).getDefinition() - .isProtected()) - continue properties; - - if (fromProperty.getDefinition().isProtected()) - continue properties; - - if (propertyName.equals("jcr:created") - || propertyName.equals("jcr:createdBy") - || propertyName.equals("jcr:lastModified") - || propertyName.equals("jcr:lastModifiedBy")) - continue properties; - - if (fromProperty.isMultiple()) { - toNode.setProperty(propertyName, fromProperty.getValues()); - } else { - toNode.setProperty(propertyName, fromProperty.getValue()); - } - } - - // update jcr:lastModified and jcr:lastModifiedBy in toNode in case - // they existed, before adding the mixins - updateLastModified(toNode); - - // add mixins - for (NodeType mixinType : fromNode.getMixinNodeTypes()) { - toNode.addMixin(mixinType.getName()); - } - - // process children nodes - NodeIterator nit = fromNode.getNodes(); - while (nit.hasNext()) { - Node fromChild = nit.nextNode(); - Integer index = fromChild.getIndex(); - String nodeRelPath = fromChild.getName() + "[" + index + "]"; - Node toChild; - if (toNode.hasNode(nodeRelPath)) - toChild = toNode.getNode(nodeRelPath); - else - toChild = toNode.addNode(fromChild.getName(), fromChild - .getPrimaryNodeType().getName()); - copy(fromChild, toChild); - } - } catch (RepositoryException e) { - throw new ArgeoException("Cannot copy " + fromNode + " to " - + toNode, e); - } - } - - /** - * Check whether all first-level properties (except jcr:* properties) are - * equal. Skip jcr:* properties - */ - public static Boolean allPropertiesEquals(Node reference, Node observed, - Boolean onlyCommonProperties) { - try { - PropertyIterator pit = reference.getProperties(); - props: while (pit.hasNext()) { - Property propReference = pit.nextProperty(); - String propName = propReference.getName(); - if (propName.startsWith("jcr:")) - continue props; - - if (!observed.hasProperty(propName)) - if (onlyCommonProperties) - continue props; - else - return false; - // TODO: deal with multiple property values? - if (!observed.getProperty(propName).getValue() - .equals(propReference.getValue())) - return false; - } - return true; - } catch (RepositoryException e) { - throw new ArgeoException("Cannot check all properties equals of " - + reference + " and " + observed, e); - } - } - - public static Map diffProperties(Node reference, - Node observed) { - Map diffs = new TreeMap(); - diffPropertiesLevel(diffs, null, reference, observed); - return diffs; - } - - /** - * Compare the properties of two nodes. Recursivity to child nodes is not - * yet supported. Skip jcr:* properties. - */ - static void diffPropertiesLevel(Map diffs, - String baseRelPath, Node reference, Node observed) { - try { - // check removed and modified - PropertyIterator pit = reference.getProperties(); - props: while (pit.hasNext()) { - Property p = pit.nextProperty(); - String name = p.getName(); - if (name.startsWith("jcr:")) - continue props; - - if (!observed.hasProperty(name)) { - String relPath = propertyRelPath(baseRelPath, name); - PropertyDiff pDiff = new PropertyDiff(PropertyDiff.REMOVED, - relPath, p.getValue(), null); - diffs.put(relPath, pDiff); - } else { - if (p.isMultiple()) { - // FIXME implement multiple - } else { - Value referenceValue = p.getValue(); - Value newValue = observed.getProperty(name).getValue(); - if (!referenceValue.equals(newValue)) { - String relPath = propertyRelPath(baseRelPath, name); - PropertyDiff pDiff = new PropertyDiff( - PropertyDiff.MODIFIED, relPath, - referenceValue, newValue); - diffs.put(relPath, pDiff); - } - } - } - } - // check added - pit = observed.getProperties(); - props: while (pit.hasNext()) { - Property p = pit.nextProperty(); - String name = p.getName(); - if (name.startsWith("jcr:")) - continue props; - if (!reference.hasProperty(name)) { - if (p.isMultiple()) { - // FIXME implement multiple - } else { - String relPath = propertyRelPath(baseRelPath, name); - PropertyDiff pDiff = new PropertyDiff( - PropertyDiff.ADDED, relPath, null, p.getValue()); - diffs.put(relPath, pDiff); - } - } - } - } catch (RepositoryException e) { - throw new ArgeoException("Cannot diff " + reference + " and " - + observed, e); - } - } - - /** - * Compare only a restricted list of properties of two nodes. No - * recursivity. - * - */ - public static Map diffProperties(Node reference, - Node observed, List properties) { - Map diffs = new TreeMap(); - try { - Iterator pit = properties.iterator(); - - props: while (pit.hasNext()) { - String name = pit.next(); - if (!reference.hasProperty(name)) { - if (!observed.hasProperty(name)) - continue props; - Value val = observed.getProperty(name).getValue(); - try { - // empty String but not null - if ("".equals(val.getString())) - continue props; - } catch (Exception e) { - // not parseable as String, silent - } - PropertyDiff pDiff = new PropertyDiff(PropertyDiff.ADDED, - name, null, val); - diffs.put(name, pDiff); - } else if (!observed.hasProperty(name)) { - PropertyDiff pDiff = new PropertyDiff(PropertyDiff.REMOVED, - name, reference.getProperty(name).getValue(), null); - diffs.put(name, pDiff); - } else { - Value referenceValue = reference.getProperty(name) - .getValue(); - Value newValue = observed.getProperty(name).getValue(); - if (!referenceValue.equals(newValue)) { - PropertyDiff pDiff = new PropertyDiff( - PropertyDiff.MODIFIED, name, referenceValue, - newValue); - diffs.put(name, pDiff); - } - } - } - } catch (RepositoryException e) { - throw new ArgeoException("Cannot diff " + reference + " and " - + observed, e); - } - return diffs; - } - - /** Builds a property relPath to be used in the diff. */ - private static String propertyRelPath(String baseRelPath, - String propertyName) { - if (baseRelPath == null) - return propertyName; - else - return baseRelPath + '/' + propertyName; - } - - /** - * Normalizes a name so that it can be stored in contexts not supporting - * names with ':' (typically databases). Replaces ':' by '_'. - */ - public static String normalize(String name) { - return name.replace(':', '_'); - } - - /** - * Replaces characters which are invalid in a JCR name by '_'. Currently not - * exhaustive. - * - * @see JcrUtils#INVALID_NAME_CHARACTERS - */ - public static String replaceInvalidChars(String name) { - return replaceInvalidChars(name, '_'); - } - - /** - * Replaces characters which are invalid in a JCR name. Currently not - * exhaustive. - * - * @see JcrUtils#INVALID_NAME_CHARACTERS - */ - public static String replaceInvalidChars(String name, char replacement) { - boolean modified = false; - char[] arr = name.toCharArray(); - for (int i = 0; i < arr.length; i++) { - char c = arr[i]; - invalid: for (char invalid : INVALID_NAME_CHARACTERS) { - if (c == invalid) { - arr[i] = replacement; - modified = true; - break invalid; - } - } - } - if (modified) - return new String(arr); - else - // do not create new object if unnecessary - return name; - } - - /** - * Removes forbidden characters from a path, replacing them with '_' - * - * @deprecated use {@link #replaceInvalidChars(String)} instead - */ - public static String removeForbiddenCharacters(String str) { - return str.replace('[', '_').replace(']', '_').replace('/', '_') - .replace('*', '_'); - - } - - /** Cleanly disposes a {@link Binary} even if it is null. */ - public static void closeQuietly(Binary binary) { - if (binary == null) - return; - binary.dispose(); - } - - /** Retrieve a {@link Binary} as a byte array */ - public static byte[] getBinaryAsBytes(Property property) { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - InputStream in = null; - Binary binary = null; - try { - binary = property.getBinary(); - in = binary.getStream(); - IOUtils.copy(in, out); - return out.toByteArray(); - } catch (Exception e) { - throw new ArgeoException("Cannot read binary " + property - + " as bytes", e); - } finally { - IOUtils.closeQuietly(out); - IOUtils.closeQuietly(in); - closeQuietly(binary); - } - } - - /** Writes a {@link Binary} from a byte array */ - public static void setBinaryAsBytes(Node node, String property, byte[] bytes) { - InputStream in = null; - Binary binary = null; - try { - in = new ByteArrayInputStream(bytes); - binary = node.getSession().getValueFactory().createBinary(in); - node.setProperty(property, binary); - } catch (Exception e) { - throw new ArgeoException("Cannot read binary " + property - + " as bytes", e); - } finally { - IOUtils.closeQuietly(in); - closeQuietly(binary); - } - } - - /** - * Creates depth from a string (typically a username) by adding levels based - * on its first characters: "aBcD",2 => a/aB - */ - public static String firstCharsToPath(String str, Integer nbrOfChars) { - if (str.length() < nbrOfChars) - throw new ArgeoException("String " + str - + " length must be greater or equal than " + nbrOfChars); - StringBuffer path = new StringBuffer(""); - StringBuffer curr = new StringBuffer(""); - for (int i = 0; i < nbrOfChars; i++) { - curr.append(str.charAt(i)); - path.append(curr); - if (i < nbrOfChars - 1) - path.append('/'); - } - return path.toString(); - } - - /** - * Discards the current changes in the session attached to this node. To be - * used typically in a catch block. - * - * @see #discardQuietly(Session) - */ - public static void discardUnderlyingSessionQuietly(Node node) { - try { - discardQuietly(node.getSession()); - } catch (RepositoryException e) { - log.warn("Cannot quietly discard session of node " + node + ": " - + e.getMessage()); - } - } - - /** - * Discards the current changes in a session by calling - * {@link Session#refresh(boolean)} with false, only logging - * potential errors when doing so. To be used typically in a catch block. - */ - public static void discardQuietly(Session session) { - try { - if (session != null) - session.refresh(false); - } catch (RepositoryException e) { - log.warn("Cannot quietly discard session " + session + ": " - + e.getMessage()); - } - } - - /** - * Login to a workspace with implicit credentials, creates the workspace - * with these credentials if it does not already exist. - */ - public static Session loginOrCreateWorkspace(Repository repository, - String workspaceName) throws RepositoryException { - Session workspaceSession = null; - Session defaultSession = null; - try { - try { - workspaceSession = repository.login(workspaceName); - } catch (NoSuchWorkspaceException e) { - // try to create workspace - defaultSession = repository.login(); - defaultSession.getWorkspace().createWorkspace(workspaceName); - workspaceSession = repository.login(workspaceName); - } - return workspaceSession; - } finally { - logoutQuietly(defaultSession); - } - } - - /** Logs out the session, not throwing any exception, even if it is null. */ - public static void logoutQuietly(Session session) { - try { - if (session != null) - if (session.isLive()) - session.logout(); - } catch (Exception e) { - // silent - } - } - - /** - * Convenient method to add a listener. uuids passed as null, deep=true, - * local=true, only one node type - */ - public static void addListener(Session session, EventListener listener, - int eventTypes, String basePath, String nodeType) { - try { - session.getWorkspace() - .getObservationManager() - .addEventListener( - listener, - eventTypes, - basePath, - true, - null, - nodeType == null ? null : new String[] { nodeType }, - true); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot add JCR listener " + listener - + " to session " + session, e); - } - } - - /** Removes a listener without throwing exception */ - public static void removeListenerQuietly(Session session, - EventListener listener) { - if (session == null || !session.isLive()) - return; - try { - session.getWorkspace().getObservationManager() - .removeEventListener(listener); - } catch (RepositoryException e) { - // silent - } - } - - /** - * Quietly unregisters an {@link EventListener} from the udnerlying - * workspace of this node. - */ - public static void unregisterQuietly(Node node, EventListener eventListener) { - try { - unregisterQuietly(node.getSession().getWorkspace(), eventListener); - } catch (RepositoryException e) { - // silent - if (log.isTraceEnabled()) - log.trace("Could not unregister event listener " - + eventListener); - } - } - - /** Quietly unregisters an {@link EventListener} from this workspace */ - public static void unregisterQuietly(Workspace workspace, - EventListener eventListener) { - if (eventListener == null) - return; - try { - workspace.getObservationManager() - .removeEventListener(eventListener); - } catch (RepositoryException e) { - // silent - if (log.isTraceEnabled()) - log.trace("Could not unregister event listener " - + eventListener); - } - } - - /** - * If this node is has the {@link NodeType#MIX_LAST_MODIFIED} mixin, it - * updates the {@link Property#JCR_LAST_MODIFIED} property with the current - * time and the {@link Property#JCR_LAST_MODIFIED_BY} property with the - * underlying session user id. In Jackrabbit 2.x, these properties - * are not automatically updated, hence the need for manual update. The - * session is not saved. - */ - public static void updateLastModified(Node node) { - try { - if (!node.isNodeType(NodeType.MIX_LAST_MODIFIED)) - node.addMixin(NodeType.MIX_LAST_MODIFIED); - node.setProperty(Property.JCR_LAST_MODIFIED, - new GregorianCalendar()); - node.setProperty(Property.JCR_LAST_MODIFIED_BY, node.getSession() - .getUserID()); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot update last modified on " + node, - e); - } - } - - /** - * Update lastModified recursively until this parent. - * - * @param node - * the node - * @param untilPath - * the base path, null is equivalent to "/" - */ - public static void updateLastModifiedAndParents(Node node, String untilPath) { - try { - if (untilPath != null && !node.getPath().startsWith(untilPath)) - throw new ArgeoException(node + " is not under " + untilPath); - updateLastModified(node); - if (untilPath == null) { - if (!node.getPath().equals("/")) - updateLastModifiedAndParents(node.getParent(), untilPath); - } else { - if (!node.getPath().equals(untilPath)) - updateLastModifiedAndParents(node.getParent(), untilPath); - } - } catch (RepositoryException e) { - throw new ArgeoException("Cannot update lastModified from " + node - + " until " + untilPath, e); - } - } - - /** - * Returns a String representing the short version (see Node type - * Notation attributes grammar) of the main business attributes of this - * property definition - * - * @param prop - */ - public static String getPropertyDefinitionAsString(Property prop) { - StringBuffer sbuf = new StringBuffer(); - try { - if (prop.getDefinition().isAutoCreated()) - sbuf.append("a"); - if (prop.getDefinition().isMandatory()) - sbuf.append("m"); - if (prop.getDefinition().isProtected()) - sbuf.append("p"); - if (prop.getDefinition().isMultiple()) - sbuf.append("*"); - } catch (RepositoryException re) { - throw new ArgeoException( - "unexpected error while getting property definition as String", - re); - } - return sbuf.toString(); - } - - /** - * Estimate the sub tree size from current node. Computation is based on the - * Jcr {@link Property.getLength()} method. Note : it is not the exact size - * used on the disk by the current part of the JCR Tree. - */ - - public static long getNodeApproxSize(Node node) { - long curNodeSize = 0; - try { - PropertyIterator pi = node.getProperties(); - while (pi.hasNext()) { - Property prop = pi.nextProperty(); - if (prop.isMultiple()) { - int nb = prop.getLengths().length; - for (int i = 0; i < nb; i++) { - curNodeSize += (prop.getLengths()[i] > 0 ? prop - .getLengths()[i] : 0); - } - } else - curNodeSize += (prop.getLength() > 0 ? prop.getLength() : 0); - } - - NodeIterator ni = node.getNodes(); - while (ni.hasNext()) - curNodeSize += getNodeApproxSize(ni.nextNode()); - return curNodeSize; - } catch (RepositoryException re) { - throw new ArgeoException( - "Unexpected error while recursively determining node size.", - re); - } - } - - /* - * SECURITY - */ - - /** - * Convenience method for adding a single privilege to a principal (user or - * role), typically jcr:all - */ - public synchronized static void addPrivilege(Session session, String path, - String principal, String privilege) throws RepositoryException { - List privileges = new ArrayList(); - privileges.add(session.getAccessControlManager().privilegeFromName( - privilege)); - addPrivileges(session, path, new SimplePrincipal(principal), privileges); - } - - /** - * Add privileges on a path to a {@link Principal}. The path must already - * exist. Session is saved. Synchronized to prevent concurrent modifications - * of the same node. - */ - public synchronized static Boolean addPrivileges(Session session, - String path, Principal principal, List privs) - throws RepositoryException { - // make sure the session is in line with the persisted state - session.refresh(false); - AccessControlManager acm = session.getAccessControlManager(); - AccessControlList acl = getAccessControlList(acm, path); - - accessControlEntries: for (AccessControlEntry ace : acl - .getAccessControlEntries()) { - Principal currentPrincipal = ace.getPrincipal(); - if (currentPrincipal.getName().equals(principal.getName())) { - Privilege[] currentPrivileges = ace.getPrivileges(); - if (currentPrivileges.length != privs.size()) - break accessControlEntries; - for (int i = 0; i < currentPrivileges.length; i++) { - Privilege currP = currentPrivileges[i]; - Privilege p = privs.get(i); - if (!currP.getName().equals(p.getName())) { - break accessControlEntries; - } - } - return false; - } - } - - Privilege[] privileges = privs.toArray(new Privilege[privs.size()]); - acl.addAccessControlEntry(principal, privileges); - acm.setPolicy(path, acl); - if (log.isDebugEnabled()) { - StringBuffer privBuf = new StringBuffer(); - for (Privilege priv : privs) - privBuf.append(priv.getName()); - log.debug("Added privileges " + privBuf + " to " - + principal.getName() + " on " + path + " in '" - + session.getWorkspace().getName() + "'"); - } - session.refresh(true); - session.save(); - return true; - } - - /** Gets access control list for this path, throws exception if not found */ - public synchronized static AccessControlList getAccessControlList( - AccessControlManager acm, String path) throws RepositoryException { - // search for an access control list - AccessControlList acl = null; - AccessControlPolicyIterator policyIterator = acm - .getApplicablePolicies(path); - if (policyIterator.hasNext()) { - while (policyIterator.hasNext()) { - AccessControlPolicy acp = policyIterator - .nextAccessControlPolicy(); - if (acp instanceof AccessControlList) - acl = ((AccessControlList) acp); - } - } else { - AccessControlPolicy[] existingPolicies = acm.getPolicies(path); - for (AccessControlPolicy acp : existingPolicies) { - if (acp instanceof AccessControlList) - acl = ((AccessControlList) acp); - } - } - if (acl != null) - return acl; - else - throw new ArgeoException("ACL not found at " + path); - } - - /** Clear authorizations for a user at this path */ - public synchronized static void clearAccessControList(Session session, - String path, String username) throws RepositoryException { - AccessControlManager acm = session.getAccessControlManager(); - AccessControlList acl = getAccessControlList(acm, path); - for (AccessControlEntry ace : acl.getAccessControlEntries()) { - if (ace.getPrincipal().getName().equals(username)) { - acl.removeAccessControlEntry(ace); - } - } - } - - /* - * FILES UTILITIES - */ - /** - * Creates the nodes making the path as {@link NodeType#NT_FOLDER} - */ - public static Node mkfolders(Session session, String path) { - return mkdirs(session, path, NodeType.NT_FOLDER, NodeType.NT_FOLDER, - false); - } - - /** - * Copy only nt:folder and nt:file, without their additional types and - * properties. - * - * @param recursive - * if true copies folders as well, otherwise only first level - * files - * @return how many files were copied - */ - @SuppressWarnings("resource") - public static Long copyFiles(Node fromNode, Node toNode, Boolean recursive, - ArgeoMonitor monitor) { - long count = 0l; - - Binary binary = null; - InputStream in = null; - try { - NodeIterator fromChildren = fromNode.getNodes(); - while (fromChildren.hasNext()) { - if (monitor != null && monitor.isCanceled()) - throw new ArgeoException( - "Copy cancelled before it was completed"); - - Node fromChild = fromChildren.nextNode(); - String fileName = fromChild.getName(); - if (fromChild.isNodeType(NodeType.NT_FILE)) { - if (monitor != null) - monitor.subTask("Copy " + fileName); - binary = fromChild.getNode(Node.JCR_CONTENT) - .getProperty(Property.JCR_DATA).getBinary(); - in = binary.getStream(); - copyStreamAsFile(toNode, fileName, in); - IOUtils.closeQuietly(in); - closeQuietly(binary); - - // save session - toNode.getSession().save(); - count++; - - if (log.isDebugEnabled()) - log.debug("Copied file " + fromChild.getPath()); - if (monitor != null) - monitor.worked(1); - } else if (fromChild.isNodeType(NodeType.NT_FOLDER) - && recursive) { - Node toChildFolder; - if (toNode.hasNode(fileName)) { - toChildFolder = toNode.getNode(fileName); - if (!toChildFolder.isNodeType(NodeType.NT_FOLDER)) - throw new ArgeoException(toChildFolder - + " is not of type nt:folder"); - } else { - toChildFolder = toNode.addNode(fileName, - NodeType.NT_FOLDER); - - // save session - toNode.getSession().save(); - } - count = count - + copyFiles(fromChild, toChildFolder, recursive, - monitor); - } - } - return count; - } catch (RepositoryException e) { - throw new ArgeoException("Cannot copy files between " + fromNode - + " and " + toNode); - } finally { - // in case there was an exception - IOUtils.closeQuietly(in); - closeQuietly(binary); - } - } - - /** - * Iteratively count all file nodes in subtree, inefficient but can be - * useful when query are poorly supported, such as in remoting. - */ - public static Long countFiles(Node node) { - Long localCount = 0l; - try { - for (NodeIterator nit = node.getNodes(); nit.hasNext();) { - Node child = nit.nextNode(); - if (child.isNodeType(NodeType.NT_FOLDER)) - localCount = localCount + countFiles(child); - else if (child.isNodeType(NodeType.NT_FILE)) - localCount = localCount + 1; - } - } catch (RepositoryException e) { - throw new ArgeoException("Cannot count all children of " + node); - } - return localCount; - } - - /** - * Copy a file as an nt:file, assuming an nt:folder hierarchy. The session - * is NOT saved. - * - * @return the created file node - */ - public static Node copyFile(Node folderNode, File file) { - InputStream in = null; - try { - in = new FileInputStream(file); - return copyStreamAsFile(folderNode, file.getName(), in); - } catch (IOException e) { - throw new ArgeoException("Cannot copy file " + file + " under " - + folderNode, e); - } finally { - IOUtils.closeQuietly(in); - } - } - - /** Copy bytes as an nt:file */ - public static Node copyBytesAsFile(Node folderNode, String fileName, - byte[] bytes) { - InputStream in = null; - try { - in = new ByteArrayInputStream(bytes); - return copyStreamAsFile(folderNode, fileName, in); - } catch (Exception e) { - throw new ArgeoException("Cannot copy file " + fileName + " under " - + folderNode, e); - } finally { - IOUtils.closeQuietly(in); - } - } - - /** - * Copy a stream as an nt:file, assuming an nt:folder hierarchy. The session - * is NOT saved. - * - * @return the created file node - */ - public static Node copyStreamAsFile(Node folderNode, String fileName, - InputStream in) { - Binary binary = null; - try { - Node fileNode; - Node contentNode; - if (folderNode.hasNode(fileName)) { - fileNode = folderNode.getNode(fileName); - if (!fileNode.isNodeType(NodeType.NT_FILE)) - throw new ArgeoException(fileNode - + " is not of type nt:file"); - // we assume that the content node is already there - contentNode = fileNode.getNode(Node.JCR_CONTENT); - } else { - fileNode = folderNode.addNode(fileName, NodeType.NT_FILE); - contentNode = fileNode.addNode(Node.JCR_CONTENT, - NodeType.NT_RESOURCE); - } - binary = contentNode.getSession().getValueFactory() - .createBinary(in); - contentNode.setProperty(Property.JCR_DATA, binary); - return fileNode; - } catch (Exception e) { - throw new ArgeoException("Cannot create file node " + fileName - + " under " + folderNode, e); - } finally { - closeQuietly(binary); - } - } - - /** Computes the checksum of an nt:file */ - public static String checksumFile(Node fileNode, String algorithm) { - Binary data = null; - InputStream in = null; - try { - data = fileNode.getNode(Node.JCR_CONTENT) - .getProperty(Property.JCR_DATA).getBinary(); - in = data.getStream(); - return DigestUtils.digest(algorithm, in); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot checksum file " + fileNode, e); - } finally { - IOUtils.closeQuietly(in); - closeQuietly(data); - } - } - -} diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/MaintainedRepository.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/MaintainedRepository.java deleted file mode 100644 index 702d47a5c..000000000 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/MaintainedRepository.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.argeo.jcr; - -import javax.jcr.Repository; - -/** Abstracts maintenance operations on a {@link Repository} */ -public interface MaintainedRepository extends Repository { - -} diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/NodeMapper.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/NodeMapper.java deleted file mode 100644 index af792c3ca..000000000 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/NodeMapper.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr; - -import javax.jcr.Node; -import javax.jcr.Session; - -public interface NodeMapper { - public Object load(Node node); - - public void update(Node node, Object obj); - - public Node save(Session session, String path, Object obj); - - public void setNodeMapperProvider(NodeMapperProvider nmp); -} diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/NodeMapperProvider.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/NodeMapperProvider.java deleted file mode 100644 index 07e623bfd..000000000 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/NodeMapperProvider.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr; - -import javax.jcr.Node; - -/** Provides a node mapper relevant for this node. */ -public interface NodeMapperProvider { - - /** - * Node Mapper is chosen regarding the Jcr path of the node parameter - * @param Node node - * @return the node mapper or null if no relevant node mapper can be found. */ - public NodeMapper findNodeMapper(Node node); -} diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/PropertyDiff.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/PropertyDiff.java deleted file mode 100644 index bdd316f31..000000000 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/PropertyDiff.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr; - -import javax.jcr.Value; - -import org.argeo.ArgeoException; - -/** The result of the comparison of two JCR properties. */ -public class PropertyDiff { - public final static Integer MODIFIED = 0; - public final static Integer ADDED = 1; - public final static Integer REMOVED = 2; - - private final Integer type; - private final String relPath; - private final Value referenceValue; - private final Value newValue; - - public PropertyDiff(Integer type, String relPath, Value referenceValue, - Value newValue) { - super(); - - if (type == MODIFIED) { - if (referenceValue == null || newValue == null) - throw new ArgeoException( - "Reference and new values must be specified."); - } else if (type == ADDED) { - if (referenceValue != null || newValue == null) - throw new ArgeoException( - "New value and only it must be specified."); - } else if (type == REMOVED) { - if (referenceValue == null || newValue != null) - throw new ArgeoException( - "Reference value and only it must be specified."); - } else { - throw new ArgeoException("Unkown diff type " + type); - } - - if (relPath == null) - throw new ArgeoException("Relative path must be specified"); - - this.type = type; - this.relPath = relPath; - this.referenceValue = referenceValue; - this.newValue = newValue; - } - - public Integer getType() { - return type; - } - - public String getRelPath() { - return relPath; - } - - public Value getReferenceValue() { - return referenceValue; - } - - public Value getNewValue() { - return newValue; - } - -} diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/RepositoryRegister.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/RepositoryRegister.java deleted file mode 100644 index 2e3d4550d..000000000 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/RepositoryRegister.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr; - -import java.util.Map; - -import javax.jcr.Repository; -import javax.jcr.RepositoryFactory; - -/** Allows to register repositories by name. */ -public interface RepositoryRegister extends RepositoryFactory { - /** - * The registered {@link Repository} as a read-only map. Note that this - * method should be called for each access in order to be sure to be up to - * date in case repositories have registered/unregistered - */ - public Map getRepositories(); -} diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ThreadBoundJcrSessionFactory.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ThreadBoundJcrSessionFactory.java deleted file mode 100644 index 193f22c48..000000000 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ThreadBoundJcrSessionFactory.java +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import javax.jcr.LoginException; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.SimpleCredentials; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.ArgeoException; - -/** Proxy JCR sessions and attach them to calling threads. */ -public abstract class ThreadBoundJcrSessionFactory { - private final static Log log = LogFactory - .getLog(ThreadBoundJcrSessionFactory.class); - - private Repository repository; - /** can be injected as list, only used if repository is null */ - private List repositories; - - private ThreadLocal session = new ThreadLocal(); - private final Session proxiedSession; - /** If workspace is null, default will be used. */ - private String workspace = null; - - private String defaultUsername = "demo"; - private String defaultPassword = "demo"; - private Boolean forceDefaultCredentials = false; - - private boolean active = true; - - // monitoring - private final List threads = Collections - .synchronizedList(new ArrayList()); - private final Map activeSessions = Collections - .synchronizedMap(new HashMap()); - private MonitoringThread monitoringThread; - - public ThreadBoundJcrSessionFactory() { - Class[] interfaces = { Session.class }; - proxiedSession = (Session) Proxy.newProxyInstance( - ThreadBoundJcrSessionFactory.class.getClassLoader(), - interfaces, new JcrSessionInvocationHandler()); - } - - /** Logs in to the repository using various strategies. */ - protected synchronized Session login() { - if (!isActive()) - throw new ArgeoException("Thread bound session factory inactive"); - - // discard session previously attached to this thread - Thread thread = Thread.currentThread(); - if (activeSessions.containsKey(thread.getId())) { - Session oldSession = activeSessions.remove(thread.getId()); - oldSession.logout(); - session.remove(); - } - - Session newSession = null; - // first try to login without credentials, assuming the underlying login - // module will have dealt with authentication (typically using Spring - // Security) - if (!forceDefaultCredentials) - try { - newSession = repository().login(workspace); - } catch (LoginException e1) { - log.warn("Cannot login without credentials: " + e1.getMessage()); - // invalid credentials, go to the next step - } catch (RepositoryException e1) { - // other kind of exception, fail - throw new ArgeoException("Cannot log in to repository", e1); - } - - // log using default username / password (useful for testing purposes) - if (newSession == null) - try { - SimpleCredentials sc = new SimpleCredentials(defaultUsername, - defaultPassword.toCharArray()); - newSession = repository().login(sc, workspace); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot log in to repository", e); - } - - session.set(newSession); - // Log and monitor new session - if (log.isTraceEnabled()) - log.trace("Logged in to JCR session " + newSession + "; userId=" - + newSession.getUserID()); - - // monitoring - activeSessions.put(thread.getId(), newSession); - threads.add(thread); - return newSession; - } - - public Object getObject() { - return proxiedSession; - } - - public void init() throws Exception { - monitoringThread = new MonitoringThread(); - monitoringThread.start(); - } - - public synchronized void dispose() throws Exception { - if (activeSessions.size() == 0) - return; - - if (log.isTraceEnabled()) - log.trace("Cleaning up " + activeSessions.size() - + " active JCR sessions..."); - - deactivate(); - for (Session sess : activeSessions.values()) { - JcrUtils.logoutQuietly(sess); - } - activeSessions.clear(); - } - - protected Boolean isActive() { - return active; - } - - protected synchronized void deactivate() { - active = false; - notifyAll(); - } - - protected synchronized void removeSession(Thread thread) { - if (!isActive()) - return; - activeSessions.remove(thread.getId()); - threads.remove(thread); - } - - protected synchronized void cleanDeadThreads() { - if (!isActive()) - return; - Iterator it = threads.iterator(); - while (it.hasNext()) { - Thread thread = it.next(); - if (!thread.isAlive() && isActive()) { - if (activeSessions.containsKey(thread.getId())) { - Session session = activeSessions.get(thread.getId()); - activeSessions.remove(thread.getId()); - session.logout(); - if (log.isTraceEnabled()) - log.trace("Cleaned up JCR session (userID=" - + session.getUserID() + ") from dead thread " - + thread.getId()); - } - it.remove(); - } - } - try { - wait(1000); - } catch (InterruptedException e) { - // silent - } - } - - public Class getObjectType() { - return Session.class; - } - - public boolean isSingleton() { - return true; - } - - /** - * Called before a method is actually called, allowing to check the session - * or re-login it (e.g. if authentication has changed). The default - * implementation returns the session. - */ - protected Session preCall(Session session) { - return session; - } - - protected Repository repository() { - if (repository != null) - return repository; - if (repositories != null) { - // hardened for OSGi dynamic services - Iterator it = repositories.iterator(); - if (it.hasNext()) - return it.next(); - } - throw new ArgeoException("No repository injected"); - } - - // /** Useful for declarative registration of OSGi services (blueprint) */ - // public void register(Repository repository, Map params) { - // this.repository = repository; - // } - // - // /** Useful for declarative registration of OSGi services (blueprint) */ - // public void unregister(Repository repository, Map params) { - // this.repository = null; - // } - - public void setRepository(Repository repository) { - this.repository = repository; - } - - public void setRepositories(List repositories) { - this.repositories = repositories; - } - - public void setDefaultUsername(String defaultUsername) { - this.defaultUsername = defaultUsername; - } - - public void setDefaultPassword(String defaultPassword) { - this.defaultPassword = defaultPassword; - } - - public void setForceDefaultCredentials(Boolean forceDefaultCredentials) { - this.forceDefaultCredentials = forceDefaultCredentials; - } - - public void setWorkspace(String workspace) { - this.workspace = workspace; - } - - protected class JcrSessionInvocationHandler implements InvocationHandler { - - public Object invoke(Object proxy, Method method, Object[] args) - throws Throwable, RepositoryException { - Session threadSession = session.get(); - if (threadSession == null) { - if ("logout".equals(method.getName()))// no need to login - return Void.TYPE; - else if ("toString".equals(method.getName()))// maybe logging - return "Uninitialized Argeo thread bound JCR session"; - threadSession = login(); - } - - preCall(threadSession); - Object ret; - try { - ret = method.invoke(threadSession, args); - } catch (InvocationTargetException e) { - Throwable cause = e.getCause(); - if (cause instanceof RepositoryException) - throw (RepositoryException) cause; - else - throw cause; - } - if ("logout".equals(method.getName())) { - session.remove(); - Thread thread = Thread.currentThread(); - removeSession(thread); - if (log.isTraceEnabled()) - log.trace("Logged out JCR session (userId=" - + threadSession.getUserID() + ") on thread " - + thread.getId()); - } - return ret; - } - } - - /** Monitors registered thread in order to clean up dead ones. */ - private class MonitoringThread extends Thread { - - public MonitoringThread() { - super("ThreadBound JCR Session Monitor"); - } - - @Override - public void run() { - while (isActive()) { - cleanDeadThreads(); - } - } - - } -} diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/UserJcrUtils.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/UserJcrUtils.java deleted file mode 100644 index 1758802f8..000000000 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/UserJcrUtils.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.query.Query; -import javax.jcr.query.qom.Constraint; -import javax.jcr.query.qom.DynamicOperand; -import javax.jcr.query.qom.QueryObjectModelFactory; -import javax.jcr.query.qom.Selector; -import javax.jcr.query.qom.StaticOperand; - -import org.argeo.ArgeoException; - -/** Utilities related to the user home and properties based on Argeo JCR model. */ -public class UserJcrUtils { - /** The home base path. Not yet configurable */ - public final static String DEFAULT_HOME_BASE_PATH = "/home"; - - /** - * Returns the home node of the user or null if none was found. - * - * @param session - * the session to use in order to perform the search, this can be - * a session with a different user ID than the one searched, - * typically when a system or admin session is used. - * @param username - * the username of the user - */ - public static Node getUserHome(Session session, String username) { - try { - // String homePath = UserJcrUtils.getUserHomePath(username); - // return session.itemExists(homePath) ? session.getNode(homePath) - // : null; - // kept for example of QOM queries - QueryObjectModelFactory qomf = session.getWorkspace() - .getQueryManager().getQOMFactory(); - Selector userHomeSel = qomf.selector(ArgeoTypes.ARGEO_USER_HOME, - "userHome"); - DynamicOperand userIdDop = qomf.propertyValue( - userHomeSel.getSelectorName(), ArgeoNames.ARGEO_USER_ID); - StaticOperand userIdSop = qomf.literal(session.getValueFactory() - .createValue(username)); - Constraint constraint = qomf.comparison(userIdDop, - QueryObjectModelFactory.JCR_OPERATOR_EQUAL_TO, userIdSop); - Query query = qomf.createQuery(userHomeSel, constraint, null, null); - return JcrUtils.querySingleNode(query); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot find home for user " + username, e); - } - } - - public static Node getUserProfile(Session session, String username) { - try { - QueryObjectModelFactory qomf = session.getWorkspace() - .getQueryManager().getQOMFactory(); - Selector userHomeSel = qomf.selector(ArgeoTypes.ARGEO_USER_PROFILE, - "userProfile"); - DynamicOperand userIdDop = qomf.propertyValue( - userHomeSel.getSelectorName(), ArgeoNames.ARGEO_USER_ID); - StaticOperand userIdSop = qomf.literal(session.getValueFactory() - .createValue(username)); - Constraint constraint = qomf.comparison(userIdDop, - QueryObjectModelFactory.JCR_OPERATOR_EQUAL_TO, userIdSop); - Query query = qomf.createQuery(userHomeSel, constraint, null, null); - return JcrUtils.querySingleNode(query); - } catch (RepositoryException e) { - throw new ArgeoException( - "Cannot find profile for user " + username, e); - } - } - - /** Returns the home node of the session user or null if none was found. */ - public static Node getUserHome(Session session) { - String userID = session.getUserID(); - return getUserHome(session, userID); - } - - private UserJcrUtils() { - } -} diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/VersionDiff.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/VersionDiff.java deleted file mode 100644 index e6ae9130b..000000000 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/VersionDiff.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr; - -import java.util.Calendar; -import java.util.Map; - -/** - * Generic Object that enables the creation of history reports based on a JCR - * versionable node. userId and creation date are added to the map of - * PropertyDiff. - * - * These two fields might be null - * - */ -public class VersionDiff { - - private String userId; - private Map diffs; - private Calendar updateTime; - - public VersionDiff(String userId, Calendar updateTime, - Map diffs) { - this.userId = userId; - this.updateTime = updateTime; - this.diffs = diffs; - } - - public String getUserId() { - return userId; - } - - public Map getDiffs() { - return diffs; - } - - public Calendar getUpdateTime() { - return updateTime; - } -} diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/proxy/AbstractUrlProxy.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/proxy/AbstractUrlProxy.java deleted file mode 100644 index 8a66f3102..000000000 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/proxy/AbstractUrlProxy.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.proxy; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; - -import javax.jcr.Binary; -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.nodetype.NodeType; - -import org.apache.commons.io.IOUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.ArgeoException; -import org.argeo.jcr.JcrUtils; - -/** Base class for URL based proxys. */ -public abstract class AbstractUrlProxy implements ResourceProxy { - private final static Log log = LogFactory.getLog(AbstractUrlProxy.class); - - private Repository jcrRepository; - private Session jcrAdminSession; - private String proxyWorkspace = "proxy"; - - protected abstract Node retrieve(Session session, String path); - - void init() { - try { - jcrAdminSession = JcrUtils.loginOrCreateWorkspace(jcrRepository, - proxyWorkspace); - beforeInitSessionSave(jcrAdminSession); - if (jcrAdminSession.hasPendingChanges()) - jcrAdminSession.save(); - } catch (Exception e) { - JcrUtils.discardQuietly(jcrAdminSession); - throw new ArgeoException("Cannot initialize Maven proxy", e); - } - } - - /** - * Called before the (admin) session is saved at the end of the - * initialization. Does nothing by default, to be overridden. - */ - protected void beforeInitSessionSave(Session session) - throws RepositoryException { - } - - void destroy() { - JcrUtils.logoutQuietly(jcrAdminSession); - } - - /** - * Called before the (admin) session is logged out when resources are - * released. Does nothing by default, to be overridden. - */ - protected void beforeDestroySessionLogout() throws RepositoryException { - } - - public Node proxy(String path) { - // we open a JCR session with client credentials in order not to use the - // admin session in multiple thread or make it a bottleneck. - Node nodeAdmin = null; - Node nodeClient = null; - Session clientSession = null; - try { - clientSession = jcrRepository.login(proxyWorkspace); - if (!clientSession.itemExists(path) - || shouldUpdate(clientSession, path)) { - nodeAdmin = retrieveAndSave(path); - if (nodeAdmin != null) - nodeClient = clientSession.getNode(path); - } else - nodeClient = clientSession.getNode(path); - return nodeClient; - } catch (RepositoryException e) { - throw new ArgeoException("Cannot proxy " + path, e); - } finally { - if (nodeClient == null) - JcrUtils.logoutQuietly(clientSession); - } - } - - protected synchronized Node retrieveAndSave(String path) { - try { - Node node = retrieve(jcrAdminSession, path); - if (node == null) - return null; - jcrAdminSession.save(); - return node; - } catch (RepositoryException e) { - JcrUtils.discardQuietly(jcrAdminSession); - throw new ArgeoException("Cannot retrieve and save " + path, e); - } finally { - notifyAll(); - } - } - - /** Session is not saved */ - protected synchronized Node proxyUrl(Session session, String remoteUrl, - String path) throws RepositoryException { - Node node = null; - if (session.itemExists(path)) { - // throw new ArgeoException("Node " + path + " already exists"); - } - InputStream in = null; - try { - URL u = new URL(remoteUrl); - in = u.openStream(); - node = importFile(session, path, in); - } catch (IOException e) { - if (log.isDebugEnabled()) { - log.debug("Cannot read " + remoteUrl + ", skipping... " - + e.getMessage()); - // log.trace("Cannot read because of ", e); - } - JcrUtils.discardQuietly(session); - } finally { - IOUtils.closeQuietly(in); - } - return node; - } - - protected synchronized Node importFile(Session session, String path, - InputStream in) throws RepositoryException { - Binary binary = null; - try { - Node content = null; - Node node = null; - if (!session.itemExists(path)) { - node = JcrUtils.mkdirs(session, path, NodeType.NT_FILE, - NodeType.NT_FOLDER, false); - content = node.addNode(Node.JCR_CONTENT, NodeType.NT_RESOURCE); - } else { - node = session.getNode(path); - content = node.getNode(Node.JCR_CONTENT); - } - binary = session.getValueFactory().createBinary(in); - content.setProperty(Property.JCR_DATA, binary); - JcrUtils.updateLastModifiedAndParents(node, null); - return node; - } finally { - JcrUtils.closeQuietly(binary); - } - } - - /** Whether the file should be updated. */ - protected Boolean shouldUpdate(Session clientSession, String nodePath) { - return false; - } - - public void setJcrRepository(Repository jcrRepository) { - this.jcrRepository = jcrRepository; - } - - public void setProxyWorkspace(String localWorkspace) { - this.proxyWorkspace = localWorkspace; - } - -} diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/proxy/ResourceProxy.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/proxy/ResourceProxy.java deleted file mode 100644 index b4fb33286..000000000 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/proxy/ResourceProxy.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.proxy; - -import javax.jcr.Node; - -/** A proxy which nows how to resolve and synchronize relative URLs */ -public interface ResourceProxy { - /** - * Proxy the file referenced by this relative path in the underlying - * repository. A new session is created by each call, so the underlying - * session of the returned node must be closed by the caller. - * - * @return the proxied Node, null if the resource was not found - * (e.g. HTTP 404) - */ - public Node proxy(String relativePath); -} diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/security/JcrAuthorizations.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/security/JcrAuthorizations.java deleted file mode 100644 index 491f8a6fe..000000000 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/security/JcrAuthorizations.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.security; - -import java.security.Principal; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.security.AccessControlManager; -import javax.jcr.security.Privilege; - -import org.argeo.ArgeoException; -import org.argeo.jcr.JcrUtils; -import org.argeo.util.security.SimplePrincipal; - -/** Apply authorizations to a JCR repository. */ -public class JcrAuthorizations implements Runnable { - // private final static Log log = - // LogFactory.getLog(JcrAuthorizations.class); - - private Repository repository; - private String workspace = null; - - private String securityWorkspace = "security"; - - /** - * key := privilege1,privilege2/path/to/node
- * value := group1,group2,user1 - */ - private Map principalPrivileges = new HashMap(); - - public void run() { - String currentWorkspace = workspace; - Session session = null; - try { - if (workspace != null && workspace.equals("*")) { - session = repository.login(); - String[] workspaces = session.getWorkspace() - .getAccessibleWorkspaceNames(); - JcrUtils.logoutQuietly(session); - for (String wksp : workspaces) { - currentWorkspace = wksp; - if (currentWorkspace.equals(securityWorkspace)) - continue; - session = repository.login(currentWorkspace); - initAuthorizations(session); - JcrUtils.logoutQuietly(session); - } - } else { - session = repository.login(workspace); - initAuthorizations(session); - } - } catch (Exception e) { - JcrUtils.discardQuietly(session); - throw new ArgeoException( - "Cannot set authorizations " + principalPrivileges - + " on workspace " + currentWorkspace, e); - } finally { - JcrUtils.logoutQuietly(session); - } - } - - protected void processWorkspace(String workspace) { - Session session = null; - try { - session = repository.login(workspace); - initAuthorizations(session); - } catch (Exception e) { - JcrUtils.discardQuietly(session); - throw new ArgeoException("Cannot set authorizations " - + principalPrivileges + " on repository " + repository, e); - } finally { - JcrUtils.logoutQuietly(session); - } - } - - /** @deprecated call {@link #run()} instead. */ - @Deprecated - public void init() { - run(); - } - - protected void initAuthorizations(Session session) - throws RepositoryException { - AccessControlManager acm = session.getAccessControlManager(); - - for (String privileges : principalPrivileges.keySet()) { - String path = null; - int slashIndex = privileges.indexOf('/'); - if (slashIndex == 0) { - throw new ArgeoException("Privilege " + privileges - + " badly formatted it starts with /"); - } else if (slashIndex > 0) { - path = privileges.substring(slashIndex); - privileges = privileges.substring(0, slashIndex); - } - - if (path == null) - path = "/"; - - List privs = new ArrayList(); - for (String priv : privileges.split(",")) { - privs.add(acm.privilegeFromName(priv)); - } - - String principalNames = principalPrivileges.get(privileges); - for (String principalName : principalNames.split(",")) { - Principal principal = getOrCreatePrincipal(session, - principalName); - JcrUtils.addPrivileges(session, path, principal, privs); - // if (log.isDebugEnabled()) { - // StringBuffer privBuf = new StringBuffer(); - // for (Privilege priv : privs) - // privBuf.append(priv.getName()); - // log.debug("Added privileges " + privBuf + " to " - // + principal.getName() + " on " + path + " in '" - // + session.getWorkspace().getName() + "'"); - // } - } - } - - // if (log.isDebugEnabled()) - // log.debug("JCR authorizations applied on '" - // + session.getWorkspace().getName() + "'"); - } - - /** - * Returns a {@link SimplePrincipal}, does not check whether it exists since - * such capabilities is not provided by the standard JCR API. Can be - * overridden to provide smarter handling - */ - protected Principal getOrCreatePrincipal(Session session, - String principalName) throws RepositoryException { - return new SimplePrincipal(principalName); - } - - // public static void addPrivileges(Session session, Principal principal, - // String path, List privs) throws RepositoryException { - // AccessControlManager acm = session.getAccessControlManager(); - // // search for an access control list - // AccessControlList acl = null; - // AccessControlPolicyIterator policyIterator = acm - // .getApplicablePolicies(path); - // if (policyIterator.hasNext()) { - // while (policyIterator.hasNext()) { - // AccessControlPolicy acp = policyIterator - // .nextAccessControlPolicy(); - // if (acp instanceof AccessControlList) - // acl = ((AccessControlList) acp); - // } - // } else { - // AccessControlPolicy[] existingPolicies = acm.getPolicies(path); - // for (AccessControlPolicy acp : existingPolicies) { - // if (acp instanceof AccessControlList) - // acl = ((AccessControlList) acp); - // } - // } - // - // if (acl != null) { - // acl.addAccessControlEntry(principal, - // privs.toArray(new Privilege[privs.size()])); - // acm.setPolicy(path, acl); - // session.save(); - // if (log.isDebugEnabled()) { - // StringBuffer buf = new StringBuffer(""); - // for (int i = 0; i < privs.size(); i++) { - // if (i != 0) - // buf.append(','); - // buf.append(privs.get(i).getName()); - // } - // log.debug("Added privilege(s) '" + buf + "' to '" - // + principal.getName() + "' on " + path - // + " from workspace '" - // + session.getWorkspace().getName() + "'"); - // } - // } else { - // throw new ArgeoException("Don't know how to apply privileges " - // + privs + " to " + principal + " on " + path - // + " from workspace '" + session.getWorkspace().getName() - // + "'"); - // } - // } - - @Deprecated - public void setGroupPrivileges(Map groupPrivileges) { - this.principalPrivileges = groupPrivileges; - } - - public void setPrincipalPrivileges(Map principalPrivileges) { - this.principalPrivileges = principalPrivileges; - } - - public void setRepository(Repository repository) { - this.repository = repository; - } - - public void setWorkspace(String workspace) { - this.workspace = workspace; - } - - public void setSecurityWorkspace(String securityWorkspace) { - this.securityWorkspace = securityWorkspace; - } - -} diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/spring/BeanNodeMapper.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/spring/BeanNodeMapper.java deleted file mode 100644 index 9f70f5c58..000000000 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/spring/BeanNodeMapper.java +++ /dev/null @@ -1,649 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.spring; - -import java.beans.PropertyDescriptor; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.StringTokenizer; - -import javax.jcr.Binary; -import javax.jcr.ItemNotFoundException; -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.Property; -import javax.jcr.PropertyIterator; -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.Value; -import javax.jcr.ValueFactory; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.ArgeoException; -import org.argeo.jcr.JcrUtils; -import org.argeo.jcr.NodeMapper; -import org.argeo.jcr.NodeMapperProvider; -import org.springframework.beans.BeanWrapper; -import org.springframework.beans.BeanWrapperImpl; - -public class BeanNodeMapper implements NodeMapper { - private final static Log log = LogFactory.getLog(BeanNodeMapper.class); - - private final static String NODE_VALUE = "value"; - - // private String keyNode = "bean:key"; - private String uuidProperty = "uuid"; - private String classProperty = "class"; - - private Boolean versioning = false; - private Boolean strictUuidReference = false; - - // TODO define a primaryNodeType Strategy - private String primaryNodeType = null; - - private ClassLoader classLoader = getClass().getClassLoader(); - - private NodeMapperProvider nodeMapperProvider; - - /** - * exposed method to retrieve a bean from a node - */ - public Object load(Node node) { - try { - if (nodeMapperProvider != null) { - NodeMapper nodeMapper = nodeMapperProvider.findNodeMapper(node); - if (nodeMapper != this) { - return nodeMapper.load(node); - } - } - return nodeToBean(node); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot load object from node " + node, e); - } - } - - /** Update an existing node with an object */ - public void update(Node node, Object obj) { - try { - if (nodeMapperProvider != null) { - - NodeMapper nodeMapper = nodeMapperProvider.findNodeMapper(node); - if (nodeMapper != this) { - nodeMapper.update(node, obj); - } else - beanToNode(createBeanWrapper(obj), node); - } else - beanToNode(createBeanWrapper(obj), node); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot update node " + node + " with " - + obj, e); - } - } - - /** - * if no storage path is given; we use canonical path - * - * @see this.storagePath() - */ - public Node save(Session session, Object obj) { - return save(session, storagePath(obj), obj); - } - - /** - * Create a new node to store an object. If the parentNode doesn't exist, it - * is created - * - * the primaryNodeType may be initialized before - */ - public Node save(Session session, String path, Object obj) { - try { - final Node node; - String parentPath = JcrUtils.parentPath(path); - // find or create parent node - Node parentNode; - if (session.itemExists(path)) - parentNode = (Node) session.getItem(parentPath); - else { - parentNode = JcrUtils.mkdirs(session, parentPath, null, null, - versioning); - } - // create node - - if (primaryNodeType != null) - node = parentNode.addNode(JcrUtils.lastPathElement(path), - primaryNodeType); - else - node = parentNode.addNode(JcrUtils.lastPathElement(path)); - - // Check specific cases - if (nodeMapperProvider != null) { - NodeMapper nodeMapper = nodeMapperProvider.findNodeMapper(node); - if (nodeMapper != this) { - nodeMapper.update(node, obj); - return node; - } - } - update(node, obj); - return node; - } catch (ArgeoException e) { - throw e; - } catch (Exception e) { - throw new ArgeoException("Cannot save or update " + obj + " under " - + path, e); - } - } - - /** - * Parse the FQN of a class to string with '/' delimiters Prefix the - * returned string with "/objects/" - */ - public String storagePath(Object obj) { - String clss = obj.getClass().getName(); - StringBuffer buf = new StringBuffer("/objects/"); - StringTokenizer st = new StringTokenizer(clss, "."); - while (st.hasMoreTokens()) { - buf.append(st.nextToken()).append('/'); - } - buf.append(obj.toString()); - return buf.toString(); - } - - @SuppressWarnings("unchecked") - /** - * Transforms a node into an object of the class defined by classProperty Property - */ - protected Object nodeToBean(Node node) throws RepositoryException { - if (log.isTraceEnabled()) - log.trace("Load " + node); - - try { - String clssName = node.getProperty(classProperty).getValue() - .getString(); - - BeanWrapper beanWrapper = createBeanWrapper(loadClass(clssName)); - - // process properties - PropertyIterator propIt = node.getProperties(); - props: while (propIt.hasNext()) { - Property prop = propIt.nextProperty(); - if (!beanWrapper.isWritableProperty(prop.getName())) - continue props; - - PropertyDescriptor pd = beanWrapper.getPropertyDescriptor(prop - .getName()); - Class propClass = pd.getPropertyType(); - - if (log.isTraceEnabled()) - log.trace("Load " + prop + ", propClass=" + propClass - + ", property descriptor=" + pd); - - // primitive list - if (propClass != null && List.class.isAssignableFrom(propClass)) { - List lst = new ArrayList(); - Class valuesClass = classFromProperty(prop); - if (valuesClass != null) - for (Value value : prop.getValues()) { - lst.add(asObject(value, valuesClass)); - } - continue props; - } - - // Case of other type of property accepted by jcr - // Long, Double, String, Binary, Date, Boolean, Name - Object value = asObject(prop.getValue(), pd.getPropertyType()); - if (value != null) - beanWrapper.setPropertyValue(prop.getName(), value); - } - - // process children nodes - NodeIterator nodeIt = node.getNodes(); - nodes: while (nodeIt.hasNext()) { - Node childNode = nodeIt.nextNode(); - String name = childNode.getName(); - if (!beanWrapper.isWritableProperty(name)) - continue nodes; - - PropertyDescriptor pd = beanWrapper.getPropertyDescriptor(name); - Class propClass = pd.getPropertyType(); - - // objects list - if (propClass != null && List.class.isAssignableFrom(propClass)) { - String lstClass = childNode.getProperty(classProperty) - .getString(); - List lst; - try { - lst = (List) loadClass(lstClass).newInstance(); - } catch (Exception e) { - lst = new ArrayList(); - } - - if (childNode.hasNodes()) { - // Look for children nodes - NodeIterator valuesIt = childNode.getNodes(); - while (valuesIt.hasNext()) { - Node lstValueNode = valuesIt.nextNode(); - Object lstValue = nodeToBean(lstValueNode); - lst.add(lstValue); - } - } else { - // look for a property with the same name which will - // provide - // primitives - Property childProp = childNode.getProperty(childNode - .getName()); - Class valuesClass = classFromProperty(childProp); - if (valuesClass != null) - if (childProp.getDefinition().isMultiple()) - for (Value value : childProp.getValues()) { - lst.add(asObject(value, valuesClass)); - } - else - lst.add(asObject(childProp.getValue(), - valuesClass)); - } - beanWrapper.setPropertyValue(name, lst); - continue nodes; - } - - // objects map - if (propClass != null && Map.class.isAssignableFrom(propClass)) { - String mapClass = childNode.getProperty(classProperty) - .getString(); - Map map; - try { - map = (Map) loadClass(mapClass) - .newInstance(); - } catch (Exception e) { - map = new HashMap(); - } - - // properties - PropertyIterator keysPropIt = childNode.getProperties(); - keyProps: while (keysPropIt.hasNext()) { - Property keyProp = keysPropIt.nextProperty(); - // FIXME: use property editor - String key = keyProp.getName(); - if (classProperty.equals(key)) - continue keyProps; - - Class keyPropClass = classFromProperty(keyProp); - if (keyPropClass != null) { - Object mapValue = asObject(keyProp.getValue(), - keyPropClass); - map.put(key, mapValue); - } - } - - // node - NodeIterator keysIt = childNode.getNodes(); - while (keysIt.hasNext()) { - Node mapValueNode = keysIt.nextNode(); - // FIXME: use property editor - Object key = mapValueNode.getName(); - - Object mapValue = nodeToBean(mapValueNode); - - map.put(key, mapValue); - } - beanWrapper.setPropertyValue(name, map); - continue nodes; - } - - // default - Object value = nodeToBean(childNode); - beanWrapper.setPropertyValue(name, value); - - } - return beanWrapper.getWrappedInstance(); - } catch (Exception e) { - throw new ArgeoException("Cannot map node " + node, e); - } - } - - /** - * Transforms an object to the specified jcr Node in order to persist it. - * - * @param beanWrapper - * @param node - * @throws RepositoryException - */ - protected void beanToNode(BeanWrapper beanWrapper, Node node) - throws RepositoryException { - properties: for (PropertyDescriptor pd : beanWrapper - .getPropertyDescriptors()) { - String name = pd.getName(); - if (!beanWrapper.isReadableProperty(name)) - continue properties;// skip - - Object value = beanWrapper.getPropertyValue(name); - if (value == null) { - // remove values when updating - if (node.hasProperty(name)) - node.setProperty(name, (Value) null); - if (node.hasNode(name)) - node.getNode(name).remove(); - - continue properties; - } - - // if (uuidProperty != null && uuidProperty.equals(name)) { - // // node.addMixin(ArgeoJcrConstants.MIX_REFERENCEABLE); - // node.setProperty(ArgeoJcrConstants.JCR_UUID, value.toString()); - // continue properties; - // } - - if ("class".equals(name)) { - if (classProperty != null) { - node.setProperty(classProperty, - ((Class) value).getName()); - // TODO: store a class hierarchy? - } - continue properties; - } - - // Some bean reference other classes. We must deal with this case - if (value instanceof Class) { - node.setProperty(name, ((Class) value).getName()); - continue properties; - } - - Value val = asValue(node.getSession(), value); - if (val != null) { - node.setProperty(name, val); - continue properties; - } - - if (value instanceof List) { - List lst = (List) value; - addList(node, name, lst); - continue properties; - } - - if (value instanceof Map) { - Map map = (Map) value; - addMap(node, name, map); - continue properties; - } - - BeanWrapper child = createBeanWrapper(value); - // TODO: delegate to another mapper - - // TODO: deal with references - // Node childNode = findChildReference(session, child); - // if (childNode != null) { - // node.setProperty(name, childNode); - // continue properties; - // } - - // default case (recursive) - if (node.hasNode(name)) {// update - // TODO: optimize - node.getNode(name).remove(); - } - Node childNode = node.addNode(name); - beanToNode(child, childNode); - } - } - - /** - * Process specific case of list - * - * @param node - * @param name - * @param lst - * @throws RepositoryException - */ - protected void addList(Node node, String name, List lst) - throws RepositoryException { - if (node.hasNode(name)) {// update - // TODO: optimize - node.getNode(name).remove(); - } - - Node listNode = node.addNode(name); - listNode.setProperty(classProperty, lst.getClass().getName()); - Value[] values = new Value[lst.size()]; - boolean atLeastOneSet = false; - for (int i = 0; i < lst.size(); i++) { - Object lstValue = lst.get(i); - values[i] = asValue(node.getSession(), lstValue); - if (values[i] != null) { - atLeastOneSet = true; - } else { - Node childNode = findChildReference(node.getSession(), - createBeanWrapper(lstValue)); - if (childNode != null) { - values[i] = node.getSession().getValueFactory() - .createValue(childNode); - atLeastOneSet = true; - } - } - } - - // will be either properties or nodes, not both - if (!atLeastOneSet && lst.size() != 0) { - for (Object lstValue : lst) { - Node childNode = listNode.addNode(NODE_VALUE); - beanToNode(createBeanWrapper(lstValue), childNode); - } - } else { - listNode.setProperty(name, values); - } - } - - /** - * Process specific case of maps. - * - * @param node - * @param name - * @param map - * @throws RepositoryException - */ - protected void addMap(Node node, String name, Map map) - throws RepositoryException { - if (node.hasNode(name)) {// update - // TODO: optimize - node.getNode(name).remove(); - } - - Node mapNode = node.addNode(name); - mapNode.setProperty(classProperty, map.getClass().getName()); - for (Object key : map.keySet()) { - Object mapValue = map.get(key); - // PropertyEditor pe = beanWrapper.findCustomEditor(key.getClass(), - // null); - String keyStr; - // if (pe == null) { - if (key instanceof CharSequence) - keyStr = key.toString(); - else - throw new ArgeoException( - "Cannot find property editor for class " - + key.getClass()); - // } else { - // pe.setValue(key); - // keyStr = pe.getAsText(); - // } - // TODO: check string format - - Value mapVal = asValue(node.getSession(), mapValue); - if (mapVal != null) - mapNode.setProperty(keyStr, mapVal); - else { - Node entryNode = mapNode.addNode(keyStr); - beanToNode(createBeanWrapper(mapValue), entryNode); - } - - } - - } - - protected BeanWrapper createBeanWrapper(Object obj) { - return new BeanWrapperImpl(obj); - } - - protected BeanWrapper createBeanWrapper(Class clss) { - return new BeanWrapperImpl(clss); - } - - /** Returns null if value cannot be found */ - protected Value asValue(Session session, Object value) - throws RepositoryException { - ValueFactory valueFactory = session.getValueFactory(); - if (value instanceof Integer) - return valueFactory.createValue((Integer) value); - else if (value instanceof Long) - return valueFactory.createValue((Long) value); - else if (value instanceof Float) - return valueFactory.createValue((Float) value); - else if (value instanceof Double) - return valueFactory.createValue((Double) value); - else if (value instanceof Boolean) - return valueFactory.createValue((Boolean) value); - else if (value instanceof Calendar) - return valueFactory.createValue((Calendar) value); - else if (value instanceof Date) { - Calendar cal = new GregorianCalendar(); - cal.setTime((Date) value); - return valueFactory.createValue(cal); - } else if (value instanceof CharSequence) - return valueFactory.createValue(value.toString()); - else if (value instanceof InputStream) { - Binary binary = session.getValueFactory().createBinary( - (InputStream) value); - return valueFactory.createValue(binary); - } else - return null; - } - - protected Class classFromProperty(Property property) - throws RepositoryException { - switch (property.getType()) { - case PropertyType.LONG: - return Long.class; - case PropertyType.DOUBLE: - return Double.class; - case PropertyType.STRING: - return String.class; - case PropertyType.BOOLEAN: - return Boolean.class; - case PropertyType.DATE: - return Calendar.class; - case PropertyType.NAME: - return null; - default: - throw new ArgeoException("Cannot find class for property " - + property + ", type=" - + PropertyType.nameFromValue(property.getType())); - } - } - - protected Object asObject(Value value, Class propClass) - throws RepositoryException { - if (propClass.equals(Integer.class)) - return (int) value.getLong(); - else if (propClass.equals(Long.class)) - return value.getLong(); - else if (propClass.equals(Float.class)) - return (float) value.getDouble(); - else if (propClass.equals(Double.class)) - return value.getDouble(); - else if (propClass.equals(Boolean.class)) - return value.getBoolean(); - else if (CharSequence.class.isAssignableFrom(propClass)) - return value.getString(); - else if (InputStream.class.isAssignableFrom(propClass)) - return value.getBinary().getStream(); - else if (Calendar.class.isAssignableFrom(propClass)) - return value.getDate(); - else if (Date.class.isAssignableFrom(propClass)) - return value.getDate().getTime(); - else - return null; - } - - protected Node findChildReference(Session session, BeanWrapper child) - throws RepositoryException { - if (child.isReadableProperty(uuidProperty)) { - String childUuid = child.getPropertyValue(uuidProperty).toString(); - try { - return session.getNodeByIdentifier(childUuid); - } catch (ItemNotFoundException e) { - if (strictUuidReference) - throw new ArgeoException("No node found with uuid " - + childUuid, e); - } - } - return null; - } - - protected Class loadClass(String name) { - // log.debug("Class loader: " + classLoader); - try { - return classLoader.loadClass(name); - } catch (ClassNotFoundException e) { - throw new ArgeoException("Cannot load class " + name, e); - } - } - - protected String propertyName(String name) { - return name; - } - - public void setVersioning(Boolean versioning) { - this.versioning = versioning; - } - - public void setUuidProperty(String uuidProperty) { - this.uuidProperty = uuidProperty; - } - - public void setClassProperty(String classProperty) { - this.classProperty = classProperty; - } - - public void setStrictUuidReference(Boolean strictUuidReference) { - this.strictUuidReference = strictUuidReference; - } - - public void setPrimaryNodeType(String primaryNodeType) { - this.primaryNodeType = primaryNodeType; - } - - public void setClassLoader(ClassLoader classLoader) { - this.classLoader = classLoader; - } - - public void setNodeMapperProvider(NodeMapperProvider nodeMapperProvider) { - this.nodeMapperProvider = nodeMapperProvider; - } - - public String getPrimaryNodeType() { - return this.primaryNodeType; - } - - public String getClassProperty() { - return this.classProperty; - } -} diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/spring/ThreadBoundSession.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/spring/ThreadBoundSession.java deleted file mode 100644 index a46bef1fe..000000000 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/spring/ThreadBoundSession.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.spring; - -import org.argeo.jcr.ThreadBoundJcrSessionFactory; -import org.springframework.beans.factory.DisposableBean; -import org.springframework.beans.factory.FactoryBean; -import org.springframework.beans.factory.InitializingBean; - -public class ThreadBoundSession extends ThreadBoundJcrSessionFactory implements FactoryBean, InitializingBean, DisposableBean{ - public void afterPropertiesSet() throws Exception { - init(); - } - - public void destroy() throws Exception { - dispose(); - } - -} diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/tabular/JcrTabularRowIterator.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/tabular/JcrTabularRowIterator.java deleted file mode 100644 index ca0635c95..000000000 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/tabular/JcrTabularRowIterator.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.tabular; - -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ArrayBlockingQueue; - -import javax.jcr.Binary; -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.Property; -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; - -import org.apache.commons.io.IOUtils; -import org.argeo.ArgeoException; -import org.argeo.jcr.ArgeoTypes; -import org.argeo.util.CsvParser; -import org.argeo.util.tabular.ArrayTabularRow; -import org.argeo.util.tabular.TabularColumn; -import org.argeo.util.tabular.TabularRow; -import org.argeo.util.tabular.TabularRowIterator; - -/** Iterates over the rows of a {@link ArgeoTypes#ARGEO_TABLE} node. */ -public class JcrTabularRowIterator implements TabularRowIterator { - private Boolean hasNext = null; - private Boolean parsingCompleted = false; - - private Long currentRowNumber = 0l; - - private List header = new ArrayList(); - - /** referenced so that we can close it */ - private Binary binary; - private InputStream in; - - private CsvParser csvParser; - private ArrayBlockingQueue> textLines; - - public JcrTabularRowIterator(Node tableNode) { - try { - for (NodeIterator it = tableNode.getNodes(); it.hasNext();) { - Node node = it.nextNode(); - if (node.isNodeType(ArgeoTypes.ARGEO_COLUMN)) { - Integer type = PropertyType.valueFromName(node.getProperty( - Property.JCR_REQUIRED_TYPE).getString()); - TabularColumn tc = new TabularColumn(node.getProperty( - Property.JCR_TITLE).getString(), type); - header.add(tc); - } - } - Node contentNode = tableNode.getNode(Property.JCR_CONTENT); - if (contentNode.isNodeType(ArgeoTypes.ARGEO_CSV)) { - textLines = new ArrayBlockingQueue>(1000); - csvParser = new CsvParser() { - protected void processLine(Integer lineNumber, - List header, List tokens) { - try { - textLines.put(tokens); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - // textLines.add(tokens); - if (hasNext == null) { - hasNext = true; - synchronized (JcrTabularRowIterator.this) { - JcrTabularRowIterator.this.notifyAll(); - } - } - } - }; - csvParser.setNoHeader(true); - binary = contentNode.getProperty(Property.JCR_DATA).getBinary(); - in = binary.getStream(); - Thread thread = new Thread(contentNode.getPath() + " reader") { - public void run() { - try { - csvParser.parse(in); - } finally { - parsingCompleted = true; - IOUtils.closeQuietly(in); - } - } - }; - thread.start(); - } - } catch (RepositoryException e) { - throw new ArgeoException("Cannot read table " + tableNode, e); - } - } - - public synchronized boolean hasNext() { - // we don't know if there is anything available - // while (hasNext == null) - // try { - // wait(); - // } catch (InterruptedException e) { - // // silent - // // FIXME better deal with interruption - // Thread.currentThread().interrupt(); - // break; - // } - - // buffer not empty - if (!textLines.isEmpty()) - return true; - - // maybe the parsing is finished but the flag has not been set - while (!parsingCompleted && textLines.isEmpty()) - try { - wait(100); - } catch (InterruptedException e) { - // silent - // FIXME better deal with interruption - Thread.currentThread().interrupt(); - break; - } - - // buffer not empty - if (!textLines.isEmpty()) - return true; - - // (parsingCompleted && textLines.isEmpty()) - return false; - - // if (!hasNext && textLines.isEmpty()) { - // if (in != null) { - // IOUtils.closeQuietly(in); - // in = null; - // } - // if (binary != null) { - // JcrUtils.closeQuietly(binary); - // binary = null; - // } - // return false; - // } else - // return true; - } - - public synchronized TabularRow next() { - try { - List tokens = textLines.take(); - List objs = new ArrayList(tokens.size()); - for (String token : tokens) { - // TODO convert to other formats using header - objs.add(token); - } - currentRowNumber++; - return new ArrayTabularRow(objs); - } catch (InterruptedException e) { - // silent - // FIXME better deal with interruption - } - return null; - } - - public void remove() { - throw new UnsupportedOperationException(); - } - - public Long getCurrentRowNumber() { - return currentRowNumber; - } - - public List getHeader() { - return header; - } - -} diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/tabular/JcrTabularWriter.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/tabular/JcrTabularWriter.java deleted file mode 100644 index 718ff2374..000000000 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/tabular/JcrTabularWriter.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.tabular; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.InputStream; -import java.util.List; - -import javax.jcr.Binary; -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; - -import org.apache.commons.io.IOUtils; -import org.argeo.ArgeoException; -import org.argeo.jcr.ArgeoTypes; -import org.argeo.jcr.JcrUtils; -import org.argeo.util.CsvWriter; -import org.argeo.util.tabular.TabularColumn; -import org.argeo.util.tabular.TabularWriter; - -/** Write / reference tabular content in a JCR repository. */ -public class JcrTabularWriter implements TabularWriter { - private Node contentNode; - private ByteArrayOutputStream out; - private CsvWriter csvWriter; - - @SuppressWarnings("unused") - private final List columns; - - /** Creates a table node */ - public JcrTabularWriter(Node tableNode, List columns, - String contentNodeType) { - try { - this.columns = columns; - for (TabularColumn column : columns) { - String normalized = JcrUtils.replaceInvalidChars(column - .getName()); - Node columnNode = tableNode.addNode(normalized, - ArgeoTypes.ARGEO_COLUMN); - columnNode.setProperty(Property.JCR_TITLE, column.getName()); - if (column.getType() != null) - columnNode.setProperty(Property.JCR_REQUIRED_TYPE, - PropertyType.nameFromValue(column.getType())); - else - columnNode.setProperty(Property.JCR_REQUIRED_TYPE, - PropertyType.TYPENAME_STRING); - } - contentNode = tableNode.addNode(Property.JCR_CONTENT, - contentNodeType); - if (contentNodeType.equals(ArgeoTypes.ARGEO_CSV)) { - contentNode.setProperty(Property.JCR_MIMETYPE, "text/csv"); - contentNode.setProperty(Property.JCR_ENCODING, "UTF-8"); - out = new ByteArrayOutputStream(); - csvWriter = new CsvWriter(out); - } - } catch (RepositoryException e) { - throw new ArgeoException("Cannot create table node " + tableNode, e); - } - } - - public void appendRow(Object[] row) { - csvWriter.writeLine(row); - } - - public void close() { - Binary binary = null; - InputStream in = null; - try { - // TODO parallelize with pipes and writing from another thread - in = new ByteArrayInputStream(out.toByteArray()); - binary = contentNode.getSession().getValueFactory() - .createBinary(in); - contentNode.setProperty(Property.JCR_DATA, binary); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot store data in " + contentNode, e); - } finally { - IOUtils.closeQuietly(in); - JcrUtils.closeQuietly(binary); - } - } -} diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/unit/AbstractJcrTestCase.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/unit/AbstractJcrTestCase.java deleted file mode 100644 index 530605eac..000000000 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/unit/AbstractJcrTestCase.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.unit; - -import java.io.File; - -import javax.jcr.Repository; -import javax.jcr.Session; -import javax.jcr.SimpleCredentials; - -import junit.framework.TestCase; - -import org.apache.commons.io.FileUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.ArgeoException; - -public abstract class AbstractJcrTestCase extends TestCase { - private final static Log log = LogFactory.getLog(AbstractJcrTestCase.class); - - private Repository repository; - private Session session = null; - - protected abstract File getRepositoryFile() throws Exception; - - protected abstract Repository createRepository() throws Exception; - - @Override - protected void setUp() throws Exception { - File homeDir = getHomeDir(); - FileUtils.deleteDirectory(homeDir); - repository = createRepository(); - } - - protected File getHomeDir() { - File homeDir = new File(System.getProperty("java.io.tmpdir"), - AbstractJcrTestCase.class.getSimpleName() + "-" - + System.getProperty("user.name")); - return homeDir; - } - - @Override - protected void tearDown() throws Exception { - if (session != null) { - session.logout(); - if (log.isDebugEnabled()) - log.debug("Logout session"); - } - } - - protected Session session() { - if (session == null) { - try { - if (log.isDebugEnabled()) - log.debug("Login session"); - session = getRepository().login( - new SimpleCredentials("demo", "demo".toCharArray())); - } catch (Exception e) { - throw new ArgeoException("Cannot login to repository", e); - } - } - return session; - } - - protected Repository getRepository() { - return repository; - } - - /** - * enables children class to set an existing repository in case it is not - * deleted on startup, to test migration by instance - */ - protected void setRepository(Repository repository) { - this.repository = repository; - } -} diff --git a/server/runtime/org.argeo.server.jcr/src/main/resources/org/argeo/jcr/argeo.cnd b/server/runtime/org.argeo.server.jcr/src/main/resources/org/argeo/jcr/argeo.cnd deleted file mode 100644 index fbfea9dd9..000000000 --- a/server/runtime/org.argeo.server.jcr/src/main/resources/org/argeo/jcr/argeo.cnd +++ /dev/null @@ -1,72 +0,0 @@ - - -// GENERIC TYPES NOT AVAILABLE IN JCR -[argeo:link] > mix:created, mix:lastModified -mixin -// URI(s) -- argeo:uri (STRING) m - -[argeo:references] > nt:unstructured -- * (REFERENCE) * - -// DATA MODEL -[argeo:dataModel] > mix:created, mix:lastModified, mix:versionable -mixin -- argeo:uri (STRING) m -- argeo:dataModelVersion (STRING) m - -// USER NODES -// user should be lower case, between 3 and 15 characters long -[argeo:userHome] > mix:created, mix:lastModified -mixin -- argeo:userID (STRING) m -- argeo:remoteRoles (STRING) * -// deprecated. for backward compatibility: -+ argeo:profile (argeo:userProfile) -+ argeo:keyring (argeo:pbeSpec) -+ argeo:preferences (argeo:preferenceNode) - -[argeo:userProfile] > mix:created, mix:lastModified, mix:title, mix:versionable -mixin -- argeo:userID (STRING) m -- argeo:enabled (BOOLEAN) -- argeo:accountNonExpired (BOOLEAN) -- argeo:accountNonLocked (BOOLEAN) -- argeo:credentialsNonExpired (BOOLEAN) - -[argeo:preferenceNode] > mix:lastModified, mix:versionable -mixin -+ * (argeo:preferenceNode) * version - -[argeo:remoteRepository] > nt:unstructured -- argeo:uri (STRING) -- argeo:userID (STRING) -+ argeo:password (argeo:encrypted) - -// TABULAR CONTENT -[argeo:table] > nt:file -+ * (argeo:column) * - -[argeo:column] > mix:title -- jcr:requiredType (STRING) = 'STRING' - -[argeo:csv] > nt:resource - -// CRYPTO -[argeo:encrypted] > nt:base -mixin -// initialization vector used by some algorithms -- argeo:iv (BINARY) - -[argeo:pbeKeySpec] > nt:base -mixin -- argeo:secretKeyFactory (STRING) -- argeo:salt (BINARY) -- argeo:iterationCount (LONG) -- argeo:keyLength (LONG) -- argeo:secretKeyEncryption (STRING) - -[argeo:pbeSpec] > argeo:pbeKeySpec -mixin -- argeo:cipher (STRING) - diff --git a/server/runtime/org.argeo.server.jcr/src/test/java/org/argeo/jcr/AbstractInternalJackrabbitTestCase.java b/server/runtime/org.argeo.server.jcr/src/test/java/org/argeo/jcr/AbstractInternalJackrabbitTestCase.java deleted file mode 100644 index 23281d075..000000000 --- a/server/runtime/org.argeo.server.jcr/src/test/java/org/argeo/jcr/AbstractInternalJackrabbitTestCase.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr; - -import java.io.File; - -import javax.jcr.Repository; - -import org.apache.jackrabbit.core.TransientRepository; -import org.argeo.jcr.unit.AbstractJcrTestCase; -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.Resource; - -/** Factorizes configuration of an in memory transient repository */ -public abstract class AbstractInternalJackrabbitTestCase extends - AbstractJcrTestCase { - protected File getRepositoryFile() throws Exception { - Resource res = new ClassPathResource( - "org/argeo/server/jcr/repository-memory.xml"); - return res.getFile(); - } - - protected Repository createRepository() throws Exception { - Repository repository = new TransientRepository(getRepositoryFile(), - getHomeDir()); - return repository; - } - -} diff --git a/server/runtime/org.argeo.server.jcr/src/test/java/org/argeo/jcr/CollectionsObject.java b/server/runtime/org.argeo.server.jcr/src/test/java/org/argeo/jcr/CollectionsObject.java deleted file mode 100644 index 1cbb931a7..000000000 --- a/server/runtime/org.argeo.server.jcr/src/test/java/org/argeo/jcr/CollectionsObject.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class CollectionsObject { - private String id; - private String label; - private SimpleObject simpleObject; - private List stringList = new ArrayList(); - private Map floatMap = new HashMap(); - private Map objectMap = new HashMap(); - private Map> mapOfMaps = new HashMap>(); - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getLabel() { - return label; - } - - public void setLabel(String label) { - this.label = label; - } - - public SimpleObject getSimpleObject() { - return simpleObject; - } - - public void setSimpleObject(SimpleObject simpleObject) { - this.simpleObject = simpleObject; - } - - public List getStringList() { - return stringList; - } - - public void setStringList(List stringList) { - this.stringList = stringList; - } - - public Map getFloatMap() { - return floatMap; - } - - public void setFloatMap(Map floatMap) { - this.floatMap = floatMap; - } - - public Map getObjectMap() { - return objectMap; - } - - public void setObjectMap(Map objectMap) { - this.objectMap = objectMap; - } - - public Map> getMapOfMaps() { - return mapOfMaps; - } - - public void setMapOfMaps(Map> mapOfMaps) { - this.mapOfMaps = mapOfMaps; - } -} diff --git a/server/runtime/org.argeo.server.jcr/src/test/java/org/argeo/jcr/MapperTest.java b/server/runtime/org.argeo.server.jcr/src/test/java/org/argeo/jcr/MapperTest.java deleted file mode 100644 index 5486ff458..000000000 --- a/server/runtime/org.argeo.server.jcr/src/test/java/org/argeo/jcr/MapperTest.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr; - -import javax.jcr.Node; - -import org.argeo.jcr.spring.BeanNodeMapper; - -public class MapperTest extends AbstractInternalJackrabbitTestCase { - public void testSimpleObject() throws Exception { - SimpleObject mySo = new SimpleObject(); - mySo.setInteger(100); - mySo.setString("hello world"); - - OtherObject oo1 = new OtherObject(); - oo1.setKey("someKey"); - oo1.setValue("stringValue"); - mySo.setOtherObject(oo1); - - OtherObject oo2 = new OtherObject(); - oo2.setKey("anotherSimpleObject"); - oo2.setValue(new SimpleObject()); - mySo.setAnotherObject(oo2); - - BeanNodeMapper bnm = new BeanNodeMapper(); - - Node node = bnm.save(session(), mySo); - session().save(); - JcrUtils.debug(node); - } -} diff --git a/server/runtime/org.argeo.server.jcr/src/test/java/org/argeo/jcr/OtherObject.java b/server/runtime/org.argeo.server.jcr/src/test/java/org/argeo/jcr/OtherObject.java deleted file mode 100644 index 5cce8ffaa..000000000 --- a/server/runtime/org.argeo.server.jcr/src/test/java/org/argeo/jcr/OtherObject.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr; - -public class OtherObject { - private String key; - private Object value; - - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - public Object getValue() { - return value; - } - - public void setValue(Object value) { - this.value = value; - } -} diff --git a/server/runtime/org.argeo.server.jcr/src/test/java/org/argeo/jcr/SimpleObject.java b/server/runtime/org.argeo.server.jcr/src/test/java/org/argeo/jcr/SimpleObject.java deleted file mode 100644 index cdc32fc99..000000000 --- a/server/runtime/org.argeo.server.jcr/src/test/java/org/argeo/jcr/SimpleObject.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr; - -import java.util.UUID; - -public class SimpleObject { - private String string; - private String uuid = UUID.randomUUID().toString(); - private Integer integer; - private OtherObject otherObject; - private OtherObject anotherObject; - - public String getString() { - return string; - } - - public void setString(String sting) { - this.string = sting; - } - - public Integer getInteger() { - return integer; - } - - public void setInteger(Integer integer) { - this.integer = integer; - } - - public OtherObject getOtherObject() { - return otherObject; - } - - public void setOtherObject(OtherObject otherObject) { - this.otherObject = otherObject; - } - - public OtherObject getAnotherObject() { - return anotherObject; - } - - public void setAnotherObject(OtherObject anotherObject) { - this.anotherObject = anotherObject; - } - - @Override - public boolean equals(Object obj) { - return string.equals(((SimpleObject) obj).string); - } - - @Override - public int hashCode() { - return string.hashCode(); - } - - public void setUuid(String uuid) { - this.uuid = uuid; - } - - public String getUuid() { - return uuid; - } - -} diff --git a/server/runtime/org.argeo.server.jcr/src/test/java/org/argeo/jcr/tabular/JcrTabularTest.java b/server/runtime/org.argeo.server.jcr/src/test/java/org/argeo/jcr/tabular/JcrTabularTest.java deleted file mode 100644 index 2045f9ae5..000000000 --- a/server/runtime/org.argeo.server.jcr/src/test/java/org/argeo/jcr/tabular/JcrTabularTest.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.tabular; - -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.List; - -import javax.jcr.Node; -import javax.jcr.PropertyType; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.jackrabbit.commons.cnd.CndImporter; -import org.argeo.jcr.AbstractInternalJackrabbitTestCase; -import org.argeo.jcr.ArgeoNames; -import org.argeo.jcr.ArgeoTypes; -import org.argeo.util.tabular.TabularColumn; -import org.argeo.util.tabular.TabularRow; -import org.argeo.util.tabular.TabularRowIterator; -import org.argeo.util.tabular.TabularWriter; - -public class JcrTabularTest extends AbstractInternalJackrabbitTestCase { - private final static Log log = LogFactory.getLog(JcrTabularTest.class); - - public void testWriteReadCsv() throws Exception { - session().setNamespacePrefix("argeo", ArgeoNames.ARGEO_NAMESPACE); - InputStreamReader reader = new InputStreamReader(getClass() - .getResourceAsStream("/org/argeo/jcr/argeo.cnd")); - CndImporter.registerNodeTypes(reader, session()); - reader.close(); - - // write - Integer columnCount = 15; - Long rowCount = 1000l; - String stringValue = "test, \ntest"; - - List header = new ArrayList(); - for (int i = 0; i < columnCount; i++) { - header.add(new TabularColumn("col" + i, PropertyType.STRING)); - } - Node tableNode = session().getRootNode().addNode("table", - ArgeoTypes.ARGEO_TABLE); - TabularWriter writer = new JcrTabularWriter(tableNode, header, - ArgeoTypes.ARGEO_CSV); - for (int i = 0; i < rowCount; i++) { - List objs = new ArrayList(); - for (int j = 0; j < columnCount; j++) { - objs.add(stringValue); - } - writer.appendRow(objs.toArray()); - } - writer.close(); - session().save(); - - if (log.isDebugEnabled()) - log.debug("Wrote tabular content " + rowCount + " rows, " - + columnCount + " columns"); - // read - TabularRowIterator rowIt = new JcrTabularRowIterator(tableNode); - Long count = 0l; - while (rowIt.hasNext()) { - TabularRow tr = rowIt.next(); - assertEquals(header.size(), tr.size()); - count++; - } - assertEquals(rowCount, count); - if (log.isDebugEnabled()) - log.debug("Read tabular content " + rowCount + " rows, " - + columnCount + " columns"); - } -} diff --git a/server/runtime/org.argeo.server.jcr/src/test/java/org/argeo/server/jcr/JcrResourceAdapterTest.java b/server/runtime/org.argeo.server.jcr/src/test/java/org/argeo/server/jcr/JcrResourceAdapterTest.java deleted file mode 100644 index b691572e9..000000000 --- a/server/runtime/org.argeo.server.jcr/src/test/java/org/argeo/server/jcr/JcrResourceAdapterTest.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.server.jcr; - -import java.io.InputStream; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.List; - -import org.apache.commons.io.IOUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.jcr.AbstractInternalJackrabbitTestCase; -import org.argeo.jcr.JcrResourceAdapter; -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.Resource; - -public class JcrResourceAdapterTest extends AbstractInternalJackrabbitTestCase { - private static SimpleDateFormat sdf = new SimpleDateFormat( - "yyyyMMdd:hhmmss.SSS"); - - private final static Log log = LogFactory - .getLog(JcrResourceAdapterTest.class); - - private JcrResourceAdapter jra; - - public void testCreate() throws Exception { - String basePath = "/test/subdir"; - jra.mkdirs(basePath); - Resource res = new ClassPathResource("org/argeo/server/jcr/dummy00.xls"); - String filePath = basePath + "/dummy.xml"; - jra.create(filePath, res.getInputStream(), "application/vnd.ms-excel"); - InputStream in = jra.retrieve(filePath); - assertTrue(IOUtils.contentEquals(res.getInputStream(), in)); - } - - public void testVersioning() throws Exception { - String basePath = "/test/versions"; - jra.mkdirs(basePath); - String filePath = basePath + "/dummy.xml"; - Resource res00 = new ClassPathResource( - "org/argeo/server/jcr/dummy00.xls"); - jra.create(filePath, res00.getInputStream(), "application/vnd.ms-excel"); - Resource res01 = new ClassPathResource( - "org/argeo/server/jcr/dummy01.xls"); - jra.update(filePath, res01.getInputStream()); - Resource res02 = new ClassPathResource( - "org/argeo/server/jcr/dummy02.xls"); - jra.update(filePath, res02.getInputStream()); - - List versions = jra.listVersions(filePath); - log.debug("Versions of " + filePath); - int count = 0; - for (Calendar version : versions) { - log.debug(" " + (count == 0 ? "base" : count - 1) + "\t" - + sdf.format(version.getTime())); - count++; - } - - assertEquals(4, versions.size()); - - InputStream in = jra.retrieve(filePath, 1); - assertTrue(IOUtils.contentEquals(res01.getInputStream(), in)); - in = jra.retrieve(filePath, 0); - assertTrue(IOUtils.contentEquals(res00.getInputStream(), in)); - in = jra.retrieve(filePath, 2); - assertTrue(IOUtils.contentEquals(res02.getInputStream(), in)); - Resource res03 = new ClassPathResource( - "org/argeo/server/jcr/dummy03.xls"); - jra.update(filePath, res03.getInputStream()); - in = jra.retrieve(filePath, 1); - assertTrue(IOUtils.contentEquals(res01.getInputStream(), in)); - } - - @Override - protected void setUp() throws Exception { - log.debug("SET UP"); - super.setUp(); - jra = new JcrResourceAdapter(); - jra.setSession(session()); - } - - @Override - protected void tearDown() throws Exception { - log.debug("TEAR DOWN"); - super.tearDown(); - } -} diff --git a/server/runtime/org.argeo.server.jcr/src/test/resources/log4j.properties b/server/runtime/org.argeo.server.jcr/src/test/resources/log4j.properties deleted file mode 100644 index ca995af8e..000000000 --- a/server/runtime/org.argeo.server.jcr/src/test/resources/log4j.properties +++ /dev/null @@ -1,13 +0,0 @@ -log4j.rootLogger=WARN, console - -## Levels -log4j.logger.org.argeo=DEBUG -log4j.logger.org.apache.jackrabbit=OFF - -## Appenders -# console is set to be a ConsoleAppender. -log4j.appender.console=org.apache.log4j.ConsoleAppender - -# console uses PatternLayout. -log4j.appender.console.layout=org.apache.log4j.PatternLayout -log4j.appender.console.layout.ConversionPattern= %-5p %d{ISO8601} %m - %c%n diff --git a/server/runtime/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/dummy00.xls b/server/runtime/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/dummy00.xls deleted file mode 100644 index e5846fef7..000000000 Binary files a/server/runtime/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/dummy00.xls and /dev/null differ diff --git a/server/runtime/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/dummy01.xls b/server/runtime/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/dummy01.xls deleted file mode 100644 index b5c6b5539..000000000 Binary files a/server/runtime/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/dummy01.xls and /dev/null differ diff --git a/server/runtime/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/dummy02.xls b/server/runtime/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/dummy02.xls deleted file mode 100644 index d73bc6605..000000000 Binary files a/server/runtime/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/dummy02.xls and /dev/null differ diff --git a/server/runtime/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/dummy03.xls b/server/runtime/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/dummy03.xls deleted file mode 100644 index 0759cb927..000000000 Binary files a/server/runtime/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/dummy03.xls and /dev/null differ diff --git a/server/runtime/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/repository-h2.xml b/server/runtime/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/repository-h2.xml deleted file mode 100644 index ef3f0c426..000000000 --- a/server/runtime/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/repository-h2.xml +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/server/runtime/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/repository-memory.xml b/server/runtime/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/repository-memory.xml deleted file mode 100644 index 839542417..000000000 --- a/server/runtime/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/repository-memory.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/server/runtime/org.argeo.server.json/pom.xml b/server/runtime/org.argeo.server.json/pom.xml index a66bfd618..abd44614c 100644 --- a/server/runtime/org.argeo.server.json/pom.xml +++ b/server/runtime/org.argeo.server.json/pom.xml @@ -1,8 +1,8 @@ 4.0.0 - org.argeo.commons.server - runtime + org.argeo.commons + argeo-commons 2.1.12-SNAPSHOT .. @@ -39,7 +39,7 @@ - org.argeo.commons.server + org.argeo.commons org.argeo.server.core 2.1.12-SNAPSHOT diff --git a/server/runtime/org.argeo.server.jxl/pom.xml b/server/runtime/org.argeo.server.jxl/pom.xml index 5d8032944..b75892a07 100644 --- a/server/runtime/org.argeo.server.jxl/pom.xml +++ b/server/runtime/org.argeo.server.jxl/pom.xml @@ -1,8 +1,8 @@ 4.0.0 - org.argeo.commons.server - runtime + org.argeo.commons + argeo-commons 2.1.12-SNAPSHOT .. @@ -39,7 +39,7 @@ - org.argeo.commons.server + org.argeo.commons org.argeo.server.core 2.1.12-SNAPSHOT @@ -57,7 +57,7 @@ test - org.argeo.commons.base + org.argeo.commons org.argeo.dep.log4j 2.1.12-SNAPSHOT pom diff --git a/server/runtime/org.argeo.server.modeshape/pom.xml b/server/runtime/org.argeo.server.modeshape/pom.xml index 40ff85db4..d66de882b 100644 --- a/server/runtime/org.argeo.server.modeshape/pom.xml +++ b/server/runtime/org.argeo.server.modeshape/pom.xml @@ -1,8 +1,8 @@ 4.0.0 - org.argeo.commons.server - runtime + org.argeo.commons + argeo-commons 2.1.12-SNAPSHOT .. @@ -38,7 +38,7 @@ - org.argeo.commons.server + org.argeo.commons org.argeo.server.jcr 2.1.12-SNAPSHOT @@ -54,7 +54,7 @@ - org.argeo.commons.base + org.argeo.commons org.argeo.dep.log4j 2.1.12-SNAPSHOT pom @@ -62,7 +62,7 @@ - org.argeo.commons.base + org.argeo.commons org.argeo.osgi.boot 2.1.12-SNAPSHOT test diff --git a/server/runtime/org.argeo.server.webextender/pom.xml b/server/runtime/org.argeo.server.webextender/pom.xml index 5a8675474..aadf95af0 100644 --- a/server/runtime/org.argeo.server.webextender/pom.xml +++ b/server/runtime/org.argeo.server.webextender/pom.xml @@ -1,8 +1,8 @@ 4.0.0 - org.argeo.commons.server - runtime + org.argeo.commons + argeo-commons 2.1.12-SNAPSHOT .. diff --git a/server/runtime/pom.xml b/server/runtime/pom.xml index b3b4410ac..4c9e9dde2 100644 --- a/server/runtime/pom.xml +++ b/server/runtime/pom.xml @@ -7,8 +7,8 @@ server .. - org.argeo.commons.server - runtime + org.argeo.commons + argeo-commons Commons Server Runtime pom