(childInfos.size());
for (org.alfresco.service.cmr.model.FileInfo info : childInfos)
diff --git a/source/java/org/alfresco/model/ContentModel.java b/source/java/org/alfresco/model/ContentModel.java
index 30b61e3627..5710ccce5a 100644
--- a/source/java/org/alfresco/model/ContentModel.java
+++ b/source/java/org/alfresco/model/ContentModel.java
@@ -58,6 +58,7 @@ public interface ContentModel
static final QName PROP_SYS_VERSION_REVISION = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "versionRevision");
static final QName PROP_SYS_VERSION_LABEL = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "versionLabel");
static final QName PROP_SYS_VERSION_SCHEMA = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "versionSchema");
+ static final QName PROP_SYS_LICENSE = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "license");
//
// Content Model Definitions
diff --git a/source/java/org/alfresco/repo/admin/patch/AbstractPatch.java b/source/java/org/alfresco/repo/admin/patch/AbstractPatch.java
index 5629712c8f..6cefc9dfc3 100644
--- a/source/java/org/alfresco/repo/admin/patch/AbstractPatch.java
+++ b/source/java/org/alfresco/repo/admin/patch/AbstractPatch.java
@@ -37,6 +37,15 @@ import org.apache.commons.logging.LogFactory;
*/
public abstract class AbstractPatch implements Patch
{
+ /**
+ * I18N message when properties nto set.
+ *
+ * - {0} = property name
+ * - {1} = patch instance
+ *
+ */
+ public static final String ERR_PROPERTY_NOT_SET = "patch.general.property_not_set";
+
private static Log logger = LogFactory.getLog(AbstractPatch.class);
private String id;
@@ -215,30 +224,38 @@ public abstract class AbstractPatch implements Patch
{
return ((this.fixesFromSchema <= version) && (version <= fixesToSchema));
}
+
+ /**
+ * Performs a null check on the supplied value.
+ *
+ * @param value value to check
+ * @param name name of the property to report
+ */
+ protected final void checkPropertyNotNull(Object value, String name)
+ {
+ if (value == null)
+ {
+ throw new PatchException(ERR_PROPERTY_NOT_SET, "bootstrapView", this);
+ }
+ }
/**
- * Check that the schema version properties have been set appropriately
+ * Check that the schema version properties have been set appropriately.
+ * Derived classes can override this method to perform their own validation provided
+ * that this method is called by the derived class.
*/
- private void checkProperties()
+ protected void checkProperties()
{
// check that the necessary properties have been set
- if (id == null || description == null)
- {
- throw new AlfrescoRuntimeException(
- "Patch properties 'id', 'fixesFromSchema' and 'description' have not all been set on this patch: \n" +
- " patch: " + this);
- }
- else if (fixesFromSchema == -1 || fixesToSchema == -1 || targetSchema == -1)
+ checkPropertyNotNull(id, "id");
+ checkPropertyNotNull(description, "description");
+ checkPropertyNotNull(transactionService, "transactionService");
+ if (fixesFromSchema == -1 || fixesToSchema == -1 || targetSchema == -1)
{
throw new AlfrescoRuntimeException(
"Patch properties 'fixesFromSchema', 'fixesToSchema' and 'targetSchema' have not all been set on this patch: \n" +
" patch: " + this);
}
- else if (transactionService == null)
- {
- throw new AlfrescoRuntimeException("'transactionService' property has not been set: \n" +
- " patch: " + this);
- }
}
/**
diff --git a/source/java/org/alfresco/repo/admin/patch/impl/GenericBootstrapPatch.java b/source/java/org/alfresco/repo/admin/patch/impl/GenericBootstrapPatch.java
new file mode 100644
index 0000000000..89fcf541aa
--- /dev/null
+++ b/source/java/org/alfresco/repo/admin/patch/impl/GenericBootstrapPatch.java
@@ -0,0 +1,144 @@
+/*
+ * 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.util.Collections;
+import java.util.List;
+import java.util.Properties;
+
+import org.alfresco.i18n.I18NUtil;
+import org.alfresco.repo.admin.patch.AbstractPatch;
+import org.alfresco.repo.importer.ImporterBootstrap;
+import org.alfresco.service.cmr.admin.PatchException;
+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;
+
+/**
+ * Generic patch that uses existing {@link org.alfresco.repo.importer.ImporterBootstrap importers}
+ * to import snippets into the system. These snippets would otherwise have been bootstrapped by
+ * a clean install.
+ *
+ * By providing this class with a bootstrap view and an importer, it can check whether the path
+ * exists and perform the import if it doesn't.
+ *
+ * @author Derek Hulley
+ */
+public class GenericBootstrapPatch extends AbstractPatch
+{
+ private static final String MSG_EXISTS = "patch.genericBootstrap.result.exists";
+ private static final String MSG_CREATED = "patch.genericBootstrap.result.created";
+ private static final String ERR_MULTIPLE_FOUND = "patch.genericBootstrap.err.multiple_found";
+
+ private NamespaceService namespaceService;
+ private NodeService nodeService;
+ private SearchService searchService;
+ private ImporterBootstrap importerBootstrap;
+ private String checkPath;
+ private Properties bootstrapView;
+
+ 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 importerBootstrap the bootstrap bean that performs the user store bootstrap
+ */
+ public void setImporterBootstrap(ImporterBootstrap importerBootstrap)
+ {
+ this.importerBootstrap = importerBootstrap;
+ }
+
+ /**
+ * Set the XPath statement that must be executed to check whether the import data is
+ * already present or not.
+ *
+ * @param checkPath an XPath statement
+ */
+ public void setCheckPath(String checkPath)
+ {
+ this.checkPath = checkPath;
+ }
+
+ /**
+ * @see ImporterBootstrap#setBootstrapViews(List)
+ *
+ * @param bootstrapView the bootstrap location
+ */
+ public void setBootstrapView(Properties bootstrapView)
+ {
+ this.bootstrapView = bootstrapView;
+ }
+
+ @Override
+ protected void checkProperties()
+ {
+ checkPropertyNotNull(namespaceService, "blah");
+ checkPropertyNotNull(nodeService, "nodeService");
+ checkPropertyNotNull(searchService, "searchService");
+ checkPropertyNotNull(importerBootstrap, "importerBootstrap");
+ checkPropertyNotNull(checkPath, "checkPath");
+ checkPropertyNotNull(bootstrapView, "bootstrapView");
+ // fulfil contract of override
+ super.checkProperties();
+ }
+
+ @Override
+ protected String applyInternal() throws Exception
+ {
+ StoreRef storeRef = importerBootstrap.getStoreRef();
+ NodeRef rootNodeRef = nodeService.getRootNode(storeRef);
+ List results = searchService.selectNodes(
+ rootNodeRef,
+ checkPath,
+ null,
+ namespaceService,
+ false);
+ if (results.size() > 1)
+ {
+ throw new PatchException(ERR_MULTIPLE_FOUND, checkPath);
+ }
+ else if (results.size() == 1)
+ {
+ // nothing to do - it exsists
+ return I18NUtil.getMessage(MSG_EXISTS, checkPath);
+
+ }
+ String path = bootstrapView.getProperty("path");
+ List bootstrapViews = Collections.singletonList(bootstrapView);
+ // modify the bootstrapper
+ importerBootstrap.setBootstrapViews(bootstrapViews);
+ importerBootstrap.setUseExistingStore(true); // allow import into existing store
+
+ importerBootstrap.bootstrap();
+ // done
+ return I18NUtil.getMessage(MSG_CREATED, path, rootNodeRef);
+ }
+}
diff --git a/source/java/org/alfresco/repo/descriptor/DescriptorServiceImpl.java b/source/java/org/alfresco/repo/descriptor/DescriptorServiceImpl.java
index d2ad5ee7e7..7e05f84dea 100644
--- a/source/java/org/alfresco/repo/descriptor/DescriptorServiceImpl.java
+++ b/source/java/org/alfresco/repo/descriptor/DescriptorServiceImpl.java
@@ -18,6 +18,8 @@ package org.alfresco.repo.descriptor;
import java.io.IOException;
import java.io.Serializable;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -34,12 +36,18 @@ import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.descriptor.Descriptor;
import org.alfresco.service.descriptor.DescriptorService;
+import org.alfresco.service.license.LicenseDescriptor;
+import org.alfresco.service.license.LicenseException;
+import org.alfresco.service.license.LicenseService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
@@ -51,10 +59,12 @@ import org.springframework.core.io.Resource;
*
* @author David Caruana
*/
-public class DescriptorServiceImpl implements DescriptorService, ApplicationListener, InitializingBean
+public class DescriptorServiceImpl implements DescriptorService, ApplicationListener, InitializingBean, ApplicationContextAware
{
private static Log logger = LogFactory.getLog(DescriptorServiceImpl.class);
+ private ApplicationContext applicationContext;
+
private Properties serverProperties;
private ImporterBootstrap systemBootstrap;
@@ -62,11 +72,19 @@ public class DescriptorServiceImpl implements DescriptorService, ApplicationList
private NodeService nodeService;
private SearchService searchService;
private TransactionService transactionService;
+ private LicenseService licenseService = null;
private Descriptor serverDescriptor;
private Descriptor installedRepoDescriptor;
+
-
+ /* (non-Javadoc)
+ * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
+ */
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
+ {
+ this.applicationContext = applicationContext;
+ }
/**
* Sets the server descriptor from a resource file
@@ -120,7 +138,7 @@ public class DescriptorServiceImpl implements DescriptorService, ApplicationList
{
this.searchService = searchService;
}
-
+
/* (non-Javadoc)
* @see org.alfresco.service.descriptor.DescriptorService#getDescriptor()
*/
@@ -137,6 +155,14 @@ public class DescriptorServiceImpl implements DescriptorService, ApplicationList
return installedRepoDescriptor;
}
+ /* (non-Javadoc)
+ * @see org.alfresco.service.descriptor.DescriptorService#getLicenseDescriptor()
+ */
+ public LicenseDescriptor getLicenseDescriptor()
+ {
+ return licenseService.getLicense();
+ }
+
/**
* @param event
*/
@@ -150,9 +176,12 @@ public class DescriptorServiceImpl implements DescriptorService, ApplicationList
{
public Descriptor doWork()
{
+ // verify license, but only if license component is installed
+ licenseService.verifyLicense();
+
// persist the server descriptor values
updateCurrentRepositoryDescriptor(serverDescriptor);
-
+
// return the repository installed descriptor
return createInstalledRepositoryDescriptor();
}
@@ -168,6 +197,9 @@ public class DescriptorServiceImpl implements DescriptorService, ApplicationList
{
// initialise server descriptor
serverDescriptor = createServerDescriptor();
+
+ // initialise license service (if installed)
+ initialiseLicenseService();
}
/**
@@ -306,6 +338,77 @@ public class DescriptorServiceImpl implements DescriptorService, ApplicationList
return descriptorNodeRef;
}
+ /**
+ * Initialise License Service
+ */
+ private void initialiseLicenseService()
+ {
+ try
+ {
+ // NOTE: We could tie in the License Component via Spring configuration, but then it could
+ // be declaratively taken out in an installed environment.
+ Class licenseComponentClass = Class.forName("org.alfresco.license.LicenseComponent");
+ Constructor constructor = licenseComponentClass.getConstructor(new Class[] { ApplicationContext.class} );
+ licenseService = (LicenseService)constructor.newInstance(new Object[] { applicationContext } );
+ }
+ catch (ClassNotFoundException e)
+ {
+ licenseService = new NOOPLicenseService();
+ }
+ catch (SecurityException e)
+ {
+ throw new AlfrescoRuntimeException("Failed to initialise license service", e);
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw new AlfrescoRuntimeException("Failed to initialise license service", e);
+ }
+ catch (NoSuchMethodException e)
+ {
+ throw new AlfrescoRuntimeException("Failed to initialise license service", e);
+ }
+ catch (InvocationTargetException e)
+ {
+ throw new AlfrescoRuntimeException("Failed to initialise license service", e);
+ }
+ catch (InstantiationException e)
+ {
+ throw new AlfrescoRuntimeException("Failed to initialise license service", e);
+ }
+ catch (IllegalAccessException e)
+ {
+ throw new AlfrescoRuntimeException("Failed to initialise license service", e);
+ }
+ }
+
+ /**
+ * Dummy License Service
+ */
+ private class NOOPLicenseService implements LicenseService
+ {
+ /* (non-Javadoc)
+ * @see org.alfresco.service.license.LicenseService#install()
+ */
+ public void installLicense() throws LicenseException
+ {
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.service.license.LicenseService#verify()
+ */
+ public void verifyLicense() throws LicenseException
+ {
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.service.license.LicenseService#getLicense()
+ */
+ public LicenseDescriptor getLicense() throws LicenseException
+ {
+ return null;
+ }
+ }
+
/**
* Unknown descriptor
*
diff --git a/source/java/org/alfresco/repo/descriptor/DescriptorStartupLog.java b/source/java/org/alfresco/repo/descriptor/DescriptorStartupLog.java
index 8870123bd0..3ad304833a 100644
--- a/source/java/org/alfresco/repo/descriptor/DescriptorStartupLog.java
+++ b/source/java/org/alfresco/repo/descriptor/DescriptorStartupLog.java
@@ -16,10 +16,12 @@
*/
package org.alfresco.repo.descriptor;
+import java.util.Date;
import java.util.Map;
import org.alfresco.service.descriptor.Descriptor;
import org.alfresco.service.descriptor.DescriptorService;
+import org.alfresco.service.license.LicenseDescriptor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationEvent;
@@ -79,6 +81,27 @@ public class DescriptorStartupLog implements ApplicationListener
logger.warn(String.format("Alfresco JVM - WARNING - maximum heap size %.3fMB is less than recommended 512MB", maxHeapMB));
}
}
+
+ // Log License Descriptors (if applicable)
+ LicenseDescriptor license = descriptorService.getLicenseDescriptor();
+ if (license != null && logger.isInfoEnabled())
+ {
+ String subject = license.getSubject();
+ String msg = "Alfresco license: " + subject;
+ Date validUntil = license.getValidUntil();
+ if (validUntil != null)
+ {
+ Integer days = license.getDays();
+ Integer remainingDays = license.getRemainingDays();
+
+ msg += " limited to " + days + " days expiring " + validUntil + " (" + remainingDays + " days remaining)";
+ }
+ else
+ {
+ msg += " (does not expire)";
+ }
+ logger.info(msg);
+ }
// Log Repository Descriptors
if (logger.isInfoEnabled())
@@ -90,16 +113,8 @@ public class DescriptorStartupLog implements ApplicationListener
int serverSchemaVersion = serverDescriptor.getSchema();
String installedRepoVersion = installedRepoDescriptor.getVersion();
int installedSchemaVersion = installedRepoDescriptor.getSchema();
- logger.info(
- String.format(
- "Alfresco started (%s): " +
- "Current version %s schema %d - " +
- "Installed version %s schema %d",
- serverEdition,
- serverVersion,
- serverSchemaVersion,
- installedRepoVersion,
- installedSchemaVersion));
+ logger.info(String.format("Alfresco started (%s): Current version %s schema %d - Installed version %s schema %d",
+ serverEdition, serverVersion, serverSchemaVersion, installedRepoVersion, installedSchemaVersion));
}
}
}
diff --git a/source/java/org/alfresco/repo/importer/ImporterBootstrap.java b/source/java/org/alfresco/repo/importer/ImporterBootstrap.java
index 6efb178564..0c17c9d103 100644
--- a/source/java/org/alfresco/repo/importer/ImporterBootstrap.java
+++ b/source/java/org/alfresco/repo/importer/ImporterBootstrap.java
@@ -72,6 +72,7 @@ public class ImporterBootstrap implements ApplicationListener
// Dependencies
private boolean allowWrite = true;
+ private boolean useExistingStore = false;
private TransactionService transactionService;
private NamespaceService namespaceService;
private NodeService nodeService;
@@ -94,6 +95,18 @@ public class ImporterBootstrap implements ApplicationListener
this.allowWrite = write;
}
+ /**
+ * Set whether the importer bootstrap should only perform an import if the store
+ * being referenced doesn't already exist.
+ *
+ * @param useExistingStore true to allow imports into an existing store,
+ * otherwise false (default) to only import if the store doesn't exist.
+ */
+ public void setUseExistingStore(boolean useExistingStore)
+ {
+ this.useExistingStore = useExistingStore;
+ }
+
/**
* Sets the Transaction Service
*
@@ -305,11 +318,13 @@ public class ImporterBootstrap implements ApplicationListener
}
else
{
- // create the store
- storeRef = nodeService.createStore(storeRef.getProtocol(), storeRef.getIdentifier());
-
- if (logger.isDebugEnabled())
- logger.debug("Created store: " + storeRef);
+ // create the store if necessary
+ if (!nodeService.exists(storeRef))
+ {
+ storeRef = nodeService.createStore(storeRef.getProtocol(), storeRef.getIdentifier());
+ if (logger.isDebugEnabled())
+ logger.debug("Created store: " + storeRef);
+ }
// bootstrap the store contents
if (bootstrapViews != null)
@@ -538,12 +553,16 @@ public class ImporterBootstrap implements ApplicationListener
*/
private boolean performBootstrap()
{
- if (nodeService.exists(storeRef))
+ if (useExistingStore)
+ {
+ // it doesn't matter if the store exists or not
+ return true;
+ }
+ else if (nodeService.exists(storeRef))
{
return false;
}
-
- if (mustNotExistStoreUrls != null)
+ else if (mustNotExistStoreUrls != null)
{
for (String storeUrl : mustNotExistStoreUrls)
{
diff --git a/source/java/org/alfresco/repo/rule/RulesAspect.java b/source/java/org/alfresco/repo/rule/RulesAspect.java
index 8a8f4c623d..9771da3872 100644
--- a/source/java/org/alfresco/repo/rule/RulesAspect.java
+++ b/source/java/org/alfresco/repo/rule/RulesAspect.java
@@ -115,11 +115,15 @@ public class RulesAspect
this.ruleService.disableRules(nodeRef);
try
{
- this.nodeService.createNode(
- nodeRef,
- RuleModel.ASSOC_RULE_FOLDER,
- RuleModel.ASSOC_RULE_FOLDER,
- ContentModel.TYPE_SYSTEM_FOLDER);
+ int count = this.nodeService.getChildAssocs(nodeRef, RuleModel.ASSOC_RULE_FOLDER, RuleModel.ASSOC_RULE_FOLDER).size();
+ if (count == 0)
+ {
+ this.nodeService.createNode(
+ nodeRef,
+ RuleModel.ASSOC_RULE_FOLDER,
+ RuleModel.ASSOC_RULE_FOLDER,
+ ContentModel.TYPE_SYSTEM_FOLDER);
+ }
}
finally
{
diff --git a/source/java/org/alfresco/repo/search/impl/lucene/LuceneAnalyser.java b/source/java/org/alfresco/repo/search/impl/lucene/LuceneAnalyser.java
index 732010a3d8..f59560a93a 100644
--- a/source/java/org/alfresco/repo/search/impl/lucene/LuceneAnalyser.java
+++ b/source/java/org/alfresco/repo/search/impl/lucene/LuceneAnalyser.java
@@ -108,29 +108,17 @@ public class LuceneAnalyser extends Analyzer
{
analyser = new WhitespaceAnalyzer();
}
+ else if (fieldName.equals("TEXT"))
+ {
+ DataTypeDefinition dataType = dictionaryService.getDataType(DataTypeDefinition.TEXT);
+ analyser = loadAnalyzer(dataType);
+ }
else if (fieldName.startsWith("@"))
{
QName propertyQName = QName.createQName(fieldName.substring(1));
PropertyDefinition propertyDef = dictionaryService.getProperty(propertyQName);
DataTypeDefinition dataType = (propertyDef == null) ? dictionaryService.getDataType(DataTypeDefinition.TEXT) : propertyDef.getDataType();
- String analyserClassName = dataType.getAnalyserClassName();
- try
- {
- Class> clazz = Class.forName(analyserClassName);
- analyser = (Analyzer)clazz.newInstance();
- }
- catch (ClassNotFoundException e)
- {
- throw new RuntimeException("Unable to load analyser for property " + fieldName.substring(1) + " of type " + dataType.getName() + " using " + analyserClassName);
- }
- catch (InstantiationException e)
- {
- throw new RuntimeException("Unable to load analyser for property " + fieldName.substring(1) + " of type " + dataType.getName() + " using " + analyserClassName);
- }
- catch (IllegalAccessException e)
- {
- throw new RuntimeException("Unable to load analyser for property " + fieldName.substring(1) + " of type " + dataType.getName() + " using " + analyserClassName);
- }
+ analyser = loadAnalyzer(dataType);
}
else
{
@@ -139,4 +127,28 @@ public class LuceneAnalyser extends Analyzer
analysers.put(fieldName, analyser);
return analyser;
}
+
+ private Analyzer loadAnalyzer(DataTypeDefinition dataType)
+ {
+ String analyserClassName = dataType.getAnalyserClassName();
+ try
+ {
+ Class> clazz = Class.forName(analyserClassName);
+ Analyzer analyser = (Analyzer)clazz.newInstance();
+ return analyser;
+ }
+ catch (ClassNotFoundException e)
+ {
+ throw new RuntimeException("Unable to load analyser for property of type " + dataType.getName() + " using " + analyserClassName);
+ }
+ catch (InstantiationException e)
+ {
+ throw new RuntimeException("Unable to load analyser for property of type " + dataType.getName() + " using " + analyserClassName);
+ }
+ catch (IllegalAccessException e)
+ {
+ throw new RuntimeException("Unable to load analyser for property of type " + dataType.getName() + " using " + analyserClassName);
+ }
+ }
+
}
diff --git a/source/java/org/alfresco/repo/security/authentication/DefaultMutableAuthenticationDao.java b/source/java/org/alfresco/repo/security/authentication/DefaultMutableAuthenticationDao.java
index 267d907b4f..55fbf2d4cc 100644
--- a/source/java/org/alfresco/repo/security/authentication/DefaultMutableAuthenticationDao.java
+++ b/source/java/org/alfresco/repo/security/authentication/DefaultMutableAuthenticationDao.java
@@ -80,16 +80,6 @@ public class DefaultMutableAuthenticationDao implements MutableAuthenticationDao
return true;
}
- /**
- * Get the store ref where user objects are persisted.
- *
- * @return
- */
- public StoreRef getUserStoreRef()
- {
- throw new AlfrescoRuntimeException("Not implemented");
- }
-
/**
* Enable/disable a user.
*
diff --git a/source/java/org/alfresco/repo/security/authentication/MutableAuthenticationDao.java b/source/java/org/alfresco/repo/security/authentication/MutableAuthenticationDao.java
index cee31c0a31..22389bbc4a 100644
--- a/source/java/org/alfresco/repo/security/authentication/MutableAuthenticationDao.java
+++ b/source/java/org/alfresco/repo/security/authentication/MutableAuthenticationDao.java
@@ -21,8 +21,6 @@ import java.util.Date;
import net.sf.acegisecurity.providers.dao.AuthenticationDao;
import net.sf.acegisecurity.providers.dao.SaltSource;
-import org.alfresco.service.cmr.repository.StoreRef;
-
/**
* A service provider interface to provide both acegi integration via AuthenticationDao and SaltSource
* and mutability support for user definitions.
@@ -65,14 +63,6 @@ public interface MutableAuthenticationDao extends AuthenticationDao, SaltSource
*/
public boolean userExists(String userName);
-
- /**
- * Get the store ref where user objects are persisted.
- *
- * @return
- */
- public StoreRef getUserStoreRef();
-
/**
* Enable/disable a user.
*
diff --git a/source/java/org/alfresco/repo/security/authentication/RepositoryAuthenticationDao.java b/source/java/org/alfresco/repo/security/authentication/RepositoryAuthenticationDao.java
index baa90beb8f..d9a544d25d 100644
--- a/source/java/org/alfresco/repo/security/authentication/RepositoryAuthenticationDao.java
+++ b/source/java/org/alfresco/repo/security/authentication/RepositoryAuthenticationDao.java
@@ -29,16 +29,14 @@ import net.sf.acegisecurity.providers.dao.User;
import net.sf.acegisecurity.providers.dao.UsernameNotFoundException;
import net.sf.acegisecurity.providers.encoding.PasswordEncoder;
+import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
-import org.alfresco.repo.search.QueryParameterDefImpl;
-import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
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.repository.datatype.DefaultTypeConverter;
-import org.alfresco.service.cmr.search.QueryParameterDefinition;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.ResultSetRow;
import org.alfresco.service.cmr.search.SearchParameters;
@@ -50,10 +48,7 @@ import org.springframework.dao.DataAccessException;
public class RepositoryAuthenticationDao implements MutableAuthenticationDao
{
-
- private static final String SYSTEM_FOLDER = "/sys:system";
-
- private static final String PEOPLE_FOLDER = SYSTEM_FOLDER + "/sys:people";
+ private static final StoreRef STOREREF_USERS = new StoreRef("user", "alfrescoUserStore");
private NodeService nodeService;
@@ -65,8 +60,6 @@ public class RepositoryAuthenticationDao implements MutableAuthenticationDao
private PasswordEncoder passwordEncoder;
- private StoreRef userStoreRef;
-
private boolean userNamesAreCaseSensitive;
public boolean getUserNamesAreCaseSensitive()
@@ -132,7 +125,7 @@ public class RepositoryAuthenticationDao implements MutableAuthenticationDao
SearchParameters sp = new SearchParameters();
sp.setLanguage(SearchService.LANGUAGE_LUCENE);
sp.setQuery("@usr\\:username:" + userName);
- sp.addStore(getUserStoreRef());
+ sp.addStore(STOREREF_USERS);
sp.excludeDataInTheCurrentTransaction(false);
ResultSet rs = null;
@@ -175,7 +168,7 @@ public class RepositoryAuthenticationDao implements MutableAuthenticationDao
{
throw new AuthenticationException("User already exists: " + userName);
}
- NodeRef typesNode = getOrCreateTypeLocation();
+ NodeRef typesNode = getUserFolderLocation();
Map properties = new HashMap();
properties.put(ContentModel.PROP_USER_USERNAME, userName);
String salt = null; // GUID.generate();
@@ -185,41 +178,47 @@ public class RepositoryAuthenticationDao implements MutableAuthenticationDao
properties.put(ContentModel.PROP_CREDENTIALS_EXPIRE, Boolean.valueOf(false));
properties.put(ContentModel.PROP_ENABLED, Boolean.valueOf(true));
properties.put(ContentModel.PROP_ACCOUNT_LOCKED, Boolean.valueOf(false));
- nodeService.createNode(typesNode, ContentModel.ASSOC_CHILDREN, ContentModel.TYPE_USER, ContentModel.TYPE_USER,
+ nodeService.createNode(
+ typesNode,
+ ContentModel.ASSOC_CHILDREN,
+ ContentModel.TYPE_USER,
+ ContentModel.TYPE_USER,
properties);
}
- private NodeRef getOrCreateTypeLocation()
+ private NodeRef getUserFolderLocation()
{
- NodeRef rootNode = nodeService.getRootNode(getUserStoreRef());
- List results = nodeService.getChildAssocs(rootNode, RegexQNamePattern.MATCH_ALL, QName
- .createQName("sys", "system", namespacePrefixResolver));
- NodeRef sysNode = null;
+ QName qnameAssocSystem = QName.createQName("sys", "system", namespacePrefixResolver);
+ QName qnameAssocUsers = QName.createQName("sys", "people", namespacePrefixResolver); // see AR-527
+ NodeRef rootNode = nodeService.getRootNode(STOREREF_USERS);
+ List results = nodeService.getChildAssocs(
+ rootNode,
+ RegexQNamePattern.MATCH_ALL,
+ qnameAssocSystem);
+ NodeRef sysNodeRef = null;
if (results.size() == 0)
{
- sysNode = nodeService.createNode(rootNode, ContentModel.ASSOC_CHILDREN,
- QName.createQName("sys", "system", namespacePrefixResolver), ContentModel.TYPE_CONTAINER)
- .getChildRef();
+ throw new AlfrescoRuntimeException("Required authority system folder path not found: " + qnameAssocSystem);
}
else
{
- sysNode = results.get(0).getChildRef();
+ sysNodeRef = results.get(0).getChildRef();
}
- results = nodeService.getChildAssocs(sysNode, RegexQNamePattern.MATCH_ALL, QName.createQName("sys", "people",
- namespacePrefixResolver));
- NodeRef typesNode = null;
+ results = nodeService.getChildAssocs(
+ sysNodeRef,
+ RegexQNamePattern.MATCH_ALL,
+ qnameAssocUsers);
+ NodeRef userNodeRef = null;
if (results.size() == 0)
{
- typesNode = nodeService.createNode(sysNode, ContentModel.ASSOC_CHILDREN,
- QName.createQName("sys", "people", namespacePrefixResolver), ContentModel.TYPE_CONTAINER)
- .getChildRef();
+ throw new AlfrescoRuntimeException("Required user folder path not found: " + qnameAssocUsers);
}
else
{
- typesNode = results.get(0).getChildRef();
+ userNodeRef = results.get(0).getChildRef();
}
- return typesNode;
+ return userNodeRef;
}
public void updateUser(String userName, char[] rawPassword) throws AuthenticationException
@@ -248,20 +247,6 @@ public class RepositoryAuthenticationDao implements MutableAuthenticationDao
nodeService.deleteNode(userRef);
}
- public synchronized StoreRef getUserStoreRef()
- {
- if (userStoreRef == null)
- {
- userStoreRef = new StoreRef("user", "alfrescoUserStore");
- }
- if (!nodeService.exists(userStoreRef))
- {
- nodeService.createStore(userStoreRef.getProtocol(), userStoreRef.getIdentifier());
- }
-
- return userStoreRef;
- }
-
public Object getSalt(UserDetails userDetails)
{
// NodeRef userRef = getUserOrNull(userDetails.getUsername());
diff --git a/source/java/org/alfresco/repo/security/permissions/impl/model/PermissionModelTest.java b/source/java/org/alfresco/repo/security/permissions/impl/model/PermissionModelTest.java
index 39a4eecf2d..861d8678eb 100644
--- a/source/java/org/alfresco/repo/security/permissions/impl/model/PermissionModelTest.java
+++ b/source/java/org/alfresco/repo/security/permissions/impl/model/PermissionModelTest.java
@@ -26,7 +26,7 @@ import org.alfresco.service.namespace.QName;
public class PermissionModelTest extends AbstractPermissionTest
{
-
+
public PermissionModelTest()
{
super();
@@ -40,6 +40,30 @@ public class PermissionModelTest extends AbstractPermissionTest
assertEquals(5, grantees.size());
}
+ public void testIncludePermissionGroups2()
+ {
+ Set grantees = permissionModelDAO.getGranteePermissions(new SimplePermissionReference(QName.createQName("cm", "cmobject",
+ namespacePrefixResolver), "Contributor"));
+
+ assertEquals(11, grantees.size());
+ }
+
+ public void testIncludePermissionGroups3()
+ {
+ Set grantees = permissionModelDAO.getGranteePermissions(new SimplePermissionReference(QName.createQName("cm", "cmobject",
+ namespacePrefixResolver), "Editor"));
+
+ assertEquals(11, grantees.size());
+ }
+
+ public void testIncludePermissionGroups4()
+ {
+ Set grantees = permissionModelDAO.getGranteePermissions(new SimplePermissionReference(QName.createQName("cm", "cmobject",
+ namespacePrefixResolver), "Collaborator"));
+
+ assertEquals(16, grantees.size());
+ }
+
public void testGetGrantingPermissions()
{
Set granters = permissionModelDAO.getGrantingPermissions(new SimplePermissionReference(QName.createQName("sys", "base",
diff --git a/source/java/org/alfresco/repo/security/person/PersonServiceImpl.java b/source/java/org/alfresco/repo/security/person/PersonServiceImpl.java
index 29f1bb4427..7acae79d16 100644
--- a/source/java/org/alfresco/repo/security/person/PersonServiceImpl.java
+++ b/source/java/org/alfresco/repo/security/person/PersonServiceImpl.java
@@ -25,9 +25,9 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
+import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.permissions.PermissionServiceSPI;
-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;
@@ -41,7 +41,6 @@ import org.alfresco.service.cmr.security.NoSuchPersonException;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.alfresco.service.namespace.QName;
-import org.alfresco.service.namespace.RegexQNamePattern;
public class PersonServiceImpl implements PersonService
{
@@ -148,8 +147,9 @@ public class PersonServiceImpl implements PersonService
NodeRef nodeRef = row.getNodeRef();
if (nodeService.exists(nodeRef))
{
- String realUserName = DefaultTypeConverter.INSTANCE.convert(String.class, nodeService.getProperty(
- nodeRef, ContentModel.PROP_USERNAME));
+ String realUserName = DefaultTypeConverter.INSTANCE.convert(
+ String.class,
+ nodeService.getProperty(nodeRef, ContentModel.PROP_USERNAME));
realUserName = userNamesAreCaseSensitive ? realUserName : realUserName.toLowerCase();
if (realUserName.equals(userName))
{
@@ -235,47 +235,26 @@ public class PersonServiceImpl implements PersonService
.get(ContentModel.PROP_USERNAME));
String userName = userNamesAreCaseSensitive ? caseSensitiveUserName : caseSensitiveUserName.toLowerCase();
properties.put(ContentModel.PROP_USERNAME, userName);
- return nodeService.createNode(getPeopleContainer(), ContentModel.ASSOC_CHILDREN, ContentModel.TYPE_PERSON,
- ContentModel.TYPE_PERSON, properties).getChildRef();
+ return nodeService.createNode(
+ getPeopleContainer(),
+ ContentModel.ASSOC_CHILDREN,
+ ContentModel.TYPE_PERSON,
+ ContentModel.TYPE_PERSON,
+ properties).getChildRef();
}
public NodeRef getPeopleContainer()
{
NodeRef rootNodeRef = nodeService.getRootNode(storeRef);
- List results = searchService.selectNodes(rootNodeRef, PEOPLE_FOLDER, null, namespacePrefixResolver,
+ List results = searchService.selectNodes(
+ rootNodeRef,
+ PEOPLE_FOLDER,
+ null,
+ namespacePrefixResolver,
false);
- NodeRef typesNode = null;
if (results.size() == 0)
{
-
- List result = nodeService.getChildAssocs(rootNodeRef, RegexQNamePattern.MATCH_ALL,
- QName.createQName("sys", "system", namespacePrefixResolver));
- NodeRef sysNode = null;
- if (result.size() == 0)
- {
- sysNode = nodeService.createNode(rootNodeRef, ContentModel.ASSOC_CHILDREN,
- QName.createQName("sys", "system", namespacePrefixResolver), ContentModel.TYPE_CONTAINER)
- .getChildRef();
- }
- else
- {
- sysNode = result.get(0).getChildRef();
- }
- result = nodeService.getChildAssocs(sysNode, RegexQNamePattern.MATCH_ALL, QName.createQName("sys",
- "people", namespacePrefixResolver));
-
- if (result.size() == 0)
- {
- typesNode = nodeService.createNode(sysNode, ContentModel.ASSOC_CHILDREN,
- QName.createQName("sys", "people", namespacePrefixResolver), ContentModel.TYPE_CONTAINER)
- .getChildRef();
- return typesNode;
- }
- else
- {
- return result.get(0).getChildRef();
- }
-
+ throw new AlfrescoRuntimeException("Required people system path not found: " + PEOPLE_FOLDER);
}
else
{
diff --git a/source/java/org/alfresco/service/cmr/admin/PatchException.java b/source/java/org/alfresco/service/cmr/admin/PatchException.java
index bcf1f78a17..54cc7a6c1e 100644
--- a/source/java/org/alfresco/service/cmr/admin/PatchException.java
+++ b/source/java/org/alfresco/service/cmr/admin/PatchException.java
@@ -27,21 +27,20 @@ public class PatchException extends AlfrescoRuntimeException
{
private static final long serialVersionUID = 7022368915143884315L;
- private String report;
-
/**
- * @param report the patch failure report
+ * @param msgId the patch failure message ID
*/
- public PatchException(String report)
+ public PatchException(String msgId)
{
- super(report);
+ super(msgId);
}
/**
- * @return Returns the patch failure report
+ * @param msgId the patch failure message ID
+ * @param args variable number of message arguments
*/
- public String getReport()
+ public PatchException(String msgId, Object ... args)
{
- return report;
+ super(msgId, args);
}
}
diff --git a/source/java/org/alfresco/service/cmr/model/FileFolderService.java b/source/java/org/alfresco/service/cmr/model/FileFolderService.java
index 16cf4c162f..9b828dcc4a 100644
--- a/source/java/org/alfresco/service/cmr/model/FileFolderService.java
+++ b/source/java/org/alfresco/service/cmr/model/FileFolderService.java
@@ -61,6 +61,14 @@ public interface FileFolderService
* Searches for all files and folders with the matching name pattern,
* using wildcard characters * and ?.
*
+ * @param contextNodeRef the context of the search. This node will never be returned
+ * as part of the search results.
+ * @param namePattern the name of the file or folder to search for, or a
+ * {@link org.alfresco.util.SearchLanguageConversion#DEF_LUCENE wildcard} pattern
+ * to search for.
+ * @param includeSubFolders true to search the entire hierarchy below the search context
+ * @return Returns a list of file or folder matches
+ *
* @see #search(NodeRef, String, boolean, boolean, boolean)
*/
public List search(
diff --git a/source/java/org/alfresco/service/descriptor/DescriptorService.java b/source/java/org/alfresco/service/descriptor/DescriptorService.java
index 3096ea7fb3..54f13a3d7d 100644
--- a/source/java/org/alfresco/service/descriptor/DescriptorService.java
+++ b/source/java/org/alfresco/service/descriptor/DescriptorService.java
@@ -16,6 +16,8 @@
*/
package org.alfresco.service.descriptor;
+import org.alfresco.service.license.LicenseDescriptor;
+
/**
* Service for retrieving meta-data about Alfresco stack.
@@ -40,4 +42,12 @@ public interface DescriptorService
* @return repository descriptor
*/
public Descriptor getInstalledRepositoryDescriptor();
+
+ /**
+ * Gets the License Service
+ *
+ * @return the license service
+ */
+ public LicenseDescriptor getLicenseDescriptor();
+
}
diff --git a/source/java/org/alfresco/service/license/LicenseDescriptor.java b/source/java/org/alfresco/service/license/LicenseDescriptor.java
new file mode 100644
index 0000000000..81f2e75aad
--- /dev/null
+++ b/source/java/org/alfresco/service/license/LicenseDescriptor.java
@@ -0,0 +1,80 @@
+/*
+ * 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.service.license;
+
+import java.security.Principal;
+import java.util.Date;
+
+
+/**
+ * Provides access to License information.
+ *
+ * @author davidc
+ */
+public interface LicenseDescriptor
+{
+
+ /**
+ * Gets the date license was issued
+ *
+ * @return issue date
+ */
+ public Date getIssued();
+
+ /**
+ * Gets the date license is valid till
+ *
+ * @return valid until date (or null, if no time limit)
+ */
+ public Date getValidUntil();
+
+ /**
+ * Gets the length (in days) of license validity
+ *
+ * @return length in days of license validity (or null, if no time limit)
+ */
+ public Integer getDays();
+
+ /**
+ * Ges the number of remaining days left on license
+ *
+ * @return remaining days (or null, if no time limit)
+ */
+ public Integer getRemainingDays();
+
+ /**
+ * Gets the subject of the license
+ *
+ * @return the subject
+ */
+ public String getSubject();
+
+ /**
+ * Gets the holder of the license
+ *
+ * @return the holder
+ */
+ public Principal getHolder();
+
+ /**
+ * Gets the issuer of the license
+ *
+ * @return the issuer
+ */
+ public Principal getIssuer();
+
+}
diff --git a/source/java/org/alfresco/service/license/LicenseException.java b/source/java/org/alfresco/service/license/LicenseException.java
new file mode 100644
index 0000000000..e5a44fbb3d
--- /dev/null
+++ b/source/java/org/alfresco/service/license/LicenseException.java
@@ -0,0 +1,40 @@
+/*
+ * 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.service.license;
+
+
+/**
+ * Base Exception of License Exceptions.
+ *
+ * @author David Caruana
+ */
+public class LicenseException extends RuntimeException
+{
+ private static final long serialVersionUID = -6463994144095426247L;
+
+
+ public LicenseException(String msg)
+ {
+ super(msg);
+ }
+
+ public LicenseException(String msg, Throwable cause)
+ {
+ super(msg, cause);
+ }
+
+}
diff --git a/source/java/org/alfresco/service/license/LicenseService.java b/source/java/org/alfresco/service/license/LicenseService.java
new file mode 100644
index 0000000000..e0ae017b24
--- /dev/null
+++ b/source/java/org/alfresco/service/license/LicenseService.java
@@ -0,0 +1,43 @@
+/*
+ * 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.service.license;
+
+
+/**
+ * Contract for managing licenses
+ *
+ * @author davidc
+ */
+public interface LicenseService
+{
+
+ /**
+ * Verify License
+ *
+ * @throws LicenseException
+ */
+ public void verifyLicense() throws LicenseException;
+
+ /**
+ * Get description of installed license
+ *
+ * @return license descriptor (or null, if one is not installed)
+ * @throws LicenseException
+ */
+ public LicenseDescriptor getLicense() throws LicenseException;
+
+}
diff --git a/source/java/org/alfresco/util/SearchLanguageConversion.java b/source/java/org/alfresco/util/SearchLanguageConversion.java
index 856f2723d2..b5be2f5d76 100644
--- a/source/java/org/alfresco/util/SearchLanguageConversion.java
+++ b/source/java/org/alfresco/util/SearchLanguageConversion.java
@@ -49,6 +49,16 @@ public class SearchLanguageConversion
* Lucene syntax summary: {@link QueryParser#escape(String) Lucene Query Parser}
*/
public static LanguageDefinition DEF_LUCENE = new LuceneLanguageDef();
+ /**
+ * CIFS name patch query language summary:
+ *
+ * - Escape: \ (but not used)
+ * - Single char search: ?
+ * - Multiple char search: *
+ * - Reserved: "*\<>?/:|£%&+;
+ *
+ */
+ public static LanguageDefinition DEF_CIFS = new SimpleLanguageDef('\\', "*", "?", "\"*\\<>?/:|£%&+;");
/**
* Escape a string according to the XPath like function syntax.
@@ -128,6 +138,18 @@ public class SearchLanguageConversion
return convert(DEF_XPATH_LIKE, DEF_LUCENE, xpathLikeClause);
}
+ /**
+ * Convert a CIFS name path into the equivalent Lucene query.
+ *
+ * @param cifsNamePath the CIFS named path
+ * @return Returns a valid Lucene expression that is equivalent to the
+ * given CIFS name path
+ */
+ public static String convertCifsToLucene(String cifsNamePath)
+ {
+ return convert(DEF_CIFS, DEF_LUCENE, cifsNamePath);
+ }
+
public static String convert(LanguageDefinition from, LanguageDefinition to, String query)
{
char[] chars = query.toCharArray();