Merge of BRANCHES/DEV/4.2_ENT_DEV/ADMIN_CONSOLE2 - Admin Console 46775:47636

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@47742 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Kevin Roast
2013-03-07 11:36:01 +00:00
parent 0831ef655a
commit b86cd5e5b2
8 changed files with 242 additions and 154 deletions

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2005-2010 Alfresco Software Limited. * Copyright (C) 2005-2013 Alfresco Software Limited.
* *
* This file is part of Alfresco * 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.framework.ProxyFactoryBean;
import org.springframework.aop.support.DefaultPointcutAdvisor; import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.factory.NoSuchBeanDefinitionException; 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 * 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()) 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) if (ChainingSubsystemProxyFactory.this.sourceBeanName == null)
{ {
Map<?, ?> beans = ChainingSubsystemProxyFactory.this.applicationContextManager Map<?, ?> beans = context.getBeansOfType(method.getDeclaringClass());
.getApplicationContext(instance).getBeansOfType(method.getDeclaringClass());
Object activeBean = null; Object activeBean = null;
for (Object bean : beans.values()) for (Object bean : beans.values())
{ {
@@ -93,9 +104,7 @@ public class ChainingSubsystemProxyFactory extends ProxyFactoryBean
{ {
try try
{ {
Object bean = ChainingSubsystemProxyFactory.this.applicationContextManager Object bean = context.getBean(ChainingSubsystemProxyFactory.this.sourceBeanName);
.getApplicationContext(instance).getBean(
ChainingSubsystemProxyFactory.this.sourceBeanName);
// Ignore inactive beans // Ignore inactive beans
if (!(bean instanceof ActivateableBean) || ((ActivateableBean) bean).isActive()) if (!(bean instanceof ActivateableBean) || ((ActivateableBean) bean).isActive())
@@ -138,7 +147,7 @@ public class ChainingSubsystemProxyFactory extends ProxyFactoryBean
* (non-Javadoc) * (non-Javadoc)
* @see org.springframework.aop.framework.AdvisedSupport#setInterfaces(java.lang.Class[]) * @see org.springframework.aop.framework.AdvisedSupport#setInterfaces(java.lang.Class[])
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("rawtypes")
@Override @Override
public void setInterfaces(Class[] interfaces) public void setInterfaces(Class[] interfaces)
{ {

View File

@@ -37,7 +37,6 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware; 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.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.ListFactoryBean; import org.springframework.beans.factory.config.ListFactoryBean;
@@ -554,6 +553,9 @@ public class ChildApplicationContextFactory extends AbstractPropertyBackedBean i
/** The child application context. */ /** The child application context. */
private ClassPathXmlApplicationContext applicationContext; private ClassPathXmlApplicationContext applicationContext;
/** Error when we last tried to start. */
private RuntimeException lastStartupError;
/** /**
* Instantiates a new application context state. * Instantiates a new application context state.
* *
@@ -632,6 +634,7 @@ public class ChildApplicationContextFactory extends AbstractPropertyBackedBean i
throw new IllegalStateException("Illegal write to property \"" throw new IllegalStateException("Illegal write to property \""
+ ChildApplicationContextFactory.TYPE_NAME_PROPERTY + "\""); + ChildApplicationContextFactory.TYPE_NAME_PROPERTY + "\"");
} }
this.lastStartupError = null;
Class<?> type = ChildApplicationContextFactory.this.compositePropertyTypes.get(name); Class<?> type = ChildApplicationContextFactory.this.compositePropertyTypes.get(name);
if (type != null) if (type != null)
{ {
@@ -727,14 +730,32 @@ public class ChildApplicationContextFactory extends AbstractPropertyBackedBean i
// properties. // properties.
if (this.applicationContext == null) 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 ChildApplicationContextFactory.logger
.info("Starting '" + getCategory() + "' subsystem, ID: " + getId()); .info("Starting '" + getCategory() + "' subsystem, ID: " + getId());
ClassPathXmlApplicationContext applicationContext = ChildApplicationContextFactory.this.new ChildApplicationContext( ClassPathXmlApplicationContext applicationContext = ChildApplicationContextFactory.this.new ChildApplicationContext(
this.properties, this.compositeProperties); this.properties, this.compositeProperties);
applicationContext.refresh(); try
this.applicationContext = applicationContext; {
ChildApplicationContextFactory.logger.info("Startup of '" + getCategory() + "' subsystem, ID: " applicationContext.refresh();
+ getId() + " complete"); 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;
}
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2005-2010 Alfresco Software Limited. * Copyright (C) 2005-2013 Alfresco Software Limited.
* *
* This file is part of Alfresco * This file is part of Alfresco
* *
@@ -291,9 +291,26 @@ public class DefaultChildApplicationContextManager extends AbstractPropertyBacke
*/ */
public void start() public void start()
{ {
boolean oneSuccess = false;
RuntimeException lastError = null;
for (String instance : getInstanceIds()) 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;
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2005-2010 Alfresco Software Limited. * Copyright (C) 2005-2013 Alfresco Software Limited.
* *
* This file is part of Alfresco * This file is part of Alfresco
* *
@@ -72,9 +72,9 @@ public class SubsystemChainingAuthenticationComponent extends AbstractChainingAu
List<AuthenticationComponent> result = new LinkedList<AuthenticationComponent>(); List<AuthenticationComponent> result = new LinkedList<AuthenticationComponent>();
for (String instance : this.applicationContextManager.getInstanceIds()) for (String instance : this.applicationContextManager.getInstanceIds())
{ {
ApplicationContext context = this.applicationContextManager.getApplicationContext(instance);
try try
{ {
ApplicationContext context = this.applicationContextManager.getApplicationContext(instance);
AuthenticationComponent authenticationComponent = (AuthenticationComponent) context AuthenticationComponent authenticationComponent = (AuthenticationComponent) context
.getBean(sourceBeanName); .getBean(sourceBeanName);
// Only add active authentication components. E.g. we might have an ldap context that is only used for // 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); 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; return result;

View File

@@ -30,7 +30,6 @@ import org.alfresco.repo.management.subsystems.ChildApplicationContextManager;
import org.alfresco.repo.security.authentication.AbstractChainingAuthenticationService; import org.alfresco.repo.security.authentication.AbstractChainingAuthenticationService;
import org.alfresco.service.cmr.security.AuthenticationService; import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.cmr.security.MutableAuthenticationService; import org.alfresco.service.cmr.security.MutableAuthenticationService;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
/** /**
@@ -94,7 +93,16 @@ public class SubsystemChainingAuthenticationService extends AbstractChainingAuth
for (String instance : this.instanceIds) 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); ApplicationContext context = this.contexts.get(instance);
if (context != newContext) if (context != newContext)
{ {
@@ -104,14 +112,16 @@ public class SubsystemChainingAuthenticationService extends AbstractChainingAuth
this.lock.writeLock().lock(); this.lock.writeLock().lock();
haveWriteLock = true; haveWriteLock = true;
} }
newContext = this.applicationContextManager.getApplicationContext(instance);
this.contexts.put(instance, newContext);
try try
{ {
newContext = this.applicationContextManager.getApplicationContext(instance);
this.contexts.put(instance, newContext);
this.sourceBeans.put(instance, newContext.getBean(this.sourceBeanName)); 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); this.sourceBeans.remove(instance);
} }
} }
@@ -178,8 +188,9 @@ public class SubsystemChainingAuthenticationService extends AbstractChainingAuth
AuthenticationService authenticationService = (AuthenticationService) this.sourceBeans.get(instance); 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 // Only add active authentication components. E.g. we might have an ldap context that is only used for
// synchronizing // synchronizing
if (!(authenticationService instanceof ActivateableBean) if (authenticationService != null
|| ((ActivateableBean) authenticationService).isActive()) && (!(authenticationService instanceof ActivateableBean) || ((ActivateableBean) authenticationService)
.isActive()))
{ {
result.add(authenticationService); result.add(authenticationService);

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2005-2012 Alfresco Software Limited. * Copyright (C) 2005-2013 Alfresco Software Limited.
* *
* This file is part of Alfresco * This file is part of Alfresco
* *
@@ -465,133 +465,135 @@ public class ChainingUserRegistrySynchronizer extends AbstractLifecycleBean impl
} }
for (String id : instanceIds) for (String id : instanceIds)
{ {
ApplicationContext context = this.applicationContextManager.getApplicationContext(id); UserRegistry plugin;
try try
{ {
UserRegistry plugin = (UserRegistry) context.getBean(this.sourceBeanName); ApplicationContext context = this.applicationContextManager.getApplicationContext(id);
if (!(plugin instanceof ActivateableBean) || ((ActivateableBean) plugin).isActive()) plugin = (UserRegistry) context.getBean(this.sourceBeanName);
{
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 (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) catch (RuntimeException e)
@@ -664,18 +666,18 @@ public class ChainingUserRegistrySynchronizer extends AbstractLifecycleBean impl
{ {
continue; continue;
} }
ApplicationContext context = this.applicationContextManager.getApplicationContext(id);
try try
{ {
ApplicationContext context = this.applicationContextManager.getApplicationContext(id);
UserRegistry plugin = (UserRegistry) context.getBean(this.sourceBeanName); UserRegistry plugin = (UserRegistry) context.getBean(this.sourceBeanName);
if (!(plugin instanceof ActivateableBean) || ((ActivateableBean) plugin).isActive()) if (!(plugin instanceof ActivateableBean) || ((ActivateableBean) plugin).isActive())
{ {
return plugin.getPersonMappedProperties(); 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.
} }
} }

View File

@@ -43,14 +43,17 @@ public class WorkflowAdminServiceImpl implements WorkflowAdminService
private Set<String> enabledEngines = new HashSet<String>(); private Set<String> enabledEngines = new HashSet<String>();
private Set<String> visibleEngines = new HashSet<String>(); private Set<String> visibleEngines = new HashSet<String>();
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public boolean isEngineEnabled(String engineId) public boolean isEngineEnabled(String engineId)
{ {
return enabledEngines.contains(engineId); return enabledEngines.contains(engineId);
} }
/**
* {@inheritDoc}
*/
public void setEngineEnabled(String engineId, boolean isEnabled) public void setEngineEnabled(String engineId, boolean isEnabled)
{ {
if(isEnabled) if(isEnabled)
@@ -63,12 +66,17 @@ public class WorkflowAdminServiceImpl implements WorkflowAdminService
} }
} }
/**
* {@inheritDoc}
*/
public boolean isEngineVisible(String engineId) public boolean isEngineVisible(String engineId)
{ {
return isEngineEnabled(engineId) && visibleEngines.contains(engineId); return isEngineEnabled(engineId) && visibleEngines.contains(engineId);
} }
/**
* {@inheritDoc}
*/
public void setEngineVisibility(String engineId, boolean isVisible) public void setEngineVisibility(String engineId, boolean isVisible)
{ {
if(isVisible) if(isVisible)

View File

@@ -35,6 +35,14 @@ public interface WorkflowAdminService
*/ */
boolean isEngineEnabled(String engineId); 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 * Determines whether the workflow definitions are visible
* for the engine with the given id. * for the engine with the given id.
@@ -46,4 +54,16 @@ public interface WorkflowAdminService
* @return true if the definitions are visible * @return true if the definitions are visible
*/ */
boolean isEngineVisible(String engineId); 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);
} }