diff --git a/config/alfresco/bootstrap/system.xml b/config/alfresco/bootstrap/system.xml
index 95a9200224..fc618e8a1b 100644
--- a/config/alfresco/bootstrap/system.xml
+++ b/config/alfresco/bootstrap/system.xml
@@ -53,6 +53,7 @@
/${spaces.company_home.childname}
bootstrapHomeFolderProvider
+ 0
@@ -69,6 +70,7 @@
/${spaces.company_home.childname}/${spaces.guest_home.childname}
bootstrapHomeFolderProvider
+ 0
diff --git a/config/alfresco/messages/patch-service.properties b/config/alfresco/messages/patch-service.properties
index e150722ae5..a478b89547 100644
--- a/config/alfresco/messages/patch-service.properties
+++ b/config/alfresco/messages/patch-service.properties
@@ -280,3 +280,7 @@ patch.fixNameCrcValues.description=Fixes name CRC32 values to match UTF-8 encodi
patch.fixNameCrcValues.result=Fixed {0} name CRC32 values for UTF-8 encoding. See file {1} for details.
patch.fixNameCrcValues.fixed=Updated CRC32 value for node ID {0}, name ''{1}'': {2} -> {3}.
patch.fixNameCrcValues.unableToChange=Failed to update the CRC32 value for node ID {0}: \n Node name: {1} \n CRC old: {2} \n CRC new: {3} \n Error: {4}
+
+patch.personUsagePatch.description=Add person 'cm:sizeCurrent' property (if missing).
+patch.personUsagePatch.result1=Added 'cm:sizeCurrent' property to {0} people that were missing this property.
+patch.personUsagePatch.result2=No people were missing the 'cm:sizeCurrent' property.
diff --git a/config/alfresco/model/contentModel.xml b/config/alfresco/model/contentModel.xml
index c77f28a7a3..670d0ce538 100644
--- a/config/alfresco/model/contentModel.xml
+++ b/config/alfresco/model/contentModel.xml
@@ -250,6 +250,7 @@
d:long
true
+ true
d:long
diff --git a/config/alfresco/patch/patch-services-context.xml b/config/alfresco/patch/patch-services-context.xml
index 29bf95fe9d..f8b3ed1a7d 100644
--- a/config/alfresco/patch/patch-services-context.xml
+++ b/config/alfresco/patch/patch-services-context.xml
@@ -1933,4 +1933,22 @@
+
+ patch.personUsagePatch
+ patch.personUsagePatch.description
+ 0
+ 3004
+ 3005
+
+
+
+
+
+ ${spaces.store}
+
+
+
+
+
+
diff --git a/config/alfresco/version.properties b/config/alfresco/version.properties
index ccf92d5bb2..5d2443fa8a 100644
--- a/config/alfresco/version.properties
+++ b/config/alfresco/version.properties
@@ -19,4 +19,4 @@ version.build=@build-number@
# Schema number
-version.schema=3004
+version.schema=3005
diff --git a/source/java/org/alfresco/repo/admin/patch/impl/PersonUsagePatch.java b/source/java/org/alfresco/repo/admin/patch/impl/PersonUsagePatch.java
new file mode 100644
index 0000000000..720f824763
--- /dev/null
+++ b/source/java/org/alfresco/repo/admin/patch/impl/PersonUsagePatch.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2005-2009 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program 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 General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have received a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing"
+ */
+package org.alfresco.repo.admin.patch.impl;
+
+import org.alfresco.i18n.I18NUtil;
+import org.alfresco.model.ContentModel;
+import org.alfresco.repo.admin.patch.AbstractPatch;
+import org.alfresco.repo.node.db.NodeDaoService;
+import org.alfresco.repo.node.db.NodeDaoService.ObjectArrayQueryCallback;
+import org.alfresco.repo.tenant.TenantService;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.StoreRef;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Patch to add person usage ('cm:sizeCurrent') property to person (if missing)
+ *
+ * @author janv
+ */
+public class PersonUsagePatch extends AbstractPatch
+{
+ private static Log logger = LogFactory.getLog(PersonUsagePatch.class);
+
+ /** Success messages. */
+ private static final String MSG_SUCCESS1 = "patch.personUsagePatch.result1";
+ private static final String MSG_SUCCESS2 = "patch.personUsagePatch.result2";
+
+ private NodeDaoService nodeDaoService;
+ private StoreRef personStoreRef;
+ private TenantService tenantService;
+
+
+ public void setNodeDaoService(NodeDaoService nodeDaoService)
+ {
+ this.nodeDaoService = nodeDaoService;
+ }
+
+ public void setPersonStoreUrl(String storeUrl)
+ {
+ this.personStoreRef = new StoreRef(storeUrl);
+ }
+
+ public void setTenantService(TenantService tenantService)
+ {
+ this.tenantService = tenantService;
+ }
+
+
+ @Override
+ protected String applyInternal() throws Exception
+ {
+ logger.info("Checking for people with missing 'cm:sizeCurrent' property ...");
+
+ int count = addPersonSizeCurrentProperty();
+
+ String msg = null;
+ if (count > 0)
+ {
+ logger.info("... missing 'cm:sizeCurrent' property added to "+count+" people");
+ msg = I18NUtil.getMessage(MSG_SUCCESS1, count);
+ }
+ else
+ {
+ logger.info("... no people were missing the 'cm:sizeCurrent' property");
+ msg = I18NUtil.getMessage(MSG_SUCCESS2);
+ }
+
+ return msg;
+ }
+
+ private int addPersonSizeCurrentProperty()
+ {
+ // get people (users) with missing 'cm:sizeCurrent' property
+
+ CountObjectArrayQueryCallback userHandler = new CountObjectArrayQueryCallback();
+
+ nodeDaoService.getUsersWithoutUsageProp(tenantService.getName(personStoreRef), userHandler);
+
+ return userHandler.getCount();
+ }
+
+ private class CountObjectArrayQueryCallback implements ObjectArrayQueryCallback
+ {
+ private int count;
+
+ public CountObjectArrayQueryCallback()
+ {
+ count = 0;
+ }
+
+ public boolean handle(Object[] arr)
+ {
+ String uuid = (String)arr[0];
+
+ nodeService.setProperty(new NodeRef(personStoreRef, uuid), ContentModel.PROP_SIZE_CURRENT, null);
+
+ count++;
+
+ return true; // continue to next node (more required)
+ }
+
+ public int getCount()
+ {
+ return count;
+ }
+ };
+}
diff --git a/source/java/org/alfresco/repo/domain/hibernate/Node.hbm.xml b/source/java/org/alfresco/repo/domain/hibernate/Node.hbm.xml
index b73246e627..90796facd1 100644
--- a/source/java/org/alfresco/repo/domain/hibernate/Node.hbm.xml
+++ b/source/java/org/alfresco/repo/domain/hibernate/Node.hbm.xml
@@ -716,6 +716,22 @@
(p1.string_value != 'System' OR (p1.string_value IS NULL AND n.audit_creator != 'System'))
+
+
+
+ SELECT
+ n.uuid AS uuid
+ FROM
+ alf_node n
+ JOIN alf_store s ON (s.id = n.store_id AND n.type_qname_id = :personTypeQNameID)
+ LEFT JOIN alf_node_properties p1 ON (p1.node_id = n.id AND p1.qname_id = :sizeCurrentPropQNameID)
+ WHERE
+ s.protocol = :storeProtocol AND
+ s.identifier = :storeIdentifier AND
+ n.node_deleted = :isDeleted AND
+ p1.persisted_type_n IS NULL
+
+
diff --git a/source/java/org/alfresco/repo/node/db/NodeDaoService.java b/source/java/org/alfresco/repo/node/db/NodeDaoService.java
index 23d9b8a6e0..612104add0 100644
--- a/source/java/org/alfresco/repo/node/db/NodeDaoService.java
+++ b/source/java/org/alfresco/repo/node/db/NodeDaoService.java
@@ -503,6 +503,19 @@ public interface NodeDaoService
StoreRef storeRef,
ObjectArrayQueryCallback resultsCallback);
+ /**
+ * Iterate over all person nodes with missing usage property (for one-off patch)
+ *
+ * @param storeRef the store to search in
+ * @param handler the callback to use while iterating over the people
+ * @return Returns the values for person node uuid
+ */
+ @DirtySessionAnnotation(markDirty=true)
+ public void getUsersWithoutUsageProp(
+ StoreRef storeRef,
+ ObjectArrayQueryCallback resultsCallback);
+
+
/**
* Iterate over all person nodes to get users without a calculated usage
*
diff --git a/source/java/org/alfresco/repo/node/db/hibernate/HibernateNodeDaoServiceImpl.java b/source/java/org/alfresco/repo/node/db/hibernate/HibernateNodeDaoServiceImpl.java
index 13256e4604..56b435dfe8 100644
--- a/source/java/org/alfresco/repo/node/db/hibernate/HibernateNodeDaoServiceImpl.java
+++ b/source/java/org/alfresco/repo/node/db/hibernate/HibernateNodeDaoServiceImpl.java
@@ -163,6 +163,7 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements
private static final String QUERY_GET_NODES_WITH_PROPERTY_VALUES_BY_STRING_AND_STORE = "node.GetNodesWithPropertyValuesByStringAndStore";
private static final String QUERY_GET_CONTENT_URLS_FOR_STORE_OLD = "node.GetContentUrlsForStoreOld";
private static final String QUERY_GET_CONTENT_URLS_FOR_STORE_NEW = "node.GetContentUrlsForStoreNew";
+ private static final String QUERY_GET_USERS_WITHOUT_USAGE_PROP = "node.GetUsersWithoutUsageProp";
private static final String QUERY_GET_USERS_WITHOUT_USAGE = "node.GetUsersWithoutUsage";
private static final String QUERY_GET_USERS_WITH_USAGE = "node.GetUsersWithUsage";
private static final String QUERY_GET_NODES_WITH_PROPERTY_VALUES_BY_ACTUAL_TYPE = "node.GetNodesWithPropertyValuesByActualType";
@@ -3649,6 +3650,59 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements
// Done
}
+ public void getUsersWithoutUsageProp(
+ final StoreRef storeRef,
+ final ObjectArrayQueryCallback resultsCallback)
+ {
+ final Pair sizeCurrentPropQNamePair = qnameDAO.getQName(ContentModel.PROP_SIZE_CURRENT);
+ final Pair personTypeQNamePair = qnameDAO.getQName(ContentModel.TYPE_PERSON);
+
+ // Shortcut the query if the QNames don't exist
+ if (sizeCurrentPropQNamePair == null || personTypeQNamePair == null)
+ {
+ return;
+ }
+
+ HibernateCallback callback = new HibernateCallback()
+ {
+ public Object doInHibernate(Session session)
+ {
+ Query query = session
+ .getNamedQuery(HibernateNodeDaoServiceImpl.QUERY_GET_USERS_WITHOUT_USAGE_PROP)
+ .setString("storeProtocol", storeRef.getProtocol())
+ .setString("storeIdentifier", storeRef.getIdentifier())
+ .setParameter("sizeCurrentPropQNameID", sizeCurrentPropQNamePair.getFirst()) // cm:sizeCurrent
+ .setParameter("personTypeQNameID", personTypeQNamePair.getFirst()) // cm:person
+ .setParameter("isDeleted", false);
+ ;
+ DirtySessionMethodInterceptor.setQueryFlushMode(session, query);
+ return query.scroll(ScrollMode.FORWARD_ONLY);
+ }
+ };
+ ScrollableResults results = null;
+ try
+ {
+ results = (ScrollableResults) getHibernateTemplate().execute(callback);
+ // Callback with the results
+ Session session = getSession();
+ while (results.next())
+ {
+ Object[] arr = new Object[1];
+ arr[0] = (String)results.get(0); // node uuid
+ resultsCallback.handle(arr);
+ // Flush if required
+ DirtySessionMethodInterceptor.flushSession(session);
+ }
+ }
+ finally
+ {
+ if (results != null)
+ {
+ results.close();
+ }
+ }
+ }
+
public void getUsersWithoutUsage(
final StoreRef storeRef,
final ObjectArrayQueryCallback resultsCallback)
diff --git a/source/java/org/alfresco/repo/security/authentication/AuthenticationUtil.java b/source/java/org/alfresco/repo/security/authentication/AuthenticationUtil.java
index 68d60d463f..84a70f65e2 100644
--- a/source/java/org/alfresco/repo/security/authentication/AuthenticationUtil.java
+++ b/source/java/org/alfresco/repo/security/authentication/AuthenticationUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2008 Alfresco Software Limited.
+ * Copyright (C) 2005-2009 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -24,8 +24,8 @@
*/
package org.alfresco.repo.security.authentication;
-import java.util.Stack;
-
+import java.util.Stack;
+
import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.GrantedAuthority;
import net.sf.acegisecurity.GrantedAuthorityImpl;
@@ -37,10 +37,10 @@ import net.sf.acegisecurity.providers.dao.User;
import org.alfresco.repo.tenant.TenantService;
import org.alfresco.service.cmr.security.PermissionService;
-import org.alfresco.util.EqualsHelper;
+import org.alfresco.util.EqualsHelper;
import org.alfresco.util.log.NDC;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
/**
@@ -508,6 +508,7 @@ public class AuthenticationUtil implements InitializingBean
}
AuthenticationUtil.setRunAsUser(uid);
}
+ logNDC(uid);
result = runAsWork.doWork();
return result;
}
@@ -528,12 +529,15 @@ public class AuthenticationUtil implements InitializingBean
if (originalFullAuthentication == null)
{
AuthenticationUtil.clearCurrentSecurityContext();
+ logNDC(null);
}
else
{
AuthenticationUtil.setFullAuthentication(originalFullAuthentication);
AuthenticationUtil.setRunAsAuthentication(originalRunAsAuthentication);
- }
+
+ logNDC(getUserName(originalFullAuthentication));
+ }
}
}
@@ -599,22 +603,25 @@ public class AuthenticationUtil implements InitializingBean
{
NDC.remove();
- if (isMtEnabled())
+ if (userName != null)
{
- String[] parts = splitUserTenant(userName);
- if (parts.length == 2)
+ if (isMtEnabled())
{
- NDC.push("Tenant:" + parts[1] + " User:" + parts[0]);
+ String[] parts = splitUserTenant(userName);
+ if (parts.length == 2)
+ {
+ NDC.push("Tenant:" + parts[1] + " User:" + parts[0]);
+ }
+ else
+ {
+ NDC.push("User:" + userName);
+ }
}
else
{
NDC.push("User:" + userName);
}
}
- else
- {
- NDC.push("User:" + userName);
- }
}
private static String[] splitUserTenant(String userName)