Java tutorial
/* * #%L * Alfresco Repository * %% * Copyright (C) 2005 - 2016 Alfresco Software Limited * %% * This file is part of the Alfresco software. * If the software was purchased under a paid Alfresco license, the terms of * the paid license agreement will prevail. Otherwise, the software is * provided under the following open source license terms: * * Alfresco is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Alfresco 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. * #L% */ package org.alfresco.repo.admin; import java.io.InputStream; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.model.ApplicationModel; import org.alfresco.model.ContentModel; import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.dictionary.DictionaryDAO; import org.alfresco.repo.dictionary.M2Model; import org.alfresco.repo.dictionary.RepositoryLocation; import org.alfresco.repo.i18n.MessageService; import org.alfresco.repo.i18n.MessageServiceImpl; import org.alfresco.repo.usage.RepoUsageComponent; import org.alfresco.service.cmr.admin.RepoAdminService; import org.alfresco.service.cmr.admin.RepoUsage; import org.alfresco.service.cmr.admin.RepoUsage.UsageType; import org.alfresco.service.cmr.admin.RepoUsageStatus; import org.alfresco.service.cmr.dictionary.DictionaryException; import org.alfresco.service.cmr.dictionary.ModelDefinition; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.DuplicateChildNodeNameException; import org.alfresco.service.cmr.repository.InvalidNodeRefException; 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.SearchService; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.dao.ConcurrencyFailureException; import org.springframework.extensions.surf.util.I18NUtil; import org.springframework.extensions.surf.util.ParameterCheck; /** * Repository Admin Service Implementation. * <p> * @see RepoAdminService interface */ public class RepoAdminServiceImpl implements RepoAdminService { // Logging support private static Log logger = LogFactory.getLog(RepoAdminServiceImpl.class); // dependencies private DictionaryDAO dictionaryDAO; private SearchService searchService; private NodeService nodeService; private ContentService contentService; private NamespaceService namespaceService; private MessageService messageService; private RepoUsageComponent repoUsageComponent; private RepositoryLocation repoModelsLocation; private RepositoryLocation repoMessagesLocation; public final static String CRITERIA_ALL = "/*"; // immediate children only public final static String defaultSubtypeOfDictionaryModel = "subtypeOf('cm:dictionaryModel')"; public final static String defaultSubtypeOfContent = "subtypeOf('cm:content')"; private static final String MODELS_LOCATION_NOT_FOUND = "repoadmin_service.models_location_not_found"; private static final String MODELS_LOCATION_MULTIPLE_FOUND = "repoadmin_service.models_location_multiple_found"; private static final String MODEL_EXISTS = "repoadmin_service.model_exists"; private static final String MODEL_DEPLOYMENT_FAILED = "repoadmin_service.model_deployment_failed"; private static final String MODEL_UNDEPLOYMENT_FAILED = "repoadmin_service.model_undeployment_failed"; private static final String MODEL_ACTIVATION_FAILED = "repoadmin_service.model_activation_failed"; private static final String MODEL_DEACTIVATION_FAILED = "repoadmin_service.model_deactivation_failed"; private static final String MODEL_NOT_FOUND = "repoadmin_service.model_not_found"; private static final String MODELS_MULTIPLE_FOUND = "repoadmin_service.models_multiple_found"; private static final String MODEL_ALREADY_ACTIVATED = "repoadmin_service.model_already_activated"; private static final String MODEL_ALREADY_DEACTIVATED = "repoadmin_service.model_already_deactivated"; private static final String MODEL_NO_LONGER_EXISTS = "repoadmin_service.model_no_longer_exists"; private static final String MSG_RESOURCES_NOT_FOUND = "repoadmin_service.msg_resource_not_found"; private static final String MSG_RESOURCES_DEPLOYMENT_FAILED = "repoadmin_service.msg_resource_deployment_failed"; private static final String MESSAGES_LOCATION_NOT_FOUND = "repoadmin_service.messages_location_not_found"; private static final String MESSAGES_LOCATION_MULTIPLE_FOUND = "repoadmin_service.messages_location_multiple_found"; private static final String MSG_RESOURCES_UNDEPLOYMENT_FAILED = "repoadmin_service.msg_resource_undeployment_failed"; private static final String MSG_RESOURCES_RELOAD_FAILED = "repoadmin_service.msg_resource_reload_failed"; private static final String MSG_MISSING_BUNDLE_BASE_NAME = "repoadmin_service.msg_missing_bundle_base_name"; private static final String MSG_BASE_NAME_CONTAIN_UNDERSCORE = "repoadmin_service.msg_base_name_contain_underscore"; private static final String MSG_BASE_NAME_CONTAIN_PERIOD = "repoadmin_service.msg_base_name_contain_period"; public void setDictionaryDAO(DictionaryDAO dictionaryDAO) { this.dictionaryDAO = dictionaryDAO; } public void setSearchService(SearchService searchService) { this.searchService = searchService; } public void setNodeService(NodeService nodeService) { this.nodeService = nodeService; } public void setContentService(ContentService contentService) { this.contentService = contentService; } public void setNamespaceService(NamespaceService namespaceService) { this.namespaceService = namespaceService; } public void setMessageService(MessageService messageService) { this.messageService = messageService; } public void setRepoUsageComponent(RepoUsageComponent repoUsageComponent) { this.repoUsageComponent = repoUsageComponent; } public void setRepositoryModelsLocation(RepositoryLocation repoModelsLocation) { this.repoModelsLocation = repoModelsLocation; } public void setRepositoryMessagesLocation(RepositoryLocation repoMessagesLocation) { this.repoMessagesLocation = repoMessagesLocation; } public List<RepoModelDefinition> getModels() { StoreRef storeRef = repoModelsLocation.getStoreRef(); NodeRef rootNode = nodeService.getRootNode(storeRef); List<RepoModelDefinition> modelsInRepo = new ArrayList<RepoModelDefinition>(); Collection<QName> models = dictionaryDAO.getModels(true); List<String> dictionaryModels = new ArrayList<String>(); for (QName model : models) { dictionaryModels.add(model.toPrefixString()); } List<NodeRef> nodeRefs = searchService.selectNodes(rootNode, repoModelsLocation.getPath() + CRITERIA_ALL + "[" + defaultSubtypeOfDictionaryModel + "]", null, namespaceService, false); if (nodeRefs.size() > 0) { for (NodeRef nodeRef : nodeRefs) { String modelFileName = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME); String repoVersion = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_VERSION_LABEL); try { String modelName = null; ContentReader cr = contentService.getReader(nodeRef, ContentModel.TYPE_CONTENT); if (cr != null) { InputStream is = cr.getContentInputStream(); try { M2Model model = M2Model.createModel(is); modelName = model.getName(); } finally { is.close(); } } // check against models loaded in dictionary and give warning if not found if (dictionaryModels.contains(modelName)) { // note: uses dictionary model cache, rather than getting content from repo and re-compiling modelsInRepo.add(new RepoModelDefinition(modelFileName, repoVersion, dictionaryDAO.getModel(QName.createQName(modelName, namespaceService)), true)); } else { modelsInRepo.add(new RepoModelDefinition(modelFileName, repoVersion, null, false)); } } catch (Throwable t) { logger.warn("Skip model: " + modelFileName + " (" + t.getMessage() + ")"); } } } return modelsInRepo; } @Override public NodeRef deployModel(InputStream modelStream, String modelFileName, boolean activate) { try { // Check that all the passed values are not null ParameterCheck.mandatory("ModelStream", modelStream); ParameterCheck.mandatoryString("ModelFileName", modelFileName); Map<QName, Serializable> contentProps = new HashMap<QName, Serializable>(); contentProps.put(ContentModel.PROP_NAME, modelFileName); StoreRef storeRef = repoModelsLocation.getStoreRef(); NodeRef rootNode = nodeService.getRootNode(storeRef); List<NodeRef> nodeRefs = searchService.selectNodes(rootNode, repoModelsLocation.getPath(), null, namespaceService, false); if (nodeRefs.size() == 0) { throw new AlfrescoRuntimeException(MODELS_LOCATION_NOT_FOUND, new Object[] { repoModelsLocation.getPath() }); } else if (nodeRefs.size() > 1) { // unexpected: should not find multiple nodes with same name throw new AlfrescoRuntimeException(MODELS_LOCATION_MULTIPLE_FOUND, new Object[] { repoModelsLocation.getPath() }); } NodeRef customModelsSpaceNodeRef = nodeRefs.get(0); nodeRefs = searchService.selectNodes(customModelsSpaceNodeRef, "*[@cm:name='" + modelFileName + "' and " + defaultSubtypeOfDictionaryModel + "]", null, namespaceService, false); NodeRef modelNodeRef = null; if (nodeRefs.size() == 1) { // re-deploy existing model to the repository modelNodeRef = nodeRefs.get(0); } else { // deploy new model to the repository try { // note: dictionary model type has associated policies that will be invoked ChildAssociationRef association = nodeService.createNode(customModelsSpaceNodeRef, ContentModel.ASSOC_CONTAINS, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, modelFileName), ContentModel.TYPE_DICTIONARY_MODEL, contentProps); // also invokes policies for DictionaryModelType - e.g. onUpdateProperties modelNodeRef = association.getChildRef(); } catch (DuplicateChildNodeNameException dcnne) { String msg = "Model already exists: " + modelFileName + " - " + dcnne; logger.warn(msg); // for now, assume concurrency failure throw new ConcurrencyFailureException(getLocalisedMessage(MODEL_EXISTS, modelFileName)); } // add titled aspect (for Web Client display) Map<QName, Serializable> titledProps = new HashMap<QName, Serializable>(); titledProps.put(ContentModel.PROP_TITLE, modelFileName); titledProps.put(ContentModel.PROP_DESCRIPTION, modelFileName); nodeService.addAspect(modelNodeRef, ContentModel.ASPECT_TITLED, titledProps); // add versionable aspect (set auto-version) Map<QName, Serializable> versionProps = new HashMap<QName, Serializable>(); versionProps.put(ContentModel.PROP_AUTO_VERSION, true); nodeService.addAspect(modelNodeRef, ContentModel.ASPECT_VERSIONABLE, versionProps); } ContentWriter writer = contentService.getWriter(modelNodeRef, ContentModel.PROP_CONTENT, true); writer.setMimetype(MimetypeMap.MIMETYPE_XML); writer.setEncoding("UTF-8"); writer.putContent(modelStream); // also invokes policies for DictionaryModelType - e.g. onContentUpdate modelStream.close(); // activate the model nodeService.setProperty(modelNodeRef, ContentModel.PROP_MODEL_ACTIVE, Boolean.valueOf(activate)); // note: model will be loaded as part of DictionaryModelType.beforeCommit() return modelNodeRef; } catch (Throwable e) { throw new AlfrescoRuntimeException(MODEL_DEPLOYMENT_FAILED, e); } } public void deployModel(InputStream modelStream, String modelFileName) { deployModel(modelStream, modelFileName, true); } public QName activateModel(String modelFileName) { try { return activateOrDeactivate(modelFileName, true); } catch (Throwable e) { throw new AlfrescoRuntimeException(MODEL_ACTIVATION_FAILED, e); } } public QName deactivateModel(String modelFileName) { try { return activateOrDeactivate(modelFileName, false); } catch (Throwable e) { throw new AlfrescoRuntimeException(MODEL_DEACTIVATION_FAILED, e); } } private QName activateOrDeactivate(String modelFileName, boolean activate) { // Check that all the passed values are not null ParameterCheck.mandatoryString("modelFileName", modelFileName); StoreRef storeRef = repoModelsLocation.getStoreRef(); NodeRef rootNode = nodeService.getRootNode(storeRef); List<NodeRef> nodeRefs = searchService.selectNodes(rootNode, repoModelsLocation.getPath() + "//.[@cm:name='" + modelFileName + "' and " + defaultSubtypeOfDictionaryModel + "]", null, namespaceService, false); if (nodeRefs.size() == 0) { throw new AlfrescoRuntimeException(MODEL_NOT_FOUND, new Object[] { modelFileName }); } else if (nodeRefs.size() > 1) { // unexpected: should not find multiple nodes with same name throw new AlfrescoRuntimeException(MODELS_MULTIPLE_FOUND, new Object[] { modelFileName }); } NodeRef modelNodeRef = nodeRefs.get(0); boolean isActive = false; Boolean value = (Boolean) nodeService.getProperty(modelNodeRef, ContentModel.PROP_MODEL_ACTIVE); if (value != null) { isActive = value.booleanValue(); } QName modelQName = (QName) nodeService.getProperty(modelNodeRef, ContentModel.PROP_MODEL_NAME); ModelDefinition modelDef = null; if (modelQName != null) { try { modelDef = dictionaryDAO.getModel(modelQName); } catch (DictionaryException e) { logger.warn(e); } } if (activate) { // activate if (isActive) { if (modelDef != null) { // model is already activated throw new AlfrescoRuntimeException(MODEL_ALREADY_ACTIVATED, new Object[] { modelQName }); } else { logger.warn("Model is set to active but not loaded in Dictionary - trying to load..."); } } else { if (modelDef != null) { logger.warn("Model is loaded in Dictionary but is not set to active - trying to activate..."); } } } else { // deactivate if (!isActive) { if (modelDef == null) { // model is already deactivated throw new AlfrescoRuntimeException(MODEL_ALREADY_DEACTIVATED, new Object[] { modelQName }); } else { logger.warn("Model is set to inactive but loaded in Dictionary - trying to unload..."); } } else { if (modelDef == null) { logger.warn("Model is not loaded in Dictionary but is set to active - trying to deactivate..."); } } } // activate/deactivate the model nodeService.setProperty(modelNodeRef, ContentModel.PROP_MODEL_ACTIVE, new Boolean(activate)); // note: model will be loaded/unloaded as part of DictionaryModelType.beforeCommit() return modelQName; } public QName undeployModel(String modelFileName) { // Check that all the passed values are not null ParameterCheck.mandatory("modelFileName", modelFileName); QName modelQName = null; try { // find model in repository StoreRef storeRef = repoModelsLocation.getStoreRef(); NodeRef rootNode = nodeService.getRootNode(storeRef); List<NodeRef> nodeRefs = null; try { nodeRefs = searchService.selectNodes(rootNode, repoModelsLocation.getPath() + "//.[@cm:name='" + modelFileName + "' and " + defaultSubtypeOfDictionaryModel + "]", null, namespaceService, false); } catch (InvalidNodeRefException inre) { String msg = "Model no longer exists: " + modelFileName + " - " + inre; logger.warn(msg); // for now, assume concurrency failure throw new ConcurrencyFailureException(getLocalisedMessage(MODEL_NO_LONGER_EXISTS, modelFileName)); } if (nodeRefs.size() == 0) { throw new AlfrescoRuntimeException(MODEL_NOT_FOUND, new Object[] { modelFileName }); } else if (nodeRefs.size() > 1) { // unexpected: should not find multiple nodes with same name throw new AlfrescoRuntimeException(MODELS_MULTIPLE_FOUND, new Object[] { modelFileName }); } NodeRef modelNodeRef = nodeRefs.get(0); boolean isActive = false; Boolean value = (Boolean) nodeService.getProperty(modelNodeRef, ContentModel.PROP_MODEL_ACTIVE); if (value != null) { isActive = value.booleanValue(); } modelQName = (QName) nodeService.getProperty(modelNodeRef, ContentModel.PROP_MODEL_NAME); ModelDefinition modelDef = null; if (modelQName != null) { try { modelDef = dictionaryDAO.getModel(modelQName); } catch (DictionaryException e) { logger.warn(e); } } if (isActive) { if (modelDef == null) { logger.warn("Model is set to active but not loaded in Dictionary - trying to undeploy..."); } } // permanently remove model from repository nodeService.addAspect(modelNodeRef, ContentModel.ASPECT_TEMPORARY, null); try { nodeService.deleteNode(modelNodeRef); } catch (DictionaryException de) { String msg = "Model undeployment failed: " + modelFileName + " - " + de; logger.warn(msg); // for now, assume concurrency failure throw new ConcurrencyFailureException(msg); } // note: deleted model will be unloaded as part of DictionaryModelType.beforeCommit() } catch (Throwable e) { throw new AlfrescoRuntimeException(MODEL_UNDEPLOYMENT_FAILED, e); } return modelQName; } public List<String> getMessageBundles() { StoreRef storeRef = repoMessagesLocation.getStoreRef(); NodeRef rootNode = nodeService.getRootNode(storeRef); Collection<String> registeredBundles = messageService.getRegisteredBundles(); List<NodeRef> nodeRefs = searchService.selectNodes(rootNode, repoMessagesLocation.getPath() + CRITERIA_ALL + "[" + defaultSubtypeOfContent + "]", null, namespaceService, false); List<String> resourceBundlesInRepo = new ArrayList<String>(); for (NodeRef nodeRef : nodeRefs) { String resourceName = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME); String resourceBundleBaseName = null; int idx1 = resourceName.indexOf("_"); if (idx1 > 0) { resourceBundleBaseName = resourceName.substring(0, idx1); } else { int idx2 = resourceName.indexOf("."); if (idx2 > 0) { resourceBundleBaseName = resourceName.substring(0, idx2); } else { // Unexpected format logger.warn("Unexpected message resource name: " + resourceName); } } if (registeredBundles != null) { for (String registeredBundlePath : registeredBundles) { if (registeredBundlePath.endsWith(resourceBundleBaseName) && (!resourceBundlesInRepo.contains(resourceBundleBaseName))) { resourceBundlesInRepo.add(resourceBundleBaseName); } } } else { // unexpected logger.error("Message bundle not registered: " + resourceBundleBaseName); } } return resourceBundlesInRepo; } public String deployMessageBundle(String resourceClasspath) { // Check that all the passed values are not null ParameterCheck.mandatory("ResourceClasspath", resourceClasspath); String bundleBaseName = resourceClasspath; // note: resource path should be in form path1/path2/path3/bundlebasename int idx = resourceClasspath.lastIndexOf("/"); if (idx != -1) { if (idx < (resourceClasspath.length() - 1)) { bundleBaseName = resourceClasspath.substring(idx + 1); } else { bundleBaseName = null; } } checkBundleBaseName(bundleBaseName); String pattern = "classpath*:" + resourceClasspath + "*" + MessageServiceImpl.PROPERTIES_FILE_SUFFIX; PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); try { Resource[] resources = resolver.getResources(pattern); if ((resources != null) && (resources.length > 0)) { ArrayList<String> names = new ArrayList<String>(); ArrayList<Resource> filteredResources = new ArrayList<Resource>(); for (int i = 0; i < resources.length; i++) { String filename = resources[i].getFilename(); if (!names.contains(filename)) { names.add(filename); filteredResources.add(resources[i]); } } for (Resource resource : filteredResources) { InputStream fileStream = resource.getInputStream(); String filename = resource.getFilename(); deployMessageResourceFile(resourceClasspath, filename, fileStream, false); } // register bundle StoreRef storeRef = repoMessagesLocation.getStoreRef(); String repoBundlePath = storeRef.toString() + repoMessagesLocation.getPath() + "/cm:" + bundleBaseName; messageService.registerResourceBundle(repoBundlePath); logger.info("Message resource bundle deployed: " + bundleBaseName); } else { logger.warn("No message resources found: " + resourceClasspath); throw new AlfrescoRuntimeException(MSG_RESOURCES_NOT_FOUND, new Object[] { resourceClasspath }); } } catch (Throwable e) { throw new AlfrescoRuntimeException(MSG_RESOURCES_DEPLOYMENT_FAILED, new Object[] { resourceClasspath }, e); } return bundleBaseName; } /* * Deploy message resource file */ private void deployMessageResourceFile(String bundleBasePath, String name, InputStream resourceStream, boolean registerResourceBundle) { // Check that all the passed values are not null ParameterCheck.mandatory("BundleBasePath", bundleBasePath); ParameterCheck.mandatory("Name", name); ParameterCheck.mandatory("ResourceStream", resourceStream); try { Map<QName, Serializable> contentProps = new HashMap<QName, Serializable>(); contentProps.put(ContentModel.PROP_NAME, name); StoreRef storeRef = repoMessagesLocation.getStoreRef(); NodeRef rootNode = nodeService.getRootNode(storeRef); List<NodeRef> nodeRefs = searchService.selectNodes(rootNode, repoMessagesLocation.getPath(), null, namespaceService, false); if (nodeRefs.size() == 0) { throw new AlfrescoRuntimeException(MESSAGES_LOCATION_NOT_FOUND, new Object[] { repoMessagesLocation.getPath() }); } else if (nodeRefs.size() > 1) { // unexpected: should not find multiple nodes with same name throw new AlfrescoRuntimeException(MESSAGES_LOCATION_MULTIPLE_FOUND, new Object[] { repoMessagesLocation.getPath() }); } NodeRef customLabelsNodeRef = nodeRefs.get(0); ChildAssociationRef association = nodeService.createNode(customLabelsNodeRef, ContentModel.ASSOC_CONTAINS, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, name), ContentModel.TYPE_CONTENT, contentProps); NodeRef content = association.getChildRef(); // add titled aspect (for Web Client display) Map<QName, Serializable> titledProps = new HashMap<QName, Serializable>(); titledProps.put(ContentModel.PROP_TITLE, name); titledProps.put(ContentModel.PROP_DESCRIPTION, name); nodeService.addAspect(content, ContentModel.ASPECT_TITLED, titledProps); // add inline-editable aspect Map<QName, Serializable> editProps = new HashMap<QName, Serializable>(1, 1.0f); editProps.put(ApplicationModel.PROP_EDITINLINE, true); nodeService.addAspect(content, ApplicationModel.ASPECT_INLINEEDITABLE, editProps); ContentWriter writer = contentService.getWriter(content, ContentModel.PROP_CONTENT, true); writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); writer.setEncoding("UTF-8"); writer.putContent(resourceStream); resourceStream.close(); if (registerResourceBundle == true) { String bundleBaseName = null; int idx = bundleBasePath.lastIndexOf("/"); if ((idx != -1) && (idx != bundleBasePath.length() - 1)) { bundleBaseName = bundleBasePath.substring(idx + 1); } else { bundleBaseName = bundleBasePath; } String repoBundlePath = storeRef.toString() + repoMessagesLocation.getPath() + "/cm:" + bundleBaseName; messageService.registerResourceBundle(repoBundlePath); } logger.info("Message resource deployed: " + name); } catch (Throwable e) { throw new AlfrescoRuntimeException("Message resource deployment failed", e); } } public void undeployMessageBundle(String bundleBaseName) { checkBundleBaseName(bundleBaseName); try { StoreRef storeRef = repoMessagesLocation.getStoreRef(); // unregister bundle String repoBundlePath = storeRef.toString() + repoMessagesLocation.getPath() + "/cm:" + bundleBaseName; messageService.unregisterResourceBundle(repoBundlePath); NodeRef rootNode = nodeService.getRootNode(storeRef); List<NodeRef> nodeRefs = searchService.selectNodes(rootNode, repoMessagesLocation.getPath() + CRITERIA_ALL, null, namespaceService, false); boolean found = false; for (NodeRef nodeRef : nodeRefs) { String resourceName = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME); if (bundleBaseName.equals(messageService.getBaseBundleName(resourceName))) { // remove message resource file from the repository nodeService.deleteNode(nodeRef); found = true; // continue to undeploy any others } } if (found) { logger.info("Message resources undeployed: " + bundleBaseName); } else { throw new AlfrescoRuntimeException(MSG_RESOURCES_NOT_FOUND, new Object[] { repoBundlePath }); } } catch (Throwable t) { throw new AlfrescoRuntimeException(MSG_RESOURCES_UNDEPLOYMENT_FAILED, t); } } public void reloadMessageBundle(String bundleBaseName) { checkBundleBaseName(bundleBaseName); try { StoreRef storeRef = repoMessagesLocation.getStoreRef(); // re-register bundle String repoBundlePath = storeRef.toString() + repoMessagesLocation.getPath() + "/cm:" + bundleBaseName; NodeRef rootNode = nodeService.getRootNode(storeRef); List<NodeRef> nodeRefs = searchService.selectNodes(rootNode, repoMessagesLocation.getPath() + CRITERIA_ALL, null, namespaceService, false); boolean found = false; for (NodeRef nodeRef : nodeRefs) { String resourceName = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME); if (bundleBaseName.equals(messageService.getBaseBundleName(resourceName))) { found = true; break; } } if (found) { messageService.unregisterResourceBundle(repoBundlePath); messageService.registerResourceBundle(repoBundlePath); logger.info("Message resources re-loaded: " + bundleBaseName); } else { throw new AlfrescoRuntimeException(MSG_RESOURCES_NOT_FOUND, new Object[] { repoBundlePath }); } } catch (Throwable e) { throw new AlfrescoRuntimeException(MSG_RESOURCES_RELOAD_FAILED, e); } } private void checkBundleBaseName(String bundleBaseName) { if ((bundleBaseName == null) || (bundleBaseName.equals(""))) { throw new AlfrescoRuntimeException(MSG_MISSING_BUNDLE_BASE_NAME); } if (bundleBaseName.indexOf("_") != -1) { // currently limited due to parser in MessageServiceImpl.getBaseBundleName throw new AlfrescoRuntimeException(MSG_BASE_NAME_CONTAIN_UNDERSCORE, new Object[] { bundleBaseName }); } if (bundleBaseName.indexOf(".") != -1) { throw new AlfrescoRuntimeException(MSG_BASE_NAME_CONTAIN_PERIOD, new Object[] { bundleBaseName }); } } @Override public RepoUsage getRestrictions() { return repoUsageComponent.getRestrictions(); } @Override public RepoUsage getUsage() { return repoUsageComponent.getUsage(); } @Override public boolean updateUsage(UsageType usageType) { return repoUsageComponent.updateUsage(usageType); } @Override public RepoUsageStatus getUsageStatus() { return repoUsageComponent.getUsageStatus(); } private String getLocalisedMessage(String msgId, Object... params) { String localisedMsg = I18NUtil.getMessage(msgId, params); if (localisedMsg == null) { localisedMsg = msgId; } return localisedMsg; } }