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} + - + + + + + + ${ldap.synchronisation.java.naming.factory.initial} + + + + + + + ${ldap.synchronisation.java.naming.provider.url} + + + + + + + + ${ldap.synchronisation.java.naming.security.authentication} + + + + + + ${ldap.synchronisation.java.naming.security.principal} + + + + + ${ldap.authentication.java.naming.security.credentials} + + + + 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; + } +}