diff --git a/config/alfresco/activities/activities-SqlMapConfig.xml b/config/alfresco/activities/activities-SqlMapConfig.xml
index 82edb581a9..0150a8edb4 100644
--- a/config/alfresco/activities/activities-SqlMapConfig.xml
+++ b/config/alfresco/activities/activities-SqlMapConfig.xml
@@ -5,9 +5,9 @@
"http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
-
-
-
-
+
+
+
+
diff --git a/config/alfresco/activities/activities-feed-context.xml b/config/alfresco/activities/activities-feed-context.xml
index 0e837163b0..79d1efaefc 100644
--- a/config/alfresco/activities/activities-feed-context.xml
+++ b/config/alfresco/activities/activities-feed-context.xml
@@ -14,15 +14,32 @@
-
-
- true
-
-
+
+
+ javax.sql.DataSource
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+ getConnection
+
+
+
+
classpath:alfresco/activities/activities-SqlMapConfig.xml
+
+
diff --git a/config/alfresco/authentication-services-context.xml b/config/alfresco/authentication-services-context.xml
index fd35fcfae3..4e83d14459 100644
--- a/config/alfresco/authentication-services-context.xml
+++ b/config/alfresco/authentication-services-context.xml
@@ -74,33 +74,29 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+ alfrescoAuthentication
+
+
+
+
+
+
+
+
+
+ org.alfresco.repo.security.authentication.AuthenticationComponent
+ org.alfresco.repo.security.authentication.MutableAuthenticationDao
+
+
+
+
@@ -160,31 +156,9 @@
-
-
-
-
-
-
-
-
-
- true
-
-
-
-
-
-
-
-
-
-
-
-
+
+
diff --git a/config/alfresco/authority-services-context.xml b/config/alfresco/authority-services-context.xml
index 8183879829..57cab9eb50 100644
--- a/config/alfresco/authority-services-context.xml
+++ b/config/alfresco/authority-services-context.xml
@@ -25,29 +25,13 @@
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- admin
- administrator
-
-
-
diff --git a/config/alfresco/core-services-context.xml b/config/alfresco/core-services-context.xml
index 21cf88194e..f98bb99c1c 100644
--- a/config/alfresco/core-services-context.xml
+++ b/config/alfresco/core-services-context.xml
@@ -15,7 +15,7 @@
+ class="org.alfresco.config.JndiPropertyPlaceholderConfigurer">
true
@@ -42,7 +42,7 @@
+ class="org.alfresco.config.JndiPropertyPlaceholderConfigurer">
true
@@ -181,7 +181,7 @@
-
+
${db.driver}
@@ -208,6 +208,15 @@
+
+
+ java:comp/env/jdbc/dataSource
+
+
+
+
+
+
diff --git a/config/alfresco/hibernate-context.xml b/config/alfresco/hibernate-context.xml
index c13bca8fe4..4f65ba988a 100644
--- a/config/alfresco/hibernate-context.xml
+++ b/config/alfresco/hibernate-context.xml
@@ -4,7 +4,7 @@
-
+
hibernate.dialect
diff --git a/config/alfresco/subsystems/alfrescoAuthentication/alfresco-authentication-context.xml b/config/alfresco/subsystems/alfrescoAuthentication/alfresco-authentication-context.xml
new file mode 100644
index 0000000000..2d969dd10a
--- /dev/null
+++ b/config/alfresco/subsystems/alfrescoAuthentication/alfresco-authentication-context.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+ ${alfresco.authentication.allowGuestLogin}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/config/alfresco/subsystems/alfrescoAuthentication/alfresco-authentication.properties b/config/alfresco/subsystems/alfrescoAuthentication/alfresco-authentication.properties
new file mode 100644
index 0000000000..56b72a9958
--- /dev/null
+++ b/config/alfresco/subsystems/alfrescoAuthentication/alfresco-authentication.properties
@@ -0,0 +1 @@
+alfresco.authentication.allowGuestLogin=true
\ No newline at end of file
diff --git a/config/alfresco/extension/jaas-authentication-context.xml.sample b/config/alfresco/subsystems/kerberosAuthentication/kerberos-authentication-context.xml
similarity index 82%
rename from config/alfresco/extension/jaas-authentication-context.xml.sample
rename to config/alfresco/subsystems/kerberosAuthentication/kerberos-authentication-context.xml
index 60da5074e9..da5c06c61a 100644
--- a/config/alfresco/extension/jaas-authentication-context.xml.sample
+++ b/config/alfresco/subsystems/kerberosAuthentication/kerberos-authentication-context.xml
@@ -7,13 +7,13 @@
- DEFAULT.REALM
+ ${kerberos.authentication.realm}
- Alfresco
+ ${kerberos.authentication.user.configEntryName}
@@ -24,6 +24,9 @@
+
+ ${kerberos.authentication.defaultAdministratorUserNames}
+
diff --git a/config/alfresco/subsystems/kerberosAuthentication/kerberos-authentication.properties b/config/alfresco/subsystems/kerberosAuthentication/kerberos-authentication.properties
new file mode 100644
index 0000000000..d59f7a1cd7
--- /dev/null
+++ b/config/alfresco/subsystems/kerberosAuthentication/kerberos-authentication.properties
@@ -0,0 +1,3 @@
+kerberos.authentication.realm=ALFRESCO.ORG
+kerberos.authentication.user.configEntryName=Alfresco
+kerberos.authentication.defaultAdministratorUserNames=
\ No newline at end of file
diff --git a/config/alfresco/extension/ldap-authentication-context.xml.sample b/config/alfresco/subsystems/ldapAuthentication/ldap-authentication-context.xml
similarity index 89%
rename from config/alfresco/extension/ldap-authentication-context.xml.sample
rename to config/alfresco/subsystems/ldapAuthentication/ldap-authentication-context.xml
index 225141e2f4..9bb98ea2a0 100644
--- a/config/alfresco/extension/ldap-authentication-context.xml.sample
+++ b/config/alfresco/subsystems/ldapAuthentication/ldap-authentication-context.xml
@@ -1,19 +1,7 @@
-
-
-
-
-
-
- true
-
-
- classpath:alfresco/extension/ldap-authentication.properties
-
-
-
+
@@ -68,6 +56,12 @@
${ldap.authentication.escapeCommasInUid}
+
+ ${ldap.authentication.allowGuestLogin}
+
+
+ ${ldap.authentication.defaultAdministratorUserNames}
+
-
+
+
+
+
+
diff --git a/config/alfresco/extension/ldap-synchronisation.properties b/config/alfresco/subsystems/ldapSynchronization/ldap-synchronisation.properties
similarity index 77%
rename from config/alfresco/extension/ldap-synchronisation.properties
rename to config/alfresco/subsystems/ldapSynchronization/ldap-synchronisation.properties
index ffd1392f9d..de4d485827 100644
--- a/config/alfresco/extension/ldap-synchronisation.properties
+++ b/config/alfresco/subsystems/ldapSynchronization/ldap-synchronisation.properties
@@ -2,6 +2,21 @@
# This properties file is used to configure LDAP syncronisation
#
+# The LDAP context factory to use
+ldap.synchronisation.java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory
+
+# The URL to connect to the LDAP server
+ldap.synchronisation.java.naming.provider.url=ldap://openldap.domain.com:389
+
+# The synchronisation mechanism to use
+ldap.synchronisation.java.naming.security.authentication=DIGEST-MD5
+
+# The default principal to use (only used for LDAP sync)
+ldap.synchronisation.java.naming.security.principal=reader
+
+# The password for the default principal (only used for LDAP sync)
+ldap.synchronisation.java.naming.security.credentials=secret
+
# The query to find the people to import
ldap.synchronisation.personQuery=(objectclass=inetOrgPerson)
diff --git a/config/alfresco/subsystems/ntlmAuthentication/ntlm-authentication-context.properties b/config/alfresco/subsystems/ntlmAuthentication/ntlm-authentication-context.properties
new file mode 100644
index 0000000000..0922ca2cce
--- /dev/null
+++ b/config/alfresco/subsystems/ntlmAuthentication/ntlm-authentication-context.properties
@@ -0,0 +1,5 @@
+ntlm.authentication.useLocalServer=false
+ntlm.authentication.domain=DOMAIN
+ntlm.authentication.servers=
+ntlm.authentication.guestAccess=false
+ntlm.authentication.defaultAdministratorUserNames=
\ No newline at end of file
diff --git a/config/alfresco/extension/ntlm-authentication-context.xml.sample b/config/alfresco/subsystems/ntlmAuthentication/ntlm-authentication-context.xml
similarity index 79%
rename from config/alfresco/extension/ntlm-authentication-context.xml.sample
rename to config/alfresco/subsystems/ntlmAuthentication/ntlm-authentication-context.xml
index 77f0fa2246..9342073852 100644
--- a/config/alfresco/extension/ntlm-authentication-context.xml.sample
+++ b/config/alfresco/subsystems/ntlmAuthentication/ntlm-authentication-context.xml
@@ -3,47 +3,53 @@
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- false
-
-
- 192.168.0.1
-
-
-
-
-
-
-
-
-
-
-
- false
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ${ntlm.authentication.useLocalServer}
+
+
+ ${ntlm.authentication.domain}
+
+
+ ${ntlm.authentication.servers}
+
+
+
+
+
+
+
+
+
+
+
+ ${ntlm.authentication.guestAccess}
+
+
+ ${ntlm.authentication.defaultAdministratorUserNames}
+
+
+
\ No newline at end of file
diff --git a/source/java/org/alfresco/repo/management/DefaultManagedApplicationContextFactory.java b/source/java/org/alfresco/repo/management/DefaultManagedApplicationContextFactory.java
new file mode 100644
index 0000000000..911a36c801
--- /dev/null
+++ b/source/java/org/alfresco/repo/management/DefaultManagedApplicationContextFactory.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2005-2009 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have received a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing"
+ */
+package org.alfresco.repo.management;
+
+import java.util.Properties;
+
+import org.alfresco.service.Managed;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.BeanNameAware;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
+import org.springframework.beans.factory.config.PropertiesFactoryBean;
+import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+/**
+ * A factory allowing initialisation of an entire 'subsystem' in a child application context. As with other
+ * {@link ManagedBean}s, can be stopped, reconfigured, started and tested. Doesn't actually implement FactoryBean
+ * because we need first class access to the factory itself to be able to configure its properties.
+ */
+public class DefaultManagedApplicationContextFactory implements ManagedApplicationContextFactory,
+ InitializingBean, ApplicationContextAware, BeanNameAware
+{
+ private static final long serialVersionUID = 6368629257690177326L;
+ private ApplicationContext parent;
+ private String beanName;
+ private ClassPathXmlApplicationContext applicationContext;
+ private Properties properties;
+
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.
+ * ApplicationContext)
+ */
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
+ {
+ this.parent = applicationContext;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.beans.factory.BeanNameAware#setBeanName(java.lang.String)
+ */
+ public void setBeanName(String name)
+ {
+ this.beanName = name;
+ }
+
+ /**
+ * @param properties
+ * the properties to set
+ */
+ @Managed(category="management")
+ public void setProperties(Properties properties)
+ {
+ this.properties = properties;
+ }
+
+ /**
+ * @return the properties
+ */
+ public Properties getProperties()
+ {
+ return this.properties;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
+ */
+ public void afterPropertiesSet() throws Exception
+ {
+ PropertiesFactoryBean factory = new PropertiesFactoryBean();
+ if (this.properties != null)
+ {
+ factory.setLocalOverride(true);
+ factory.setProperties(this.properties);
+ }
+ factory.setLocations(this.parent.getResources("classpath*:alfresco/subsystems/" + this.beanName
+ + "/*.properties"));
+ factory.afterPropertiesSet();
+ this.properties = (Properties) factory.getObject();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.alfresco.enterprise.repo.management.ConfigurableBean#onStart()
+ */
+ public void onStart()
+ {
+ this.applicationContext = new ClassPathXmlApplicationContext(new String[]
+ {
+ "classpath*:alfresco/subsystems/" + this.beanName + "/*-context.xml"
+ }, false, this.parent);
+ // Add all the post processors of the parent, e.g. to make sure system placeholders get expanded properly
+ for (Object postProcessor : this.parent.getBeansOfType(BeanFactoryPostProcessor.class).values())
+ {
+ this.applicationContext.addBeanFactoryPostProcessor((BeanFactoryPostProcessor) postProcessor);
+ }
+ // Add a property placeholder configurer, with the subsystem-scoped default properties
+ PropertyPlaceholderConfigurer configurer = new PropertyPlaceholderConfigurer();
+ configurer.setProperties(this.properties);
+ configurer.setIgnoreUnresolvablePlaceholders(true);
+ this.applicationContext.addBeanFactoryPostProcessor(configurer);
+ this.applicationContext.setClassLoader(parent.getClassLoader());
+ this.applicationContext.refresh();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.alfresco.enterprise.repo.management.ConfigurableBean#onTest()
+ */
+ public void onTest()
+ {
+ this.applicationContext.getBean("testBean");
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.beans.factory.DisposableBean#destroy()
+ */
+ public void destroy() throws Exception
+ {
+ if (this.applicationContext != null)
+ {
+ this.applicationContext.close();
+ this.applicationContext = null;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.management.ManagedApplicationContextFactory#getApplicationContext()
+ */
+ public ApplicationContext getApplicationContext()
+ {
+ return this.applicationContext;
+ }
+}
diff --git a/source/java/org/alfresco/repo/management/JmxDumpUtil.java b/source/java/org/alfresco/repo/management/JmxDumpUtil.java
new file mode 100644
index 0000000000..f267750bfa
--- /dev/null
+++ b/source/java/org/alfresco/repo/management/JmxDumpUtil.java
@@ -0,0 +1,350 @@
+/*
+ * Copyright (C) 2005-2009 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have received a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing"
+ */
+package org.alfresco.repo.management;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.lang.reflect.Array;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import javax.management.JMException;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanInfo;
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectName;
+import javax.management.openmbean.CompositeData;
+
+/**
+ * A utility class providing a method to dump a local or remote MBeanServer's entire object tree for support purposes.
+ * Nested arrays and CompositeData objects in MBean attribute values are handled.
+ *
+ * @author dward
+ */
+public class JmxDumpUtil
+{
+ /** Table header for attribute names. */
+ private static final String NAME_HEADER = "Attribute Name";
+
+ /** Table header for attribute values. */
+ private static final String VALUE_HEADER = "Attribute Value";
+
+ /** Place holder for nulls. */
+ private static final String NULL_VALUE = "";
+
+ /** Place holder for unreadable values. */
+ private static final String UNREADABLE_VALUE = "";
+
+ /**
+ * Dumps a local or remote MBeanServer's entire object tree for support purposes. Nested arrays and CompositeData
+ * objects in MBean attribute values are handled.
+ *
+ * @param connection
+ * the server connection (or server itself)
+ * @param out
+ * PrintWriter to write the output to
+ * @throws IOException
+ * Signals that an I/O exception has occurred.
+ */
+ public static void dumpConnection(MBeanServerConnection connection, PrintWriter out) throws IOException
+ {
+ // Get all the object names
+ Set objectNames = connection.queryNames(null, null);
+
+ // Sort the names
+ objectNames = new TreeSet(objectNames);
+
+ // Dump each MBean
+ for (ObjectName objectName : objectNames)
+ {
+ try
+ {
+ printMBeanInfo(connection, objectName, out);
+ }
+ catch (JMException e)
+ {
+ // Sometimes beans can disappear while we are examining them
+ }
+ }
+ }
+
+ /**
+ * Dumps the details of a single MBean.
+ *
+ * @param connection
+ * the server connection (or server itself)
+ * @param objectName
+ * the object name
+ * @param out
+ * PrintWriter to write the output to
+ * @throws IOException
+ * Signals that an I/O exception has occurred.
+ * @throws JMException
+ * Signals a JMX error
+ */
+ private static void printMBeanInfo(MBeanServerConnection connection, ObjectName objectName, PrintWriter out)
+ throws IOException, JMException
+ {
+ Map attributes = new TreeMap();
+ MBeanInfo info = connection.getMBeanInfo(objectName);
+ attributes.put("** Object Name", objectName.toString());
+ attributes.put("** Object Type", info.getClassName());
+ for (MBeanAttributeInfo element : info.getAttributes())
+ {
+ Object value;
+ if (element.isReadable())
+ {
+ try
+ {
+ value = connection.getAttribute(objectName, element.getName());
+ }
+ catch (Exception e)
+ {
+ value = JmxDumpUtil.UNREADABLE_VALUE;
+ }
+ }
+ else
+ {
+ value = JmxDumpUtil.UNREADABLE_VALUE;
+ }
+ attributes.put(element.getName(), value);
+ }
+ tabulate(JmxDumpUtil.NAME_HEADER, JmxDumpUtil.VALUE_HEADER, attributes, out, 0);
+ }
+
+ /**
+ * Dumps the details of a single CompositeData object.
+ *
+ * @param composite
+ * the composite object
+ * @param out
+ * PrintWriter to write the output to
+ * @param nestLevel
+ * the nesting level
+ * @throws IOException
+ * Signals that an I/O exception has occurred.
+ */
+ private static void printCompositeInfo(CompositeData composite, PrintWriter out, int nestLevel) throws IOException
+ {
+ Map attributes = new TreeMap();
+ for (String key : composite.getCompositeType().keySet())
+ {
+ Object value;
+ try
+ {
+ value = composite.get(key);
+ }
+ catch (Exception e)
+ {
+ value = JmxDumpUtil.UNREADABLE_VALUE;
+ }
+ attributes.put(key, value);
+ }
+ tabulate(JmxDumpUtil.NAME_HEADER, JmxDumpUtil.VALUE_HEADER, attributes, out, nestLevel);
+ }
+
+ /**
+ * Tabulates a given String -> Object Map.
+ *
+ * @param keyHeader
+ * the key header
+ * @param valueHeader
+ * the value header
+ * @param rows
+ * Map containing key value pairs forming the rows
+ * @param out
+ * PrintWriter to write the output to
+ * @param nestLevel
+ * the nesting level
+ * @throws IOException
+ * Signals that an I/O exception has occurred.
+ */
+ private static void tabulate(String keyHeader, String valueHeader, Map rows, PrintWriter out,
+ int nestLevel) throws IOException
+ {
+ if (rows.isEmpty())
+ {
+ return;
+ }
+ // Calculate column lengths
+ int maxKeyLength = keyHeader.length(), maxValLength = valueHeader.length();
+ for (Map.Entry entry : rows.entrySet())
+ {
+ maxKeyLength = Math.max(maxKeyLength, entry.getKey().length());
+ maxValLength = Math.max(maxValLength, getValueLength(entry.getValue()));
+ }
+ // Output Header
+ outputRow(out, maxKeyLength, keyHeader, valueHeader, nestLevel);
+ indent(out, nestLevel);
+ for (int col = 0; col < maxKeyLength; col++)
+ {
+ out.print('-');
+ }
+ out.print(' ');
+ for (int col = 0; col < maxValLength; col++)
+ {
+ out.print('-');
+ }
+ out.println();
+
+ // Output Body
+ for (Map.Entry entry : rows.entrySet())
+ {
+ outputRow(out, maxKeyLength, entry.getKey(), entry.getValue(), nestLevel);
+ }
+ out.println();
+ }
+
+ /**
+ * Outputs spaces in the left hand margin appropriate for the given nesting level.
+ *
+ * @param out
+ * PrintWriter to write the output to
+ * @param nestLevel
+ * the nesting level
+ */
+ private static void indent(PrintWriter out, int nestLevel)
+ {
+ int size = nestLevel * 3;
+ for (int i = 0; i < size; i++)
+ {
+ out.print(' ');
+ }
+ }
+
+ /**
+ * Outputs a single row in a two-column table. The first column is padded with spaces so that the second column is
+ * aligned.
+ *
+ * @param out
+ * PrintWriter to write the output to
+ * @param maxKeyLength
+ * maximum number of characters in the first column
+ * @param key
+ * the first column value
+ * @param value
+ * the second column value
+ * @param nestLevel
+ * the nesting level
+ * @throws IOException
+ * Signals that an I/O exception has occurred.
+ */
+ private static void outputRow(PrintWriter out, int maxKeyLength, String key, Object value, int nestLevel)
+ throws IOException
+ {
+ indent(out, nestLevel);
+ out.print(key);
+ for (int i = key.length() - 1; i < maxKeyLength; i++)
+ {
+ out.print(' ');
+ }
+ outputValue(out, value, nestLevel);
+ }
+
+ /**
+ * Outputs a single value, dealing with nested arrays and CompositeData objects.
+ *
+ * @param out
+ * PrintWriter to write the output to
+ * @param value
+ * the value to output
+ * @param nestLevel
+ * the nesting level
+ * @throws IOException
+ * Signals that an I/O exception has occurred.
+ */
+ private static void outputValue(PrintWriter out, Object value, int nestLevel) throws IOException
+ {
+ if (value == null)
+ {
+ out.println(JmxDumpUtil.NULL_VALUE);
+ }
+ else if (value.getClass().isArray())
+ {
+ int length = Array.getLength(value);
+ if (length == 0)
+ {
+ out.println("[]");
+ }
+ else
+ {
+ out.println();
+ indent(out, nestLevel + 1);
+ out.println('[');
+ for (int i = 0; i < length; i++)
+ {
+ indent(out, nestLevel + 2);
+ outputValue(out, Array.get(value, i), nestLevel + 2);
+ if (i + 1 < length)
+ {
+ indent(out, nestLevel + 1);
+ out.println(',');
+ }
+ }
+ indent(out, nestLevel + 1);
+ out.println(']');
+ }
+ }
+ else if (value instanceof CompositeData)
+ {
+ out.println();
+ indent(out, nestLevel + 1);
+ out.println('[');
+ printCompositeInfo((CompositeData) value, out, nestLevel + 2);
+ indent(out, nestLevel + 1);
+ out.println(']');
+ }
+ else
+ {
+ out.println(value.toString());
+ }
+ }
+
+ /**
+ * Gets the number of characters required to encode a value.
+ *
+ * @param value
+ * the value to be encoded
+ * @return the number of characters
+ */
+ private static int getValueLength(Object value)
+ {
+ if (value == null)
+ {
+ return JmxDumpUtil.NULL_VALUE.length();
+ }
+ else if (value.getClass().isArray() || value instanceof CompositeData)
+ {
+ // We continue arrays and composites on a new line
+ return 0;
+ }
+ else
+ {
+ return value.toString().length();
+ }
+ }
+}
diff --git a/source/java/org/alfresco/repo/management/ManagedApplicationContextFactory.java b/source/java/org/alfresco/repo/management/ManagedApplicationContextFactory.java
new file mode 100644
index 0000000000..70b340d82e
--- /dev/null
+++ b/source/java/org/alfresco/repo/management/ManagedApplicationContextFactory.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2005-2009 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have received a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing"
+ */
+package org.alfresco.repo.management;
+
+import org.springframework.context.ApplicationContext;
+
+/**
+ * An interface for {@link ManagedBean}s providing access to a child application context corresonding to a particular
+ * subsystem. As with other {@link ManagedBean}s, can be stopped, reconfigured, started and tested. Doesn't actually
+ * implement FactoryBean because we need first class access to the factory itself to be able to configure its
+ * properties.
+ *
+ * @author dward
+ */
+public interface ManagedApplicationContextFactory extends ManagedBean
+{
+ /**
+ * Gets the application context, configured according to the properties of the factory.
+ *
+ * @return the application context
+ */
+ public ApplicationContext getApplicationContext();
+}
diff --git a/source/java/org/alfresco/repo/management/ManagedBean.java b/source/java/org/alfresco/repo/management/ManagedBean.java
new file mode 100644
index 0000000000..42489b36d5
--- /dev/null
+++ b/source/java/org/alfresco/repo/management/ManagedBean.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2005-2009 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have received a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing"
+ */
+package org.alfresco.repo.management;
+
+import org.springframework.beans.factory.DisposableBean;
+
+/**
+ * An interface for beans that can be reconfigured using an administration UI or JMX console. A bean in use must be
+ * 'stopped' before it can be configured with {@link #destroy}. After reconfiguration, it can then be put back into use
+ * with {@link #onStart} and if this is successful, further tests can be carried out with {@link #onTest}.
+ *
+ * @author dward
+ */
+public interface ManagedBean extends DisposableBean
+{
+ /**
+ * Puts the bean into use after its properties have been set.
+ */
+ public void onStart();
+
+ /**
+ * Carries out tests on the bean after it has been started.
+ */
+ public void onTest();
+}
diff --git a/source/java/org/alfresco/repo/management/ManagedSubsystemProxyFactory.java b/source/java/org/alfresco/repo/management/ManagedSubsystemProxyFactory.java
new file mode 100644
index 0000000000..78dee79410
--- /dev/null
+++ b/source/java/org/alfresco/repo/management/ManagedSubsystemProxyFactory.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2005-2009 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have received a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing"
+ */
+package org.alfresco.repo.management;
+
+import java.lang.reflect.Method;
+import java.util.Map;
+
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+import org.springframework.aop.framework.ProxyFactoryBean;
+import org.springframework.aop.support.DefaultPointcutAdvisor;
+
+/**
+ * A factory bean, normally used in conjunction with {@link DefaultManagedApplicationContextFactory} allowing selected
+ * interfaces in a child application context to be proxied by a bean in the parent application context. This allows
+ * 'hot-swapping' and reconfiguration of entire subsystems.
+ */
+public class ManagedSubsystemProxyFactory extends ProxyFactoryBean
+{
+ private static final long serialVersionUID = -4186421942840611218L;
+
+ /** The source application context factory. */
+ private ManagedApplicationContextFactory sourceApplicationContextFactory;
+
+ /** An optional bean name to look up in the source application context **/
+ private String sourceBeanName;
+
+ /**
+ * Instantiates a new managed subsystem proxy factory.
+ */
+ public ManagedSubsystemProxyFactory()
+ {
+ addAdvisor(new DefaultPointcutAdvisor(new MethodInterceptor()
+ {
+ public Object invoke(MethodInvocation mi) throws Throwable
+ {
+ Method method = mi.getMethod();
+ if (ManagedSubsystemProxyFactory.this.sourceBeanName == null)
+ {
+ Map, ?> beans = ManagedSubsystemProxyFactory.this.sourceApplicationContextFactory
+ .getApplicationContext().getBeansOfType(method.getDeclaringClass());
+ if (beans.size() != 1)
+ {
+ throw new RuntimeException("Don't know where to route call to method " + method);
+ }
+ return method.invoke(beans.values().iterator().next(), mi.getArguments());
+ }
+ else
+ {
+ Object bean = ManagedSubsystemProxyFactory.this.sourceApplicationContextFactory
+ .getApplicationContext().getBean(ManagedSubsystemProxyFactory.this.sourceBeanName);
+ return method.invoke(bean, mi.getArguments());
+
+ }
+ }
+ }));
+ }
+
+ /**
+ * Sets the source application context factory.
+ *
+ * @param sourceApplicationContextFactory
+ * the sourceApplicationContextFactory to set
+ */
+ public void setSourceApplicationContextFactory(ManagedApplicationContextFactory sourceApplicationContextFactory)
+ {
+ this.sourceApplicationContextFactory = sourceApplicationContextFactory;
+ }
+
+ /**
+ * Sets optional bean name to target all calls to in the source application context. If not set, an appropriate
+ * bean is looked up based on method class.
+ *
+ * @param sourceBeanName
+ * the sourceBeanName to set
+ */
+ public void setSourceBeanName(String sourceBeanName)
+ {
+ this.sourceBeanName = sourceBeanName;
+ }
+}
diff --git a/source/java/org/alfresco/repo/management/SwitchableManagedApplicationContextFactory.java b/source/java/org/alfresco/repo/management/SwitchableManagedApplicationContextFactory.java
new file mode 100644
index 0000000000..1429f31d9a
--- /dev/null
+++ b/source/java/org/alfresco/repo/management/SwitchableManagedApplicationContextFactory.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2005-2009 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have received a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing"
+ */
+package org.alfresco.repo.management;
+
+import org.alfresco.service.Managed;
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+
+/**
+ * A configurable proxy for a set of {@link ManagedApplicationContextFactory} beans that allows dynamic selection of one
+ * or more alternative subsystems via {@link #setSourceBeanName}. As with other {@link ManagedBean}s, can be stopped,
+ * reconfigured, started and tested. Doesn't actually implement FactoryBean because we need first class access to the
+ * factory itself to be able to configure its properties.
+ */
+public class SwitchableManagedApplicationContextFactory implements ApplicationContextAware,
+ ManagedApplicationContextFactory
+{
+ /** The parent application context. */
+ private ApplicationContext parent;
+
+ /** The bean name of the source {@link ManagedApplicationContextFactory}. */
+ private String sourceBeanName;
+
+ /** The current source application context factory. */
+ private ManagedApplicationContextFactory sourceApplicationContextFactory;
+
+ /**
+ * Sets the bean name of the source {@link ManagedApplicationContextFactory}.
+ *
+ * @param sourceBeanName
+ * the bean name
+ * @throws Exception
+ * on error
+ */
+ @Managed(category = "management")
+ public synchronized void setSourceBeanName(String sourceBeanName) throws Exception
+ {
+ if (this.sourceApplicationContextFactory != null)
+ {
+ destroy();
+ this.sourceBeanName = sourceBeanName;
+ onStart();
+ }
+ else
+ {
+ this.sourceBeanName = sourceBeanName;
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.
+ * ApplicationContext)
+ */
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
+ {
+ this.parent = applicationContext;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.alfresco.enterprise.repo.management.ConfigurableBean#onStart()
+ */
+ public synchronized void onStart()
+ {
+ this.sourceApplicationContextFactory = (ManagedApplicationContextFactory) this.parent
+ .getBean(this.sourceBeanName);
+ this.sourceApplicationContextFactory.onStart();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.alfresco.enterprise.repo.management.ConfigurableBean#onTest()
+ */
+ public synchronized void onTest()
+ {
+ if (this.sourceApplicationContextFactory != null)
+ {
+ this.sourceApplicationContextFactory.onTest();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.beans.factory.DisposableBean#destroy()
+ */
+ public synchronized void destroy() throws Exception
+ {
+ if (this.sourceApplicationContextFactory != null)
+ {
+ this.sourceApplicationContextFactory.destroy();
+ }
+ this.sourceApplicationContextFactory = null;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.alfresco.repo.management.ManagedApplicationContextFactory#getApplicationContext()
+ */
+ public synchronized ApplicationContext getApplicationContext()
+ {
+ if (this.sourceApplicationContextFactory == null)
+ {
+ onStart();
+ }
+ return this.sourceApplicationContextFactory.getApplicationContext();
+ }
+}
diff --git a/source/java/org/alfresco/repo/security/authentication/AbstractAuthenticationComponent.java b/source/java/org/alfresco/repo/security/authentication/AbstractAuthenticationComponent.java
index 596521e91d..444c43f03b 100644
--- a/source/java/org/alfresco/repo/security/authentication/AbstractAuthenticationComponent.java
+++ b/source/java/org/alfresco/repo/security/authentication/AbstractAuthenticationComponent.java
@@ -24,6 +24,11 @@
*/
package org.alfresco.repo.security.authentication;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Set;
+import java.util.TreeSet;
+
import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.GrantedAuthority;
import net.sf.acegisecurity.GrantedAuthorityImpl;
@@ -65,6 +70,8 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
private NodeService nodeService;
private TransactionService transactionService;
+
+ private Set defaultAdministratorUserNames = Collections.emptySet();
private boolean autoCreatePeopleOnLogin = true;
@@ -494,4 +501,39 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
}
}
}
+
+ /*
+ * (non-Javadoc)
+ * @see org.alfresco.repo.security.authentication.AuthenticationComponent#getDefaultAdministratorUserNames()
+ */
+ public Set getDefaultAdministratorUserNames()
+ {
+ return this.defaultAdministratorUserNames;
+ }
+
+ /**
+ * Sets the user names who for this particular authentication system should be considered administrators by default.
+ *
+ * @param defaultAdministratorUserNames
+ * a set of user names
+ */
+ public void setDefaultAdministratorUserNames(Set defaultAdministratorUserNames)
+ {
+ this.defaultAdministratorUserNames = defaultAdministratorUserNames;
+ }
+
+ /**
+ * Convenience method to allow the administrator user names to be specified as a comma separated list
+ *
+ * @param defaultAdministratorUserNames
+ */
+ public void setDefaultAdministratorUserNames(String defaultAdministratorUserNames)
+ {
+ Set nameSet = new TreeSet();
+ if (!defaultAdministratorUserNames.isEmpty())
+ {
+ nameSet.addAll(Arrays.asList(defaultAdministratorUserNames.split(",")));
+ }
+ setDefaultAdministratorUserNames(nameSet);
+ }
}
diff --git a/source/java/org/alfresco/repo/security/authentication/AuthenticationComponent.java b/source/java/org/alfresco/repo/security/authentication/AuthenticationComponent.java
index 1a7b678f35..f61c5c56ec 100644
--- a/source/java/org/alfresco/repo/security/authentication/AuthenticationComponent.java
+++ b/source/java/org/alfresco/repo/security/authentication/AuthenticationComponent.java
@@ -24,6 +24,8 @@
*/
package org.alfresco.repo.security.authentication;
+import java.util.Set;
+
import net.sf.acegisecurity.Authentication;
public interface AuthenticationComponent
@@ -134,4 +136,13 @@ public interface AuthenticationComponent
* Get the MD4 password hash, as required by NTLM based authentication methods.
*/
public String getMD4HashedPassword(String userName);
+
+ /**
+ * Gets a set of user names who for this particular authentication system should be considered administrators by
+ * default. If the security framework is case sensitive these values should be case sensitive user names. If the
+ * security framework is not case sensitive these values should be the lower-case user names.
+ *
+ * @return a set of user names
+ */
+ public Set getDefaultAdministratorUserNames();
}
diff --git a/source/java/org/alfresco/repo/security/authentication/AuthenticationComponentImpl.java b/source/java/org/alfresco/repo/security/authentication/AuthenticationComponentImpl.java
index c2ef72bf3c..9ac5fb22d8 100644
--- a/source/java/org/alfresco/repo/security/authentication/AuthenticationComponentImpl.java
+++ b/source/java/org/alfresco/repo/security/authentication/AuthenticationComponentImpl.java
@@ -26,6 +26,8 @@ package org.alfresco.repo.security.authentication;
import java.io.PrintWriter;
import java.io.StringWriter;
+import java.util.Collections;
+import java.util.Set;
import net.sf.acegisecurity.AuthenticationManager;
import net.sf.acegisecurity.UserDetails;
@@ -59,28 +61,29 @@ public class AuthenticationComponentImpl extends AbstractAuthenticationComponent
*
* @param authenticationDao
*/
- @Managed(category="Security")
+ @Managed(category = "Security")
public void setAuthenticationDao(MutableAuthenticationDao authenticationDao)
{
this.authenticationDao = authenticationDao;
}
-
+
/**
* Authenticate
*/
+ @Override
protected void authenticateImpl(String userName, char[] password) throws AuthenticationException
{
try
{
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userName,
new String(password));
- authenticationManager.authenticate(authentication);
+ this.authenticationManager.authenticate(authentication);
setCurrentUser(userName);
}
catch (net.sf.acegisecurity.AuthenticationException ae)
{
- // This is a bit gross, I admit, but when LDAP is
+ // This is a bit gross, I admit, but when LDAP is
// configured ae, above, is non-serializable and breaks
// remote authentication.
StringWriter sw = new StringWriter();
@@ -92,28 +95,28 @@ public class AuthenticationComponentImpl extends AbstractAuthenticationComponent
}
}
-
/**
- * We actually have an acegi object so override the default method.
+ * We actually have an acegi object so override the default method.
*/
+ @Override
protected UserDetails getUserDetails(String userName)
{
- return (UserDetails) authenticationDao.loadUserByUsername(userName);
+ return this.authenticationDao.loadUserByUsername(userName);
}
-
/**
* Get the password hash from the DAO
*/
+ @Override
public String getMD4HashedPassword(String userName)
{
- return authenticationDao.getMD4HashedPassword(userName);
+ return this.authenticationDao.getMD4HashedPassword(userName);
}
-
/**
- * This implementation supported MD4 password hashes.
+ * This implementation supported MD4 password hashes.
*/
+ @Override
public NTLMMode getNTLMMode()
{
return NTLMMode.MD4_PROVIDER;
@@ -124,6 +127,14 @@ public class AuthenticationComponentImpl extends AbstractAuthenticationComponent
{
return true;
}
-
-
+
+ /*
+ * (non-Javadoc)
+ * @see org.alfresco.repo.security.authentication.AuthenticationComponent#getDefaultAdministratorUserNames()
+ */
+ @Override
+ public Set getDefaultAdministratorUserNames()
+ {
+ return Collections.singleton(AuthenticationUtil.getAdminUserName());
+ }
}
diff --git a/source/java/org/alfresco/repo/security/authentication/AuthenticationServiceImpl.java b/source/java/org/alfresco/repo/security/authentication/AuthenticationServiceImpl.java
index fc60757cfd..d72f698bdb 100644
--- a/source/java/org/alfresco/repo/security/authentication/AuthenticationServiceImpl.java
+++ b/source/java/org/alfresco/repo/security/authentication/AuthenticationServiceImpl.java
@@ -303,4 +303,13 @@ public class AuthenticationServiceImpl extends AbstractAuthenticationService
{
return Collections.singleton(ticketComponent);
}
+
+ /*
+ * (non-Javadoc)
+ * @see org.alfresco.service.cmr.security.AuthenticationService#getDefaultAdministratorUserNames()
+ */
+ public Set getDefaultAdministratorUserNames()
+ {
+ return authenticationComponent.getDefaultAdministratorUserNames();
+ }
}
diff --git a/source/java/org/alfresco/repo/security/authentication/ChainingAuthenticationComponentImpl.java b/source/java/org/alfresco/repo/security/authentication/ChainingAuthenticationComponentImpl.java
index 34de536d88..49e47b4280 100644
--- a/source/java/org/alfresco/repo/security/authentication/ChainingAuthenticationComponentImpl.java
+++ b/source/java/org/alfresco/repo/security/authentication/ChainingAuthenticationComponentImpl.java
@@ -26,6 +26,8 @@ package org.alfresco.repo.security.authentication;
import java.util.ArrayList;
import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
import net.sf.acegisecurity.Authentication;
@@ -434,4 +436,17 @@ public class ChainingAuthenticationComponentImpl implements AuthenticationCompon
}
}
+ /*
+ * (non-Javadoc)
+ * @see org.alfresco.repo.security.authentication.AuthenticationComponent#getDefaultAdministratorUserNames()
+ */
+ public Set getDefaultAdministratorUserNames()
+ {
+ Set defaultAdministratorUserNames = new TreeSet();
+ for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
+ {
+ defaultAdministratorUserNames.addAll(authComponent.getDefaultAdministratorUserNames());
+ }
+ return defaultAdministratorUserNames;
+ }
}
diff --git a/source/java/org/alfresco/repo/security/authentication/ChainingAuthenticationServiceImpl.java b/source/java/org/alfresco/repo/security/authentication/ChainingAuthenticationServiceImpl.java
index a650cb25bc..323ff7a9dd 100644
--- a/source/java/org/alfresco/repo/security/authentication/ChainingAuthenticationServiceImpl.java
+++ b/source/java/org/alfresco/repo/security/authentication/ChainingAuthenticationServiceImpl.java
@@ -28,6 +28,7 @@ import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.TreeSet;
import org.alfresco.service.Managed;
import org.alfresco.service.cmr.security.AuthenticationService;
@@ -470,4 +471,13 @@ public class ChainingAuthenticationServiceImpl extends AbstractAuthenticationSer
return tcs;
}
+ public Set getDefaultAdministratorUserNames()
+ {
+ Set defaultAdministratorUserNames = new TreeSet();
+ for (AuthenticationService authService : getUsableAuthenticationServices())
+ {
+ defaultAdministratorUserNames.addAll(authService.getDefaultAdministratorUserNames());
+ }
+ return defaultAdministratorUserNames;
+ }
}
diff --git a/source/java/org/alfresco/repo/security/authentication/TestAuthenticationServiceImpl.java b/source/java/org/alfresco/repo/security/authentication/TestAuthenticationServiceImpl.java
index 14bd082549..47adeab1bf 100644
--- a/source/java/org/alfresco/repo/security/authentication/TestAuthenticationServiceImpl.java
+++ b/source/java/org/alfresco/repo/security/authentication/TestAuthenticationServiceImpl.java
@@ -473,6 +473,11 @@ public class TestAuthenticationServiceImpl implements AuthenticationService
return authentication;
}
+ public Set getDefaultAdministratorUserNames()
+ {
+ return Collections.singleton(AuthenticationUtil.getAdminUserName());
+ }
+
private static final String SYSTEM_USER_NAME = "System";
}
diff --git a/source/java/org/alfresco/repo/security/authentication/ntlm/NTLMAuthenticationComponentImpl.java b/source/java/org/alfresco/repo/security/authentication/ntlm/NTLMAuthenticationComponentImpl.java
index 878af3e0c0..486b4d1f6d 100644
--- a/source/java/org/alfresco/repo/security/authentication/ntlm/NTLMAuthenticationComponentImpl.java
+++ b/source/java/org/alfresco/repo/security/authentication/ntlm/NTLMAuthenticationComponentImpl.java
@@ -52,16 +52,11 @@ import org.alfresco.jlan.server.auth.passthru.PassthruServers;
import org.alfresco.jlan.smb.Protocol;
import org.alfresco.jlan.smb.SMBException;
import org.alfresco.jlan.smb.SMBStatus;
-import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AbstractAuthenticationComponent;
import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.repo.security.authentication.NTLMMode;
import org.alfresco.service.Managed;
-import org.alfresco.service.cmr.repository.NodeRef;
-import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.NoSuchPersonException;
-import org.alfresco.service.cmr.security.PersonService;
-import org.alfresco.service.transaction.TransactionService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -284,21 +279,23 @@ public class NTLMAuthenticationComponentImpl extends AbstractAuthenticationCompo
*/
@Managed(category="Security")
public void setDomain(String domain) {
-
- // Check if the passthru server list is already configured
-
- if ( m_passthruServers.getTotalServerCount() > 0)
- throw new AlfrescoRuntimeException("Passthru server list already configured");
-
- // Configure the passthru authentication server list using the domain controllers
-
- try
- {
- m_passthruServers.setDomain(domain);
- }
- catch ( IOException ex)
- {
- throw new AlfrescoRuntimeException("Failed to set passthru domain, " + ex);
+ if (!domain.isEmpty())
+ {
+ // Check if the passthru server list is already configured
+
+ if ( m_passthruServers.getTotalServerCount() > 0)
+ throw new AlfrescoRuntimeException("Passthru server list already configured");
+
+ // Configure the passthru authentication server list using the domain controllers
+
+ try
+ {
+ m_passthruServers.setDomain(domain);
+ }
+ catch ( IOException ex)
+ {
+ throw new AlfrescoRuntimeException("Failed to set passthru domain, " + ex);
+ }
}
}
@@ -308,16 +305,18 @@ public class NTLMAuthenticationComponentImpl extends AbstractAuthenticationCompo
* @param servers String
*/
@Managed(category="Security")
- public void setServers(String servers) {
-
- // Check if the passthru server list is already configured
-
- if ( m_passthruServers.getTotalServerCount() > 0)
- throw new AlfrescoRuntimeException("Passthru server list already configured");
-
- // Configure the passthru authenticaiton list using a list of server names/addresses
-
- m_passthruServers.setServerList(servers);
+ public void setServers(String servers) {
+ if (!servers.isEmpty())
+ {
+ // Check if the passthru server list is already configured
+
+ if (m_passthruServers.getTotalServerCount() > 0)
+ throw new AlfrescoRuntimeException("Passthru server list already configured");
+
+ // Configure the passthru authenticaiton list using a list of server names/addresses
+
+ m_passthruServers.setServerList(servers);
+ }
}
/**
diff --git a/source/java/org/alfresco/repo/security/authority/AuthorityServiceImpl.java b/source/java/org/alfresco/repo/security/authority/AuthorityServiceImpl.java
index cbc8a40f55..52314fc861 100644
--- a/source/java/org/alfresco/repo/security/authority/AuthorityServiceImpl.java
+++ b/source/java/org/alfresco/repo/security/authority/AuthorityServiceImpl.java
@@ -36,6 +36,7 @@ import org.alfresco.repo.tenant.TenantService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
+import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.service.cmr.security.AuthorityType;
import org.alfresco.service.cmr.security.PermissionService;
@@ -61,6 +62,8 @@ public class AuthorityServiceImpl implements AuthorityService, InitializingBean
private AuthorityDAO authorityDAO;
+ private AuthenticationService authenticationService;
+
private PermissionServiceSPI permissionServiceSPI;
private Set adminSet = Collections.singleton(PermissionService.ADMINISTRATOR_AUTHORITY);
@@ -69,8 +72,6 @@ public class AuthorityServiceImpl implements AuthorityService, InitializingBean
private Set allSet = Collections.singleton(PermissionService.ALL_AUTHORITIES);
- private Set adminUsers = Collections.emptySet();
-
private Set adminGroups = Collections.emptySet();
public AuthorityServiceImpl()
@@ -97,7 +98,12 @@ public class AuthorityServiceImpl implements AuthorityService, InitializingBean
{
this.authorityDAO = authorityDAO;
}
-
+
+ public void setAuthenticationService(AuthenticationService authenticationService)
+ {
+ this.authenticationService = authenticationService;
+ }
+
public void setPermissionServiceSPI(PermissionServiceSPI permissionServiceSPI)
{
this.permissionServiceSPI = permissionServiceSPI;
@@ -108,11 +114,6 @@ public class AuthorityServiceImpl implements AuthorityService, InitializingBean
logger.warn("Bean property 'authenticationService' no longer required on 'AuthorityServiceImpl'.");
}
- public void setAdminUsers(Set adminUsers)
- {
- this.adminUsers = adminUsers;
- }
-
public void setAdminGroups(Set adminGroups)
{
this.adminGroups = adminGroups;
@@ -170,6 +171,8 @@ public class AuthorityServiceImpl implements AuthorityService, InitializingBean
// Work out mapped roles
// Check named admin users
+ Set adminUsers = this.authenticationService.getDefaultAdministratorUserNames();
+
// note: for multi-tenancy, this currently relies on a naming convention which assumes that all tenant admins will
// have the same base name as the default non-tenant specific admin. Typically "admin" is the default required admin user,
// although, if for example "bob" is also listed as an admin then all tenant-specific bob's will also have admin authority
diff --git a/source/java/org/alfresco/service/cmr/security/AuthenticationService.java b/source/java/org/alfresco/service/cmr/security/AuthenticationService.java
index b5cde4e515..a9089e2de6 100644
--- a/source/java/org/alfresco/service/cmr/security/AuthenticationService.java
+++ b/source/java/org/alfresco/service/cmr/security/AuthenticationService.java
@@ -231,5 +231,13 @@ public interface AuthenticationService
*/
@Auditable
public Set getDomiansThatAllowUserPasswordChanges();
+
+ /**
+ * Gets a set of user names who should be considered administrators by default.
+ *
+ * @return a set of user names
+ */
+ @Auditable
+ public Set getDefaultAdministratorUserNames();
}
diff --git a/source/java/org/alfresco/util/AutoCommitInterceptor.java b/source/java/org/alfresco/util/AutoCommitInterceptor.java
new file mode 100644
index 0000000000..77a6c41687
--- /dev/null
+++ b/source/java/org/alfresco/util/AutoCommitInterceptor.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2005-2009 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have received a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing"
+ */
+package org.alfresco.util;
+
+import java.sql.Connection;
+
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+
+/**
+ * Can be used to wrap a datasource to ensure that the connections that it returns have auto-commit switched on.
+ *
+ * @author dward
+ */
+public class AutoCommitInterceptor implements MethodInterceptor
+{
+ public Object invoke(MethodInvocation mi) throws Throwable
+ {
+ Connection result = (Connection) mi.proceed();
+ result.setAutoCommit(true);
+ return result;
+ }
+}