diff --git a/repository/src/main/java/org/alfresco/repo/dictionary/DictionaryRepositoryBootstrap.java b/repository/src/main/java/org/alfresco/repo/dictionary/DictionaryRepositoryBootstrap.java index 654939cdf4..57c3416ad4 100644 --- a/repository/src/main/java/org/alfresco/repo/dictionary/DictionaryRepositoryBootstrap.java +++ b/repository/src/main/java/org/alfresco/repo/dictionary/DictionaryRepositoryBootstrap.java @@ -415,12 +415,13 @@ implements TenantDeployer, DictionaryListener, /*TenantDictionaryListener, */Mes for (NodeRef messageResource : nodeRefs) { - String resourceName = (String) nodeService.getProperty(messageResource, ContentModel.PROP_NAME); - - String bundleBaseName = messageService.getBaseBundleName(resourceName); + String messageResourcePath = nodeService.getPath(messageResource).toPrefixString(namespaceService); + String bundleBasePrefixedName = messageResourcePath.substring(messageResourcePath.lastIndexOf("/")); + String bundleBaseName = messageService.getBaseBundleName(bundleBasePrefixedName); if (!resourceBundleBaseNames.contains(bundleBaseName)) { + messageService.registerResourceBundle(storeRef.toString() + repositoryLocation.getPath() + bundleBaseName); resourceBundleBaseNames.add(bundleBaseName); } } diff --git a/repository/src/test/java/org/alfresco/repo/admin/RepoAdminServiceImplTest.java b/repository/src/test/java/org/alfresco/repo/admin/RepoAdminServiceImplTest.java index 355eccd046..4d4fb2f841 100644 --- a/repository/src/test/java/org/alfresco/repo/admin/RepoAdminServiceImplTest.java +++ b/repository/src/test/java/org/alfresco/repo/admin/RepoAdminServiceImplTest.java @@ -31,17 +31,18 @@ import java.io.PrintWriter; import java.io.Serializable; import java.io.StringWriter; import java.io.UnsupportedEncodingException; +import java.util.Collections; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; -import junit.framework.TestCase; - import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.model.ContentModel; import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.dictionary.DictionaryDAO; import org.alfresco.repo.dictionary.NamespaceDAO; +import org.alfresco.repo.i18n.MessageService; import org.alfresco.repo.node.db.DbNodeServiceImpl; import org.alfresco.repo.policy.BehaviourFilter; import org.alfresco.repo.security.authentication.AuthenticationUtil; @@ -50,6 +51,7 @@ import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransacti import org.alfresco.service.cmr.admin.RepoAdminService; import org.alfresco.service.cmr.dictionary.ClassDefinition; import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.NodeRef; @@ -67,6 +69,8 @@ import org.apache.commons.logging.LogFactory; import org.junit.experimental.categories.Category; import org.springframework.context.ApplicationContext; +import junit.framework.TestCase; + /** * @see RepoAdminServiceImpl * @@ -88,6 +92,7 @@ public class RepoAdminServiceImplTest extends TestCase private NamespaceService namespaceService; private BehaviourFilter behaviourFilter; private DictionaryDAO dictionaryDAO; + private MessageService messageService; final String modelPrefix = "model-"; final static String MKR = "{MKR}"; @@ -140,6 +145,7 @@ public class RepoAdminServiceImplTest extends TestCase namespaceService = (NamespaceService) ctx.getBean("NamespaceService"); behaviourFilter = (BehaviourFilter)ctx.getBean("policyBehaviourFilter"); dictionaryDAO = (DictionaryDAO) ctx.getBean("dictionaryDAO"); + messageService = (MessageService) ctx.getBean("MessageService"); DbNodeServiceImpl dbNodeService = (DbNodeServiceImpl)ctx.getBean("dbNodeService"); dbNodeService.setEnableTimestampPropagation(false); @@ -865,8 +871,182 @@ public class RepoAdminServiceImplTest extends TestCase } } } - - // - // TODO - Test custom message management - // + + // Test deploy bundle from classpath + public void testDeployMessageBundleFromClasspath() throws Exception + { + String bundleBaseName = "mycustommessages"; + String resourceClasspath = "alfresco/extension/messages/" + bundleBaseName; + + final String message_key = "mycustommessages.key1"; + final String message_value_default = "This is a custom message"; + final String message_value_fr = "Ceci est un message personnalis\\u00e9"; + final String message_value_de = "Dies ist eine benutzerdefinierte Nachricht"; + + // Undeploy the bundle + if (repoAdminService.getMessageBundles().contains(bundleBaseName)) + { + repoAdminService.undeployMessageBundle(bundleBaseName); + } + + // Verify the custom bundle is registered + assertFalse("The custom bundle should not be deployed", repoAdminService.getMessageBundles().contains(bundleBaseName)); + + // Depoly the message bundle + repoAdminService.deployMessageBundle(resourceClasspath); + + // Reload the messages + repoAdminService.reloadMessageBundle(bundleBaseName); + + // Verify the custom bundle is registered + assertTrue("The custom bundle should be deployed", repoAdminService.getMessageBundles().contains(bundleBaseName)); + + // Verify we have the messages for each locale + AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); + + assertMessageValue("Cannot retrieve default message value", message_value_default, message_key, Locale.getDefault()); + assertMessageValue("Cannot retrieve french message value", message_value_fr, message_key, Locale.FRANCE); + assertMessageValue("Cannot retrieve german message value", message_value_de, message_key, Locale.GERMANY); + + // Test deploy a non existent bundle + try + { + repoAdminService.deployMessageBundle("alfresco/extension/messages/inexistentbundle"); + fail("Bundle was not supposed to be deployed"); + } + catch (Exception e) + { + // Expected to fail + } + + } + + // Test deploy bundle from repo and reload bundles + public void testDeployMessageBundleFromRepo() throws Exception + { + final String bundleBaseName = "repoBundle"; + final String message_key = "repoBundle.key1"; + final String message_value = "Value 1"; + final String message_value_fr = "Value FR"; + final String message_value_de = "Value DE"; + final String message_value_new = "New Value 1"; + + // Set location + NodeRef rootNodeRef = nodeService.getRootNode(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE); + List nodeRefs = searchService.selectNodes(rootNodeRef, "/app:company_home/app:dictionary/app:messages", null, + namespaceService, false); + assertEquals(1, nodeRefs.size()); + NodeRef messagesNodeRef = nodeRefs.get(0); + + // Clear messages of this bundle if they exist and are registered + clearRepoBundles(messagesNodeRef); + + assertEquals(0, repoAdminService.getMessageBundles().size()); + + // Create and upload the message files + NodeRef messageNode_default = createMessagesNodeWithSingleKey(messagesNodeRef, bundleBaseName, message_key, null, + message_value); + createMessagesNodeWithSingleKey(messagesNodeRef, bundleBaseName, message_key, Locale.FRANCE.toString(), message_value_fr); + createMessagesNodeWithSingleKey(messagesNodeRef, bundleBaseName, message_key, Locale.GERMANY.toString(), + message_value_de); + + // Reload the messages + repoAdminService.reloadMessageBundle(bundleBaseName); + + // Verify we have the messages for each locale + AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); + + assertMessageValue("Cannot retrieve default message value", message_value, message_key, Locale.getDefault()); + assertMessageValue("Cannot retrieve french message value", message_value_fr, message_key, Locale.FRANCE); + assertMessageValue("Cannot retrieve german message value", message_value_de, message_key, Locale.GERMANY); + + // Change the values + putContentInMessageNode(messageNode_default, message_key, message_value_new); + + // Verify we still have the old value + assertMessageValue("Unexpected change of message value", message_value, message_key, Locale.getDefault()); + + // Reload the messages + repoAdminService.reloadMessageBundle(bundleBaseName); + + // Verify new values + assertMessageValue("Change of message value not reflected", message_value_new, message_key, Locale.getDefault()); + } + + /** + * Create messages node + */ + private NodeRef createMessagesNodeWithSingleKey(NodeRef parentNode, String bundleName, String key, String locale, + String localeValue) + { + String msg_extension = ".properties"; + String filename = bundleName + msg_extension; + String messageValue = localeValue; + + if (locale != null) + { + filename = bundleName + "_" + locale + msg_extension; + } + // Create a model node + NodeRef messageNode = this.nodeService.createNode( + parentNode, + ContentModel.ASSOC_CONTAINS, + QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, filename), + ContentModel.TYPE_CONTENT, + Collections. singletonMap(ContentModel.PROP_NAME, filename) + ).getChildRef(); + + putContentInMessageNode(messageNode, key, messageValue); + + return messageNode; + + } + + /** + * Write content of message node + */ + private void putContentInMessageNode(NodeRef nodeRef, String key, String value) + { + ContentWriter contentWriter = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true); + contentWriter.setEncoding("UTF-8"); + contentWriter.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); + String messagesString = key + "=" + value; + contentWriter.putContent(messagesString); + } + + /** + * Clear Repo Bundle + */ + private void clearRepoBundles(NodeRef parentNode) + { + List repoBundles = repoAdminService.getMessageBundles(); + for (String repoBundle : repoBundles) + { + repoAdminService.undeployMessageBundle(repoBundle); + } + + List messageNodes = nodeService.getChildAssocs(parentNode); + for (ChildAssociationRef messageChildRef : messageNodes) + { + NodeRef messageNode = messageChildRef.getChildRef(); + nodeService.deleteNode(messageNode); + } + } + + /** + * Clear Repo Bundle + */ + private void assertMessageValue(String errorMessage, String expectedValue, String key, Locale locale) + { + transactionService.getRetryingTransactionHelper() + .doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() + { + public Void execute() throws Throwable + { + assertEquals(errorMessage, expectedValue, messageService.getMessage(key, locale)); + return null; + } + }); + } + } diff --git a/repository/src/test/java/org/alfresco/repo/dictionary/DictionaryRepositoryBootstrapTest.java b/repository/src/test/java/org/alfresco/repo/dictionary/DictionaryRepositoryBootstrapTest.java index 1fa78443b2..5405f853f4 100644 --- a/repository/src/test/java/org/alfresco/repo/dictionary/DictionaryRepositoryBootstrapTest.java +++ b/repository/src/test/java/org/alfresco/repo/dictionary/DictionaryRepositoryBootstrapTest.java @@ -25,9 +25,14 @@ */ package org.alfresco.repo.dictionary; +import java.io.Serializable; import java.text.MessageFormat; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.Locale; + +import javax.transaction.UserTransaction; import org.alfresco.model.ContentModel; import org.alfresco.repo.content.MimetypeMap; @@ -53,8 +58,6 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.experimental.categories.Category; - -import javax.transaction.UserTransaction; import org.springframework.transaction.annotation.Transactional; @Category(BaseSpringTestsCategory.class) @@ -94,6 +97,14 @@ public class DictionaryRepositoryBootstrapTest extends BaseSpringTest ""; + public static final String MESSAGES_KEY = "my_bootstrap_test"; + public static final String MESSAGES_VALUE = "My Message"; + public static final String MESSAGES_VALUE_FR = "Mon message"; + public static final String FOLDERNAME_MODELS = "models"; + public static final String FOLDERNAME_MESSAGES = "messages"; + public static final String BUNDLENAME_MESSAGES = "testBootstap"; + public static final String FILENAME_MESSAGES_EXT = ".properties"; + /** Behaviour filter */ private BehaviourFilter behaviourFilter; @@ -123,7 +134,8 @@ public class DictionaryRepositoryBootstrapTest extends BaseSpringTest private UserTransaction txn; private StoreRef storeRef; - private NodeRef rootNodeRef; + private NodeRef rootModelsNodeRef; + private NodeRef rootMessagesNodeRef; @Before public void before() throws Exception @@ -151,7 +163,17 @@ public class DictionaryRepositoryBootstrapTest extends BaseSpringTest // Create the store and get the root node this.storeRef = this.nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, "Test_" + System.currentTimeMillis()); - this.rootNodeRef = this.nodeService.getRootNode(this.storeRef); + + NodeRef rootNodeRef = this.nodeService.getRootNode(this.storeRef); + this.rootModelsNodeRef = this.nodeService + .createNode(rootNodeRef, ContentModel.ASSOC_CHILDREN, + QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, FOLDERNAME_MODELS), ContentModel.TYPE_FOLDER) + .getChildRef(); + + this.rootMessagesNodeRef = this.nodeService + .createNode(rootNodeRef, ContentModel.ASSOC_CHILDREN, + QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, FOLDERNAME_MESSAGES), ContentModel.TYPE_FOLDER) + .getChildRef(); txn.commit(); @@ -167,18 +189,20 @@ public class DictionaryRepositoryBootstrapTest extends BaseSpringTest this.bootstrap.setNamespaceService(this.namespaceService); this.bootstrap.setMessageService(this.messageService); this.bootstrap.setPolicyComponent(this.policyComponent); - - RepositoryLocation location = new RepositoryLocation(); - location.setStoreProtocol(this.storeRef.getProtocol()); - location.setStoreId(this.storeRef.getIdentifier()); - location.setQueryLanguage(RepositoryLocation.LANGUAGE_PATH); - // NOTE: we are not setting the path for now .. in doing so we are searching the root node only - - List locations = new ArrayList(); - locations.add(location); - - this.bootstrap.setRepositoryModelsLocations(locations); - + + RepositoryLocation modelsLocation = new RepositoryLocation(this.storeRef, + this.nodeService.getPath(rootModelsNodeRef).toPrefixString(namespaceService), RepositoryLocation.LANGUAGE_PATH); + RepositoryLocation messagesLocation = new RepositoryLocation(this.storeRef, + this.nodeService.getPath(rootMessagesNodeRef).toPrefixString(namespaceService), RepositoryLocation.LANGUAGE_PATH); + + List modelsLocations = new ArrayList(); + modelsLocations.add(modelsLocation); + List messagesLocations = new ArrayList(); + messagesLocations.add(messagesLocation); + + this.bootstrap.setRepositoryModelsLocations(modelsLocations); + this.bootstrap.setRepositoryMessagesLocations(messagesLocations); + // register with dictionary service this.bootstrap.register(); txn.commit(); @@ -224,7 +248,15 @@ public class DictionaryRepositoryBootstrapTest extends BaseSpringTest "Test model one", "base1", "prop1"); - + + // Create a message file for the default locale + NodeRef messageNodeDefaultLoc = createMessagesNode(null, null); + // Create a message file for the french locale + createMessagesNode(Locale.FRANCE.toString(), MESSAGES_VALUE_FR); + // Construct baseBundleName for validation + String baseBundleName = storeRef.toString() + + messageService.getBaseBundleName(nodeService.getPath(messageNodeDefaultLoc).toPrefixString(namespaceService)); + // Check that the model is not in the dictionary yet try { @@ -251,6 +283,12 @@ public class DictionaryRepositoryBootstrapTest extends BaseSpringTest QName.createQName("http://www.alfresco.org/model/test3DictionaryBootstrapFromRepo/1.0", "testModel3")); assertNotNull(modelDefinition3); + // Check if the messages were registered correctly + assertTrue("The message bundle should be registered", messageService.getRegisteredBundles().contains(baseBundleName)); + assertEquals("The default message value is not as expected", MESSAGES_VALUE, messageService.getMessage(MESSAGES_KEY)); + assertEquals("The message value in french is not as expected", MESSAGES_VALUE_FR, + messageService.getMessage(MESSAGES_KEY, Locale.FRANCE)); + txn.commit(); } @@ -277,7 +315,7 @@ public class DictionaryRepositoryBootstrapTest extends BaseSpringTest { // Create a model node NodeRef model = this.nodeService.createNode( - this.rootNodeRef, + this.rootModelsNodeRef, ContentModel.ASSOC_CHILDREN, QName.createQName("{test}models"), ContentModel.TYPE_DICTIONARY_MODEL).getChildRef(); @@ -300,6 +338,39 @@ public class DictionaryRepositoryBootstrapTest extends BaseSpringTest return model; } + /** + * Create messages node + * + * @return NodeRef + */ + private NodeRef createMessagesNode(String locale, String localeValue) + { + String filename = BUNDLENAME_MESSAGES + FILENAME_MESSAGES_EXT; + String messageValue = MESSAGES_VALUE; + + if (locale != null) + { + filename = BUNDLENAME_MESSAGES + "_" + locale + FILENAME_MESSAGES_EXT; + messageValue = localeValue; + } + // Create a model node + NodeRef messageNode = this.nodeService.createNode( + this.rootMessagesNodeRef, + ContentModel.ASSOC_CHILDREN, + QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, filename), + ContentModel.TYPE_CONTENT, + Collections. singletonMap(ContentModel.PROP_NAME, filename) + ).getChildRef(); + + ContentWriter contentWriter = this.contentService.getWriter(messageNode, ContentModel.PROP_CONTENT, true); + contentWriter.setEncoding("UTF-8"); + contentWriter.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); + String messagesString = MESSAGES_KEY + "=" + messageValue; + contentWriter.putContent(messagesString); + + return messageNode; + } + /** * * Gets the model string diff --git a/repository/src/test/resources/alfresco/extension/messages/mycustommessages.properties b/repository/src/test/resources/alfresco/extension/messages/mycustommessages.properties new file mode 100644 index 0000000000..d76451ec52 --- /dev/null +++ b/repository/src/test/resources/alfresco/extension/messages/mycustommessages.properties @@ -0,0 +1 @@ +mycustommessages.key1=This is a custom message \ No newline at end of file diff --git a/repository/src/test/resources/alfresco/extension/messages/mycustommessages_de_DE.properties b/repository/src/test/resources/alfresco/extension/messages/mycustommessages_de_DE.properties new file mode 100644 index 0000000000..79144943b8 --- /dev/null +++ b/repository/src/test/resources/alfresco/extension/messages/mycustommessages_de_DE.properties @@ -0,0 +1 @@ +mycustommessages.key1=Dies ist eine benutzerdefinierte Nachricht \ No newline at end of file diff --git a/repository/src/test/resources/alfresco/extension/messages/mycustommessages_fr_FR.properties b/repository/src/test/resources/alfresco/extension/messages/mycustommessages_fr_FR.properties new file mode 100644 index 0000000000..e47e1023ae --- /dev/null +++ b/repository/src/test/resources/alfresco/extension/messages/mycustommessages_fr_FR.properties @@ -0,0 +1 @@ +mycustommessages.key1=Ceci est un message personnalis\u00e9 \ No newline at end of file