diff --git a/source/java/org/alfresco/repo/management/subsystems/ChainingSubsystemProxyFactory.java b/source/java/org/alfresco/repo/management/subsystems/ChainingSubsystemProxyFactory.java index df297bf447..ebd5762ec5 100644 --- a/source/java/org/alfresco/repo/management/subsystems/ChainingSubsystemProxyFactory.java +++ b/source/java/org/alfresco/repo/management/subsystems/ChainingSubsystemProxyFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2010 Alfresco Software Limited. + * Copyright (C) 2005-2013 Alfresco Software Limited. * * This file is part of Alfresco * @@ -27,6 +27,7 @@ import org.aopalliance.intercept.MethodInvocation; import org.springframework.aop.framework.ProxyFactoryBean; import org.springframework.aop.support.DefaultPointcutAdvisor; import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.context.ApplicationContext; /** * A factory bean, used in conjunction with {@link ChildApplicationContextManager} allowing selected interfaces to be @@ -63,10 +64,20 @@ public class ChainingSubsystemProxyFactory extends ProxyFactoryBean { for (String instance : applicationContextManager.getInstanceIds()) { + ApplicationContext context; + try + { + context = ChainingSubsystemProxyFactory.this.applicationContextManager + .getApplicationContext(instance); + } + catch (RuntimeException e) + { + // This subsystem won't start. The reason would have been logged. Ignore and continue. + continue; + } if (ChainingSubsystemProxyFactory.this.sourceBeanName == null) { - Map beans = ChainingSubsystemProxyFactory.this.applicationContextManager - .getApplicationContext(instance).getBeansOfType(method.getDeclaringClass()); + Map beans = context.getBeansOfType(method.getDeclaringClass()); Object activeBean = null; for (Object bean : beans.values()) { @@ -93,9 +104,7 @@ public class ChainingSubsystemProxyFactory extends ProxyFactoryBean { try { - Object bean = ChainingSubsystemProxyFactory.this.applicationContextManager - .getApplicationContext(instance).getBean( - ChainingSubsystemProxyFactory.this.sourceBeanName); + Object bean = context.getBean(ChainingSubsystemProxyFactory.this.sourceBeanName); // Ignore inactive beans if (!(bean instanceof ActivateableBean) || ((ActivateableBean) bean).isActive()) @@ -138,7 +147,7 @@ public class ChainingSubsystemProxyFactory extends ProxyFactoryBean * (non-Javadoc) * @see org.springframework.aop.framework.AdvisedSupport#setInterfaces(java.lang.Class[]) */ - @SuppressWarnings("unchecked") + @SuppressWarnings("rawtypes") @Override public void setInterfaces(Class[] interfaces) { diff --git a/source/java/org/alfresco/repo/management/subsystems/ChildApplicationContextFactory.java b/source/java/org/alfresco/repo/management/subsystems/ChildApplicationContextFactory.java index a0b5dbdeab..f23c0c81f8 100644 --- a/source/java/org/alfresco/repo/management/subsystems/ChildApplicationContextFactory.java +++ b/source/java/org/alfresco/repo/management/subsystems/ChildApplicationContextFactory.java @@ -37,7 +37,6 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanNameAware; -import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.ListFactoryBean; @@ -553,6 +552,9 @@ public class ChildApplicationContextFactory extends AbstractPropertyBackedBean i /** The child application context. */ private ClassPathXmlApplicationContext applicationContext; + + /** Error when we last tried to start. */ + private RuntimeException lastStartupError; /** * Instantiates a new application context state. @@ -632,6 +634,7 @@ public class ChildApplicationContextFactory extends AbstractPropertyBackedBean i throw new IllegalStateException("Illegal write to property \"" + ChildApplicationContextFactory.TYPE_NAME_PROPERTY + "\""); } + this.lastStartupError = null; Class type = ChildApplicationContextFactory.this.compositePropertyTypes.get(name); if (type != null) { @@ -727,14 +730,32 @@ public class ChildApplicationContextFactory extends AbstractPropertyBackedBean i // properties. if (this.applicationContext == null) { + // The properties haven't been edited since we last tried to start up and fail, so rethrow the exception + // without logging + if (this.lastStartupError != null) + { + throw this.lastStartupError; + } + ChildApplicationContextFactory.logger .info("Starting '" + getCategory() + "' subsystem, ID: " + getId()); ClassPathXmlApplicationContext applicationContext = ChildApplicationContextFactory.this.new ChildApplicationContext( this.properties, this.compositeProperties); - applicationContext.refresh(); - this.applicationContext = applicationContext; - ChildApplicationContextFactory.logger.info("Startup of '" + getCategory() + "' subsystem, ID: " - + getId() + " complete"); + try + { + applicationContext.refresh(); + this.applicationContext = applicationContext; + ChildApplicationContextFactory.logger.info("Startup of '" + getCategory() + "' subsystem, ID: " + + getId() + " complete"); + } + catch (RuntimeException e) + { + // Log startup errors and remember for next time + ChildApplicationContextFactory.logger.warn("Startup of '" + getCategory() + "' subsystem, ID: " + + getId() + " failed", e); + this.lastStartupError = e; + throw e; + } } } diff --git a/source/java/org/alfresco/repo/management/subsystems/DefaultChildApplicationContextManager.java b/source/java/org/alfresco/repo/management/subsystems/DefaultChildApplicationContextManager.java index ab81811db6..c899255b72 100644 --- a/source/java/org/alfresco/repo/management/subsystems/DefaultChildApplicationContextManager.java +++ b/source/java/org/alfresco/repo/management/subsystems/DefaultChildApplicationContextManager.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2010 Alfresco Software Limited. + * Copyright (C) 2005-2013 Alfresco Software Limited. * * This file is part of Alfresco * @@ -291,9 +291,26 @@ public class DefaultChildApplicationContextManager extends AbstractPropertyBacke */ public void start() { + boolean oneSuccess = false; + RuntimeException lastError = null; for (String instance : getInstanceIds()) { - getApplicationContext(instance); + try + { + getApplicationContext(instance); + oneSuccess = true; + } + catch (RuntimeException e) + { + // One of the subsystems failed to initialize. The cause would have been logged. Treat this as + // non-fatal + lastError = e; + } + } + // If we weren't able to start any subsystems, then pass on the last error + if (lastError != null && !oneSuccess) + { + throw lastError; } } diff --git a/source/java/org/alfresco/repo/security/authentication/subsystems/SubsystemChainingAuthenticationComponent.java b/source/java/org/alfresco/repo/security/authentication/subsystems/SubsystemChainingAuthenticationComponent.java index 372ed1a84c..5a27e64f99 100644 --- a/source/java/org/alfresco/repo/security/authentication/subsystems/SubsystemChainingAuthenticationComponent.java +++ b/source/java/org/alfresco/repo/security/authentication/subsystems/SubsystemChainingAuthenticationComponent.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2010 Alfresco Software Limited. + * Copyright (C) 2005-2013 Alfresco Software Limited. * * This file is part of Alfresco * @@ -72,9 +72,9 @@ public class SubsystemChainingAuthenticationComponent extends AbstractChainingAu List result = new LinkedList(); for (String instance : this.applicationContextManager.getInstanceIds()) { - ApplicationContext context = this.applicationContextManager.getApplicationContext(instance); try { + ApplicationContext context = this.applicationContextManager.getApplicationContext(instance); AuthenticationComponent authenticationComponent = (AuthenticationComponent) context .getBean(sourceBeanName); // Only add active authentication components. E.g. we might have an ldap context that is only used for @@ -85,9 +85,9 @@ public class SubsystemChainingAuthenticationComponent extends AbstractChainingAu result.add(authenticationComponent); } } - catch (NoSuchBeanDefinitionException e) + catch (RuntimeException e) { - // Ignore and continue + // The bean doesn't exist or this subsystem won't start. The reason would have been logged. Ignore and continue. } } return result; diff --git a/source/java/org/alfresco/repo/security/authentication/subsystems/SubsystemChainingAuthenticationService.java b/source/java/org/alfresco/repo/security/authentication/subsystems/SubsystemChainingAuthenticationService.java index 09c120044c..b5ffbc224b 100644 --- a/source/java/org/alfresco/repo/security/authentication/subsystems/SubsystemChainingAuthenticationService.java +++ b/source/java/org/alfresco/repo/security/authentication/subsystems/SubsystemChainingAuthenticationService.java @@ -30,7 +30,6 @@ import org.alfresco.repo.management.subsystems.ChildApplicationContextManager; import org.alfresco.repo.security.authentication.AbstractChainingAuthenticationService; import org.alfresco.service.cmr.security.AuthenticationService; import org.alfresco.service.cmr.security.MutableAuthenticationService; -import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.context.ApplicationContext; /** @@ -94,7 +93,16 @@ public class SubsystemChainingAuthenticationService extends AbstractChainingAuth for (String instance : this.instanceIds) { - ApplicationContext newContext = this.applicationContextManager.getApplicationContext(instance); + ApplicationContext newContext; + try + { + newContext = this.applicationContextManager.getApplicationContext(instance); + } + catch (RuntimeException e) + { + // This subsystem won't start. The reason would have been logged. Ignore and continue. + newContext = null; + } ApplicationContext context = this.contexts.get(instance); if (context != newContext) { @@ -104,14 +112,16 @@ public class SubsystemChainingAuthenticationService extends AbstractChainingAuth this.lock.writeLock().lock(); haveWriteLock = true; } - newContext = this.applicationContextManager.getApplicationContext(instance); - this.contexts.put(instance, newContext); try { + newContext = this.applicationContextManager.getApplicationContext(instance); + this.contexts.put(instance, newContext); this.sourceBeans.put(instance, newContext.getBean(this.sourceBeanName)); } - catch (NoSuchBeanDefinitionException e) + catch (RuntimeException e) { + // This subsystem won't start or the bean doesn't exist. The reason would have been logged. Ignore and continue. + this.contexts.remove(instance); this.sourceBeans.remove(instance); } } @@ -178,8 +188,9 @@ public class SubsystemChainingAuthenticationService extends AbstractChainingAuth AuthenticationService authenticationService = (AuthenticationService) this.sourceBeans.get(instance); // Only add active authentication components. E.g. we might have an ldap context that is only used for // synchronizing - if (!(authenticationService instanceof ActivateableBean) - || ((ActivateableBean) authenticationService).isActive()) + if (authenticationService != null + && (!(authenticationService instanceof ActivateableBean) || ((ActivateableBean) authenticationService) + .isActive())) { result.add(authenticationService); diff --git a/source/java/org/alfresco/repo/security/sync/ChainingUserRegistrySynchronizer.java b/source/java/org/alfresco/repo/security/sync/ChainingUserRegistrySynchronizer.java index c21dd8af8b..7bc7a8008f 100644 --- a/source/java/org/alfresco/repo/security/sync/ChainingUserRegistrySynchronizer.java +++ b/source/java/org/alfresco/repo/security/sync/ChainingUserRegistrySynchronizer.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2012 Alfresco Software Limited. + * Copyright (C) 2005-2013 Alfresco Software Limited. * * This file is part of Alfresco * @@ -465,133 +465,135 @@ public class ChainingUserRegistrySynchronizer extends AbstractLifecycleBean impl } for (String id : instanceIds) { - ApplicationContext context = this.applicationContextManager.getApplicationContext(id); + UserRegistry plugin; try { - UserRegistry plugin = (UserRegistry) context.getBean(this.sourceBeanName); - if (!(plugin instanceof ActivateableBean) || ((ActivateableBean) plugin).isActive()) - { - if (ChainingUserRegistrySynchronizer.logger.isDebugEnabled()) - { - mbeanServer = (MBeanServerConnection) getApplicationContext().getBean("alfrescoMBeanServer"); - try - { - StringBuilder nameBuff = new StringBuilder(200).append("Alfresco:Type=Configuration,Category=Authentication,id1=managed,id2=").append( - URLDecoder.decode(id, "UTF-8")); - ObjectName name = new ObjectName(nameBuff.toString()); - if (mbeanServer != null && mbeanServer.isRegistered(name)) - { - MBeanInfo info = mbeanServer.getMBeanInfo(name); - MBeanAttributeInfo[] attributes = info.getAttributes(); - ChainingUserRegistrySynchronizer.logger.debug(id + " attributes:"); - for (MBeanAttributeInfo attribute : attributes) - { - Object value = mbeanServer.getAttribute(name, attribute.getName()); - ChainingUserRegistrySynchronizer.logger.debug(attribute.getName() + " = " + value); - } - } - } - catch(UnsupportedEncodingException e) - { - if (ChainingUserRegistrySynchronizer.logger.isWarnEnabled()) - { - ChainingUserRegistrySynchronizer.logger - .warn("Exception during logging", e); - } - } - catch (MalformedObjectNameException e) - { - if (ChainingUserRegistrySynchronizer.logger.isWarnEnabled()) - { - ChainingUserRegistrySynchronizer.logger - .warn("Exception during logging", e); - } - } - catch (InstanceNotFoundException e) - { - if (ChainingUserRegistrySynchronizer.logger.isWarnEnabled()) - { - ChainingUserRegistrySynchronizer.logger - .warn("Exception during logging", e); - } - } - catch (IntrospectionException e) - { - if (ChainingUserRegistrySynchronizer.logger.isWarnEnabled()) - { - ChainingUserRegistrySynchronizer.logger - .warn("Exception during logging", e); - } - } - catch (AttributeNotFoundException e) - { - if (ChainingUserRegistrySynchronizer.logger.isWarnEnabled()) - { - ChainingUserRegistrySynchronizer.logger - .warn("Exception during logging", e); - } - } - catch (ReflectionException e) - { - if (ChainingUserRegistrySynchronizer.logger.isWarnEnabled()) - { - ChainingUserRegistrySynchronizer.logger - .warn("Exception during logging", e); - } - } - catch (MBeanException e) - { - if (ChainingUserRegistrySynchronizer.logger.isWarnEnabled()) - { - ChainingUserRegistrySynchronizer.logger - .warn("Exception during logging", e); - } - } - catch (IOException e) - { - if (ChainingUserRegistrySynchronizer.logger.isWarnEnabled()) - { - ChainingUserRegistrySynchronizer.logger - .warn("Exception during logging", e); - } - } - - } - if (ChainingUserRegistrySynchronizer.logger.isInfoEnabled()) - { - ChainingUserRegistrySynchronizer.logger - .info("Synchronizing users and groups with user registry '" + id + "'"); - } - if (isFullSync && ChainingUserRegistrySynchronizer.logger.isWarnEnabled()) - { - ChainingUserRegistrySynchronizer.logger - .warn("Full synchronization with user registry '" - + id + "'"); - if (allowDeletions) - { - ChainingUserRegistrySynchronizer.logger - .warn("Some users and groups previously created by synchronization with this user registry may be removed."); - } - else - { - ChainingUserRegistrySynchronizer.logger - .warn("Deletions are disabled. Users and groups removed from this registry will be logged only and will remain in the repository. Users previously found in a different registry will be moved in the repository rather than recreated."); - } - } - // Work out whether we should do the work in a separate transaction (it's most performant if we - // bunch it into small transactions, but if we are doing a sync on login, it has to be the same - // transaction) - boolean requiresNew = splitTxns - || AlfrescoTransactionSupport.getTransactionReadState() == TxnReadState.TXN_READ_ONLY; - - syncWithPlugin(id, plugin, forceUpdate, isFullSync, requiresNew, visitedZoneIds, allZoneIds); - } + ApplicationContext context = this.applicationContextManager.getApplicationContext(id); + plugin = (UserRegistry) context.getBean(this.sourceBeanName); } - catch (NoSuchBeanDefinitionException e) + catch (RuntimeException e) { - // Ignore and continue + // The bean doesn't exist or this subsystem won't start. The reason would have been logged. Ignore and continue. + continue; } + + if (!(plugin instanceof ActivateableBean) || ((ActivateableBean) plugin).isActive()) + { + if (ChainingUserRegistrySynchronizer.logger.isDebugEnabled()) + { + mbeanServer = (MBeanServerConnection) getApplicationContext().getBean("alfrescoMBeanServer"); + try + { + StringBuilder nameBuff = new StringBuilder(200).append("Alfresco:Type=Configuration,Category=Authentication,id1=managed,id2=").append( + URLDecoder.decode(id, "UTF-8")); + ObjectName name = new ObjectName(nameBuff.toString()); + if (mbeanServer != null && mbeanServer.isRegistered(name)) + { + MBeanInfo info = mbeanServer.getMBeanInfo(name); + MBeanAttributeInfo[] attributes = info.getAttributes(); + ChainingUserRegistrySynchronizer.logger.debug(id + " attributes:"); + for (MBeanAttributeInfo attribute : attributes) + { + Object value = mbeanServer.getAttribute(name, attribute.getName()); + ChainingUserRegistrySynchronizer.logger.debug(attribute.getName() + " = " + value); + } + } + } + catch(UnsupportedEncodingException e) + { + if (ChainingUserRegistrySynchronizer.logger.isWarnEnabled()) + { + ChainingUserRegistrySynchronizer.logger + .warn("Exception during logging", e); + } + } + catch (MalformedObjectNameException e) + { + if (ChainingUserRegistrySynchronizer.logger.isWarnEnabled()) + { + ChainingUserRegistrySynchronizer.logger + .warn("Exception during logging", e); + } + } + catch (InstanceNotFoundException e) + { + if (ChainingUserRegistrySynchronizer.logger.isWarnEnabled()) + { + ChainingUserRegistrySynchronizer.logger + .warn("Exception during logging", e); + } + } + catch (IntrospectionException e) + { + if (ChainingUserRegistrySynchronizer.logger.isWarnEnabled()) + { + ChainingUserRegistrySynchronizer.logger + .warn("Exception during logging", e); + } + } + catch (AttributeNotFoundException e) + { + if (ChainingUserRegistrySynchronizer.logger.isWarnEnabled()) + { + ChainingUserRegistrySynchronizer.logger + .warn("Exception during logging", e); + } + } + catch (ReflectionException e) + { + if (ChainingUserRegistrySynchronizer.logger.isWarnEnabled()) + { + ChainingUserRegistrySynchronizer.logger + .warn("Exception during logging", e); + } + } + catch (MBeanException e) + { + if (ChainingUserRegistrySynchronizer.logger.isWarnEnabled()) + { + ChainingUserRegistrySynchronizer.logger + .warn("Exception during logging", e); + } + } + catch (IOException e) + { + if (ChainingUserRegistrySynchronizer.logger.isWarnEnabled()) + { + ChainingUserRegistrySynchronizer.logger + .warn("Exception during logging", e); + } + } + } + if (ChainingUserRegistrySynchronizer.logger.isInfoEnabled()) + { + ChainingUserRegistrySynchronizer.logger + .info("Synchronizing users and groups with user registry '" + id + "'"); + } + if (isFullSync && ChainingUserRegistrySynchronizer.logger.isWarnEnabled()) + { + ChainingUserRegistrySynchronizer.logger + .warn("Full synchronization with user registry '" + + id + "'"); + if (allowDeletions) + { + ChainingUserRegistrySynchronizer.logger + .warn("Some users and groups previously created by synchronization with this user registry may be removed."); + } + else + { + ChainingUserRegistrySynchronizer.logger + .warn("Deletions are disabled. Users and groups removed from this registry will be logged only and will remain in the repository. Users previously found in a different registry will be moved in the repository rather than recreated."); + } + } + // Work out whether we should do the work in a separate transaction (it's most performant if we + // bunch it into small transactions, but if we are doing a sync on login, it has to be the same + // transaction) + boolean requiresNew = splitTxns + || AlfrescoTransactionSupport.getTransactionReadState() == TxnReadState.TXN_READ_ONLY; + + syncWithPlugin(id, plugin, forceUpdate, isFullSync, requiresNew, visitedZoneIds, allZoneIds); + } } } catch (RuntimeException e) @@ -664,18 +666,18 @@ public class ChainingUserRegistrySynchronizer extends AbstractLifecycleBean impl { continue; } - ApplicationContext context = this.applicationContextManager.getApplicationContext(id); try { + ApplicationContext context = this.applicationContextManager.getApplicationContext(id); UserRegistry plugin = (UserRegistry) context.getBean(this.sourceBeanName); if (!(plugin instanceof ActivateableBean) || ((ActivateableBean) plugin).isActive()) { return plugin.getPersonMappedProperties(); } } - catch (NoSuchBeanDefinitionException e) + catch (RuntimeException e) { - // Ignore and continue + // The bean doesn't exist or this subsystem won't start. The reason would have been logged. Ignore and continue. } } diff --git a/source/java/org/alfresco/repo/workflow/WorkflowAdminServiceImpl.java b/source/java/org/alfresco/repo/workflow/WorkflowAdminServiceImpl.java index f1d0159529..79156c5123 100644 --- a/source/java/org/alfresco/repo/workflow/WorkflowAdminServiceImpl.java +++ b/source/java/org/alfresco/repo/workflow/WorkflowAdminServiceImpl.java @@ -43,14 +43,17 @@ public class WorkflowAdminServiceImpl implements WorkflowAdminService private Set enabledEngines = new HashSet(); private Set visibleEngines = new HashSet(); - /** + /** * {@inheritDoc} - */ + */ public boolean isEngineEnabled(String engineId) { return enabledEngines.contains(engineId); } + /** + * {@inheritDoc} + */ public void setEngineEnabled(String engineId, boolean isEnabled) { if(isEnabled) @@ -63,12 +66,17 @@ public class WorkflowAdminServiceImpl implements WorkflowAdminService } } - + /** + * {@inheritDoc} + */ public boolean isEngineVisible(String engineId) { return isEngineEnabled(engineId) && visibleEngines.contains(engineId); } + /** + * {@inheritDoc} + */ public void setEngineVisibility(String engineId, boolean isVisible) { if(isVisible) diff --git a/source/java/org/alfresco/service/cmr/workflow/WorkflowAdminService.java b/source/java/org/alfresco/service/cmr/workflow/WorkflowAdminService.java index b00b58efa9..5e5f7016dd 100644 --- a/source/java/org/alfresco/service/cmr/workflow/WorkflowAdminService.java +++ b/source/java/org/alfresco/service/cmr/workflow/WorkflowAdminService.java @@ -34,7 +34,15 @@ public interface WorkflowAdminService * @return true if the engine id is valid and is enabled */ boolean isEngineEnabled(String engineId); - + + /** + * Enables/disables the engine with the given id. + * + * @param engineId The id of a workflow engine + * @param isEnabled true to enable the engine, false to disable + */ + public void setEngineEnabled(String engineId, boolean isEnabled); + /** * Determines whether the workflow definitions are visible * for the engine with the given id. @@ -46,4 +54,16 @@ public interface WorkflowAdminService * @return true if the definitions are visible */ boolean isEngineVisible(String engineId); + + /** + * Sets the visiblity of workflow definitions + * for the engine with the given id. + * + * NOTE: Workflow definitions can always be retrieved directly + * i.e. via name or id + * + * @param engineId The id of a workflow engine + * @param isVisible true if the definitions are visible + */ + public void setEngineVisibility(String engineId, boolean isVisible); }