[jboss-as] - Simplified systemd files - Added jboss-as-cli module - Make it possible to run as different user i

Marek Goldmann goldmann at fedoraproject.org
Mon Apr 16 19:33:55 UTC 2012


commit f7ed32ec9b95161422e09e3ad840d1e252d80f7c
Author: Marek Goldmann <mgoldman at redhat.com>
Date:   Mon Apr 16 21:21:26 2012 +0200

    - Simplified systemd files
    - Added jboss-as-cli module
    - Make it possible to run as different user in different direcotry by changing JBOSS_BASE_DIR
    - Fixed issues with using add-user.sh script
    - Changed validation API jar to bean-validation
    - Added jboss-as-cp script to be able to use JBoss AS from different dir as different user
    - Removed activation AS7 module - it's already in JDK
    - Make it possible to add a user also when JBoss AS is run from different directory

 0045-Added-jboss-as-cli-module.patch               |  135 ++
 ...OME-when-jboss-cli.sh-is-executed-through.patch |   31 +
 0047-Simplified-systemd-files.patch                |  121 +
 ...OSS_BASE_DIR-is-checked-in-standalone.sh-.patch |   33 +
 0049-Added-domain-add-user-module.patch            |   34 +
 ...s-from-systemd-service-we-don-t-need-dupl.patch |  121 +
 ...-systemd-config-file-location-we-want-to-.patch |   30 +
 0052-Remove-activation-module.patch                |  241 ++
 0053-Use-properties-in-add-user-AS7-module.patch   | 2539 ++++++++++++++++++++
 jboss-as-cp.sh                                     |   59 +
 jboss-as.spec                                      |  111 +-
 11 files changed, 3424 insertions(+), 31 deletions(-)
---
diff --git a/0045-Added-jboss-as-cli-module.patch b/0045-Added-jboss-as-cli-module.patch
new file mode 100644
index 0000000..743e744
--- /dev/null
+++ b/0045-Added-jboss-as-cli-module.patch
@@ -0,0 +1,135 @@
+From 43fbef5e2027b413c956326582a297da57a8bed1 Mon Sep 17 00:00:00 2001
+From: Patryk Obara <dreamer.tan at gmail.com>
+Date: Thu, 5 Apr 2012 12:54:16 +0200
+Subject: [PATCH 45/47] Added-jboss-as-cli-module
+
+With jline as dependency.
+---
+ build/build.xml |   16 ++++++++--------
+ build/pom.xml   |   20 ++++++++++----------
+ pom.xml         |    2 +-
+ 3 files changed, 19 insertions(+), 19 deletions(-)
+
+diff --git a/build/build.xml b/build/build.xml
+index 529af0e..04c2e76 100644
+--- a/build/build.xml
++++ b/build/build.xml
+@@ -145,6 +145,10 @@
+             <maven-resource group="org.hibernate.javax.persistence" artifact="hibernate-jpa-2.0-api"/>
+         </module-def>
+ 
++        <module-def name="jline">
++            <maven-resource group="jline" artifact="jline"/>
++        </module-def>
++
+         <module-def name="org.infinispan">
+             <maven-resource group="org.infinispan" artifact="infinispan-core"/>
+         </module-def>
+@@ -299,6 +303,10 @@
+             <maven-resource group="org.jboss.ironjacamar" artifact="ironjacamar-jdbc"/>
+         </module-def>
+ 
++        <module-def name="org.jboss.as.cli">
++            <maven-resource group="org.jboss.as" artifact="jboss-as-cli"/>
++        </module-def>
++
+         <module-def name="org.jboss.as.clustering.api">
+             <maven-resource group="org.jboss.as" artifact="jboss-as-clustering-api"/>
+         </module-def>
+@@ -719,10 +727,6 @@
+             <maven-resource group="org.jboss.spec.javax.xml.ws" artifact="jboss-jaxws-api_2.2_spec"/>
+         </module-def>
+ 
+-        <module-def name="jline">
+-            <maven-resource group="jline" artifact="jline"/>
+-        </module-def>
+-
+         <module-def name="net.sourceforge.cssparser">
+             <maven-resource group="net.sourceforge.cssparser" artifact="cssparser"/>
+         </module-def>
+@@ -898,10 +902,6 @@
+             <maven-resource-with-classifier group="org.jboss.as" artifact="jboss-as-console" classifier="resources"/>
+         </module-def>
+ 
+-        <module-def name="org.jboss.as.cli">
+-            <maven-resource group="org.jboss.as" artifact="jboss-as-cli"/>
+-        </module-def>
+-
+         <module-def name="org.jboss.as.configadmin">
+             <maven-resource group="org.jboss.as" artifact="jboss-as-configadmin"/>
+         </module-def>
+diff --git a/build/pom.xml b/build/pom.xml
+index 499f542..bd882b7 100644
+--- a/build/pom.xml
++++ b/build/pom.xml
+@@ -180,6 +180,11 @@
+ 
+         <dependency>
+             <groupId>org.jboss.as</groupId>
++            <artifactId>jboss-as-cli</artifactId>
++        </dependency>
++
++        <dependency>
++            <groupId>org.jboss.as</groupId>
+             <artifactId>jboss-as-clustering-common</artifactId>
+         </dependency>
+ 
+@@ -589,6 +594,11 @@
+         </dependency>
+ 
+         <dependency>
++            <groupId>jline</groupId>
++            <artifactId>jline</artifactId>
++        </dependency>
++
++        <dependency>
+             <groupId>joda-time</groupId>
+             <artifactId>joda-time</artifactId>
+         </dependency>
+@@ -745,11 +755,6 @@
+                 </dependency>
+ 
+                 <dependency>
+-                    <groupId>jline</groupId>
+-                    <artifactId>jline</artifactId>
+-                </dependency>
+-
+-                <dependency>
+                     <groupId>junit</groupId>
+                     <artifactId>junit</artifactId>
+                 </dependency>
+@@ -1066,11 +1071,6 @@
+ 
+                 <dependency>
+                     <groupId>org.jboss.as</groupId>
+-                    <artifactId>jboss-as-cli</artifactId>
+-                </dependency>
+-
+-                <dependency>
+-                    <groupId>org.jboss.as</groupId>
+                     <artifactId>jboss-as-client-all</artifactId>
+                     <scope>provided</scope>
+                 </dependency>
+diff --git a/pom.xml b/pom.xml
+index b9e503d..13ba795 100644
+--- a/pom.xml
++++ b/pom.xml
+@@ -265,6 +265,7 @@
+     <modules>
+         <module>build</module>
+         <module>build-config</module>
++        <module>cli</module>
+         <module>clustering</module>
+         <module>connector</module>
+         <module>controller</module>
+@@ -5921,7 +5922,6 @@
+                 <module>build</module>
+                 <module>build-config</module>
+                 <module>arquillian</module>
+-                <module>cli</module>
+                 <module>client/ejb</module>
+                 <module>client/jms</module>
+                 <module>client/shade</module>
+-- 
+1.7.10
+
diff --git a/0046-Fix-JBOSS_HOME-when-jboss-cli.sh-is-executed-through.patch b/0046-Fix-JBOSS_HOME-when-jboss-cli.sh-is-executed-through.patch
new file mode 100644
index 0000000..3df4780
--- /dev/null
+++ b/0046-Fix-JBOSS_HOME-when-jboss-cli.sh-is-executed-through.patch
@@ -0,0 +1,31 @@
+From 65d80242031d8541935b9c924cc024357b5348fc Mon Sep 17 00:00:00 2001
+From: Patryk Obara <dreamer.tan at gmail.com>
+Date: Thu, 5 Apr 2012 18:42:05 +0200
+Subject: [PATCH 46/47] Fix JBOSS_HOME when jboss-cli.sh is executed through
+ symbolic link
+
+---
+ build/src/main/resources/bin/jboss-cli.sh |    8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/build/src/main/resources/bin/jboss-cli.sh b/build/src/main/resources/bin/jboss-cli.sh
+index a9d1c5d..a1108f5 100755
+--- a/build/src/main/resources/bin/jboss-cli.sh
++++ b/build/src/main/resources/bin/jboss-cli.sh
+@@ -1,6 +1,12 @@
+ #!/bin/sh
+ 
+-DIRNAME=`dirname "$0"`
++# Set proper dirname if script is executed through symlink
++LINK=`readlink "$0"`
++if [ "x$LINK" = "x" ]; then
++    DIRNAME=`dirname "$0"`
++else
++    DIRNAME=`dirname "$LINK"`
++fi
+ 
+ # OS specific support (must be 'true' or 'false').
+ cygwin=false;
+-- 
+1.7.10
+
diff --git a/0047-Simplified-systemd-files.patch b/0047-Simplified-systemd-files.patch
new file mode 100644
index 0000000..695944e
--- /dev/null
+++ b/0047-Simplified-systemd-files.patch
@@ -0,0 +1,121 @@
+From 7cb54243b2b040a9da681762919741f4fdd3314a Mon Sep 17 00:00:00 2001
+From: Marek Goldmann <mgoldman at redhat.com>
+Date: Thu, 12 Apr 2012 13:28:41 +0200
+Subject: [PATCH 47/47] Simplified systemd files
+
+---
+ .../main/resources/bin/initscripts/jboss-as.conf   |   22 --------------------
+ .../bin/initscripts/systemd/jboss-as.conf          |    4 ++++
+ .../bin/initscripts/systemd/jboss-as.service       |    9 +++++---
+ .../resources/bin/initscripts/sysv/jboss-as.conf   |   22 ++++++++++++++++++++
+ build/src/main/resources/bin/standalone.sh         |    4 ++++
+ 5 files changed, 36 insertions(+), 25 deletions(-)
+ delete mode 100644 build/src/main/resources/bin/initscripts/jboss-as.conf
+ create mode 100644 build/src/main/resources/bin/initscripts/systemd/jboss-as.conf
+ create mode 100644 build/src/main/resources/bin/initscripts/sysv/jboss-as.conf
+
+diff --git a/build/src/main/resources/bin/initscripts/jboss-as.conf b/build/src/main/resources/bin/initscripts/jboss-as.conf
+deleted file mode 100644
+index cbe4aa7..0000000
+--- a/build/src/main/resources/bin/initscripts/jboss-as.conf
++++ /dev/null
+@@ -1,22 +0,0 @@
+-# General configuration for the init.d scripts,
+-# not necessarily for JBoss AS itself.
+-
+-# The username who should own the process.
+-#
+-JBOSS_USER=jboss-as
+-
+-# The amount of time to wait for startup
+-#
+-# STARTUP_WAIT=30
+-
+-# The amount of time to wait for shutdown
+-#
+-# SHUTDOWN_WAIT=30
+-
+-# Location to keep the console log
+-#
+-# JBOSS_CONSOLE_LOG=/var/log/jboss-as/console.log
+-
+-# The configuration you want to run
+-#
+-JBOSS_CONFIG=standalone-web.xml
+diff --git a/build/src/main/resources/bin/initscripts/systemd/jboss-as.conf b/build/src/main/resources/bin/initscripts/systemd/jboss-as.conf
+new file mode 100644
+index 0000000..82699ad
+--- /dev/null
++++ b/build/src/main/resources/bin/initscripts/systemd/jboss-as.conf
+@@ -0,0 +1,4 @@
++# The configuration you want to run
++#
++JBOSS_CONFIG=standalone-web.xml
++
+diff --git a/build/src/main/resources/bin/initscripts/systemd/jboss-as.service b/build/src/main/resources/bin/initscripts/systemd/jboss-as.service
+index b7a4a56..1542968 100644
+--- a/build/src/main/resources/bin/initscripts/systemd/jboss-as.service
++++ b/build/src/main/resources/bin/initscripts/systemd/jboss-as.service
+@@ -3,10 +3,13 @@ Description=The JBoss Application Server
+ After=syslog.target network.target
+ 
+ [Service]
+-Type=forking
++Environment=LAUNCH_JBOSS_IN_BACKGROUND=1
++EnvironmentFile=-/etc/jboss-as.conf
++User=jboss-as
++LimitNOFILE=102642
+ PIDFile=/var/run/jboss-as/jboss-as.pid
+-ExecStart=/usr/bin/jboss-as $OPTIONS start
+-ExecStop=/usr/bin/jboss-as stop
++ExecStart=/usr/share/jboss-as/bin/standalone.sh -c $JBOSS_CONFIG
+ 
+ [Install]
+ WantedBy=multi-user.target
++
+diff --git a/build/src/main/resources/bin/initscripts/sysv/jboss-as.conf b/build/src/main/resources/bin/initscripts/sysv/jboss-as.conf
+new file mode 100644
+index 0000000..d999aca
+--- /dev/null
++++ b/build/src/main/resources/bin/initscripts/sysv/jboss-as.conf
+@@ -0,0 +1,22 @@
++# General configuration for the init.d scripts,
++# not necessarily for JBoss AS itself.
++
++# The username who should own the process.
++#
++# JBOSS_USER=jboss-as
++
++# The amount of time to wait for startup
++#
++# STARTUP_WAIT=30
++
++# The amount of time to wait for shutdown
++#
++# SHUTDOWN_WAIT=30
++
++# Location to keep the console log
++#
++# JBOSS_CONSOLE_LOG=/var/log/jboss-as/console.log
++
++# The configuration you want to run
++#
++# JBOSS_CONFIG=standalone.xml
+diff --git a/build/src/main/resources/bin/standalone.sh b/build/src/main/resources/bin/standalone.sh
+index d7387f9..1e02120 100755
+--- a/build/src/main/resources/bin/standalone.sh
++++ b/build/src/main/resources/bin/standalone.sh
+@@ -147,6 +147,10 @@ fi
+ if [ "x$JBOSS_CONFIG_DIR" = "x" ]; then
+    JBOSS_CONFIG_DIR="$JBOSS_BASE_DIR/configuration"
+ fi
++# determine the default pid file location dir, if not set
++if [ "x$JBOSS_PIDFILE" = "x" ]; then
++   JBOSS_PIDFILE="/var/run/jboss-as/jboss-as.pid"
++fi
+ 
+ # For Cygwin, switch paths to Windows format before running java
+ if $cygwin; then
+-- 
+1.7.10
+
diff --git a/0048-AS7-3800-JBOSS_BASE_DIR-is-checked-in-standalone.sh-.patch b/0048-AS7-3800-JBOSS_BASE_DIR-is-checked-in-standalone.sh-.patch
new file mode 100644
index 0000000..2c98c6f
--- /dev/null
+++ b/0048-AS7-3800-JBOSS_BASE_DIR-is-checked-in-standalone.sh-.patch
@@ -0,0 +1,33 @@
+From d5a79ab1f7506a8e43c231b5c15447b468e4a3b7 Mon Sep 17 00:00:00 2001
+From: Marek Goldmann <mgoldman at redhat.com>
+Date: Thu, 5 Apr 2012 16:10:47 +0200
+Subject: [PATCH 48/48] [AS7-3800] JBOSS_BASE_DIR is checked in standalone.sh
+ but not used to set -Djboss.server.base.dir
+
+---
+ build/src/main/resources/bin/standalone.sh |    2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/build/src/main/resources/bin/standalone.sh b/build/src/main/resources/bin/standalone.sh
+index 1e02120..7aee924 100755
+--- a/build/src/main/resources/bin/standalone.sh
++++ b/build/src/main/resources/bin/standalone.sh
+@@ -186,6 +186,7 @@ while true; do
+          -jaxpmodule "javax.xml.jaxp-provider" \
+          org.jboss.as.standalone \
+          -Djboss.home.dir=\"$JBOSS_HOME\" \
++         -Djboss.server.base.dir=\"$JBOSS_BASE_DIR\" \
+          "$@"
+       JBOSS_STATUS=$?
+    else
+@@ -198,6 +199,7 @@ while true; do
+          -jaxpmodule "javax.xml.jaxp-provider" \
+          org.jboss.as.standalone \
+          -Djboss.home.dir=\"$JBOSS_HOME\" \
++         -Djboss.server.base.dir=\"$JBOSS_BASE_DIR\" \
+          "$@" "&"
+       JBOSS_PID=$!
+       # Trap common signals and relay them to the jboss process
+-- 
+1.7.10
+
diff --git a/0049-Added-domain-add-user-module.patch b/0049-Added-domain-add-user-module.patch
new file mode 100644
index 0000000..70e4c8d
--- /dev/null
+++ b/0049-Added-domain-add-user-module.patch
@@ -0,0 +1,34 @@
+From be152c72271132cc0614e291b4c822b3c6593e6f Mon Sep 17 00:00:00 2001
+From: Marek Goldmann <mgoldman at redhat.com>
+Date: Fri, 13 Apr 2012 13:38:24 +0200
+Subject: [PATCH 49/49] Added domain-add-user module
+
+---
+ build/build.xml |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/build/build.xml b/build/build.xml
+index 04c2e76..636e2b5 100644
+--- a/build/build.xml
++++ b/build/build.xml
+@@ -371,6 +371,8 @@
+             <maven-resource group="org.jboss.as" artifact="jboss-as-deployment-scanner"/>
+         </module-def>
+ 
++        <module-def name="org.jboss.as.domain-add-user" />
++
+         <module-def name="org.jboss.as.domain-http-error-context">
+             <maven-resource group="org.jboss.as" artifact="jboss-as-domain-http-error-context"/>
+         </module-def>
+@@ -910,8 +912,6 @@
+             <maven-resource group="org.jboss.as" artifact="jboss-as-cmp"/>
+         </module-def>
+ 
+-    	<module-def name="org.jboss.as.domain-add-user" />
+-
+         <module-def name="org.jboss.as.host-controller">
+             <maven-resource group="org.jboss.as" artifact="jboss-as-host-controller"/>
+         </module-def>
+-- 
+1.7.10
+
diff --git a/0050-Discard-logs-from-systemd-service-we-don-t-need-dupl.patch b/0050-Discard-logs-from-systemd-service-we-don-t-need-dupl.patch
new file mode 100644
index 0000000..48c32f9
--- /dev/null
+++ b/0050-Discard-logs-from-systemd-service-we-don-t-need-dupl.patch
@@ -0,0 +1,121 @@
+From 54fd06a9919fd5bd40a6a5ebc7cf212edffc90d2 Mon Sep 17 00:00:00 2001
+From: Marek Goldmann <mgoldman at redhat.com>
+Date: Fri, 13 Apr 2012 16:37:06 +0200
+Subject: [PATCH 50/50] Discard logs from systemd service, we don't need
+ duplication
+
+---
+ .../bin/initscripts/systemd/jboss-as.service       |    1 +
+ .../resources/bin/initscripts/systemd/jboss-as.sh  |   88 --------------------
+ 2 files changed, 1 insertion(+), 88 deletions(-)
+ delete mode 100755 build/src/main/resources/bin/initscripts/systemd/jboss-as.sh
+
+diff --git a/build/src/main/resources/bin/initscripts/systemd/jboss-as.service b/build/src/main/resources/bin/initscripts/systemd/jboss-as.service
+index 1542968..41e54e6 100644
+--- a/build/src/main/resources/bin/initscripts/systemd/jboss-as.service
++++ b/build/src/main/resources/bin/initscripts/systemd/jboss-as.service
+@@ -9,6 +9,7 @@ User=jboss-as
+ LimitNOFILE=102642
+ PIDFile=/var/run/jboss-as/jboss-as.pid
+ ExecStart=/usr/share/jboss-as/bin/standalone.sh -c $JBOSS_CONFIG
++StandardOutput=null
+ 
+ [Install]
+ WantedBy=multi-user.target
+diff --git a/build/src/main/resources/bin/initscripts/systemd/jboss-as.sh b/build/src/main/resources/bin/initscripts/systemd/jboss-as.sh
+deleted file mode 100755
+index da57af6..0000000
+--- a/build/src/main/resources/bin/initscripts/systemd/jboss-as.sh
++++ /dev/null
+@@ -1,88 +0,0 @@
+-#!/bin/sh
+-
+-# Load Java configuration.
+-[ -r /etc/java/java.conf ] && . /etc/java/java.conf
+-
+-export JAVA_HOME
+-
+-# Load JBoss AS configuration.
+-if [ -z "$JBOSS_CONF" ]; then
+-  JBOSS_CONF="/etc/sysconfig/jboss-as"
+-fi
+-
+-[ -r "$JBOSS_CONF" ] && . "${JBOSS_CONF}"
+-
+-if [ -z "$JBOSS_HOME" ]; then
+-  JBOSS_HOME=/usr/share/jboss-as
+-fi
+-
+-export JBOSS_HOME
+-
+-if [ -z "$JBOSS_PIDFILE" ]; then
+-  JBOSS_PIDFILE=/var/run/jboss-as/jboss-as.pid
+-fi
+-
+-if [ -z "$JBOSS_CONSOLE_LOG" ]; then
+-  JBOSS_CONSOLE_LOG=/var/log/jboss-as/console.log
+-fi
+-
+-if [ -z "$JBOSS_CONFIG" ]; then
+-  JBOSS_CONFIG=standalone.xml
+-fi
+-
+-if [ -z "$JBOSS_SCRIPT" ]; then
+-  JBOSS_SCRIPT=$JBOSS_HOME/bin/standalone.sh
+-fi
+-
+-# For SELinux we need to use 'runuser' not 'su'
+-if [ -x "/sbin/runuser" ]; then
+-  SU="/sbin/runuser -s /bin/sh"
+-else
+-  SU="/bin/su -s /bin/sh"
+-fi
+-
+-start() {
+-  if [ -f $JBOSS_PIDFILE ]; then
+-    read ppid < $JBOSS_PIDFILE
+-    if [ `ps --pid $ppid 2> /dev/null | grep -c $ppid 2> /dev/null` -eq '1' ]; then
+-      failure
+-      echo
+-      return 1 
+-    else
+-      rm -f $JBOSS_PIDFILE
+-    fi
+-  fi
+-  mkdir -p $(dirname $JBOSS_CONSOLE_LOG)
+-  cat /dev/null > $JBOSS_CONSOLE_LOG
+-
+-  mkdir -p $(dirname $JBOSS_PIDFILE)
+-  chown $JBOSS_USER $(dirname $JBOSS_PIDFILE) || true
+-
+-  $SU - $JBOSS_USER -c "LAUNCH_JBOSS_IN_BACKGROUND=1 JBOSS_PIDFILE=$JBOSS_PIDFILE $JBOSS_SCRIPT -c $JBOSS_CONFIG" 2>&1 > $JBOSS_CONSOLE_LOG &
+-}
+-
+-stop() {
+-  if [ -f $JBOSS_PIDFILE ]; then
+-    read kpid < $JBOSS_PIDFILE
+-    kill -15 $kpid
+-    rm -f $JBOSS_PIDFILE
+-  fi
+-}
+-
+-case "$1" in
+-  start)
+-      start
+-      ;;
+-  stop)
+-      stop
+-      ;;
+-  restart)
+-      $0 stop
+-      $0 start
+-      ;;
+-  *)
+-      echo "Usage: $0 {start|stop|restart}"
+-      exit 1
+-      ;;
+-esac
+-
+-- 
+1.7.10
+
diff --git a/0051-Changed-the-systemd-config-file-location-we-want-to-.patch b/0051-Changed-the-systemd-config-file-location-we-want-to-.patch
new file mode 100644
index 0000000..36f798b
--- /dev/null
+++ b/0051-Changed-the-systemd-config-file-location-we-want-to-.patch
@@ -0,0 +1,30 @@
+From e098d57c28c63922e1f6a78c741f2a8cea5cd86a Mon Sep 17 00:00:00 2001
+From: Marek Goldmann <mgoldman at redhat.com>
+Date: Mon, 16 Apr 2012 15:39:32 +0200
+Subject: [PATCH 51/51] Changed the systemd config file location + we want to
+ start JBoss AS before httpd
+
+---
+ build/src/main/resources/bin/initscripts/systemd/jboss-as.service |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/build/src/main/resources/bin/initscripts/systemd/jboss-as.service b/build/src/main/resources/bin/initscripts/systemd/jboss-as.service
+index 41e54e6..32c1c10 100644
+--- a/build/src/main/resources/bin/initscripts/systemd/jboss-as.service
++++ b/build/src/main/resources/bin/initscripts/systemd/jboss-as.service
+@@ -1,10 +1,11 @@
+ [Unit]
+ Description=The JBoss Application Server
+ After=syslog.target network.target
++Before=httpd.service
+ 
+ [Service]
+ Environment=LAUNCH_JBOSS_IN_BACKGROUND=1
+-EnvironmentFile=-/etc/jboss-as.conf
++EnvironmentFile=-/etc/jboss-as/jboss-as.conf
+ User=jboss-as
+ LimitNOFILE=102642
+ PIDFile=/var/run/jboss-as/jboss-as.pid
+-- 
+1.7.10
+
diff --git a/0052-Remove-activation-module.patch b/0052-Remove-activation-module.patch
new file mode 100644
index 0000000..4a407f9
--- /dev/null
+++ b/0052-Remove-activation-module.patch
@@ -0,0 +1,241 @@
+From ab566f0fdf0ecbba2435e1e981a6df53eca6c8c2 Mon Sep 17 00:00:00 2001
+From: Marek Goldmann <mgoldman at redhat.com>
+Date: Mon, 16 Apr 2012 17:45:12 +0200
+Subject: [PATCH 52/52] Remove activation module
+
+---
+ build/build.xml                                    |    4 --
+ build/pom.xml                                      |    5 ---
+ build/src/license/licenses.xml                     |   16 --------
+ .../resources/modules/javaee/api/main/module.xml   |    1 -
+ .../modules/javax/activation/api/main/module.xml   |   39 --------------------
+ .../resources/modules/javax/api/main/module.xml    |    1 +
+ .../modules/javax/mail/api/main/module.xml         |    1 -
+ .../modules/javax/xml/bind/api/main/module.xml     |    1 -
+ .../modules/javax/xml/registry/api/main/module.xml |    2 +-
+ .../codehaus/jackson/jackson-xc/main/module.xml    |    3 +-
+ .../jboss/resteasy/resteasy-jaxrs/main/module.xml  |    1 -
+ pom.xml                                            |    7 ----
+ 12 files changed, 3 insertions(+), 78 deletions(-)
+ delete mode 100644 build/src/main/resources/modules/javax/activation/api/main/module.xml
+
+diff --git a/build/build.xml b/build/build.xml
+index 636e2b5..77fc784 100644
+--- a/build/build.xml
++++ b/build/build.xml
+@@ -699,10 +699,6 @@
+             <maven-resource group="gnu-getopt" artifact="getopt" />
+         </module-def>
+ 
+-        <module-def name="javax.activation.api">
+-            <maven-resource group="javax.activation" artifact="activation"/>
+-        </module-def>
+-
+         <module-def name="javax.faces.api" slot="1.2">
+             <maven-resource group="javax.faces" artifact="jsf-api"/>
+         </module-def>
+diff --git a/build/pom.xml b/build/pom.xml
+index bd882b7..365d2fc 100644
+--- a/build/pom.xml
++++ b/build/pom.xml
+@@ -720,11 +720,6 @@
+                 -->
+ 
+                 <dependency>
+-                    <groupId>javax.activation</groupId>
+-                    <artifactId>activation</artifactId>
+-                </dependency>
+-
+-                <dependency>
+                     <groupId>javax.faces</groupId>
+                     <artifactId>jsf-api</artifactId>
+                 </dependency>
+diff --git a/build/src/license/licenses.xml b/build/src/license/licenses.xml
+index 3e5dbc2..dc4ea97 100644
+--- a/build/src/license/licenses.xml
++++ b/build/src/license/licenses.xml
+@@ -241,22 +241,6 @@
+       </licenses>
+     </dependency>
+     <dependency>
+-      <groupId>javax.activation</groupId>
+-      <artifactId>activation</artifactId>
+-      <licenses>
+-        <license>
+-          <name>Common Development and Distribution License</name>
+-          <url>http://repository.jboss.org/licenses/cddl.txt</url>
+-          <distribution>repo</distribution>
+-        </license>
+-        <license>
+-          <name>GNU General Public License, Version 2 with the Classpath Exception</name>
+-          <url>http://repository.jboss.org/licenses/gpl-2.0-ce.txt</url>
+-          <distribution>repo</distribution>
+-        </license>
+-      </licenses>
+-    </dependency>
+-    <dependency>
+       <groupId>javax.enterprise</groupId>
+       <artifactId>cdi-api</artifactId>
+       <licenses>
+diff --git a/build/src/main/resources/modules/javaee/api/main/module.xml b/build/src/main/resources/modules/javaee/api/main/module.xml
+index 40c62e4..fb439ce 100644
+--- a/build/src/main/resources/modules/javaee/api/main/module.xml
++++ b/build/src/main/resources/modules/javaee/api/main/module.xml
+@@ -28,7 +28,6 @@
+     </resources>
+ 
+     <dependencies>
+-       <!--  <module name="javax.activation.api" export="true"/> is in JDK -->
+         <module name="javax.annotation.api" export="true"/>
+         <module name="javax.ejb.api" export="true"/>
+         <module name="javax.el.api" export="true"/>
+diff --git a/build/src/main/resources/modules/javax/activation/api/main/module.xml b/build/src/main/resources/modules/javax/activation/api/main/module.xml
+deleted file mode 100644
+index 7b73e1f..0000000
+--- a/build/src/main/resources/modules/javax/activation/api/main/module.xml
++++ /dev/null
+@@ -1,39 +0,0 @@
+-<?xml version="1.0" encoding="UTF-8"?>
+-
+-<!--
+-  ~ JBoss, Home of Professional Open Source.
+-  ~ Copyright 2010, Red Hat, Inc., and individual contributors
+-  ~ as indicated by the @author tags. See the copyright.txt file in the
+-  ~ distribution for a full listing of individual contributors.
+-  ~
+-  ~ This is free software; you can redistribute it and/or modify it
+-  ~ under the terms of the GNU Lesser General Public License as
+-  ~ published by the Free Software Foundation; either version 2.1 of
+-  ~ the License, or (at your option) any later version.
+-  ~
+-  ~ This software 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
+-  ~ Lesser General Public License for more details.
+-  ~
+-  ~ You should have received a copy of the GNU Lesser General Public
+-  ~ License along with this software; if not, write to the Free
+-  ~ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+-  ~ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+-  -->
+-
+-<module xmlns="urn:jboss:module:1.1" name="javax.activation.api">
+-    <dependencies>
+-        <module name="javax.api" />
+-        <module name="javax.mail.api">
+-            <imports><include path="META-INF"/></imports>
+-        </module>
+-        <module name="com.sun.xml.messaging.saaj"/>
+-        <module name="org.jboss.ws.native.jbossws-native-core"/>
+-        <module name="org.apache.cxf" optional="true"/>
+-    </dependencies>
+-
+-    <resources>
+-        <!-- Insert resources here -->
+-    </resources>
+-</module>
+diff --git a/build/src/main/resources/modules/javax/api/main/module.xml b/build/src/main/resources/modules/javax/api/main/module.xml
+index 5470de4..3206521 100644
+--- a/build/src/main/resources/modules/javax/api/main/module.xml
++++ b/build/src/main/resources/modules/javax/api/main/module.xml
+@@ -27,6 +27,7 @@
+             <paths>
+                 <path name="javax/accessibility"/>
+                 <path name="javax/activity"/>
++                <path name="javax/activation"/>
+                 <path name="javax/crypto"/>
+                 <path name="javax/crypto/interfaces"/>
+                 <path name="javax/crypto/spec"/>
+diff --git a/build/src/main/resources/modules/javax/mail/api/main/module.xml b/build/src/main/resources/modules/javax/mail/api/main/module.xml
+index 1b60ac1..59b2f5a 100644
+--- a/build/src/main/resources/modules/javax/mail/api/main/module.xml
++++ b/build/src/main/resources/modules/javax/mail/api/main/module.xml
+@@ -24,7 +24,6 @@
+ 
+ <module xmlns="urn:jboss:module:1.1" name="javax.mail.api">
+     <dependencies>
+-        <module name="javax.activation.api" optional="true"/>
+         <module name="javax.api"/>
+     </dependencies>
+ 
+diff --git a/build/src/main/resources/modules/javax/xml/bind/api/main/module.xml b/build/src/main/resources/modules/javax/xml/bind/api/main/module.xml
+index 6376d6f..d68235c 100644
+--- a/build/src/main/resources/modules/javax/xml/bind/api/main/module.xml
++++ b/build/src/main/resources/modules/javax/xml/bind/api/main/module.xml
+@@ -26,7 +26,6 @@
+ 
+ 
+     <dependencies>
+-        <!-- <module name="javax.activation.api" export="true"/> is in JDK -->
+         <module name="javax.xml.stream.api"/>
+         <module name="com.sun.xml.bind" services="import"/>
+         <module name="javax.api"/>
+diff --git a/build/src/main/resources/modules/javax/xml/registry/api/main/module.xml b/build/src/main/resources/modules/javax/xml/registry/api/main/module.xml
+index 0b4a509..c49fde8 100644
+--- a/build/src/main/resources/modules/javax/xml/registry/api/main/module.xml
++++ b/build/src/main/resources/modules/javax/xml/registry/api/main/module.xml
+@@ -24,7 +24,7 @@
+ 
+ <module xmlns="urn:jboss:module:1.1" name="javax.xml.registry.api">
+     <dependencies>
+-        <module name="javax.activation.api" export="true"/>
++        <module name="javax.api" export="true"/>
+     </dependencies>
+ 
+     <resources>
+diff --git a/build/src/main/resources/modules/org/codehaus/jackson/jackson-xc/main/module.xml b/build/src/main/resources/modules/org/codehaus/jackson/jackson-xc/main/module.xml
+index 2c5b473..3a9ea01 100644
+--- a/build/src/main/resources/modules/org/codehaus/jackson/jackson-xc/main/module.xml
++++ b/build/src/main/resources/modules/org/codehaus/jackson/jackson-xc/main/module.xml
+@@ -32,9 +32,8 @@
+ 
+     <dependencies>
+         <module name="javax.api"/>
+-        <module name="javax.activation.api"/>
+         <module name="javax.xml.bind.api"/>
+         <module name="org.codehaus.jackson.jackson-mapper-asl"/>
+         <module name="org.codehaus.jackson.jackson-core-asl"/>
+     </dependencies>
+-</module>
+\ No newline at end of file
++</module>
+diff --git a/build/src/main/resources/modules/org/jboss/resteasy/resteasy-jaxrs/main/module.xml b/build/src/main/resources/modules/org/jboss/resteasy/resteasy-jaxrs/main/module.xml
+index 0c06cc0..4f821ff 100644
+--- a/build/src/main/resources/modules/org/jboss/resteasy/resteasy-jaxrs/main/module.xml
++++ b/build/src/main/resources/modules/org/jboss/resteasy/resteasy-jaxrs/main/module.xml
+@@ -34,7 +34,6 @@
+     <dependencies>
+         <module name="javax.api"/>
+         <module name="javax.annotation.api"/>
+-        <module name="javax.activation.api"/>
+         <module name="javax.ws.rs.api"/>
+         <module name="org.apache.commons.codec" />
+         <module name="org.apache.httpcomponents" />
+diff --git a/pom.xml b/pom.xml
+index 13ba795..56c7d43 100644
+--- a/pom.xml
++++ b/pom.xml
+@@ -89,7 +89,6 @@
+         <version.dom4j>1.6.1</version.dom4j>
+         <version.gnu.getopt>1.0.13</version.gnu.getopt>
+         <version.jacorb>2.3.1.jbossorg-1</version.jacorb>
+-        <version.javax.activation>1.1.1</version.javax.activation>
+         <version.javax.enterprise>1.0-SP4</version.javax.enterprise>
+         <version.javax.faces.jsf-api.1.2>1.2_15-jbossorg-2</version.javax.faces.jsf-api.1.2>
+         <version.javax.faces.jsf-impl>2.1.5-jbossorg-1</version.javax.faces.jsf-impl>
+@@ -1279,12 +1278,6 @@
+             </dependency>
+ 
+             <dependency>
+-                <groupId>javax.activation</groupId>
+-                <artifactId>activation</artifactId>
+-                <version>${version.javax.activation}</version>
+-            </dependency>
+-
+-            <dependency>
+                 <groupId>javax.enterprise</groupId>
+                 <artifactId>cdi-api</artifactId>
+                 <version>${version.javax.enterprise}</version>
+-- 
+1.7.10
+
diff --git a/0053-Use-properties-in-add-user-AS7-module.patch b/0053-Use-properties-in-add-user-AS7-module.patch
new file mode 100644
index 0000000..75170e8
--- /dev/null
+++ b/0053-Use-properties-in-add-user-AS7-module.patch
@@ -0,0 +1,2539 @@
+From 5e20ac99edbb5b858716d6a139d3b59113eefdcb Mon Sep 17 00:00:00 2001
+From: Marek Goldmann <mgoldman at redhat.com>
+Date: Mon, 16 Apr 2012 18:23:15 +0200
+Subject: [PATCH 53/53] Use properties in add-user AS7 module
+
+---
+ build/src/main/resources/bin/add-user.sh           |   11 +
+ .../management/DomainManagementMessages.java       |   66 ++-
+ .../management/security/AddPropertiesUser.java     |  584 ++------------------
+ .../domain/management/security/ConsoleWrapper.java |   85 +++
+ .../as/domain/management/security/JavaConsole.java |   66 +++
+ .../management/security/PropertiesFileLoader.java  |   60 +-
+ .../domain/management/security/state/AddUser.java  |   88 +++
+ .../security/state/ConfirmationChoice.java         |   95 ++++
+ .../security/state/DuplicateUserCheckState.java    |   68 +++
+ .../management/security/state/ErrorState.java      |   74 +++
+ .../security/state/PromptNewUserState.java         |  114 ++++
+ .../security/state/PromptPasswordState.java        |   86 +++
+ .../security/state/PropertyFileFinder.java         |  190 +++++++
+ .../security/state/PropertyFilePrompt.java         |  104 ++++
+ .../as/domain/management/security/state/State.java |   34 ++
+ .../management/security/state/StateValues.java     |  142 +++++
+ .../security/state/UpdatePropertiesHandler.java    |  111 ++++
+ .../management/security/state/UpdateUser.java      |   88 +++
+ .../security/state/UserPropertiesFileHandler.java  |   38 ++
+ .../management/security/state/WeakCheckState.java  |   90 +++
+ 20 files changed, 1631 insertions(+), 563 deletions(-)
+ create mode 100644 domain-management/src/main/java/org/jboss/as/domain/management/security/ConsoleWrapper.java
+ create mode 100644 domain-management/src/main/java/org/jboss/as/domain/management/security/JavaConsole.java
+ create mode 100644 domain-management/src/main/java/org/jboss/as/domain/management/security/state/AddUser.java
+ create mode 100644 domain-management/src/main/java/org/jboss/as/domain/management/security/state/ConfirmationChoice.java
+ create mode 100644 domain-management/src/main/java/org/jboss/as/domain/management/security/state/DuplicateUserCheckState.java
+ create mode 100644 domain-management/src/main/java/org/jboss/as/domain/management/security/state/ErrorState.java
+ create mode 100644 domain-management/src/main/java/org/jboss/as/domain/management/security/state/PromptNewUserState.java
+ create mode 100644 domain-management/src/main/java/org/jboss/as/domain/management/security/state/PromptPasswordState.java
+ create mode 100644 domain-management/src/main/java/org/jboss/as/domain/management/security/state/PropertyFileFinder.java
+ create mode 100644 domain-management/src/main/java/org/jboss/as/domain/management/security/state/PropertyFilePrompt.java
+ create mode 100644 domain-management/src/main/java/org/jboss/as/domain/management/security/state/State.java
+ create mode 100644 domain-management/src/main/java/org/jboss/as/domain/management/security/state/StateValues.java
+ create mode 100644 domain-management/src/main/java/org/jboss/as/domain/management/security/state/UpdatePropertiesHandler.java
+ create mode 100644 domain-management/src/main/java/org/jboss/as/domain/management/security/state/UpdateUser.java
+ create mode 100644 domain-management/src/main/java/org/jboss/as/domain/management/security/state/UserPropertiesFileHandler.java
+ create mode 100644 domain-management/src/main/java/org/jboss/as/domain/management/security/state/WeakCheckState.java
+
+diff --git a/build/src/main/resources/bin/add-user.sh b/build/src/main/resources/bin/add-user.sh
+index dfb0c8b..eeb6ccc 100755
+--- a/build/src/main/resources/bin/add-user.sh
++++ b/build/src/main/resources/bin/add-user.sh
+@@ -51,6 +51,15 @@ if [ "x$JBOSS_MODULEPATH" = "x" ]; then
+     JBOSS_MODULEPATH="$JBOSS_HOME/modules"
+ fi
+ 
++# determine the default base dir, if not set
++if [ "x$JBOSS_BASE_DIR" = "x" ]; then
++   JBOSS_BASE_DIR="$JBOSS_HOME/standalone"
++fi
++# determine the default base dir for domain mode, if not set
++if [ "x$JBOSS_DOMAIN_BASE_DIR" = "x" ]; then
++   JBOSS_DOMAIN_BASE_DIR="$JBOSS_HOME/domain"
++fi
++
+ # For Cygwin, switch paths to Windows format before running java
+ if $cygwin; then
+     JBOSS_HOME=`cygpath --path --windows "$JBOSS_HOME"`
+@@ -64,6 +73,8 @@ fi
+ #JAVA_OPTS="$JAVA_OPTS -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y"
+ 
+ eval \"$JAVA\" $JAVA_OPTS \
++         -Djboss.server.base.dir=\"$JBOSS_BASE_DIR\" \
++         -Djboss.domain.base.dir=\"$JBOSS_DOMAIN_BASE_DIR\" \
+          -jar \"$JBOSS_HOME/jboss-modules.jar\" \
+          -mp \"${JBOSS_MODULEPATH}\" \
+          org.jboss.as.domain-add-user \
+diff --git a/domain-management/src/main/java/org/jboss/as/domain/management/DomainManagementMessages.java b/domain-management/src/main/java/org/jboss/as/domain/management/DomainManagementMessages.java
+index 283a985..c9be048 100644
+--- a/domain-management/src/main/java/org/jboss/as/domain/management/DomainManagementMessages.java
++++ b/domain-management/src/main/java/org/jboss/as/domain/management/DomainManagementMessages.java
+@@ -185,7 +185,7 @@ public interface DomainManagementMessages {
+     String jbossHomeNotSet();
+ 
+     /**
+-     * A message indicating no mgmt-users.properties have been foun.
++     * A message indicating no mgmt-users.properties have been found.
+      *
+      * @return a {@link String} for the message.
+      */
+@@ -430,7 +430,7 @@ public interface DomainManagementMessages {
+     /**
+      * Creates an IllegalArgumentException indicating that a value can not be null.
+      *
+-     * @param name - The name of the paramter that can not be null.
++     * @param name - The name of the parameter that can not be null.
+      * @return an {@link IllegalArgumentException} for the error.
+      */
+     @Message(id = 15248, value = "'%s' can not be null.")
+@@ -459,7 +459,7 @@ public interface DomainManagementMessages {
+     String filePrompt();
+ 
+     /**
+-     * Propmpt the user for the roles to add the user to
++     * Prompt the user for the roles to add the user to
+      * @return
+      */
+     @Message(value = "What roles do you want this user to belong to? (Please enter a comma separated list, or leave blank for none)")
+@@ -478,4 +478,64 @@ public interface DomainManagementMessages {
+     @Message(value = "Added user '%s' with roles %s to file '%s'")
+     String addedRoles(String username, String roles, String fileName);
+ 
++    /**
++     * The error message if the choice response is invalid.
++     *
++     * TODO - On translation we will need support for checking the possible responses.
++     *
++     * @return a {@link String} for the message.
++     */
++    @Message(id = 15251, value = "Invalid response. (Valid responses are A, a, B, or b)")
++    String invalidChoiceResponse();
++
++    /**
++     * Confirmation if the current user password and roles is about to be updated.
++     *
++     * @param user - The name of the user.
++     *
++     * @return a {@link String} for the message.
++     */
++    @Message(value = "User '%s' already exits, would you like to update the existing user password and roles")
++    String aboutToUpdateUser(String user);
++
++    /**
++     * Message to inform user that the user has been updated to the file identified.
++     *
++     * @param username - The new username.
++     * @param fileName - The file the user has been added to.
++     *
++     * @return a {@link String} for the message.
++     */
++    @Message(value = "Updated user '%s' to file '%s'")
++    String updateUser(String userName, String canonicalPath);
++
++
++
++    /**
++    * The error message if updating user to the file fails.
++    *
++    * @param file - The name of the file the add failed for.
++    * @param error - The failure message.
++     *
++     * @return a {@link String} for the message.
++     */
++    @Message(id = 15254, value = "Unable to update user to %s due to error %s")
++    String unableToUpdateUser(String absolutePath, String message);
++
++    /**
++     * Message to inform user that the user has been updated to the roles file identified.
++     *
++     * @param username - The new username.
++     * @param roles - The new roles.
++     * @param fileName - The file the user has been added to.
++     *
++     * @return a {@link String} for the message.
++     */
++    @Message(value = "Updated user '%s' with roles %s to file '%s'")
++    String updatedRoles(String username, String roles, String fileName);
++
++    /*
++    * Logging IDs 15200 to 15299 are reserved for domain management, the file DomainManagementLogger also contains messages in
++    * this range commencing 15200.
++    */
+ }
+diff --git a/domain-management/src/main/java/org/jboss/as/domain/management/security/AddPropertiesUser.java b/domain-management/src/main/java/org/jboss/as/domain/management/security/AddPropertiesUser.java
+index a52f501..b27c7dd 100644
+--- a/domain-management/src/main/java/org/jboss/as/domain/management/security/AddPropertiesUser.java
++++ b/domain-management/src/main/java/org/jboss/as/domain/management/security/AddPropertiesUser.java
+@@ -22,24 +22,17 @@
+ 
+ package org.jboss.as.domain.management.security;
+ 
+-import java.io.BufferedWriter;
++import org.jboss.as.domain.management.security.state.PropertyFileFinder;
++import org.jboss.as.domain.management.security.state.PropertyFilePrompt;
++import org.jboss.as.domain.management.security.state.State;
++import org.jboss.as.domain.management.security.state.StateValues;
++
+ import java.io.Closeable;
+-import java.io.Console;
+-import java.io.File;
+-import java.io.FileInputStream;
+-import java.io.FileWriter;
+ import java.io.IOException;
+ import java.io.StringReader;
+-import java.security.NoSuchAlgorithmException;
+-import java.util.ArrayList;
+-import java.util.Arrays;
+-import java.util.HashSet;
+ import java.util.LinkedList;
+ import java.util.List;
+ import java.util.Properties;
+-import java.util.Set;
+-
+-import org.jboss.sasl.util.UsernamePasswordHashUtil;
+ 
+ import static org.jboss.as.domain.management.DomainManagementMessages.MESSAGES;
+ 
+@@ -50,36 +43,49 @@ import static org.jboss.as.domain.management.DomainManagementMessages.MESSAGES;
+  */
+ public class AddPropertiesUser {
+ 
+-    private static final String[] badUsernames = {"admin", "administrator", "root"};
++    public static final String[] BAD_USER_NAMES = {"admin", "administrator", "root"};
+ 
+-    private static final String DEFAULT_MANAGEMENT_REALM = "ManagementRealm";
+-    private static final String DEFAULT_APPLICATION_REALM = "ApplicationRealm";
++    public static final String SERVER_BASE_DIR = "jboss.server.base.dir";
++    public static final String SERVER_CONFIG_DIR = "jboss.server.config.dir";
++    public static final String DOMAIN_BASE_DIR = "jboss.domain.base.dir";
++    public static final String DOMAIN_CONFIG_DIR = "jboss.domain.config.dir";
++
++    public static final String DEFAULT_MANAGEMENT_REALM = "ManagementRealm";
++    public static final String DEFAULT_APPLICATION_REALM = "ApplicationRealm";
+     public static final String MGMT_USERS_PROPERTIES = "mgmt-users.properties";
+     public static final String APPLICATION_USERS_PROPERTIES = "application-users.properties";
+     public static final String APPLICATION_ROLES_PROPERTIES = "application-roles.properties";
+     public static final String APPLICATION_USERS_SWITCH = "-a";
+ 
+-    private static final String NEW_LINE = "\n";
+-    private static final String SPACE = " ";
++
++    private static final char CARRIAGE_RETURN_CHAR = '\r';
++
++    public static final String NEW_LINE = "\n";
++    public static final String SPACE = " ";
+     private static final Properties argsCliProps = new Properties();
+ 
+-    private final Console theConsole = System.console();
+ 
+-    private List<File> propertiesFiles;
+-    private List<File> roleFiles;
+-    private Set<String> knownUsers;
+-    private State nextState;
++    private ConsoleWrapper theConsole;
++
++
++    protected State nextState;
+ 
+-    private AddPropertiesUser() {
+-        if (theConsole == null) {
++    protected AddPropertiesUser() {
++        theConsole = new JavaConsole();
++        if (theConsole.getConsole() == null) {
+             throw MESSAGES.noConsoleAvailable();
+         }
+-        nextState = new PropertyFilePrompt();
++        nextState = new PropertyFilePrompt(theConsole);
++    }
++
++    protected AddPropertiesUser(ConsoleWrapper console) {
++        this.theConsole = console;
++        nextState = new PropertyFilePrompt(theConsole);
+     }
+ 
+     private AddPropertiesUser(final boolean management, final String user, final char[] password, final String realm) {
+         boolean silent = false;
+-        Values values = new Values();
++        StateValues stateValues = new StateValues();
+ 
+         String valueSilent = argsCliProps.getProperty("silent");
+ 
+@@ -87,27 +93,27 @@ public class AddPropertiesUser {
+             silent = Boolean.valueOf(valueSilent);
+         }
+         if (silent) {
+-            values.howInteractive = Interactiveness.SILENT;
++            stateValues.setHowInteractive(Interactiveness.SILENT);
+         } else {
+-            values.howInteractive = Interactiveness.NON_INTERACTIVE;
++            stateValues.setHowInteractive(Interactiveness.NON_INTERACTIVE);
+         }
+ 
+-        if ((theConsole == null) && (values.isSilent() == false)) {
++        if ((theConsole == null) && (stateValues.isSilent() == false)) {
+             throw MESSAGES.noConsoleAvailable();
+         }
+-        values.userName = user;
+-        values.password = password;
+-        values.realm = realm;
+-        values.management = management;
++        stateValues.setUserName(user);
++        stateValues.setPassword(password);
++        stateValues.setRealm(realm);
++        stateValues.setManagement(management);
+ 
+-        nextState = new PropertyFileFinder(values);
++        nextState = new PropertyFileFinder(theConsole, stateValues);
+     }
+ 
+     private AddPropertiesUser(boolean management, final String user, final char[] password) {
+         this(management, user, password, management ? DEFAULT_MANAGEMENT_REALM : DEFAULT_APPLICATION_REALM);
+     }
+ 
+-    private void run() {
++    protected void run() {
+         while ((nextState = nextState.execute()) != null) {
+         }
+     }
+@@ -154,488 +160,6 @@ public class AddPropertiesUser {
+         }
+     }
+ 
+-
+-    private class PropertyFilePrompt implements State {
+-
+-        @Override
+-        public State execute() {
+-
+-            Values values = new Values();
+-            theConsole.printf(NEW_LINE);
+-            theConsole.printf(MESSAGES.filePrompt());
+-            theConsole.printf(NEW_LINE);
+-
+-            while (true) {
+-                String temp = theConsole.readLine("(a): ");
+-                if (temp == null) {
+-                    /*
+-                     * This will return user to the command prompt so add a new line to
+-                     * ensure the command prompt is on the next line.
+-                     */
+-                    theConsole.printf(NEW_LINE);
+-                    return null;
+-                }
+-                if (temp.length() > 0) {
+-                    switch (temp.charAt(0)) {
+-                        case 'a':
+-                        case 'A':
+-                            values.management = true;
+-                            values.realm = DEFAULT_MANAGEMENT_REALM;
+-                            return new PropertyFileFinder(values);
+-                        case 'b':
+-                        case 'B':
+-                            values.management = false;
+-                            values.realm = DEFAULT_APPLICATION_REALM;
+-                            return new PropertyFileFinder(values);
+-                    }
+-                } else {
+-                    values.management = true;
+-                    values.realm = DEFAULT_MANAGEMENT_REALM;
+-                    return new PropertyFileFinder(values);
+-                }
+-            }
+-        }
+-    }
+-
+-    /**
+-     * The first state executed, responsible for searching for the relevent properties files.
+-     */
+-    private class PropertyFileFinder implements State {
+-
+-        private final Values values;
+-
+-        private PropertyFileFinder(final Values values) {
+-            this.values = values;
+-        }
+-
+-        @Override
+-        public State execute() {
+-            String jbossHome = System.getenv("JBOSS_HOME");
+-            if (jbossHome == null) {
+-                return new ErrorState(MESSAGES.jbossHomeNotSet(), null, values);
+-            }
+-
+-            List<File> foundFiles = new ArrayList<File>(2);
+-            final String fileName = values.management ? MGMT_USERS_PROPERTIES : APPLICATION_USERS_PROPERTIES;
+-            if (!findFiles(jbossHome, foundFiles, fileName)) {
+-                return new ErrorState(MESSAGES.propertiesFileNotFound(fileName), null, values);
+-            }
+-            if(!values.management) {
+-                List<File> foundRoleFiles = new ArrayList<File>(2);
+-                if (!findFiles(jbossHome, foundRoleFiles, APPLICATION_ROLES_PROPERTIES)) {
+-                    return new ErrorState(MESSAGES.propertiesFileNotFound(APPLICATION_ROLES_PROPERTIES), null, values);
+-                }
+-                roleFiles = foundRoleFiles;
+-            }
+-
+-            propertiesFiles = foundFiles;
+-
+-            Set<String> foundUsers = new HashSet<String>();
+-            for (File current : propertiesFiles) {
+-                try {
+-                    foundUsers.addAll(loadUserNames(current));
+-                } catch (IOException e) {
+-                    return new ErrorState(MESSAGES.unableToLoadUsers(current.getAbsolutePath(), e.getMessage()), null, values);
+-                }
+-            }
+-            knownUsers = foundUsers;
+-
+-            if (values == null) {
+-                return new PromptNewUserState();
+-            } else {
+-                return new PromptNewUserState(values);
+-            }
+-        }
+-
+-        private boolean findFiles(final String jbossHome, final List<File> foundFiles, final String fileName) {
+-            File standaloneProps = new File(jbossHome + "/standalone/configuration/" + fileName);
+-            if (standaloneProps.exists()) {
+-                foundFiles.add(standaloneProps);
+-            }
+-            File domainProps = new File(jbossHome + "/domain/configuration/" + fileName);
+-            if (domainProps.exists()) {
+-                foundFiles.add(domainProps);
+-            }
+-
+-            if (foundFiles.size() == 0) {
+-                return false;
+-            }
+-            return true;
+-        }
+-
+-        private Set<String> loadUserNames(final File file) throws IOException {
+-
+-            FileInputStream fis = null;
+-            try {
+-                fis = new FileInputStream(file);
+-                Properties tempProps = new Properties();
+-                tempProps.load(fis);
+-
+-                return tempProps.stringPropertyNames();
+-            } finally {
+-                safeClose(fis);
+-            }
+-
+-        }
+-
+-    }
+-
+-    /**
+-     * State to prompt the user for the realm, username and password to use, this State can be called back to so allows for a
+-     * pre-defined realm and username to be used.
+-     */
+-    private class PromptNewUserState implements State {
+-        private final Values values;
+-
+-        PromptNewUserState() {
+-            values = new Values();
+-            values.realm = DEFAULT_MANAGEMENT_REALM;
+-        }
+-
+-        PromptNewUserState(final Values values) {
+-            this.values = values;
+-        }
+-
+-        @Override
+-        public State execute() {
+-            if (values.isSilentOrNonInteractive() == false) {
+-                theConsole.printf(NEW_LINE);
+-                theConsole.printf(MESSAGES.enterNewUserDetails());
+-                theConsole.printf(NEW_LINE);
+-                values.password = null; // If interactive we want to be sure to capture this.
+-
+-                /*
+-                 * Prompt for realm.
+-                 */
+-                theConsole.printf(MESSAGES.realmPrompt(values.realm));
+-                String temp = theConsole.readLine(" : ");
+-                if (temp == null) {
+-                    /*
+-                     * This will return user to the command prompt so add a new line to
+-                     * ensure the command prompt is on the next line.
+-                     */
+-                    theConsole.printf(NEW_LINE);
+-                    return null;
+-                }
+-                if (temp.length() > 0) {
+-                    values.realm = temp;
+-                }
+-
+-                /*
+-                 * Prompt for username.
+-                 */
+-                String existingUsername = values.userName;
+-                String usernamePrompt = existingUsername == null ? MESSAGES.usernamePrompt() :
+-                        MESSAGES.usernamePrompt(existingUsername);
+-                theConsole.printf(usernamePrompt);
+-                temp = theConsole.readLine(" : ");
+-                if (temp != null && temp.length() > 0) {
+-                    existingUsername = temp;
+-                }
+-                // The user could have pressed Ctrl-D, in which case we do not use the default value.
+-                if (temp == null || existingUsername == null || existingUsername.length() == 0) {
+-                    return new ErrorState(MESSAGES.noUsernameExiting());
+-                }
+-                values.userName = existingUsername;
+-
+-                /*
+-                 * Prompt for password.
+-                 */
+-                theConsole.printf(MESSAGES.passwordPrompt());
+-                char[] tempChar = theConsole.readPassword(" : ");
+-                if (tempChar == null || tempChar.length == 0) {
+-                    return new ErrorState(MESSAGES.noPasswordExiting());
+-                }
+-
+-                theConsole.printf(MESSAGES.passwordConfirmationPrompt());
+-                char[] secondTempChar = theConsole.readPassword(" : ");
+-                if (secondTempChar == null) {
+-                    secondTempChar = new char[0]; // If re-entry missed allow fall through to comparison.
+-                }
+-
+-                if (Arrays.equals(tempChar, secondTempChar) == false) {
+-                    return new ErrorState(MESSAGES.passwordMisMatch(), this);
+-                }
+-                values.password = tempChar;
+-
+-                if(!values.management) {
+-                    theConsole.printf(MESSAGES.rolesPrompt());
+-                    values.roles = theConsole.readLine(" : ");
+-                }
+-            }
+-
+-            return new WeakCheckState(values);
+-        }
+-
+-    }
+-
+-    /**
+-     * State to check the strength of the values selected.
+-     * <p/>
+-     * TODO - Currently only very basic checks are performed, this could be updated to perform additional password strength
+-     * checks.
+-     */
+-    private class WeakCheckState implements State {
+-
+-        private Values values;
+-
+-        private WeakCheckState(Values values) {
+-            this.values = values;
+-        }
+-
+-        @Override
+-        public State execute() {
+-            State retryState = values.isSilentOrNonInteractive() ? null : new PromptNewUserState(values);
+-
+-            if (Arrays.equals(values.userName.toCharArray(), values.password)) {
+-                return new ErrorState(MESSAGES.usernamePasswordMatch(), retryState);
+-            }
+-
+-            for (char currentChar : values.userName.toCharArray()) {
+-                if ((Character.isLetter(currentChar) || Character.isDigit(currentChar)) == false) {
+-                    return new ErrorState(MESSAGES.usernameNotAlphaNumeric(), retryState);
+-                }
+-            }
+-
+-            boolean weakUserName = false;
+-            for (String current : badUsernames) {
+-                if (current.equals(values.userName.toLowerCase())) {
+-                    weakUserName = true;
+-                    break;
+-                }
+-            }
+-
+-            State continuingState = new DuplicateUserCheckState(values);
+-            if (weakUserName && values.isSilentOrNonInteractive() == false) {
+-                String message = MESSAGES.usernameEasyToGuess(values.userName);
+-                String prompt = MESSAGES.sureToAddUser(values.userName);
+-                State noState = new PromptNewUserState(values);
+-
+-                return new ConfirmationChoice(message, prompt, continuingState, noState);
+-            }
+-
+-            return continuingState;
+-        }
+-
+-    }
+-
+-    /**
+-     * State to check that the user is not already defined in any of the resolved
+-     * properties files.
+-     */
+-    private class DuplicateUserCheckState implements State {
+-
+-        private Values values;
+-
+-        private DuplicateUserCheckState(final Values values) {
+-            this.values = values;
+-        }
+-
+-        @Override
+-        public State execute() {
+-            if (knownUsers.contains(values.userName)) {
+-                State continuing = values.isSilentOrNonInteractive() ? null : new PromptNewUserState(values);
+-
+-                return new ErrorState(MESSAGES.duplicateUser(values.userName), continuing, values);
+-            }
+-
+-            State addState = new AddUser(values);
+-            final State continuingState;
+-            if (values.isSilentOrNonInteractive()) {
+-                continuingState = addState;
+-            } else {
+-                String message = MESSAGES.aboutToAddUser(values.userName, values.realm);
+-                String prompt = MESSAGES.isCorrectPrompt();
+-
+-                continuingState = new ConfirmationChoice(message, prompt, addState, new PromptNewUserState(values));
+-            }
+-
+-            return continuingState;
+-        }
+-
+-
+-    }
+-
+-    /**
+-     * State to display a message to the user with option to confirm a choice.
+-     * <p/>
+-     * This state handles either a yes or no outcome and will loop with an error
+-     * on invalid input.
+-     */
+-    private class ConfirmationChoice implements State {
+-
+-        private final String message;
+-        private final String prompt;
+-        private final State yesState;
+-        private final State noState;
+-
+-        private static final int YES = 0;
+-        private static final int NO = 1;
+-        private static final int INVALID = 2;
+-
+-        private ConfirmationChoice(final String message, final String prompt, final State yesState, final State noState) {
+-            this.message = message;
+-            this.prompt = prompt;
+-            this.yesState = yesState;
+-            this.noState = noState;
+-        }
+-
+-        @Override
+-        public State execute() {
+-            if (message != null) {
+-                theConsole.printf(message);
+-                theConsole.printf(NEW_LINE);
+-            }
+-
+-            theConsole.printf(prompt);
+-            String temp = theConsole.readLine(SPACE);
+-
+-            switch (convertResponse(temp)) {
+-                case YES:
+-                    return yesState;
+-                case NO:
+-                    return noState;
+-                default:
+-                    return new ErrorState(MESSAGES.invalidConfirmationResponse(), this);
+-            }
+-        }
+-
+-        private int convertResponse(final String response) {
+-            if (response != null) {
+-                String temp = response.toLowerCase();
+-                if ("yes".equals(temp) || "y".equals(temp)) {
+-                    return YES;
+-                }
+-
+-                if ("no".equals(temp) || "n".equals(temp)) {
+-                    return NO;
+-                }
+-            }
+-
+-            return INVALID;
+-        }
+-
+-    }
+-
+-    /**
+-     * State to perform the actual addition to the discovered properties files.
+-     * <p/>
+-     * By this time ALL validation should be complete, this State will only fail for IOExceptions encountered
+-     * performing the actual writes.
+-     */
+-    private class AddUser implements State {
+-
+-        private final Values values;
+-
+-        private AddUser(final Values values) {
+-            this.values = values;
+-        }
+-
+-        @Override
+-        public State execute() {
+-            String entry;
+-
+-            try {
+-                String hash = new UsernamePasswordHashUtil().generateHashedHexURP(values.userName, values.realm,
+-                        values.password);
+-                entry = values.userName + "=" + hash;
+-            } catch (NoSuchAlgorithmException e) {
+-                return new ErrorState(e.getMessage(), null, values);
+-            }
+-
+-            for (File current : propertiesFiles) {
+-                try {
+-                    append(entry, current);
+-                    if (values.isSilent() == false) {
+-                        theConsole.printf(MESSAGES.addedUser(values.userName, current.getCanonicalPath()));
+-                        theConsole.printf(NEW_LINE);
+-                    }
+-                } catch (IOException e) {
+-                    return new ErrorState(MESSAGES.unableToAddUser(current.getAbsolutePath(), e.getMessage()), null, values);
+-                }
+-            }
+-
+-            if(!values.management && values.roles != null && values.roles.length() > 0) {
+-                for (final File current : roleFiles) {
+-                    String role = values.userName + "=" + values.roles;
+-                    try {
+-                        append(role, current);
+-                        if (values.isSilent() == false) {
+-                            theConsole.printf(MESSAGES.addedRoles(values.userName, values.roles, current.getCanonicalPath()));
+-                            theConsole.printf(NEW_LINE);
+-                        }
+-                    } catch (IOException e) {
+-                        return new ErrorState(MESSAGES.unableToAddUser(current.getAbsolutePath(), e.getMessage()), null, values);
+-                    }
+-                }
+-            }
+-
+-            /*
+-             * At this point the files have been written and confirmation passed back so nothing else to do.
+-             */
+-            return null;
+-        }
+-
+-        private void append(final String entry, final File toFile) throws IOException {
+-            FileWriter fw = null;
+-            BufferedWriter bw = null;
+-
+-            try {
+-                fw = new FileWriter(toFile, true);
+-                bw = new BufferedWriter(fw);
+-
+-                bw.append(entry);
+-                bw.newLine();
+-            } finally {
+-                safeClose(bw);
+-                safeClose(fw);
+-            }
+-
+-        }
+-    }
+-
+-    /**
+-     * State to report an error to the user, optionally a nextState can be supplied so the process can continue even though an
+-     * error has been reported.
+-     */
+-    private class ErrorState implements State {
+-
+-        private final State nextState;
+-        private final String errorMessage;
+-        private final Values values;
+-
+-        private ErrorState(String errorMessage) {
+-            this(errorMessage, null, null);
+-        }
+-
+-        private ErrorState(String errorMessage, State nextState) {
+-            this(errorMessage, nextState, null);
+-        }
+-
+-        private ErrorState(String errorMessage, State nextState, Values values) {
+-            this.errorMessage = errorMessage;
+-            this.nextState = nextState;
+-            this.values = values;
+-        }
+-
+-        @Override
+-        public State execute() {
+-            if ((values == null) || (values != null) && (values.isSilent() == false)) {
+-                theConsole.printf(NEW_LINE);
+-                theConsole.printf(" * ");
+-                theConsole.printf(MESSAGES.errorHeader());
+-                theConsole.printf(" * ");
+-                theConsole.printf(NEW_LINE);
+-
+-                theConsole.printf(errorMessage);
+-                theConsole.printf(NEW_LINE);
+-                theConsole.printf(NEW_LINE);
+-            }
+-            return nextState;
+-        }
+-
+-    }
+-
+     private static void safeClose(Closeable c) {
+         if (c != null) {
+             try {
+@@ -645,31 +169,7 @@ public class AddPropertiesUser {
+         }
+     }
+ 
+-    private class Values {
+-        private Interactiveness howInteractive = Interactiveness.INTERACTIVE;
+-        private String realm;
+-        private String userName;
+-        private char[] password;
+-        private boolean management;
+-        private String roles;
+-
+-        private boolean isSilentOrNonInteractive() {
+-            return (howInteractive == Interactiveness.NON_INTERACTIVE) || isSilent();
+-        }
+-
+-        private boolean isSilent() {
+-            return (howInteractive == Interactiveness.SILENT);
+-        }
+-    }
+-
+-    private enum Interactiveness {
++    public enum Interactiveness {
+         SILENT, NON_INTERACTIVE, INTERACTIVE
+     }
+-
+-    private interface State {
+-
+-        State execute();
+-
+-    }
+-
+ }
+diff --git a/domain-management/src/main/java/org/jboss/as/domain/management/security/ConsoleWrapper.java b/domain-management/src/main/java/org/jboss/as/domain/management/security/ConsoleWrapper.java
+new file mode 100644
+index 0000000..b4458fa
+--- /dev/null
++++ b/domain-management/src/main/java/org/jboss/as/domain/management/security/ConsoleWrapper.java
+@@ -0,0 +1,85 @@
++/*
++ * JBoss, Home of Professional Open Source.
++ * Copyright 2012, Red Hat, Inc., and individual contributors
++ * as indicated by the @author tags. See the copyright.txt file in the
++ * distribution for a full listing of individual contributors.
++ *
++ * This is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Lesser General Public License as
++ * published by the Free Software Foundation; either version 2.1 of
++ * the License, or (at your option) any later version.
++ *
++ * This software 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
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this software; if not, write to the Free
++ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
++ */
++
++package org.jboss.as.domain.management.security;
++
++import java.io.IOError;
++import java.util.IllegalFormatException;
++
++/**
++ * Wrap the console commands
++ *
++ * @author <a href="mailto:flemming.harms at gmail.com">Flemming Harms</a>
++ */
++public interface ConsoleWrapper<T> {
++
++    /**
++     * Writes a formatted string to this console's output stream using
++     * the specified format string and arguments.
++     * see <a href="../util/Formatter.html#syntax">Format string syntax</a>
++     * @param fmt
++     * @param args
++     */
++    T format(String fmt, Object ...args) throws IllegalFormatException;
++
++    /**
++     * A convenience method to write a formatted string to this console's
++     * output stream using the specified format string and arguments.
++     *
++     * @param format
++     * @param args
++     * @throws IllegalStateException
++     */
++    void printf(String format, Object ... args) throws IllegalFormatException;
++
++    /**
++     * Provides a formatted prompt, then reads a single line of text from the
++     * console.
++     *
++     * @param fmt
++     * @param args
++     * @return A string containing the line read from the console, not
++     *          including any line-termination characters, or <tt>null</tt>
++     *          if an end of stream has been reached.
++     * @throws IOError
++     */
++    String readLine(String fmt, Object ... args) throws IOError;
++
++    /**
++     * Provides a formatted prompt, then reads a password or passphrase from
++     * the console with echoing disabled.
++     *
++     * @param fmt
++     * @param args
++     * @return  A character array containing the password or passphrase read
++     *          from the console.
++     * @throws IOError
++     */
++    char[] readPassword(String fmt, Object ... args) throws IllegalFormatException, IOError;
++
++    /**
++     *  Return the console object
++     *
++     * @return Return the console object
++     */
++    T getConsole();
++}
+diff --git a/domain-management/src/main/java/org/jboss/as/domain/management/security/JavaConsole.java b/domain-management/src/main/java/org/jboss/as/domain/management/security/JavaConsole.java
+new file mode 100644
+index 0000000..964a26a
+--- /dev/null
++++ b/domain-management/src/main/java/org/jboss/as/domain/management/security/JavaConsole.java
+@@ -0,0 +1,66 @@
++/*
++ *
++ *  * JBoss, Home of Professional Open Source.
++ *  * Copyright 2011, Red Hat, Inc., and individual contributors
++ *  * as indicated by the @author tags. See the copyright.txt file in the
++ *  * distribution for a full listing of individual contributors.
++ *  *
++ *  * This is free software; you can redistribute it and/or modify it
++ *  * under the terms of the GNU Lesser General Public License as
++ *  * published by the Free Software Foundation; either version 2.1 of
++ *  * the License, or (at your option) any later version.
++ *  *
++ *  * This software 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
++ *  * Lesser General Public License for more details.
++ *  *
++ *  * You should have received a copy of the GNU Lesser General Public
++ *  * License along with this software; if not, write to the Free
++ *  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ *  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
++ *
++ */
++
++package org.jboss.as.domain.management.security;
++
++import java.io.Console;
++import java.io.IOError;
++import java.util.IllegalFormatException;
++
++/**
++ * Describe the purpose
++ *
++ * @author <a href="mailto:flemming.harms at gmail.com">Flemming Harms</a>
++ */
++public class JavaConsole implements ConsoleWrapper<Console> {
++
++    private Console theConsole = System.console();
++
++    public void JavaConsole() {}
++
++    @Override
++    public Console format(String fmt, Object... args) throws IllegalFormatException {
++        return theConsole.format(fmt,args);
++    }
++
++    @Override
++    public void printf(String format, Object... args) throws IllegalFormatException {
++        theConsole.printf(format,args);
++    }
++
++    @Override
++    public String readLine(String fmt, Object... args) throws IOError {
++        return theConsole.readLine(fmt,args);
++    }
++
++    @Override
++    public char[] readPassword(String fmt, Object... args) throws IllegalFormatException, IOError {
++        return theConsole.readPassword(fmt,args);
++    }
++
++    @Override
++    public Console getConsole() {
++        return theConsole;
++    }
++}
+diff --git a/domain-management/src/main/java/org/jboss/as/domain/management/security/PropertiesFileLoader.java b/domain-management/src/main/java/org/jboss/as/domain/management/security/PropertiesFileLoader.java
+index 97ca458..38737cb 100644
+--- a/domain-management/src/main/java/org/jboss/as/domain/management/security/PropertiesFileLoader.java
++++ b/domain-management/src/main/java/org/jboss/as/domain/management/security/PropertiesFileLoader.java
+@@ -22,24 +22,27 @@
+ 
+ package org.jboss.as.domain.management.security;
+ 
+-import static org.jboss.as.domain.management.DomainManagementLogger.ROOT_LOGGER;
+-import static org.jboss.as.domain.management.DomainManagementMessages.MESSAGES;
++import org.jboss.msc.service.StartContext;
++import org.jboss.msc.service.StartException;
++import org.jboss.msc.service.StopContext;
++import org.jboss.msc.value.InjectedValue;
+ 
+ import java.io.BufferedReader;
+ import java.io.BufferedWriter;
+ import java.io.Closeable;
+ import java.io.File;
+ import java.io.FileInputStream;
++import java.io.FileOutputStream;
+ import java.io.FileReader;
+-import java.io.FileWriter;
+ import java.io.IOException;
+-import java.io.InputStream;
++import java.io.InputStreamReader;
++import java.io.OutputStreamWriter;
++import java.nio.charset.Charset;
++import java.util.Arrays;
+ import java.util.Properties;
+ 
+-import org.jboss.msc.service.StartContext;
+-import org.jboss.msc.service.StartException;
+-import org.jboss.msc.service.StopContext;
+-import org.jboss.msc.value.InjectedValue;
++import static org.jboss.as.domain.management.DomainManagementLogger.ROOT_LOGGER;
++import static org.jboss.as.domain.management.DomainManagementMessages.MESSAGES;
+ 
+ /**
+  * The base class for services depending on loading a properties file, loads the properties on
+@@ -49,6 +52,7 @@ import org.jboss.msc.value.InjectedValue;
+  */
+ public abstract class PropertiesFileLoader {
+ 
++    public static final char[] ESCAPE_ARRAY = new char[]{'='};
+     private final String path;
+     private final InjectedValue<String> relativeTo = new InjectedValue<String>();
+ 
+@@ -82,7 +86,7 @@ public abstract class PropertiesFileLoader {
+         propertiesFile = null;
+     }
+ 
+-    protected Properties getProperties() throws IOException {
++    public Properties getProperties() throws IOException {
+         /*
+          * This method does attempt to minimise the effect of race conditions, however this is not overly critical as if you
+          * have users attempting to authenticate at the exact point their details are added to the file there is also a chance
+@@ -99,7 +103,7 @@ public abstract class PropertiesFileLoader {
+                 if (loadReallyRequired) {
+                     ROOT_LOGGER.debugf("Reloading properties file '%s'", propertiesFile.getAbsolutePath());
+                     Properties props = new Properties();
+-                    InputStream is = new FileInputStream(propertiesFile);
++                    InputStreamReader is = new InputStreamReader(new FileInputStream(propertiesFile), Charset.forName("UTF-8"));
+                     try {
+                         props.load(is);
+                     } finally {
+@@ -118,7 +122,7 @@ public abstract class PropertiesFileLoader {
+         return properties;
+     }
+ 
+-    private synchronized void persistProperties() throws IOException {
++    public synchronized void persistProperties() throws IOException {
+         Properties toSave = (Properties) properties.clone();
+ 
+         File backup = new File(propertiesFile.getCanonicalPath() + ".bak");
+@@ -135,8 +139,7 @@ public abstract class PropertiesFileLoader {
+         FileReader fr = new FileReader(backup);
+         BufferedReader br = new BufferedReader(fr);
+ 
+-        FileWriter fw = new FileWriter(propertiesFile);
+-        BufferedWriter bw = new BufferedWriter(fw);
++        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(propertiesFile),"UTF8"));
+ 
+         try {
+             String line;
+@@ -151,8 +154,9 @@ public abstract class PropertiesFileLoader {
+                     int equals = trimmed.indexOf('=');
+                     if (equals > 0) {
+                         String userName = trimmed.substring(0, equals);
+-                        if (toSave.contains(userName)) {
+-                            bw.append(userName + "=" + toSave.getProperty(userName));
++                        if (toSave.containsKey(userName)) {
++                            String escapedUserName = escapeString(userName, ESCAPE_ARRAY);
++                            bw.append(escapedUserName + "=" + toSave.getProperty(userName));
+                             bw.newLine();
+                             toSave.remove(userName);
+                         }
+@@ -162,18 +166,38 @@ public abstract class PropertiesFileLoader {
+ 
+             // Append any additional users to the end of the file.
+             for (Object currentKey : toSave.keySet()) {
+-                bw.append(currentKey + "=" + toSave.getProperty((String) currentKey));
++                String escapedUserName = escapeString((String) currentKey, ESCAPE_ARRAY);
++                bw.append(escapedUserName + "=" + toSave.getProperty((String) currentKey));
+                 bw.newLine();
+             }
+-            bw.newLine();
+         } finally {
+             safeClose(bw);
+-            safeClose(fw);
+             safeClose(br);
+             safeClose(fr);
+         }
+     }
+ 
++
++    public static String escapeString(String name, char[] escapeArray) {
++        Arrays.sort(escapeArray);
++        for(int i = 0; i < name.length(); ++i) {
++            char ch = name.charAt(i);
++            if(Arrays.binarySearch(escapeArray,ch) >=0 ) {
++                StringBuilder builder = new StringBuilder();
++                builder.append(name, 0, i);
++                builder.append('\\').append(ch);
++                for(int j = i + 1; j < name.length(); ++j) {
++                    ch = name.charAt(j);
++                    if(Arrays.binarySearch(escapeArray,ch)>0) {
++                        builder.append('\\');
++                    }
++                    builder.append(ch);
++                }
++                return builder.toString();
++            }
++        }
++        return name;
++    }
+     private void safeClose(final Closeable c) {
+         try {
+             c.close();
+diff --git a/domain-management/src/main/java/org/jboss/as/domain/management/security/state/AddUser.java b/domain-management/src/main/java/org/jboss/as/domain/management/security/state/AddUser.java
+new file mode 100644
+index 0000000..58e92ed
+--- /dev/null
++++ b/domain-management/src/main/java/org/jboss/as/domain/management/security/state/AddUser.java
+@@ -0,0 +1,88 @@
++/*
++ * JBoss, Home of Professional Open Source.
++ * Copyright 2011, Red Hat, Inc., and individual contributors
++ * as indicated by the @author tags. See the copyright.txt file in the
++ * distribution for a full listing of individual contributors.
++ *
++ * This is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Lesser General Public License as
++ * published by the Free Software Foundation; either version 2.1 of
++ * the License, or (at your option) any later version.
++ *
++ * This software 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
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this software; if not, write to the Free
++ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
++ */
++
++
++package org.jboss.as.domain.management.security.state;
++
++import org.jboss.as.domain.management.security.ConsoleWrapper;
++import org.jboss.msc.service.StartException;
++
++import java.io.File;
++import java.io.IOException;
++import java.util.Properties;
++
++import static org.jboss.as.domain.management.DomainManagementMessages.MESSAGES;
++
++/**
++ * State to perform the actual addition to the discovered properties files.
++ * <p/>
++ * By this time ALL validation should be complete, this State will only fail for IOExceptions encountered
++ * performing the actual writes.
++ */
++public class AddUser extends UpdatePropertiesHandler implements State {
++
++    private final StateValues stateValues;
++
++    public AddUser(ConsoleWrapper theConsole, final StateValues stateValues) {
++        super(theConsole);
++        this.stateValues = stateValues;
++    }
++
++    @Override
++    public State execute() {
++        /*
++        * At this point the files have been written and confirmation passed back so nothing else to do.
++        */
++        return update(stateValues);
++    }
++
++    @Override
++    void persist(String[] entry, File file) throws IOException {
++        UserPropertiesFileHandler propertiesHandler = new UserPropertiesFileHandler(file.getAbsolutePath());
++        try {
++            propertiesHandler.start(null);
++            Properties prob = propertiesHandler.getProperties();
++            prob.setProperty(entry[0], entry[1]);
++            propertiesHandler.persistProperties();
++        } catch (StartException e) {
++            throw new IllegalStateException(MESSAGES.unableToAddUser(file.getAbsolutePath(), e.getMessage()));
++        } finally {
++            propertiesHandler.stop(null);
++        }
++
++    }
++
++    @Override
++    String consoleUserMessage(String filePath) {
++        return MESSAGES.addedUser(stateValues.getUserName(), filePath);
++    }
++
++    @Override
++    String consoleRolesMessage(String filePath) {
++        return MESSAGES.addedRoles(stateValues.getUserName(), stateValues.getRoles(), filePath);
++    }
++
++    @Override
++    String errorMessage(String filePath, Throwable e) {
++        return MESSAGES.unableToAddUser(filePath, e.getMessage());
++    }
++}
+diff --git a/domain-management/src/main/java/org/jboss/as/domain/management/security/state/ConfirmationChoice.java b/domain-management/src/main/java/org/jboss/as/domain/management/security/state/ConfirmationChoice.java
+new file mode 100644
+index 0000000..fffa6cf
+--- /dev/null
++++ b/domain-management/src/main/java/org/jboss/as/domain/management/security/state/ConfirmationChoice.java
+@@ -0,0 +1,95 @@
++/*
++ * JBoss, Home of Professional Open Source.
++ * Copyright 2011, Red Hat, Inc., and individual contributors
++ * as indicated by the @author tags. See the copyright.txt file in the
++ * distribution for a full listing of individual contributors.
++ *
++ * This is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Lesser General Public License as
++ * published by the Free Software Foundation; either version 2.1 of
++ * the License, or (at your option) any later version.
++ *
++ * This software 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
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this software; if not, write to the Free
++ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
++ */
++
++package org.jboss.as.domain.management.security.state;
++
++import org.jboss.as.domain.management.security.ConsoleWrapper;
++
++import static org.jboss.as.domain.management.DomainManagementMessages.MESSAGES;
++import static org.jboss.as.domain.management.security.AddPropertiesUser.NEW_LINE;
++import static org.jboss.as.domain.management.security.AddPropertiesUser.SPACE;
++
++/**
++ * State to display a message to the user with option to confirm a choice.
++ * <p/>
++ * This state handles either a yes or no outcome and will loop with an error
++ * on invalid input.
++ */
++public class ConfirmationChoice implements State {
++
++    private ConsoleWrapper theConsole;
++    private final String message;
++    private final String prompt;
++    private final State yesState;
++    private final State noState;
++
++    private static final int YES = 0;
++    private static final int NO = 1;
++    private static final int INVALID = 2;
++
++    public ConfirmationChoice(ConsoleWrapper theConsole,final String message, final String prompt, final State yesState, final State noState) {
++        this.theConsole = theConsole;
++        this.message = message;
++        this.prompt = prompt;
++        this.yesState = yesState;
++        this.noState = noState;
++        if (theConsole.getConsole() == null) {
++            throw MESSAGES.noConsoleAvailable();
++        }
++    }
++
++    @Override
++    public State execute() {
++        if (message != null) {
++            theConsole.printf(message);
++            theConsole.printf(NEW_LINE);
++        }
++
++        theConsole.printf(prompt);
++        String temp = theConsole.readLine(SPACE);
++
++        switch (convertResponse(temp)) {
++            case YES:
++                return yesState;
++            case NO:
++                return noState;
++            default:
++                return new ErrorState(theConsole, MESSAGES.invalidConfirmationResponse(), this);
++        }
++    }
++
++    private int convertResponse(final String response) {
++        if (response != null) {
++            String temp = response.toLowerCase();
++            if ("yes".equals(temp) || "y".equals(temp)) {
++                return YES;
++            }
++
++            if ("no".equals(temp) || "n".equals(temp)) {
++                return NO;
++            }
++        }
++
++        return INVALID;
++    }
++
++}
+diff --git a/domain-management/src/main/java/org/jboss/as/domain/management/security/state/DuplicateUserCheckState.java b/domain-management/src/main/java/org/jboss/as/domain/management/security/state/DuplicateUserCheckState.java
+new file mode 100644
+index 0000000..a222e15
+--- /dev/null
++++ b/domain-management/src/main/java/org/jboss/as/domain/management/security/state/DuplicateUserCheckState.java
+@@ -0,0 +1,68 @@
++/*
++ * JBoss, Home of Professional Open Source.
++ * Copyright 2011, Red Hat, Inc., and individual contributors
++ * as indicated by the @author tags. See the copyright.txt file in the
++ * distribution for a full listing of individual contributors.
++ *
++ * This is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Lesser General Public License as
++ * published by the Free Software Foundation; either version 2.1 of
++ * the License, or (at your option) any later version.
++ *
++ * This software 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
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this software; if not, write to the Free
++ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
++ */
++package org.jboss.as.domain.management.security.state;
++
++import org.jboss.as.domain.management.security.ConsoleWrapper;
++
++import static org.jboss.as.domain.management.DomainManagementMessages.MESSAGES;
++
++/**
++ * State to check that the user is not already defined in any of the resolved
++ * properties files.
++ */
++public class DuplicateUserCheckState implements State {
++
++    private final ConsoleWrapper theConsole;
++    private StateValues stateValues;
++
++    public DuplicateUserCheckState(final ConsoleWrapper theConsole,final StateValues stateValues) {
++        this.theConsole = theConsole;
++        this.stateValues = stateValues;
++        if (theConsole.getConsole() == null) {
++            throw MESSAGES.noConsoleAvailable();
++        }
++    }
++
++    @Override
++    public State execute() {
++        final State continuingState;
++        if (stateValues.isExistingUser()) {
++            continuingState = new UpdateUser(theConsole, stateValues);
++        } else {
++            State addState = new AddUser(theConsole, stateValues);
++
++            if (stateValues.isSilentOrNonInteractive()) {
++                continuingState = addState;
++            } else {
++                String message = MESSAGES.aboutToAddUser(stateValues.getUserName(), stateValues.getRealm());
++                String prompt = MESSAGES.isCorrectPrompt();
++
++                continuingState = new ConfirmationChoice(theConsole,message, prompt, addState, new PromptNewUserState(theConsole, stateValues));
++            }
++        }
++
++        return continuingState;
++    }
++
++
++}
++
+diff --git a/domain-management/src/main/java/org/jboss/as/domain/management/security/state/ErrorState.java b/domain-management/src/main/java/org/jboss/as/domain/management/security/state/ErrorState.java
+new file mode 100644
+index 0000000..6f875bc
+--- /dev/null
++++ b/domain-management/src/main/java/org/jboss/as/domain/management/security/state/ErrorState.java
+@@ -0,0 +1,74 @@
++/*
++ * JBoss, Home of Professional Open Source.
++ * Copyright 2011, Red Hat, Inc., and individual contributors
++ * as indicated by the @author tags. See the copyright.txt file in the
++ * distribution for a full listing of individual contributors.
++ *
++ * This is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Lesser General Public License as
++ * published by the Free Software Foundation; either version 2.1 of
++ * the License, or (at your option) any later version.
++ *
++ * This software 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
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this software; if not, write to the Free
++ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
++ */
++
++package org.jboss.as.domain.management.security.state;
++
++import org.jboss.as.domain.management.security.ConsoleWrapper;
++import static org.jboss.as.domain.management.security.AddPropertiesUser.NEW_LINE;
++import static org.jboss.as.domain.management.DomainManagementMessages.MESSAGES;
++
++/**
++ * State to report an error to the user, optionally a nextState can be supplied so the process can continue even though an
++ * error has been reported.
++ */
++public class ErrorState implements State {
++
++    private final State nextState;
++    private final String errorMessage;
++    private final StateValues stateValues;
++    private ConsoleWrapper theConsole;
++
++    public ErrorState(ConsoleWrapper theConsole, String errorMessage) {
++        this(theConsole, errorMessage, null, null);
++    }
++
++    public ErrorState(ConsoleWrapper theConsole, String errorMessage, State nextState) {
++        this(theConsole, errorMessage, nextState, null);
++    }
++
++    public ErrorState(ConsoleWrapper theConsole, String errorMessage, State nextState, StateValues stateValues) {
++        this.errorMessage = errorMessage;
++        this.nextState = nextState;
++        this.stateValues = stateValues;
++        this.theConsole = theConsole;
++        if (theConsole.getConsole() == null) {
++            throw MESSAGES.noConsoleAvailable();
++        }
++    }
++
++    @Override
++    public State execute() {
++        if ((stateValues == null) || (stateValues != null) && (stateValues.isSilent() == false)) {
++            theConsole.printf(NEW_LINE);
++            theConsole.printf(" * ");
++            theConsole.printf(MESSAGES.errorHeader());
++            theConsole.printf(" * ");
++            theConsole.printf(NEW_LINE);
++
++            theConsole.printf(errorMessage);
++            theConsole.printf(NEW_LINE);
++            theConsole.printf(NEW_LINE);
++        }
++        return nextState;
++    }
++
++}
+diff --git a/domain-management/src/main/java/org/jboss/as/domain/management/security/state/PromptNewUserState.java b/domain-management/src/main/java/org/jboss/as/domain/management/security/state/PromptNewUserState.java
+new file mode 100644
+index 0000000..f0b157a
+--- /dev/null
++++ b/domain-management/src/main/java/org/jboss/as/domain/management/security/state/PromptNewUserState.java
+@@ -0,0 +1,114 @@
++/*
++ * JBoss, Home of Professional Open Source.
++ * Copyright 2011, Red Hat, Inc., and individual contributors
++ * as indicated by the @author tags. See the copyright.txt file in the
++ * distribution for a full listing of individual contributors.
++ *
++ * This is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Lesser General Public License as
++ * published by the Free Software Foundation; either version 2.1 of
++ * the License, or (at your option) any later version.
++ *
++ * This software 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
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this software; if not, write to the Free
++ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
++ */
++
++
++package org.jboss.as.domain.management.security.state;
++
++import org.jboss.as.domain.management.security.ConsoleWrapper;
++
++import static org.jboss.as.domain.management.security.AddPropertiesUser.DEFAULT_MANAGEMENT_REALM;
++import static org.jboss.as.domain.management.security.AddPropertiesUser.NEW_LINE;
++import static org.jboss.as.domain.management.DomainManagementMessages.MESSAGES;
++
++/**
++ * State to prompt the user for the realm, username and password to use, this State can be called back to so allows for a
++ * pre-defined realm and username to be used.
++ */
++public class PromptNewUserState implements State {
++    private final StateValues stateValues;
++    private ConsoleWrapper theConsole;
++
++    public PromptNewUserState(ConsoleWrapper theConsole) {
++        this.theConsole = theConsole;
++        stateValues = new StateValues();
++        stateValues.setRealm(DEFAULT_MANAGEMENT_REALM);
++    }
++
++    public PromptNewUserState(ConsoleWrapper theConsole, final StateValues stateValues) {
++        this.theConsole = theConsole;
++        this.stateValues = stateValues;
++        if (theConsole.getConsole() == null) {
++            throw MESSAGES.noConsoleAvailable();
++        }
++    }
++
++    @Override
++    public State execute() {
++        State continuingState = new PromptPasswordState(theConsole, stateValues);
++        if (stateValues.isSilentOrNonInteractive() == false) {
++            theConsole.printf(NEW_LINE);
++            theConsole.printf(MESSAGES.enterNewUserDetails());
++            theConsole.printf(NEW_LINE);
++            stateValues.setPassword(null); // If interactive we want to be sure to capture this.
++
++            /*
++            * Prompt for realm.
++            */
++            theConsole.printf(MESSAGES.realmPrompt(stateValues.getRealm()));
++            String temp = theConsole.readLine(" : ");
++            if (temp == null) {
++                /*
++                * This will return user to the command prompt so add a new line to
++                * ensure the command prompt is on the next line.
++                */
++                theConsole.printf(NEW_LINE);
++                return null;
++            }
++            if (temp.length() > 0) {
++                stateValues.setRealm(temp);
++            }
++
++            /*
++            * Prompt for username.
++            */
++            String existingUsername = stateValues.getUserName();
++            String usernamePrompt = existingUsername == null ? MESSAGES.usernamePrompt() :
++                    MESSAGES.usernamePrompt(existingUsername);
++            theConsole.printf(usernamePrompt);
++            temp = theConsole.readLine(" : ");
++            if (temp != null && temp.length() > 0) {
++                existingUsername = temp;
++            }
++            // The user could have pressed Ctrl-D, in which case we do not use the default value.
++            if (temp == null || existingUsername == null || existingUsername.length() == 0) {
++                return new ErrorState(theConsole,MESSAGES.noUsernameExiting());
++            }
++            stateValues.setUserName(existingUsername);
++
++            if (stateValues.getKnownUsers().contains(stateValues.getUserName())) {
++                State duplicateContinuing = stateValues.isSilentOrNonInteractive() ? null : new PromptNewUserState(theConsole, stateValues);
++                if (stateValues.isSilentOrNonInteractive()) {
++                    continuingState = new ErrorState(theConsole, MESSAGES.duplicateUser(stateValues.getUserName()), duplicateContinuing, stateValues);
++                } else {
++                    String message = MESSAGES.aboutToUpdateUser(stateValues.getUserName());
++                    String prompt = MESSAGES.isCorrectPrompt();
++
++                    stateValues.setExistingUser(true);
++                    continuingState = new ConfirmationChoice(theConsole,message, prompt, continuingState, duplicateContinuing);
++                }
++            }
++        }
++
++        return continuingState;
++    }
++
++}
+\ No newline at end of file
+diff --git a/domain-management/src/main/java/org/jboss/as/domain/management/security/state/PromptPasswordState.java b/domain-management/src/main/java/org/jboss/as/domain/management/security/state/PromptPasswordState.java
+new file mode 100644
+index 0000000..91ab15a
+--- /dev/null
++++ b/domain-management/src/main/java/org/jboss/as/domain/management/security/state/PromptPasswordState.java
+@@ -0,0 +1,86 @@
++/*
++ * JBoss, Home of Professional Open Source.
++ * Copyright 2011, Red Hat, Inc., and individual contributors
++ * as indicated by the @author tags. See the copyright.txt file in the
++ * distribution for a full listing of individual contributors.
++ *
++ * This is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Lesser General Public License as
++ * published by the Free Software Foundation; either version 2.1 of
++ * the License, or (at your option) any later version.
++ *
++ * This software 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
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this software; if not, write to the Free
++ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
++ */
++
++package org.jboss.as.domain.management.security.state;
++
++import org.jboss.as.domain.management.security.ConsoleWrapper;
++
++import java.util.Arrays;
++
++import static org.jboss.as.domain.management.DomainManagementMessages.MESSAGES;
++
++/**
++ * State to prompt the user for a password
++ * <p/>
++ * This state handles password validation by let the user re-enter the password
++ * in case of the password mismatch the user will be present for an error
++ * and will re-enter the PromptPasswordState again
++ */
++public class PromptPasswordState implements State {
++
++    private ConsoleWrapper theConsole;
++    private StateValues stateValues;
++
++    public PromptPasswordState(ConsoleWrapper theConsole, StateValues stateValues) {
++        this.theConsole = theConsole;
++        this.stateValues = stateValues;
++        if (theConsole.getConsole() == null) {
++            throw MESSAGES.noConsoleAvailable();
++        }
++    }
++
++    @Override
++    public State execute() {
++        State continuingState = new WeakCheckState(theConsole, stateValues);
++        if (stateValues.isSilentOrNonInteractive() == false) {
++            /*
++            * Prompt for password.
++            */
++            theConsole.printf(MESSAGES.passwordPrompt());
++            char[] tempChar = theConsole.readPassword(" : ");
++            if (tempChar == null || tempChar.length == 0) {
++                return new ErrorState(theConsole,MESSAGES.noPasswordExiting());
++            }
++
++            theConsole.printf(MESSAGES.passwordConfirmationPrompt());
++            char[] secondTempChar = theConsole.readPassword(" : ");
++            if (secondTempChar == null) {
++                secondTempChar = new char[0]; // If re-entry missed allow fall through to comparison.
++            }
++
++            if (Arrays.equals(tempChar, secondTempChar) == false) {
++                return new ErrorState(theConsole, MESSAGES.passwordMisMatch(), this);
++            }
++            stateValues.setPassword(tempChar);
++
++            if (!stateValues.isManagement()) {
++                theConsole.printf(MESSAGES.rolesPrompt());
++                String userRoles = stateValues.getKnownRoles().get(stateValues.getUserName());
++                stateValues.setRoles(theConsole.readLine("[%1$2s]: ", (userRoles == null?"":userRoles)));
++            }
++        }
++
++        return continuingState;
++
++    }
++}
++
+diff --git a/domain-management/src/main/java/org/jboss/as/domain/management/security/state/PropertyFileFinder.java b/domain-management/src/main/java/org/jboss/as/domain/management/security/state/PropertyFileFinder.java
+new file mode 100644
+index 0000000..22f57f3
+--- /dev/null
++++ b/domain-management/src/main/java/org/jboss/as/domain/management/security/state/PropertyFileFinder.java
+@@ -0,0 +1,190 @@
++/*
++ * JBoss, Home of Professional Open Source.
++ * Copyright 2011, Red Hat, Inc., and individual contributors
++ * as indicated by the @author tags. See the copyright.txt file in the
++ * distribution for a full listing of individual contributors.
++ *
++ * This is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Lesser General Public License as
++ * published by the Free Software Foundation; either version 2.1 of
++ * the License, or (at your option) any later version.
++ *
++ * This software 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
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this software; if not, write to the Free
++ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
++ */
++
++package org.jboss.as.domain.management.security.state;
++
++/**
++ * Describe the purpose
++ *
++ * @author <a href="mailto:flemming.harms at gmail.com">Flemming Harms</a>
++ */
++
++import org.jboss.as.domain.management.security.ConsoleWrapper;
++import org.jboss.as.domain.management.security.PropertiesFileLoader;
++import org.jboss.msc.service.StartException;
++
++import java.io.Closeable;
++import java.io.File;
++import java.io.FileInputStream;
++import java.io.IOException;
++import java.io.InputStreamReader;
++import java.nio.charset.Charset;
++import java.util.ArrayList;
++import java.util.HashMap;
++import java.util.HashSet;
++import java.util.List;
++import java.util.Map;
++import java.util.Properties;
++import java.util.Set;
++import static org.jboss.as.domain.management.security.AddPropertiesUser.MGMT_USERS_PROPERTIES;
++import static org.jboss.as.domain.management.security.AddPropertiesUser.APPLICATION_USERS_PROPERTIES;
++import static org.jboss.as.domain.management.security.AddPropertiesUser.APPLICATION_ROLES_PROPERTIES;
++import static org.jboss.as.domain.management.security.AddPropertiesUser.SERVER_CONFIG_DIR;
++import static org.jboss.as.domain.management.security.AddPropertiesUser.SERVER_BASE_DIR;
++import static org.jboss.as.domain.management.security.AddPropertiesUser.DOMAIN_BASE_DIR;
++import static org.jboss.as.domain.management.security.AddPropertiesUser.DOMAIN_CONFIG_DIR;
++
++import static org.jboss.as.domain.management.DomainManagementMessages.MESSAGES;
++
++/**
++ * The first state executed, responsible for searching for the relevant properties files.
++ */
++public class PropertyFileFinder implements State {
++
++    private ConsoleWrapper theConsole;
++    private final StateValues stateValues;
++
++    public PropertyFileFinder(ConsoleWrapper theConsole,final StateValues stateValues) {
++        this.theConsole = theConsole;
++        this.stateValues = stateValues;
++        if (theConsole.getConsole() == null) {
++            throw MESSAGES.noConsoleAvailable();
++        }
++    }
++
++    @Override
++    public State execute() {
++        stateValues.setKnownRoles(new HashMap<String, String>());
++        String jbossHome = System.getenv("JBOSS_HOME");
++        if (jbossHome == null) {
++            return new ErrorState(theConsole, MESSAGES.jbossHomeNotSet(), null, stateValues);
++        }
++
++        List<File> foundFiles = new ArrayList<File>(2);
++        final String fileName = stateValues.isManagement() ? MGMT_USERS_PROPERTIES : APPLICATION_USERS_PROPERTIES;
++        if (!findFiles(jbossHome, foundFiles, fileName)) {
++            return new ErrorState(theConsole, MESSAGES.propertiesFileNotFound(fileName), null, stateValues);
++        }
++        if (!stateValues.isManagement()) {
++            List<File> foundRoleFiles = new ArrayList<File>(2);
++            if (!findFiles(jbossHome, foundRoleFiles, APPLICATION_ROLES_PROPERTIES)) {
++                return new ErrorState(theConsole, MESSAGES.propertiesFileNotFound(APPLICATION_ROLES_PROPERTIES), null, stateValues);
++            }
++            stateValues.setRoleFiles(foundRoleFiles);
++            try {
++                stateValues.setKnownRoles(loadAllRoles(foundRoleFiles));
++            } catch (Exception e) {
++                return new ErrorState(theConsole, MESSAGES.propertiesFileNotFound(APPLICATION_ROLES_PROPERTIES), null, stateValues);
++            }
++        }
++
++        stateValues.setPropertiesFiles(foundFiles);
++
++        Set<String> foundUsers = new HashSet<String>();
++        for (File current : stateValues.getPropertiesFiles()) {
++            try {
++                foundUsers.addAll(loadUserNames(current));
++            } catch (IOException e) {
++                return new ErrorState(theConsole, MESSAGES.unableToLoadUsers(current.getAbsolutePath(), e.getMessage()), null, stateValues);
++            }
++        }
++        stateValues.setKnownUsers(foundUsers);
++
++        if (stateValues == null) {
++            return new PromptNewUserState(theConsole);
++        } else {
++            return new PromptNewUserState(theConsole, stateValues);
++        }
++    }
++
++    private Map<String,String> loadAllRoles(List<File> foundRoleFiles) throws StartException, IOException {
++        Map<String, String> loadedRoles = new HashMap<String, String>();
++        for (File file : foundRoleFiles) {
++            PropertiesFileLoader propertiesLoad = null;
++            try {
++                propertiesLoad = new UserPropertiesFileHandler(file.getCanonicalPath());
++                propertiesLoad.start(null);
++                loadedRoles.putAll((Map) propertiesLoad.getProperties());
++            }  finally {
++                if (propertiesLoad!=null) {
++                    propertiesLoad.stop(null);
++                }
++            }
++        }
++        return loadedRoles;
++    }
++
++    private boolean findFiles(final String jbossHome, final List<File> foundFiles, final String fileName) {
++
++        File standaloneProps = buildFilePath(jbossHome, SERVER_CONFIG_DIR, SERVER_BASE_DIR, "standalone", fileName);
++        if (standaloneProps.exists()) {
++            foundFiles.add(standaloneProps);
++        }
++        File domainProps = buildFilePath(jbossHome, DOMAIN_CONFIG_DIR, DOMAIN_BASE_DIR, "domain", fileName);
++        if (domainProps.exists()) {
++            foundFiles.add(domainProps);
++        }
++
++        if (foundFiles.size() == 0) {
++            return false;
++        }
++        return true;
++    }
++
++    private File buildFilePath(final String jbossHome, final String serverConfigDirPropertyName,
++                               final String serverBaseDirPropertyName, final String defaultBaseDir, final String fileName) {
++
++        String configDirConfiguredPath = System.getProperty(serverConfigDirPropertyName);
++        File configDir =  configDirConfiguredPath != null ? new File(configDirConfiguredPath) : null;
++        if(configDir == null) {
++            String baseDirConfiguredPath = System.getProperty(serverBaseDirPropertyName);
++            File baseDir = baseDirConfiguredPath != null ? new File(baseDirConfiguredPath) : new File(jbossHome, defaultBaseDir);
++            configDir = new File(baseDir, "configuration");
++        }
++        return new File(configDir, fileName);
++    }
++
++    private Set<String> loadUserNames(final File file) throws IOException {
++
++        InputStreamReader fis = null;
++        try {
++            fis = new InputStreamReader(new FileInputStream(file), Charset.forName("UTF-8"));
++            Properties tempProps = new Properties();
++            tempProps.load(fis);
++
++            return tempProps.stringPropertyNames();
++        } finally {
++            safeClose(fis);
++        }
++
++    }
++
++    private static void safeClose(Closeable c) {
++        if (c != null) {
++            try {
++                c.close();
++            } catch (IOException e) {
++            }
++        }
++    }
++
++}
+diff --git a/domain-management/src/main/java/org/jboss/as/domain/management/security/state/PropertyFilePrompt.java b/domain-management/src/main/java/org/jboss/as/domain/management/security/state/PropertyFilePrompt.java
+new file mode 100644
+index 0000000..df3bbed
+--- /dev/null
++++ b/domain-management/src/main/java/org/jboss/as/domain/management/security/state/PropertyFilePrompt.java
+@@ -0,0 +1,104 @@
++/*
++ * JBoss, Home of Professional Open Source.
++ * Copyright 2011, Red Hat, Inc., and individual contributors
++ * as indicated by the @author tags. See the copyright.txt file in the
++ * distribution for a full listing of individual contributors.
++ *
++ * This is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Lesser General Public License as
++ * published by the Free Software Foundation; either version 2.1 of
++ * the License, or (at your option) any later version.
++ *
++ * This software 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
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this software; if not, write to the Free
++ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
++ */
++package org.jboss.as.domain.management.security.state;
++
++import org.jboss.as.domain.management.security.AddPropertiesUser;
++import org.jboss.as.domain.management.security.ConsoleWrapper;
++import static org.jboss.as.domain.management.security.AddPropertiesUser.DEFAULT_MANAGEMENT_REALM;
++import static org.jboss.as.domain.management.security.AddPropertiesUser.DEFAULT_APPLICATION_REALM;
++
++import static org.jboss.as.domain.management.DomainManagementMessages.MESSAGES;
++
++/**
++* Describe the purpose
++*
++* @author <a href="mailto:flemming.harms at gmail.com">Flemming Harms</a>
++*/
++public class PropertyFilePrompt implements State {
++
++    private static final int MANAGEMENT = 0;
++    private static final int APPLICATION = 1;
++    private static final int INVALID = 2;
++
++    private ConsoleWrapper theConsole;
++
++    public PropertyFilePrompt(ConsoleWrapper theConsole) {
++        this.theConsole = theConsole;
++        if (theConsole.getConsole() == null) {
++            throw MESSAGES.noConsoleAvailable();
++        }
++    }
++
++    @Override
++    public State execute() {
++        StateValues stateValues = new StateValues();
++
++        theConsole.printf(AddPropertiesUser.NEW_LINE);
++        theConsole.printf(MESSAGES.filePrompt());
++        theConsole.printf(AddPropertiesUser.NEW_LINE);
++
++        while (true) {
++            String temp = theConsole.readLine("(a): ");
++            if (temp == null) {
++                /*
++                 * This will return user to the command prompt so add a new line to ensure the command prompt is on the next
++                 * line.
++                 */
++                theConsole.printf(AddPropertiesUser.NEW_LINE);
++                return null;
++            }
++
++            if (temp.length() > 0) {
++                switch (convertResponse(temp)) {
++                    case MANAGEMENT:
++                        stateValues.setManagement(true);
++                        stateValues.setRealm(DEFAULT_MANAGEMENT_REALM);
++                        return new PropertyFileFinder(theConsole, stateValues);
++                    case APPLICATION:
++                        stateValues.setManagement(false);
++                        stateValues.setRealm(DEFAULT_APPLICATION_REALM);
++                        return new PropertyFileFinder(theConsole, stateValues);
++                    default:
++                        return new ErrorState(theConsole, MESSAGES.invalidChoiceResponse(), this);
++                }
++            } else {
++                stateValues.setManagement(true);
++                stateValues.setRealm(DEFAULT_MANAGEMENT_REALM);
++                return new PropertyFileFinder(theConsole, stateValues);
++            }
++        }
++    }
++
++    private int convertResponse(final String response) {
++        String temp = response.toLowerCase();
++        if ("A".equals(temp) || "a".equals(temp)) {
++            return MANAGEMENT;
++        }
++
++        if ("B".equals(temp) || "b".equals(temp)) {
++            return APPLICATION;
++        }
++
++        return INVALID;
++    }
++
++}
+diff --git a/domain-management/src/main/java/org/jboss/as/domain/management/security/state/State.java b/domain-management/src/main/java/org/jboss/as/domain/management/security/state/State.java
+new file mode 100644
+index 0000000..5095ab3
+--- /dev/null
++++ b/domain-management/src/main/java/org/jboss/as/domain/management/security/state/State.java
+@@ -0,0 +1,34 @@
++/*
++ * JBoss, Home of Professional Open Source.
++ * Copyright 2011, Red Hat, Inc., and individual contributors
++ * as indicated by the @author tags. See the copyright.txt file in the
++ * distribution for a full listing of individual contributors.
++ *
++ * This is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Lesser General Public License as
++ * published by the Free Software Foundation; either version 2.1 of
++ * the License, or (at your option) any later version.
++ *
++ * This software 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
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this software; if not, write to the Free
++ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
++ */
++
++package org.jboss.as.domain.management.security.state;
++
++/**
++ * Describe the purpose
++ *
++ * @author <a href="mailto:flemming.harms at gmail.com">Flemming Harms</a>
++ */
++public interface State {
++
++    State execute();
++
++}
+diff --git a/domain-management/src/main/java/org/jboss/as/domain/management/security/state/StateValues.java b/domain-management/src/main/java/org/jboss/as/domain/management/security/state/StateValues.java
+new file mode 100644
+index 0000000..27cfdff
+--- /dev/null
++++ b/domain-management/src/main/java/org/jboss/as/domain/management/security/state/StateValues.java
+@@ -0,0 +1,142 @@
++/*
++ * JBoss, Home of Professional Open Source.
++ * Copyright 2011, Red Hat, Inc., and individual contributors
++ * as indicated by the @author tags. See the copyright.txt file in the
++ * distribution for a full listing of individual contributors.
++ *
++ * This is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Lesser General Public License as
++ * published by the Free Software Foundation; either version 2.1 of
++ * the License, or (at your option) any later version.
++ *
++ * This software 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
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this software; if not, write to the Free
++ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
++ */
++
++package org.jboss.as.domain.management.security.state;
++
++import org.jboss.as.domain.management.security.AddPropertiesUser;
++
++import java.io.File;
++import java.util.List;
++import java.util.Map;
++import java.util.Set;
++
++/**
++* Place holder object to pass between the state
++*
++* @author <a href="mailto:flemming.harms at gmail.com">Flemming Harms</a>
++*/
++public class StateValues {
++    private AddPropertiesUser.Interactiveness howInteractive = AddPropertiesUser.Interactiveness.INTERACTIVE;
++    private String realm;
++    private String userName;
++    private char[] password;
++    private boolean management;
++    private String roles;
++    private boolean existingUser = false;
++    private List<File> propertiesFiles;
++    private List<File> roleFiles;
++    private Set<String> knownUsers;
++    private Map<String,String> knownRoles;
++
++    public boolean isSilentOrNonInteractive() {
++        return (howInteractive == AddPropertiesUser.Interactiveness.NON_INTERACTIVE) || isSilent();
++    }
++
++    public void setHowInteractive(AddPropertiesUser.Interactiveness howInteractive) {
++        this.howInteractive = howInteractive;
++    }
++
++
++    public boolean isSilent() {
++        return (howInteractive == AddPropertiesUser.Interactiveness.SILENT);
++    }
++
++    public boolean isExistingUser() {
++        return existingUser;
++    }
++
++    public void setExistingUser(boolean existingUser) {
++        this.existingUser = existingUser;
++    }
++
++    public String getRealm() {
++        return realm;
++    }
++
++    public void setRealm(String realm) {
++        this.realm = realm;
++    }
++
++    public String getUserName() {
++        return userName;
++    }
++
++    public void setUserName(String userName) {
++        this.userName = userName;
++    }
++
++    public char[] getPassword() {
++        return password;
++    }
++
++    public void setPassword(char[] password) {
++        this.password = password;
++    }
++
++    public boolean isManagement() {
++        return management;
++    }
++
++    public void setManagement(boolean management) {
++        this.management = management;
++    }
++
++    public String getRoles() {
++        return roles;
++    }
++
++    public void setRoles(String roles) {
++        this.roles = roles;
++    }
++
++    public List<File> getPropertiesFiles() {
++        return propertiesFiles;
++    }
++
++    public void setPropertiesFiles(List<File> propertiesFiles) {
++        this.propertiesFiles = propertiesFiles;
++    }
++
++    public List<File> getRoleFiles() {
++        return roleFiles;
++    }
++
++    public void setRoleFiles(List<File> roleFiles) {
++        this.roleFiles = roleFiles;
++    }
++
++    public Set<String> getKnownUsers() {
++        return knownUsers;
++    }
++
++    public void setKnownUsers(Set<String> knownUsers) {
++        this.knownUsers = knownUsers;
++    }
++
++    public Map<String, String> getKnownRoles() {
++        return knownRoles;
++    }
++
++    public void setKnownRoles(Map<String, String> knownRoles) {
++        this.knownRoles = knownRoles;
++    }
++}
+diff --git a/domain-management/src/main/java/org/jboss/as/domain/management/security/state/UpdatePropertiesHandler.java b/domain-management/src/main/java/org/jboss/as/domain/management/security/state/UpdatePropertiesHandler.java
+new file mode 100644
+index 0000000..bbe8bb0
+--- /dev/null
++++ b/domain-management/src/main/java/org/jboss/as/domain/management/security/state/UpdatePropertiesHandler.java
+@@ -0,0 +1,111 @@
++/*
++ * JBoss, Home of Professional Open Source.
++ * Copyright 2011, Red Hat, Inc., and individual contributors
++ * as indicated by the @author tags. See the copyright.txt file in the
++ * distribution for a full listing of individual contributors.
++ *
++ * This is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Lesser General Public License as
++ * published by the Free Software Foundation; either version 2.1 of
++ * the License, or (at your option) any later version.
++ *
++ * This software 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
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this software; if not, write to the Free
++ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
++ */
++
++
++package org.jboss.as.domain.management.security.state;
++
++import org.jboss.as.domain.management.security.ConsoleWrapper;
++import org.jboss.sasl.util.UsernamePasswordHashUtil;
++
++import java.io.File;
++import java.io.IOException;
++import java.security.NoSuchAlgorithmException;
++
++import static org.jboss.as.domain.management.security.AddPropertiesUser.NEW_LINE;
++
++public abstract class UpdatePropertiesHandler {
++
++    private ConsoleWrapper theConsole;
++
++    public UpdatePropertiesHandler(ConsoleWrapper theConsole) {
++        this.theConsole = theConsole;
++    }
++
++    /**
++     *  Implement the persistence handler for storing the properties
++     */
++    abstract void persist(String[] entry, File file) throws IOException;
++
++    /**
++     * Customize message for update or add users
++     * @param fileName - the filename of the updated property file;
++     * @return the console message that should be present to the user
++     */
++    abstract String consoleUserMessage(String fileName);
++
++    /**
++     * Customize message for update or add roles
++     * @param fileName - the filename of the updated property file;
++     * @return the console message that should be present to the user
++     */
++    abstract String consoleRolesMessage(String fileName);
++
++    /**
++     * Customize error message for update or add users roles / properties
++     * @param fileName - the filename of the updated property file;
++     * @return the console message that should be present to the user
++     */
++    abstract String errorMessage(String fileName, Throwable e);
++
++    State update(StateValues stateValues) {
++        String[] entry = new String[2];
++
++        try {
++            String hash = new UsernamePasswordHashUtil().generateHashedHexURP(stateValues.getUserName(), stateValues.getRealm(),
++                    stateValues.getPassword());
++            entry[0] = stateValues.getUserName();
++            entry[1] = hash;
++        } catch (NoSuchAlgorithmException e) {
++            return new ErrorState(theConsole, e.getMessage(), null, stateValues);
++        }
++
++        for (File current : stateValues.getPropertiesFiles()) {
++            try {
++                persist(entry, current);
++                if (stateValues.isSilent() == false) {
++                    theConsole.printf(consoleUserMessage(current.getCanonicalPath()));
++                    theConsole.printf(NEW_LINE);
++                }
++            } catch (Exception e) {
++                return new ErrorState(theConsole, errorMessage(current.getAbsolutePath(), e), null, stateValues);
++            }
++        }
++
++        if (!stateValues.isManagement() && stateValues.getRoles() != null) {
++            for (final File current : stateValues.getRoleFiles()) {
++                String[] role = {stateValues.getUserName(), stateValues.getRoles()};
++                try {
++                    persist(role, current);
++                    if (stateValues.isSilent() == false) {
++                        theConsole.printf(consoleRolesMessage(current.getCanonicalPath()));
++                        theConsole.printf(NEW_LINE);
++                    }
++                } catch (IOException e) {
++                    return new ErrorState(theConsole, errorMessage(current.getAbsolutePath(), e), null, stateValues);
++                }
++            }
++        }
++
++        return null;
++    }
++
++}
+diff --git a/domain-management/src/main/java/org/jboss/as/domain/management/security/state/UpdateUser.java b/domain-management/src/main/java/org/jboss/as/domain/management/security/state/UpdateUser.java
+new file mode 100644
+index 0000000..d652995
+--- /dev/null
++++ b/domain-management/src/main/java/org/jboss/as/domain/management/security/state/UpdateUser.java
+@@ -0,0 +1,88 @@
++/*
++ * JBoss, Home of Professional Open Source.
++ * Copyright 2011, Red Hat, Inc., and individual contributors
++ * as indicated by the @author tags. See the copyright.txt file in the
++ * distribution for a full listing of individual contributors.
++ *
++ * This is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Lesser General Public License as
++ * published by the Free Software Foundation; either version 2.1 of
++ * the License, or (at your option) any later version.
++ *
++ * This software 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
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this software; if not, write to the Free
++ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
++ */
++
++package org.jboss.as.domain.management.security.state;
++
++import org.jboss.as.domain.management.security.ConsoleWrapper;
++import org.jboss.msc.service.StartException;
++
++import java.io.File;
++import java.io.IOException;
++import java.util.Properties;
++
++import static org.jboss.as.domain.management.DomainManagementMessages.MESSAGES;
++
++/**
++ * Describe the purpose
++ *
++ * @author <a href="mailto:flemming.harms at gmail.com">Flemming Harms</a>
++ */
++public class UpdateUser extends UpdatePropertiesHandler implements State {
++
++    private final StateValues stateValues;
++
++    public UpdateUser(ConsoleWrapper theConsole,final StateValues stateValues) {
++        super(theConsole);
++        this.stateValues = stateValues;
++    }
++
++    @Override
++    public State execute() {
++        /*
++        * At this point the files have been written and confirmation passed back so nothing else to do.
++        */
++        return update(stateValues);
++    }
++
++    @Override
++    void persist(String[] entry, File file) throws IOException {
++        UserPropertiesFileHandler propertiesHandler = new UserPropertiesFileHandler(file.getAbsolutePath());
++        try {
++            propertiesHandler.start(null);
++            Properties prob = propertiesHandler.getProperties();
++            prob.setProperty(entry[0], entry[1]);
++            propertiesHandler.persistProperties();
++        } catch (StartException e) {
++            throw new IllegalStateException(MESSAGES.unableToUpdateUser(file.getAbsolutePath(), e.getMessage()));
++        } finally {
++            propertiesHandler.stop(null);
++        }
++
++    }
++
++    @Override
++    String consoleUserMessage(String fileName) {
++        return MESSAGES.updateUser(stateValues.getUserName(), fileName);
++    }
++
++    @Override
++    String consoleRolesMessage(String fileName) {
++        return MESSAGES.updatedRoles(stateValues.getUserName(), stateValues.getRoles(), fileName);
++    }
++
++    @Override
++    String errorMessage(String fileName, Throwable e) {
++        return MESSAGES.unableToUpdateUser(fileName, e.getMessage());
++    }
++}
++
++
+diff --git a/domain-management/src/main/java/org/jboss/as/domain/management/security/state/UserPropertiesFileHandler.java b/domain-management/src/main/java/org/jboss/as/domain/management/security/state/UserPropertiesFileHandler.java
+new file mode 100644
+index 0000000..a3fb0ca
+--- /dev/null
++++ b/domain-management/src/main/java/org/jboss/as/domain/management/security/state/UserPropertiesFileHandler.java
+@@ -0,0 +1,38 @@
++/*
++ * JBoss, Home of Professional Open Source.
++ * Copyright 2012, Red Hat, Inc., and individual contributors
++ * as indicated by the @author tags. See the copyright.txt file in the
++ * distribution for a full listing of individual contributors.
++ *
++ * This is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Lesser General Public License as
++ * published by the Free Software Foundation; either version 2.1 of
++ * the License, or (at your option) any later version.
++ *
++ * This software 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
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this software; if not, write to the Free
++ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
++ */
++
++
++package org.jboss.as.domain.management.security.state;
++
++import org.jboss.as.domain.management.security.PropertiesFileLoader;
++
++/**
++* Property file handler for user properties and roles
++*
++* @author <a href="mailto:flemming.harms at gmail.com">Flemming Harms</a>
++*/
++class UserPropertiesFileHandler extends PropertiesFileLoader {
++
++    UserPropertiesFileHandler(final String path) {
++        super(path);
++    }
++}
+diff --git a/domain-management/src/main/java/org/jboss/as/domain/management/security/state/WeakCheckState.java b/domain-management/src/main/java/org/jboss/as/domain/management/security/state/WeakCheckState.java
+new file mode 100644
+index 0000000..4c7d094
+--- /dev/null
++++ b/domain-management/src/main/java/org/jboss/as/domain/management/security/state/WeakCheckState.java
+@@ -0,0 +1,90 @@
++/*
++ * JBoss, Home of Professional Open Source.
++ * Copyright 2011, Red Hat, Inc., and individual contributors
++ * as indicated by the @author tags. See the copyright.txt file in the
++ * distribution for a full listing of individual contributors.
++ *
++ * This is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Lesser General Public License as
++ * published by the Free Software Foundation; either version 2.1 of
++ * the License, or (at your option) any later version.
++ *
++ * This software 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
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this software; if not, write to the Free
++ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
++ */
++
++package org.jboss.as.domain.management.security.state;
++
++import org.jboss.as.domain.management.security.ConsoleWrapper;
++
++import java.util.Arrays;
++import static org.jboss.as.domain.management.security.AddPropertiesUser.BAD_USER_NAMES;
++import static org.jboss.as.domain.management.DomainManagementMessages.MESSAGES;
++
++/**
++ * State to check the strength of the stateValues selected.
++ * <p/>
++ * TODO - Currently only very basic checks are performed, this could be updated to perform additional password strength
++ * checks.
++ */
++public class WeakCheckState implements State {
++
++    private ConsoleWrapper theConsole;
++    private StateValues stateValues;
++    private static char[] VALID_PUNCTUATION = {'.', '@', '\\', '=', ',','/'};
++
++    public WeakCheckState(ConsoleWrapper theConsole,StateValues stateValues) {
++        this.theConsole = theConsole;
++        this.stateValues = stateValues;
++        if (theConsole.getConsole() == null) {
++            throw MESSAGES.noConsoleAvailable();
++        }
++    }
++
++    private boolean isValidPunctuation(char currentChar) {
++        Arrays.sort(VALID_PUNCTUATION);
++        return (Arrays.binarySearch(VALID_PUNCTUATION,currentChar) >= 0);
++    }
++
++    @Override
++    public State execute() {
++        State retryState = stateValues.isSilentOrNonInteractive() ? null : new PromptNewUserState(theConsole, stateValues);
++
++        if (Arrays.equals(stateValues.getUserName().toCharArray(), stateValues.getPassword())) {
++            return new ErrorState(theConsole, MESSAGES.usernamePasswordMatch(), retryState);
++        }
++
++        for (char currentChar : stateValues.getUserName().toCharArray()) {
++            if ((!isValidPunctuation(currentChar)) && (Character.isLetter(currentChar) || Character.isDigit(currentChar)) == false) {
++                return new ErrorState(theConsole, MESSAGES.usernameNotAlphaNumeric(), retryState);
++            }
++        }
++
++        boolean weakUserName = false;
++        for (String current : BAD_USER_NAMES) {
++            if (current.equals(stateValues.getUserName().toLowerCase())) {
++                weakUserName = true;
++                break;
++            }
++        }
++
++        State continuingState = new DuplicateUserCheckState(theConsole, stateValues);
++        if (weakUserName && stateValues.isSilentOrNonInteractive() == false) {
++            String message = MESSAGES.usernameEasyToGuess(stateValues.getUserName());
++            String prompt = MESSAGES.sureToAddUser(stateValues.getUserName());
++            State noState = new PromptNewUserState(theConsole, stateValues);
++
++            return new ConfirmationChoice(theConsole,message, prompt, continuingState, noState);
++        }
++
++        return continuingState;
++    }
++
++}
+\ No newline at end of file
+-- 
+1.7.10
+
diff --git a/jboss-as-cp.sh b/jboss-as-cp.sh
new file mode 100755
index 0000000..c8d1e18
--- /dev/null
+++ b/jboss-as-cp.sh
@@ -0,0 +1,59 @@
+#/bin/sh
+
+usage()
+{
+cat << EOF
+usage: $0 options
+
+Makes possible to run JBoss AS in different directory by creating the structure and copying required configuration files.
+
+OPTIONS:
+   -h      Show this message
+   -c      JBoss AS configuration xml file (see \$JBOSS_HOME/docs/examples/configs/), default: standalone-web.xml
+   -l      Location where the directory structure should be created (required)
+EOF
+}
+
+STANDALONE_XML="standalone-web.xml"
+
+while getopts “hcl:” OPTION
+do
+     case $OPTION in
+         h)
+             usage
+             exit 1
+             ;;
+         c)
+             STANDALONE_XML=$OPTARG
+             ;;
+         l)
+             LOCATION=$OPTARG
+             ;;
+         ?)
+             usage
+             exit
+             ;;
+     esac
+done
+
+if [[ -z $LOCATION ]]
+then
+     usage
+     exit 1
+fi
+
+if [ "x$JBOSS_HOME" = "x" ]; then
+   JBOSS_HOME="/usr/share/jboss-as"
+fi
+
+mkdir -p ${LOCATION}/{data,deployments,log,tmp,configuration}
+
+cp $JBOSS_HOME/docs/examples/configs/$STANDALONE_XML ${LOCATION}/configuration/
+cp $JBOSS_HOME/docs/examples/properties/logging.properties ${LOCATION}/configuration/
+cp $JBOSS_HOME/docs/examples/properties/mgmt-users.properties ${LOCATION}/configuration/
+
+# Make sure the mgmt-users.properties file has correct permissions!
+chmod 600 ${LOCATION}/configuration/mgmt-users.properties
+
+echo -e "Directory ${LOCATION} ws prepared to launch JBoss AS!\n\nYou can now boot your server: JBOSS_BASE_DIR=${LOCATION} ${JBOSS_HOME}/bin/standalone.sh -c ${STANDALONE_XML}"
+
diff --git a/jboss-as.spec b/jboss-as.spec
index 6c40efe..14768c4 100644
--- a/jboss-as.spec
+++ b/jboss-as.spec
@@ -2,6 +2,8 @@
 %global namedversion %{version}%{?namedreltag}
 
 %global cachedir %{_var}/cache/%{name}
+%global libdir %{_var}/lib/%{name}
+%global rundir %{_var}/run/%{name}
 %global homedir %{_datadir}/%{name}
 %global bindir %{homedir}/bin
 %global logdir %{_var}/log/%{name}
@@ -9,11 +11,11 @@
 
 %global jbuid 185
 
-%global modules connector controller-client controller deployment-repository deployment-scanner domain-management ee ejb3 embedded jmx logging naming network platform-mbean process-controller protocol remoting security server threads transactions web weld
+%global modules cli connector controller-client controller deployment-repository deployment-scanner domain-management ee ejb3 embedded jmx logging naming network platform-mbean process-controller protocol remoting security server threads transactions web weld
 
 Name:             jboss-as
 Version:          7.1.0
-Release:          2%{?dist}
+Release:          3%{?dist}
 Summary:          JBoss Application Server
 Group:            System Environment/Daemons
 License:          LGPLv2 and ASL 2.0
@@ -25,6 +27,9 @@ URL:              http://www.jboss.org/jbossas
 # tar -cJf jboss-as-7.1.0.Final-CLEAN.tar.xz jboss-as-7.1.0.Final
 Source0:          jboss-as-%{namedversion}-CLEAN.tar.xz
 
+# Makes possible to run JBoss AS in different directory by creating the structure and copying required configuration files
+Source1:          jboss-as-cp.sh
+
 Patch0:           0001-Disable-checkstyle.patch
 Patch1:           0002-Fix-initd-script.patch
 Patch2:           0003-Build-additional-modules.patch
@@ -70,6 +75,15 @@ Patch40:          0041-AS7-3921-Upgrade-to-Remoting-JMX-1.0.2-including-swi.patc
 Patch41:          0042-Added-standalone-web.xml-example-configuration.-Use-.patch
 Patch42:          0043-Add-systemd-files-re-arrange-directory-with-init-scr.patch
 Patch43:          0044-Fixed-systemd-service-file.patch
+Patch44:          0045-Added-jboss-as-cli-module.patch
+Patch45:          0046-Fix-JBOSS_HOME-when-jboss-cli.sh-is-executed-through.patch
+Patch46:          0047-Simplified-systemd-files.patch
+Patch47:          0048-AS7-3800-JBOSS_BASE_DIR-is-checked-in-standalone.sh-.patch
+Patch48:          0049-Added-domain-add-user-module.patch
+Patch49:          0050-Discard-logs-from-systemd-service-we-don-t-need-dupl.patch
+Patch50:          0051-Changed-the-systemd-config-file-location-we-want-to-.patch
+Patch51:          0052-Remove-activation-module.patch
+Patch52:          0053-Use-properties-in-add-user-AS7-module.patch
 
 BuildArch:        noarch
 
@@ -86,7 +100,6 @@ BuildRequires:    cdi-api
 BuildRequires:    dom4j
 # TODO: ecj dependency tree is big and ugly...
 BuildRequires:    ecj
-BuildRequires:    geronimo-annotation
 BuildRequires:    guava
 BuildRequires:    h2
 BuildRequires:    hibernate-jpa-2.0-api >= 1.0.1-5
@@ -181,7 +194,6 @@ Requires:         dom4j
 # TODO: ecj dependency tree is big and ugly...
 Requires:         ecj
 Requires:         guava
-Requires:         geronimo-annotation
 Requires:         h2
 Requires:         hibernate-jpa-2.0-api >= 1.0.1-5
 Requires:         hibernate-validator >= 4.2.0
@@ -318,6 +330,15 @@ This package contains the API documentation for %{name}.
 %patch41 -p1
 %patch42 -p1
 %patch43 -p1
+%patch44 -p1
+%patch45 -p1
+%patch46 -p1
+%patch47 -p1
+%patch48 -p1
+%patch49 -p1
+%patch50 -p1
+%patch51 -p1
+%patch52 -p1
 
 %build
 # We don't have packaged all test dependencies (jboss-test for example)
@@ -329,16 +350,16 @@ install -d -m 755 $RPM_BUILD_ROOT%{_javadir}/%{name}
 install -d -m 755 $RPM_BUILD_ROOT%{_javadocdir}/%{name}
 install -d -m 755 $RPM_BUILD_ROOT%{homedir}
 install -d -m 755 $RPM_BUILD_ROOT%{confdir}
+install -d -m 755 $RPM_BUILD_ROOT%{rundir}
 install -d -m 770 $RPM_BUILD_ROOT%{cachedir}/auth
 install -d -m 755 $RPM_BUILD_ROOT%{_mavenpomdir}
 install -d -m 755 $RPM_BUILD_ROOT%{_unitdir}
-install -d -m 755 $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig
 install -d -m 755 $RPM_BUILD_ROOT%{_bindir}
 
 for mode in standalone domain; do
   install -d -m 755 $RPM_BUILD_ROOT%{homedir}/${mode}
-  install -d -m 755 $RPM_BUILD_ROOT%{cachedir}/${mode}/data
-  install -d -m 755 $RPM_BUILD_ROOT%{cachedir}/${mode}/tmp
+  install -d -m 775 $RPM_BUILD_ROOT%{libdir}/${mode}/data
+  install -d -m 755 $RPM_BUILD_ROOT%{cachedir}/${mode}
   install -d -m 775 $RPM_BUILD_ROOT%{logdir}/${mode}
 done
 
@@ -399,22 +420,33 @@ pushd build/target/jboss-as-%{namedversion}
   find bin/ -type f -name "*.bat" -delete
 
   # Install systemd files
-  mv bin/initscripts/jboss-as.conf $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/%{name}
+  mv bin/initscripts/systemd/jboss-as.conf $RPM_BUILD_ROOT%{confdir}/%{name}.conf
   mv bin/initscripts/systemd/jboss-as.service $RPM_BUILD_ROOT%{_unitdir}/%{name}.service
-  mv bin/initscripts/systemd/jboss-as.sh $RPM_BUILD_ROOT%{_bindir}/%{name}
 
   # We don't need legacy init scripts
   rm -rf bin/initscripts
 
+  # Prepare directory for properties files
+  mkdir docs/examples/properties
+
+  # Copy logging.properties and mgmt-users.properties so we can reuse it later in jboss-as-cp script
+  cp standalone/configuration/logging.properties docs/examples/properties/
+  cp standalone/configuration/mgmt-users.properties docs/examples/properties/
+  # Lower a bit the permissions, so ordinary user can copy it. It's an example file!
+  chmod 644 docs/examples/properties/mgmt-users.properties
+
   # standalone
   mv standalone/configuration $RPM_BUILD_ROOT%{confdir}/standalone
-  mv standalone/deployments $RPM_BUILD_ROOT%{cachedir}/standalone
+  mv standalone/deployments $RPM_BUILD_ROOT%{libdir}/standalone/deployments
+  mv standalone/lib $RPM_BUILD_ROOT%{libdir}/standalone/lib
+  mv standalone/tmp $RPM_BUILD_ROOT%{cachedir}/standalone/tmp
 
   # Install standalone-web.xml
   cp docs/examples/configs/standalone-web.xml $RPM_BUILD_ROOT%{confdir}/standalone/standalone-web.xml
 
   # domain
   mv domain/configuration $RPM_BUILD_ROOT%{confdir}/domain
+  mv domain/tmp $RPM_BUILD_ROOT%{cachedir}/domain/tmp
 
   # Remove all jars from modules directory - we need to symlink them
   # TODO temporary with verbose, use -delete afterwards
@@ -426,30 +458,27 @@ pushd build/target/jboss-as-%{namedversion}
   mv copyright.txt README.txt LICENSE.txt welcome-content docs bin appclient modules $RPM_BUILD_ROOT%{homedir}
 popd
 
+chmod 775 $RPM_BUILD_ROOT%{libdir}/standalone/deployments
+
 pushd $RPM_BUILD_ROOT%{homedir}
 
   # Standalone
-  ln -s %{cachedir}/standalone/deployments standalone/deployments
   ln -s %{confdir}/standalone standalone/configuration
+  ln -s %{libdir}/standalone/deployments standalone/deployments
+  ln -s %{libdir}/standalone/data standalone/data
+  ln -s %{libdir}/standalone/lib standalone/lib
+  ln -s %{logdir}/standalone standalone/log
+  ln -s %{cachedir}/standalone/tmp standalone/tmp
 
   # Domain
   ln -s %{confdir}/domain domain/configuration
+  ln -s %{libdir}/domain/data domain/data
+  ln -s %{logdir}/domain domain/log
+  ln -s %{cachedir}/domain/tmp domain/tmp
 
   # Symlink jboss-modules
   ln -s $(build-classpath jboss-modules) jboss-modules.jar
   
-  # Symlinks to log dirs
-  ln -s %{logdir}/standalone standalone/log
-  ln -s %{logdir}/domain domain/log
-
-  # temp dir
-  ln -s %{cachedir}/standalone/tmp standalone/tmp
-  ln -s %{cachedir}/domain/tmp domain/tmp
-
-  # data dir
-  ln -s %{cachedir}/standalone/data standalone/data
-  ln -s %{cachedir}/domain/data domain/data
-
   # auth dir
   ln -s %{cachedir}/auth auth
   
@@ -489,7 +518,8 @@ pushd $RPM_BUILD_ROOT%{homedir}
     ln -s $(build-classpath cdi-api) javax/enterprise/api/main/cdi-api.jar
     ln -s $(build-classpath ecj) org/jboss/as/web/main/ecj.jar
     ln -s $(build-classpath guava) com/google/guava/main/guava.jar
-    ln -s $(build-classpath geronimo-validation) javax/validation/api/main/geronimo-validation.jar
+    # TODO this is an UGLY hack, think about removing it at some point!
+    ln -s $(build-classpath bean-validation-api) javax/validation/api/main/geronimo-validation.jar
     ln -s $(build-classpath hibernate-validator) org/hibernate/validator/main/hibernate-validator.jar
     ln -s $(build-classpath hibernate-jpa-2.0-api) javax/persistence/api/main/hibernate-jpa-2.0-api.jar
 
@@ -537,7 +567,6 @@ pushd $RPM_BUILD_ROOT%{homedir}
     ln -s $(build-classpath jboss-jstl-1.2-api) javax/servlet/jstl/api/main/jboss-jstl-1.2-api.jar
     ln -s $(build-classpath jboss-jts/jbossjta) org/jboss/jts/main/jbossjta.jar
     ln -s $(build-classpath jboss-jts/jbossjta-integration) org/jboss/jts/integration/main/jbossjta-integration.jar
-    ln -s $(build-classpath log4j) org/apache/log4j/main/log4j.jar
     ln -s $(build-classpath jboss-logging) org/jboss/logging/main/jboss-logging.jar
     ln -s $(build-classpath jboss-logmanager) org/jboss/logmanager/main/jboss-logmanager.jar
     ln -s $(build-classpath jboss-logmanager-log4j) org/jboss/logmanager/log4j/main/jboss-logmanager-log4j.jar
@@ -570,7 +599,9 @@ pushd $RPM_BUILD_ROOT%{homedir}
     ln -s $(build-classpath jboss-vfs) org/jboss/vfs/main/jboss-vfs.jar
     ln -s $(build-classpath jboss-web) org/jboss/as/web/main/jboss-web.jar
     ln -s $(build-classpath jgroups) org/jgroups/main/jgroups.jar
+    ln -s $(build-classpath jline) jline/main/jline.jar
     ln -s $(build-classpath joda-time) org/joda/time/main/joda-time.jar
+    ln -s $(build-classpath log4j) org/apache/log4j/main/log4j.jar
     ln -s $(build-classpath mojarra/jsf-impl) com/sun/jsf-impl/main/jsf-impl.jar
     ln -s $(build-classpath picketbox/picketbox) org/picketbox/main/picketbox.jar
     ln -s $(build-classpath picketbox/infinispan) org/picketbox/main/infinispan.jar
@@ -591,39 +622,47 @@ pushd $RPM_BUILD_ROOT%{homedir}
   popd
 popd
 
+pushd $RPM_BUILD_ROOT%{_bindir}
+  # jboss-cli
+  ln -s %{bindir}/jboss-cli.sh jboss-cli
+
+  install -m 755 %{SOURCE1} jboss-as-cp
+popd
+
 %pre
 # Add jboss-as user and group
 getent group %{name} >/dev/null || groupadd -r %{name}
 getent passwd %{name} >/dev/null || \
     useradd -c "JBoss AS" -u %{jbuid} -g %{name} -s /bin/nologin -r -d %{homedir} %{name}
+exit 0
 
 %files
 %{homedir}/appclient
 %dir %{bindir}
 %{bindir}/*.conf
 %{bindir}/*.sh
-%{_bindir}/%{name}
+%{_bindir}
 %{homedir}/auth
 %{homedir}/domain
 %{homedir}/standalone
 %{homedir}/modules
 %{homedir}/welcome-content
 %{homedir}/jboss-modules.jar
-%{cachedir}/standalone/deployments/README.txt
-%attr(0775,root,jboss-as) %dir %{cachedir}/standalone/data
+%attr(-,root,jboss-as) %{libdir}/standalone
+%attr(-,root,jboss-as) %{libdir}/domain
+%attr(0775,root,jboss-as) %dir %{rundir}
 %attr(0775,root,jboss-as) %dir %{cachedir}/standalone/tmp
-%attr(0775,root,jboss-as) %dir %{cachedir}/domain/data
 %attr(0775,root,jboss-as) %dir %{cachedir}/domain/tmp
-%attr(0700,jboss-as,jboss-as) %dir %{cachedir}/auth
 %attr(0770,root,jboss-as) %dir %{logdir}/standalone
 %attr(0770,root,jboss-as) %dir %{logdir}/domain
 %attr(0775,root,jboss-as) %dir %{confdir}/standalone
 %attr(0775,root,jboss-as) %dir %{confdir}/domain
+%attr(0700,jboss-as,jboss-as) %dir %{cachedir}/auth
 %attr(0664,jboss-as,jboss-as) %config(noreplace) %{confdir}/standalone/*.properties
 %attr(0664,jboss-as,jboss-as) %config(noreplace) %{confdir}/standalone/*.xml
 %attr(0664,jboss-as,jboss-as) %config(noreplace) %{confdir}/domain/*.properties
 %attr(0664,jboss-as,jboss-as) %config(noreplace) %{confdir}/domain/*.xml
-%config(noreplace) %{_sysconfdir}/sysconfig/%{name}
+%config(noreplace) %{confdir}/%{name}.conf
 %{_unitdir}/%{name}.service
 %doc %{homedir}/docs
 %doc %{homedir}/copyright.txt
@@ -639,6 +678,16 @@ getent passwd %{name} >/dev/null || \
 %doc %{homedir}/LICENSE.txt
 
 %changelog
+* Mon Apr 16 2012 Marek Goldmann <mgoldman at redhat.com> 7.1.0-3
+- Simplified systemd files
+- Added jboss-as-cli module
+- Make it possible to run as different user in different direcotry by changing JBOSS_BASE_DIR
+- Fixed issues with using add-user.sh script
+- Changed validation API jar to bean-validation
+- Added jboss-as-cp script to be able to use JBoss AS from different dir as different user
+- Removed activation AS7 module - it's already in JDK
+- Make it possible to add a user also when JBoss AS is run from different directory
+
 * Wed Apr 04 2012 Marek Goldmann <mgoldman at redhat.com> 7.1.0-2
 - Fixed rpmlint issues
 - Fixed license


More information about the scm-commits mailing list