Merged DEV\EXTENSIONS to HEAD

svn merge svn://svn.alfresco.com:3691/alfresco/BRANCHES/DEV/EXTENSIONS@4848 svn://svn.alfresco.com:3691/alfresco/BRANCHES/DEV/EXTENSIONS@4850 .

   Added RegistryService and registryService beans
   Create ConfigurableService and moved the configurableService bean to be a low-level (untransactioned) component


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@4955 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2007-01-29 14:08:52 +00:00
parent 05d2cd1b28
commit 0e3da160a2
6 changed files with 535 additions and 40 deletions

View File

@@ -255,31 +255,10 @@
<!-- Indexing and Search API --> <!-- Indexing and Search API -->
<!-- --> <!-- -->
<bean id="indexerComponent" class="org.springframework.aop.framework.ProxyFactoryBean"> <bean id="indexerComponent" class="org.alfresco.repo.search.IndexerComponent">
<property name="proxyInterfaces"> <property name="indexerAndSearcherFactory">
<value>org.alfresco.repo.search.Indexer</value> <ref bean="indexerAndSearcherFactory" />
</property> </property>
<property name="target">
<bean class="org.alfresco.repo.search.IndexerComponent">
<property name="indexerAndSearcherFactory">
<ref bean="indexerAndSearcherFactory" />
</property>
</bean>
</property>
<!-- use for debugging
<property name="interceptorNames">
<list>
<idref bean="methodCallLogAdvice" />
<idref local="indexerComponent_PerformanceMonitorAdvice" />
</list>
</property>
-->
</bean>
<bean id="indexerComponent_PerformanceMonitorAdvice" class="org.alfresco.util.perf.PerformanceMonitorAdvice">
<constructor-arg>
<value>indexerComponent</value>
</constructor-arg>
</bean> </bean>
<bean id="searchService" class="org.alfresco.repo.search.SearcherComponent"> <bean id="searchService" class="org.alfresco.repo.search.SearcherComponent">
@@ -794,24 +773,32 @@
</bean> </bean>
<!-- Configurable service --> <!-- Configurable service -->
<bean id="configurableService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <bean id="configurableService" class="org.alfresco.repo.configuration.ConfigurableServiceImpl">
<property name="proxyInterfaces"> <property name="nodeService">
<value>org.alfresco.repo.configuration.ConfigurableService</value> <ref bean="nodeService" />
</property> </property>
<property name="transactionManager"> </bean>
<ref bean="transactionManager" />
<!-- Registry service -->
<bean id="registryService" class="org.alfresco.repo.admin.registry.RegistryServiceImpl" init-method="init">
<property name="authenticationComponent">
<ref bean="authenticationComponent" />
</property> </property>
<property name="target"> <property name="namespaceService">
<bean class="org.alfresco.repo.configuration.ConfigurableServiceImpl"> <ref bean="namespaceService" />
<property name="nodeService">
<ref bean="nodeService" />
</property>
</bean>
</property> </property>
<property name="transactionAttributes"> <property name="searchService">
<props> <ref bean="SearchService" />
<prop key="*">${server.transaction.mode.default}</prop> </property>
</props> <property name="nodeService">
<ref bean="NodeService" />
</property>
<!-- Root properties -->
<property name="registryStore">
<value>system://system</value>
</property>
<property name="registryRootPath">
<value>/sys:system-registry</value>
</property> </property>
</bean> </bean>

View File

@@ -1263,4 +1263,61 @@
</property> </property>
</bean> </bean>
<!-- ConfigurableService -->
<bean id="ConfigurableService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.repo.configuration.ConfigurableService</value>
</property>
<property name="target">
<ref bean="configurableService"/>
</property>
<property name="interceptorNames">
<list>
<idref local="ConfigurableService_transaction"/>
</list>
</property>
</bean>
<bean id="ConfigurableService_transaction" class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="transactionAttributes">
<props>
<prop key="is*">${server.transaction.mode.readOnly}</prop>
<prop key="get*">${server.transaction.mode.readOnly}</prop>
<prop key="*">${server.transaction.mode.default}</prop>
</props>
</property>
</bean>
<!-- RegistryService -->
<bean id="RegistryService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.repo.admin.registry.RegistryService</value>
</property>
<property name="target">
<ref bean="registryService"/>
</property>
<property name="interceptorNames">
<list>
<idref local="RegistryService_transaction"/>
</list>
</property>
</bean>
<bean id="RegistryService_transaction" class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="transactionAttributes">
<props>
<prop key="get*">${server.transaction.mode.readOnly}</prop>
<prop key="*">${server.transaction.mode.default}</prop>
</props>
</property>
</bean>
</beans> </beans>

View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) 2007 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.admin.registry;
import java.io.Serializable;
/**
* Interface for service providing access to key-value pairs for storage
* of system-controlled metadata.
*
* @author Derek Hulley
*/
public interface RegistryService
{
/**
* Assign a value to the registry key, which must be of the form <b>/a/b/c</b>.
*
* @param key the registry key path delimited with '/'.
* @param value any value that can be stored in the repository.
*/
void addValue(String key, Serializable value);
/**
* @param key the registry key path delimited with '/'.
* @return Returns the value stored in the key.
*
* @see #addValue(String, Serializable)
*/
Serializable getValue(String key);
}

View File

@@ -0,0 +1,303 @@
/*
* Copyright (C) 2007 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.admin.registry;
import java.io.Serializable;
import java.util.List;
import java.util.StringTokenizer;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.Pair;
import org.alfresco.util.PropertyCheck;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Implementation of registry service to provide generic storage
* and retrieval of system-related metadata.
*
* @author Derek Hulley
*/
public class RegistryServiceImpl implements RegistryService
{
private static Log logger = LogFactory.getLog(RegistryServiceImpl.class);
private AuthenticationComponent authenticationComponent;
private NamespaceService namespaceService;
private NodeService nodeService;
private SearchService searchService;
private StoreRef registryStoreRef;
private String registryRootPath;
public void setAuthenticationComponent(AuthenticationComponent authenticationComponent)
{
this.authenticationComponent = authenticationComponent;
}
public void setNamespaceService(NamespaceService namespaceService)
{
this.namespaceService = namespaceService;
}
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
public void setSearchService(SearchService searchService)
{
this.searchService = searchService;
}
/**
* @param registryStoreRef the store in which the registry root is found
*/
public void setRegistryStoreRef(StoreRef registryStoreRef)
{
this.registryStoreRef = registryStoreRef;
}
/**
* @see #setRegistryStoreRef(StoreRef)
*/
public void setRegistryStore(String registryStore)
{
this.setRegistryStoreRef(new StoreRef(registryStore));
}
/**
* A root path e.g. <b>/sys:systemRegistry</b>
*
* @param registryRootPath the path to the root of the registry
*/
public void setRegistryRootPath(String registryRootPath)
{
this.registryRootPath = registryRootPath;
}
public void init()
{
// Check the properties
PropertyCheck.mandatory(this, "authenticationComponent", authenticationComponent);
PropertyCheck.mandatory(this, "namespaceService", namespaceService);
PropertyCheck.mandatory(this, "nodeService", nodeService);
PropertyCheck.mandatory(this, "registryRootPath", searchService);
PropertyCheck.mandatory(this, "registryStore", registryStoreRef);
PropertyCheck.mandatory(this, "registryRootPath", registryRootPath);
}
private NodeRef getRegistryRootNodeRef()
{
NodeRef registryRootNodeRef = null;
// Ensure that the registry root node is present
ResultSet rs = searchService.query(registryStoreRef, SearchService.LANGUAGE_XPATH, registryRootPath);
if (rs.length() == 0)
{
throw new AlfrescoRuntimeException(
"Registry root not present: \n" +
" Store: " + registryStoreRef + "\n" +
" Path: " + registryRootPath);
}
else if (rs.length() > 1)
{
throw new AlfrescoRuntimeException(
"Registry root path has multiple targets: \n" +
" Store: " + registryStoreRef + "\n" +
" Path: " + registryRootPath);
}
else
{
registryRootNodeRef = rs.getNodeRef(0);
}
// Check the root
QName typeQName = nodeService.getType(registryRootNodeRef);
if (!typeQName.equals(ContentModel.TYPE_CONTAINER))
{
throw new AlfrescoRuntimeException(
"Registry root is not of type " + ContentModel.TYPE_CONTAINER + ": \n" +
" Node: " + registryRootNodeRef + "\n" +
" Type: " + typeQName);
}
// Done
if (logger.isDebugEnabled())
{
logger.debug(
"Found root for registry: \n" +
" Store: " + registryStoreRef + "\n" +
" Path : " + registryRootPath + "\n" +
" Root: " + registryRootNodeRef);
}
return registryRootNodeRef;
}
/**
* @return Returns a pair representing the node path and the property name
*/
private Pair<String, String> splitKey(String key)
{
int index = key.lastIndexOf('/');
Pair<String, String> result = null;
if (index < 0) // It is just a property
{
result = new Pair<String, String>("/", key);
}
else
{
String propertyName = key.substring(index + 1, key.length());
if (propertyName.length() == 0)
{
throw new IllegalArgumentException("The registry key is invalid: " + key);
}
result = new Pair<String, String>(key.substring(0, index), propertyName);
}
// done
return result;
}
/**
* @return Returns the node and property name represented by the key or <tt>null</tt>
* if it doesn't exist and was not allowed to be created
*/
private Pair<NodeRef, QName> getPath(String key, boolean create)
{
// Get the root
NodeRef currentNodeRef = getRegistryRootNodeRef();
// Split the key
Pair<String, String> keyPair = splitKey(key);
// Parse the key
StringTokenizer tokenizer = new StringTokenizer(keyPair.getFirst(), "/");
// Find the node and property to put the value
while (tokenizer.hasMoreTokens())
{
String token = tokenizer.nextToken();
String name = QName.createValidLocalName(token);
QName qname = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, name);
// Find the node
List<ChildAssociationRef> childAssocRefs = nodeService.getChildAssocs(
currentNodeRef,
ContentModel.ASSOC_CHILDREN,
qname);
int size = childAssocRefs.size();
if (size == 0) // Found nothing with that path
{
if (create) // Must create the path
{
// Create the node
currentNodeRef = nodeService.createNode(
currentNodeRef,
ContentModel.ASSOC_CHILDREN,
qname,
ContentModel.TYPE_CONTAINER).getChildRef();
}
else
{
// There is no node and we are not allowed to create it
currentNodeRef = null;
break;
}
}
else // Found some results for that path
{
if (size > 1 && create) // More than one association by that name
{
// Too many, so trim it down
boolean first = true;
for (ChildAssociationRef assocRef : childAssocRefs)
{
if (first)
{
first = false;
continue;
}
// Remove excess assocs
nodeService.removeChildAssociation(assocRef);
}
}
// Use the first one
currentNodeRef = childAssocRefs.get(0).getChildRef();
}
}
// Create the result
QName propertyQName = QName.createQName(
NamespaceService.SYSTEM_MODEL_1_0_URI,
QName.createValidLocalName(keyPair.getSecond()));
Pair<NodeRef, QName> resultPair = new Pair<NodeRef, QName>(currentNodeRef, propertyQName);
// done
if (logger.isDebugEnabled())
{
logger.debug("Converted registry key: \n" +
" key pair: " + keyPair + "\n" +
" result: " + resultPair);
}
if (resultPair.getFirst() == null)
{
return null;
}
else
{
return resultPair;
}
}
/**
* @inheritDoc
*/
public void addValue(String key, Serializable value)
{
// Get the path, with creation support
Pair<NodeRef, QName> keyPair = getPath(key, true);
// We know that the node exists, so just set the value
nodeService.setProperty(keyPair.getFirst(), keyPair.getSecond(), value);
// Done
if (logger.isDebugEnabled())
{
logger.debug("Added value to registry: \n" +
" Key: " + key + "\n" +
" Value: " + value);
}
}
public Serializable getValue(String key)
{
// Get the path, without creating
Pair<NodeRef, QName> keyPair = getPath(key, false);
Serializable value = null;
if (keyPair != null)
{
value = nodeService.getProperty(keyPair.getFirst(), keyPair.getSecond());
}
// Done
if (logger.isDebugEnabled())
{
logger.debug("Retrieved value from registry: \n" +
" Key: " + key + "\n" +
" Value: " + value);
}
return value;
}
}

View File

@@ -0,0 +1,104 @@
/*
* Copyright (C) 2007 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.admin.registry;
import junit.framework.TestCase;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.util.ApplicationContextHelper;
import org.springframework.context.ApplicationContext;
/**
* @see org.alfresco.repo.admin.registry.RegistryService
*
* @author Derek Hulley
*/
public class RegistryServiceImplTest extends TestCase
{
private static ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
private AuthenticationComponent authenticationComponent;
private RegistryService registryService;
@Override
protected void setUp() throws Exception
{
authenticationComponent = (AuthenticationComponent) ctx.getBean("AuthenticationComponent");
registryService = (RegistryService) ctx.getBean("RegistryService");
// Run as admin
authenticationComponent.setSystemUserAsCurrentUser();
}
@Override
protected void tearDown() throws Exception
{
// Clear authentication
try
{
authenticationComponent.clearCurrentSecurityContext();
}
catch (Throwable e)
{
e.printStackTrace();
}
}
public void testSetup() throws Exception
{
}
private static final Long VALUE_ONE = 1L;
private static final Long VALUE_TWO = 2L;
private static final Long VALUE_THREE = 3L;
private static final String KEY_A_B_C_1 = "/a/b/c/1";
private static final String KEY_A_B_C_2 = "/a/b/c/2";
private static final String KEY_A_B_C_3 = "/a/b/c/3";
private static final String KEY_A_B_C_D_1 = "/a/b/c/d/1";
private static final String KEY_A_B_C_D_2 = "/a/b/c/d/2";
private static final String KEY_A_B_C_D_3 = "/a/b/c/d/3";
private static final String KEY_SPECIAL = "/me & you/ whatever";
/**
* General writing and reading back.
*/
public void testProperUsage() throws Exception
{
registryService.addValue(KEY_A_B_C_1, VALUE_ONE);
registryService.addValue(KEY_A_B_C_2, VALUE_TWO);
registryService.addValue(KEY_A_B_C_3, VALUE_THREE);
registryService.addValue(KEY_A_B_C_D_1, VALUE_ONE);
registryService.addValue(KEY_A_B_C_D_2, VALUE_TWO);
registryService.addValue(KEY_A_B_C_D_3, VALUE_THREE);
assertEquals("Incorrect value from service registry", VALUE_ONE, registryService.getValue(KEY_A_B_C_1));
assertEquals("Incorrect value from service registry", VALUE_TWO, registryService.getValue(KEY_A_B_C_2));
assertEquals("Incorrect value from service registry", VALUE_THREE, registryService.getValue(KEY_A_B_C_3));
assertEquals("Incorrect value from service registry", VALUE_ONE, registryService.getValue(KEY_A_B_C_D_1));
assertEquals("Incorrect value from service registry", VALUE_TWO, registryService.getValue(KEY_A_B_C_D_2));
assertEquals("Incorrect value from service registry", VALUE_THREE, registryService.getValue(KEY_A_B_C_D_3));
assertNull("Missing key should return null value", registryService.getValue("/a/b/c/0"));
assertNull("Missing key should return null value", registryService.getValue("/a/b/c/d/0"));
assertNull("Missing key should return null value", registryService.getValue("/x/y/z/0"));
}
public void testSpecialCharacters()
{
registryService.addValue(KEY_SPECIAL, VALUE_THREE);
assertEquals("Incorrect value for special key", VALUE_THREE, registryService.getValue(KEY_SPECIAL));
}
}

View File

@@ -113,7 +113,7 @@ public class BaseRuleTest extends BaseSpringTest
this.ruleService = (RuleService) this.applicationContext this.ruleService = (RuleService) this.applicationContext
.getBean("ruleService"); .getBean("ruleService");
this.configService = (ConfigurableService)this.applicationContext this.configService = (ConfigurableService)this.applicationContext
.getBean("configurableService"); .getBean("ConfigurableService");
this.actionService = (ActionService)this.applicationContext.getBean("actionService"); this.actionService = (ActionService)this.applicationContext.getBean("actionService");
this.transactionService = (TransactionService)this.applicationContext.getBean("transactionComponent"); this.transactionService = (TransactionService)this.applicationContext.getBean("transactionComponent");
this.authenticationComponent = (AuthenticationComponent)this.applicationContext.getBean("authenticationComponent"); this.authenticationComponent = (AuthenticationComponent)this.applicationContext.getBean("authenticationComponent");