diff --git a/config/alfresco/authentication-services-context.xml b/config/alfresco/authentication-services-context.xml index 4c1cce00bb..104899d7bf 100644 --- a/config/alfresco/authentication-services-context.xml +++ b/config/alfresco/authentication-services-context.xml @@ -246,10 +246,9 @@ - - - - + + + ${server.transaction.allow-writes} diff --git a/config/alfresco/bootstrap-context.xml b/config/alfresco/bootstrap-context.xml index 3fade34540..1832a58de1 100644 --- a/config/alfresco/bootstrap-context.xml +++ b/config/alfresco/bootstrap-context.xml @@ -223,9 +223,6 @@ ${system.bootstrap.config_check.strict} - - false - ${dir.root} @@ -233,20 +230,23 @@ ${index.recovery.mode} - - + + - - + + + + + - + - + - + diff --git a/config/alfresco/bootstrap/descriptor.xml b/config/alfresco/bootstrap/descriptor.xml index c4923a7c56..e08a1a9527 100644 --- a/config/alfresco/bootstrap/descriptor.xml +++ b/config/alfresco/bootstrap/descriptor.xml @@ -18,6 +18,7 @@ ${version.edition} ${version.label} ${version.schema} + contentUrl=classpath:alfresco/version.properties|mimetype=text/plain|size=|encoding=UTF8 diff --git a/config/alfresco/extension/index-tracking-context.xml.sample b/config/alfresco/extension/index-tracking-context.xml.sample index 5c1343bec2..9ed6a3ae86 100644 --- a/config/alfresco/extension/index-tracking-context.xml.sample +++ b/config/alfresco/extension/index-tracking-context.xml.sample @@ -23,7 +23,7 @@ - 0,30 * * * * ? + 0,10,20,30,40,50 * * * * ? diff --git a/config/alfresco/messages/patch-service.properties b/config/alfresco/messages/patch-service.properties index a51c36136d..be27d41f71 100644 --- a/config/alfresco/messages/patch-service.properties +++ b/config/alfresco/messages/patch-service.properties @@ -104,3 +104,8 @@ patch.invalidNameEnding.description=Fixes names ending with a space or full stop patch.invalidNameEnding.result=Fixed {0} names ending with a space or full stop. See file {1} for details. patch.invalidNameEnding.err.unable_to_fix=Auto-fixing of names ending with a space or full stop failed. See file {0} for details. patch.invalidNameEnding.rewritten=Name ''{0}'' rewritten to ''{1}'' + +patch.systemDescriptorContent.description=Adds the version properties content to the system descriptor. +patch.systemDescriptorContent.result=Added the version properties content to the system descriptor. +patch.systemDescriptorContent.err.no_version_properties=The version.properties resource could not be found. +patch.systemDescriptorContent.err.no_descriptor=The system descriptor could not be found. \ No newline at end of file diff --git a/config/alfresco/messages/system-messages.properties b/config/alfresco/messages/system-messages.properties index f281f4e37e..04051ea92d 100644 --- a/config/alfresco/messages/system-messages.properties +++ b/config/alfresco/messages/system-messages.properties @@ -9,7 +9,7 @@ system.config_check.warn.dir_root=The Alfresco ''dir.root'' property is set to a system.config_check.msg.dir_root=The Alfresco root data directory (''dir.root'') is: {0} system.config_check.err.indexes.duplicate_root_node=The store ''{0}'' has a duplicate root node entry. system.config_check.err.missing_index=CONTENT INTEGRITY ERROR: Indexes not found for {0} stores. -system.config_check.err.missing_content=CONTENT INTEGRITY ERROR: Content not found for {0} stores. +system.config_check.err.missing_content=CONTENT INTEGRITY ERROR: System content not found in content store. system.config_check.err.fix_dir_root=Ensure that the ''dir.root'' property is pointing to the correct data location. system.config_check.msg.howto_index_recover=You may set 'index.recovery.mode=FULL' if you need to rebuild the indexes. system.config_check.warn.starting_with_errors=Alfresco is starting with errors. diff --git a/config/alfresco/model/systemModel.xml b/config/alfresco/model/systemModel.xml index 9cc0b93204..28e853cf73 100644 --- a/config/alfresco/model/systemModel.xml +++ b/config/alfresco/model/systemModel.xml @@ -53,6 +53,10 @@ d:any true + + d:content + false + diff --git a/config/alfresco/patch/patch-services-context.xml b/config/alfresco/patch/patch-services-context.xml index f289ed598a..75c33cf672 100644 --- a/config/alfresco/patch/patch-services-context.xml +++ b/config/alfresco/patch/patch-services-context.xml @@ -503,5 +503,19 @@ + + patch.systemDescriptorContent + patch.systemDescriptorContent.description + 0 + 22 + 23 + + + + + + + + diff --git a/config/alfresco/template-services-context.xml b/config/alfresco/template-services-context.xml index 426f23ef3b..b74598ebff 100644 --- a/config/alfresco/template-services-context.xml +++ b/config/alfresco/template-services-context.xml @@ -24,9 +24,14 @@ - - + + - + + diff --git a/config/alfresco/version.properties b/config/alfresco/version.properties index 2ca1eb46fa..9995e3cfce 100644 --- a/config/alfresco/version.properties +++ b/config/alfresco/version.properties @@ -19,4 +19,4 @@ version.build=@build-number@ # Schema number -version.schema=22 +version.schema=23 diff --git a/source/java/org/alfresco/model/ContentModel.java b/source/java/org/alfresco/model/ContentModel.java index c1590997cf..237de9ad6f 100644 --- a/source/java/org/alfresco/model/ContentModel.java +++ b/source/java/org/alfresco/model/ContentModel.java @@ -80,7 +80,7 @@ public interface ContentModel static final QName PROP_SYS_VERSION_BUILD = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "versionBuild"); static final QName PROP_SYS_VERSION_SCHEMA = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "versionSchema"); static final QName PROP_SYS_VERSION_EDITION = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "versionEdition"); - + static final QName PROP_SYS_VERSION_PROPERTIES = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "versionProperties"); // // Content Model Definitions diff --git a/source/java/org/alfresco/repo/admin/ConfigurationChecker.java b/source/java/org/alfresco/repo/admin/ConfigurationChecker.java index 25a455ac08..2fca06c16e 100644 --- a/source/java/org/alfresco/repo/admin/ConfigurationChecker.java +++ b/source/java/org/alfresco/repo/admin/ConfigurationChecker.java @@ -18,31 +18,28 @@ package org.alfresco.repo.admin; import java.io.File; import java.util.ArrayList; -import java.util.Collection; import java.util.List; -import java.util.Map; +import java.util.Properties; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.i18n.I18NUtil; +import org.alfresco.model.ContentModel; +import org.alfresco.repo.importer.ImporterBootstrap; import org.alfresco.repo.node.index.FullIndexRecoveryComponent.RecoveryMode; import org.alfresco.repo.search.impl.lucene.LuceneQueryParser; -import org.alfresco.repo.security.authentication.AuthenticationComponent; -import org.alfresco.service.cmr.dictionary.DataTypeDefinition; -import org.alfresco.service.cmr.dictionary.DictionaryService; -import org.alfresco.service.cmr.dictionary.PropertyDefinition; -import org.alfresco.service.cmr.dictionary.TypeDefinition; +import org.alfresco.repo.transaction.TransactionUtil; +import org.alfresco.repo.transaction.TransactionUtil.TransactionWork; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.InvalidStoreRefException; 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.LimitBy; import org.alfresco.service.cmr.search.ResultSet; -import org.alfresco.service.cmr.search.ResultSetRow; import org.alfresco.service.cmr.search.SearchParameters; import org.alfresco.service.cmr.search.SearchService; -import org.alfresco.service.namespace.QName; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.transaction.TransactionService; import org.alfresco.util.AbstractLifecycleBean; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -82,17 +79,16 @@ public class ConfigurationChecker extends AbstractLifecycleBean private boolean strict; private RecoveryMode indexRecoveryMode; private String dirRoot; - private boolean checkAllContent; - private AuthenticationComponent authenticationComponent; - private DictionaryService dictionaryService; + private ImporterBootstrap systemBootstrap; + private TransactionService transactionService; + private NamespaceService namespaceService; private NodeService nodeService; private SearchService searchService; private ContentService contentService; public ConfigurationChecker() { - this.checkAllContent = false; } @Override @@ -101,7 +97,6 @@ public class ConfigurationChecker extends AbstractLifecycleBean StringBuilder sb = new StringBuilder(50); sb.append("ConfigurationChecker") .append("[indexRecoveryMode=").append(indexRecoveryMode) - .append(", checkAllContent=").append(checkAllContent) .append("]"); return sb.toString(); } @@ -119,16 +114,6 @@ public class ConfigurationChecker extends AbstractLifecycleBean this.strict = strict; } - /** - * @param checkAllContent true to get all content URLs when checking for - * missing content, or false to just do a quick sanity check against - * the content store. - */ - public void setCheckAllContent(boolean checkAllContent) - { - this.checkAllContent = checkAllContent; - } - /** * Set the index recovery mode. If this is * {@link org.alfresco.repo.node.index.FullIndexRecoveryComponent.RecoveryMode#VALIDATE FULL} @@ -147,14 +132,19 @@ public class ConfigurationChecker extends AbstractLifecycleBean this.dirRoot = dirRoot; } - public void setAuthenticationComponent(AuthenticationComponent authenticationComponent) + public void setSystemBootstrap(ImporterBootstrap systemBootstrap) { - this.authenticationComponent = authenticationComponent; + this.systemBootstrap = systemBootstrap; } - public void setDictionaryService(DictionaryService dictionaryService) + public void setTransactionService(TransactionService transactionService) { - this.dictionaryService = dictionaryService; + this.transactionService = transactionService; + } + + public void setNamespaceService(NamespaceService namespaceService) + { + this.namespaceService = namespaceService; } public void setNodeService(NodeService nodeService) @@ -175,16 +165,15 @@ public class ConfigurationChecker extends AbstractLifecycleBean @Override protected void onBootstrap(ApplicationEvent event) { - // authenticate - try + TransactionWork checkWork = new TransactionWork() { - authenticationComponent.setSystemUserAsCurrentUser(); - check(); - } - finally - { - authenticationComponent.clearCurrentSecurityContext(); - } + public Object doWork() throws Exception + { + check(); + return null; + } + }; + TransactionUtil.executeInUserTransaction(transactionService, checkWork); } /** @@ -211,7 +200,6 @@ public class ConfigurationChecker extends AbstractLifecycleBean // get all root nodes from the NodeService, i.e. database List storeRefs = nodeService.getStores(); List missingIndexStoreRefs = new ArrayList(0); - List missingContentStoreRefs = new ArrayList(0); for (StoreRef storeRef : storeRefs) { NodeRef rootNodeRef = null; @@ -267,81 +255,23 @@ public class ConfigurationChecker extends AbstractLifecycleBean throw new AlfrescoRuntimeException(msg); } } - // select a content property - QName contentPropertyQName = null; - Collection typeQNames = dictionaryService.getAllTypes(); - /* BREAK POINT */ contentPropertyFound: - for (QName typeQName : typeQNames) + } + // check for the system version properties content snippet + boolean versionPropertiesContentAvailable = true; + NodeRef descriptorNodeRef = getSystemDescriptor(); + if (descriptorNodeRef != null) + { + // get the version properties + ContentReader reader = contentService.getReader( + descriptorNodeRef, + ContentModel.PROP_SYS_VERSION_PROPERTIES); + if (reader != null && !reader.exists()) { - TypeDefinition classDef = dictionaryService.getType(typeQName); - Map propertyDefs = classDef.getProperties(); - for (PropertyDefinition propertyDef : propertyDefs.values()) - { - if (!propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT)) - { - continue; - } - contentPropertyQName = propertyDef.getName(); - break contentPropertyFound; - } - } - // do a search for nodes with content - if (contentPropertyQName != null) - { - String attributeName = "\\@" + LuceneQueryParser.escape(contentPropertyQName.toString()); - - SearchParameters sp = new SearchParameters(); - sp.addStore(storeRef); - sp.setLanguage(SearchService.LANGUAGE_LUCENE); - sp.setQuery(attributeName + ":*"); - if (!checkAllContent) - { - sp.setLimit(1); - sp.setLimitBy(LimitBy.FINAL_SIZE); - } - ResultSet results = null; - try - { - results = searchService.query(sp); - // iterate and attempt to get the content - for (ResultSetRow row : results) - { - NodeRef nodeRef = row.getNodeRef(); - ContentReader reader = contentService.getReader(nodeRef, contentPropertyQName); - if (reader == null) - { - // content not written - continue; - } - else if (reader.exists()) - { - // the data is present in the content store - } - else - { - // URL is missing - missingContentStoreRefs.add(storeRef); - // debug - if (logger.isDebugEnabled()) - { - logger.debug("Content missing from store: \n" + - " store: " + storeRef + "\n" + - " content: " + reader); - } - } - // break out if necessary - if (!checkAllContent) - { - break; - } - } - } - finally - { - try { results.close(); } catch (Throwable e) {} - } + // the property is there, but the content is not + versionPropertiesContentAvailable = false; } } + // check for missing indexes int missingStoreIndexes = missingIndexStoreRefs.size(); if (missingStoreIndexes > 0) @@ -352,14 +282,13 @@ public class ConfigurationChecker extends AbstractLifecycleBean logger.info(msgRecover); } // check for missing content - int missingStoreContent = missingContentStoreRefs.size(); - if (missingStoreContent > 0) + if (!versionPropertiesContentAvailable) { - String msg = I18NUtil.getMessage(ERR_MISSING_CONTENT, missingStoreContent); + String msg = I18NUtil.getMessage(ERR_MISSING_CONTENT); logger.error(msg); } // handle either content or indexes missing - if (missingStoreIndexes > 0 || missingStoreContent > 0) + if (missingStoreIndexes > 0 || !versionPropertiesContentAvailable) { String msg = I18NUtil.getMessage(ERR_FIX_DIR_ROOT, dirRootFile); logger.error(msg); @@ -376,6 +305,29 @@ public class ConfigurationChecker extends AbstractLifecycleBean } } } + + /** + * @return Returns the system descriptor node or null + */ + public NodeRef getSystemDescriptor() + { + StoreRef systemStoreRef = systemBootstrap.getStoreRef(); + List nodeRefs = null; + if (nodeService.exists(systemStoreRef)) + { + Properties systemProperties = systemBootstrap.getConfiguration(); + String path = systemProperties.getProperty("system.descriptor.current.childname"); + String searchPath = "/" + path; + NodeRef rootNodeRef = nodeService.getRootNode(systemStoreRef); + nodeRefs = searchService.selectNodes(rootNodeRef, searchPath, null, namespaceService, false); + if (nodeRefs.size() > 0) + { + NodeRef descriptorNodeRef = nodeRefs.get(0); + return descriptorNodeRef; + } + } + return null; + } @Override protected void onShutdown(ApplicationEvent event) diff --git a/source/java/org/alfresco/repo/admin/patch/impl/SystemDescriptorContentPatch.java b/source/java/org/alfresco/repo/admin/patch/impl/SystemDescriptorContentPatch.java new file mode 100644 index 0000000000..1bf4361774 --- /dev/null +++ b/source/java/org/alfresco/repo/admin/patch/impl/SystemDescriptorContentPatch.java @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2005 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.patch.impl; + +import java.io.InputStream; + +import org.alfresco.i18n.I18NUtil; +import org.alfresco.model.ContentModel; +import org.alfresco.repo.admin.ConfigurationChecker; +import org.alfresco.repo.admin.patch.AbstractPatch; +import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.service.cmr.admin.PatchException; +import org.alfresco.service.cmr.repository.ContentService; +import org.alfresco.service.cmr.repository.ContentWriter; +import org.alfresco.service.cmr.repository.NodeRef; +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; + +/** + * Ensures that the required content snippet is added to the system descriptor + * to enable robust checking of the content store by the configuration checker. + * + * @author Derek Hulley + */ +public class SystemDescriptorContentPatch extends AbstractPatch +{ + private static final String MSG_SUCCESS = "patch.systemDescriptorContent.result"; + private static final String ERR_NO_VERSION_PROPERTIES = "patch.systemDescriptorContent.err.no_version_properties"; + private static final String ERR_NO_SYSTEM_DESCRIPTOR = "patch.systemDescriptorContent.err.no_descriptor"; + + private ConfigurationChecker configurationChecker; + private ContentService contentService; + + public SystemDescriptorContentPatch() + { + } + + public void setConfigurationChecker(ConfigurationChecker configurationChecker) + { + this.configurationChecker = configurationChecker; + } + + public void setContentService(ContentService contentService) + { + this.contentService = contentService; + } + + @Override + protected void checkProperties() + { + super.checkProperties(); + checkPropertyNotNull(configurationChecker, "configurationChecker"); + checkPropertyNotNull(contentService, "contentService"); + } + + @Override + protected String applyInternal() throws Exception + { + InputStream is = null; + try + { + // get the version.properties + ResourceLoader resourceLoader = new DefaultResourceLoader(); + Resource resource = resourceLoader.getResource("classpath:alfresco/version.properties"); + if (!resource.exists()) + { + throw new PatchException(ERR_NO_VERSION_PROPERTIES); + } + is = resource.getInputStream(); + // get the system descriptor + NodeRef descriptorNodeRef = configurationChecker.getSystemDescriptor(); + if (descriptorNodeRef == null) + { + throw new PatchException(ERR_NO_SYSTEM_DESCRIPTOR); + } + // get the writer + ContentWriter writer = contentService.getWriter(descriptorNodeRef, ContentModel.PROP_SYS_VERSION_PROPERTIES, true); + // upload + writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); + writer.setEncoding("UTF8"); + writer.putContent(is); + // done + String msg = I18NUtil.getMessage(MSG_SUCCESS); + return msg; + } + finally + { + if (is != null) + { + try { is.close(); } catch (Throwable e) {} + } + } + } +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/java/org/alfresco/repo/content/RoutingContentService.java b/source/java/org/alfresco/repo/content/RoutingContentService.java index e7321b22fa..a1b35833b3 100644 --- a/source/java/org/alfresco/repo/content/RoutingContentService.java +++ b/source/java/org/alfresco/repo/content/RoutingContentService.java @@ -329,11 +329,19 @@ public class RoutingContentService implements ContentService public ContentWriter getWriter(NodeRef nodeRef, QName propertyQName, boolean update) { + // TODO: Choose the store to write to at runtime + + if (nodeRef == null) + { + // for this case, we just give back a valid URL into the content store + ContentWriter writer = store.getWriter(null, null); + // done + return writer; + } + // check for an existing URL - the get of the reader will perform type checking ContentReader existingContentReader = getReader(nodeRef, propertyQName, false); - // TODO: Choose the store to write to at runtime - // get the content using the (potentially) existing content - the new content // can be wherever the store decides. ContentWriter writer = store.getWriter(existingContentReader, null); diff --git a/source/java/org/alfresco/repo/content/RoutingContentServiceTest.java b/source/java/org/alfresco/repo/content/RoutingContentServiceTest.java index 20c285d9cd..aa528a1b07 100644 --- a/source/java/org/alfresco/repo/content/RoutingContentServiceTest.java +++ b/source/java/org/alfresco/repo/content/RoutingContentServiceTest.java @@ -153,6 +153,29 @@ public class RoutingContentServiceTest extends TestCase assertFalse(getUserTransaction() == getUserTransaction()); // ensure txn instances aren't shared } + /** + * Check that a valid writer into the content store can be retrieved and used. + */ + public void testSimpleNonTempWriter() throws Exception + { + ContentWriter writer = contentService.getWriter(null, null, false); + assertNotNull("Writer should not be null", writer); + assertNotNull("Content URL should not be null", writer.getContentUrl()); + + // write some content + writer.putContent(SOME_CONTENT); + writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); + writer.setEncoding("UTF8"); + + // set the content property manually + nodeService.setProperty(contentNodeRef, ContentModel.PROP_CONTENT, writer.getContentData()); + + // get the reader + ContentReader reader = contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT); + assertNotNull("Reader should not be null", reader); + assertNotNull("Content URL should not be null", reader.getContentUrl()); + } + /** * Checks that the URL, mimetype and encoding are automatically set on the readers * and writers diff --git a/source/java/org/alfresco/repo/exporter/RepositoryExporterComponent.java b/source/java/org/alfresco/repo/exporter/RepositoryExporterComponent.java index 1082f9f6ea..6778178a8f 100644 --- a/source/java/org/alfresco/repo/exporter/RepositoryExporterComponent.java +++ b/source/java/org/alfresco/repo/exporter/RepositoryExporterComponent.java @@ -166,6 +166,9 @@ public class RepositoryExporterComponent implements RepositoryExporterService handle.mimeType = exportHandle.mimeType; handle.exportFile = repoExportFile; repoExportHandles.add(handle); + + // delete temporary export file + exportHandle.exportFile.delete(); } return repoExportHandles.toArray(new RepositoryExportHandle[repoExportHandles.size()]); @@ -326,7 +329,8 @@ public class RepositoryExporterComponent implements RepositoryExporterService public FileExportHandle exportStore(ExporterCrawlerParameters exportParameters, String packageName, Exporter progress) { // create a temporary file to hold the acp export - File tempFile = TempFileProvider.createTempFile("repoExp" + packageName, "." + ACPExportPackageHandler.ACP_EXTENSION); + File systemTempDir = TempFileProvider.getSystemTempDir(); + File tempFile = TempFileProvider.createTempFile("repoExp" + packageName, "." + ACPExportPackageHandler.ACP_EXTENSION, systemTempDir); // create acp export handler around the temp file File dataFile = new File(packageName); @@ -361,7 +365,8 @@ public class RepositoryExporterComponent implements RepositoryExporterService public FileExportHandle exportSystem(String packageName) { // create a temporary file to hold the system info export - File tempFile = TempFileProvider.createTempFile("repoExpSystemInfo", ".xml"); + File systemTempDir = TempFileProvider.getSystemTempDir(); + File tempFile = TempFileProvider.createTempFile("repoExpSystemInfo", ".xml", systemTempDir); try { diff --git a/source/java/org/alfresco/repo/security/permissions/impl/PermissionServiceTest.java b/source/java/org/alfresco/repo/security/permissions/impl/PermissionServiceTest.java index 970e08eb4d..8436d2fa16 100644 --- a/source/java/org/alfresco/repo/security/permissions/impl/PermissionServiceTest.java +++ b/source/java/org/alfresco/repo/security/permissions/impl/PermissionServiceTest.java @@ -489,22 +489,22 @@ public class PermissionServiceTest extends AbstractPermissionTest QName ownable = QName.createQName("cm", "ownable", namespacePrefixResolver); Set answer = permissionService.getSettablePermissions(rootNodeRef); - assertEquals(42, answer.size()); + assertEquals(36, answer.size()); nodeService.addAspect(rootNodeRef, ownable, null); answer = permissionService.getSettablePermissions(rootNodeRef); - assertEquals(42, answer.size()); + assertEquals(36, answer.size()); nodeService.removeAspect(rootNodeRef, ownable); answer = permissionService.getSettablePermissions(rootNodeRef); - assertEquals(42, answer.size()); + assertEquals(36, answer.size()); } public void testSimplePermissionOnRoot() { runAs("andy"); - assertEquals(42, permissionService.getPermissions(rootNodeRef).size()); + assertEquals(36, permissionService.getPermissions(rootNodeRef).size()); assertEquals(0, countGranted(permissionService.getPermissions(rootNodeRef))); assertEquals(0, permissionService.getAllSetPermissions(rootNodeRef).size()); @@ -517,7 +517,7 @@ public class PermissionServiceTest extends AbstractPermissionTest assertEquals(1, permissionService.getAllSetPermissions(rootNodeRef).size()); runAs("andy"); - assertEquals(42, permissionService.getPermissions(rootNodeRef).size()); + assertEquals(36, permissionService.getPermissions(rootNodeRef).size()); assertEquals(2, countGranted(permissionService.getPermissions(rootNodeRef))); assertTrue(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ_PROPERTIES)) == AccessStatus.ALLOWED); @@ -633,7 +633,7 @@ public class PermissionServiceTest extends AbstractPermissionTest permissionService.setPermission(allowAndyRead); runAs("andy"); - assertEquals(42, permissionService.getPermissions(rootNodeRef).size()); + assertEquals(36, permissionService.getPermissions(rootNodeRef).size()); assertEquals(7, countGranted(permissionService.getPermissions(rootNodeRef))); assertEquals(1, permissionService.getAllSetPermissions(rootNodeRef).size()); diff --git a/source/java/org/alfresco/repo/security/permissions/impl/model/PermissionModel.java b/source/java/org/alfresco/repo/security/permissions/impl/model/PermissionModel.java index 6fa8f16c31..96d25455c1 100644 --- a/source/java/org/alfresco/repo/security/permissions/impl/model/PermissionModel.java +++ b/source/java/org/alfresco/repo/security/permissions/impl/model/PermissionModel.java @@ -433,7 +433,7 @@ public class PermissionModel implements ModelDAO, InitializingBean // QName typeName = nodeService.getType(nodeRef); - Set permissions = getAllPermissions(typeName); + Set permissions = getAllPermissionsImpl(typeName, exposedOnly); mergeGeneralAspectPermissions(permissions, exposedOnly); // Add non mandatory aspects... Set defaultAspects = new HashSet(); diff --git a/source/java/org/alfresco/repo/template/FreeMarkerProcessor.java b/source/java/org/alfresco/repo/template/FreeMarkerProcessor.java index 6aae071809..269b76850a 100644 --- a/source/java/org/alfresco/repo/template/FreeMarkerProcessor.java +++ b/source/java/org/alfresco/repo/template/FreeMarkerProcessor.java @@ -32,6 +32,8 @@ import org.alfresco.service.cmr.repository.TemplateNode; import org.alfresco.service.cmr.repository.TemplateProcessor; import org.apache.log4j.Logger; +import bsh.This; + import freemarker.cache.MruCacheStorage; import freemarker.cache.StringTemplateLoader; import freemarker.template.Configuration; @@ -70,6 +72,9 @@ public class FreeMarkerProcessor implements TemplateProcessor /** The Content Service to use */ private ContentService contentService; + /** Template encoding */ + private String defaultEncoding; + /** * Set the node service * @@ -90,6 +95,16 @@ public class FreeMarkerProcessor implements TemplateProcessor this.contentService = contentService; } + /** + * Set the default template encoding + * + * @param defaultEncoding the default encoding + */ + public void setDefaultEncoding(String defaultEncoding) + { + this.defaultEncoding = defaultEncoding; + } + /** * Get the FreeMarker configuration for this instance * @@ -111,6 +126,12 @@ public class FreeMarkerProcessor implements TemplateProcessor // rethrow any exception so we can deal with them config.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); + // set default template encoding + if (defaultEncoding != null) + { + config.setDefaultEncoding(defaultEncoding); + } + return config; } @@ -140,6 +161,12 @@ public class FreeMarkerProcessor implements TemplateProcessor // rethrow any exception so we can deal with them config.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); + // set default template encoding + if (defaultEncoding != null) + { + config.setDefaultEncoding(defaultEncoding); + } + return config; } diff --git a/source/java/org/alfresco/service/cmr/repository/ContentService.java b/source/java/org/alfresco/service/cmr/repository/ContentService.java index f13f66192e..7e4663009f 100644 --- a/source/java/org/alfresco/service/cmr/repository/ContentService.java +++ b/source/java/org/alfresco/service/cmr/repository/ContentService.java @@ -74,8 +74,12 @@ public interface ContentService * regardless of the state of the written binary data. If the flag is on, then the node * property will be updated on the same thread as the code that closed the write * channel. + *

+ * If no node is supplied, then the writer will provide a stream into the backing content + * store, but will not be associated with any new or previous content. * - * @param nodeRef a reference to a node having a content property + * @param nodeRef a reference to a node having a content property, or null + * to just get a valid writer into a backing content store. * @param propertyQName the name of the property, which must be of type content * @param update true if the property must be updated atomically when the content write * stream is closed (attaches a listener to the stream); false if the client code