Merged V3.2 to HEAD

16652: Fix ETHREEOH-1052 - usage is not displayed (for admin & guest - after initial bootstrap, before restart)
    16778: Fix ETHREEOH-3009 - Patch required for UserUsageTrackingComponent so that new queries work on upgraded repository


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@16922 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Jan Vonka
2009-10-14 14:06:40 +00:00
parent b1433afacf
commit 8d2f4f8dd2
10 changed files with 261 additions and 16 deletions

View File

@@ -53,6 +53,7 @@
<cm:organizationId></cm:organizationId> <cm:organizationId></cm:organizationId>
<cm:homeFolder>/${spaces.company_home.childname}</cm:homeFolder> <cm:homeFolder>/${spaces.company_home.childname}</cm:homeFolder>
<cm:homeFolderProvider>bootstrapHomeFolderProvider</cm:homeFolderProvider> <cm:homeFolderProvider>bootstrapHomeFolderProvider</cm:homeFolderProvider>
<cm:sizeCurrent>0</cm:sizeCurrent>
</cm:person> </cm:person>
<!-- Guest needs to read their own person information --> <!-- Guest needs to read their own person information -->
<cm:person view:childName="cm:${alfresco_user_store.guestusername}"> <cm:person view:childName="cm:${alfresco_user_store.guestusername}">
@@ -69,6 +70,7 @@
<cm:organizationId></cm:organizationId> <cm:organizationId></cm:organizationId>
<cm:homeFolder>/${spaces.company_home.childname}/${spaces.guest_home.childname}</cm:homeFolder> <cm:homeFolder>/${spaces.company_home.childname}/${spaces.guest_home.childname}</cm:homeFolder>
<cm:homeFolderProvider>bootstrapHomeFolderProvider</cm:homeFolderProvider> <cm:homeFolderProvider>bootstrapHomeFolderProvider</cm:homeFolderProvider>
<cm:sizeCurrent>0</cm:sizeCurrent>
</cm:person> </cm:person>
</sys:children> </sys:children>
</sys:container> </sys:container>

View File

@@ -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.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.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.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.

View File

@@ -250,6 +250,7 @@
<property name="cm:sizeCurrent"> <property name="cm:sizeCurrent">
<type>d:long</type> <type>d:long</type>
<protected>true</protected> <protected>true</protected>
<mandatory enforced="true">true</mandatory>
</property> </property>
<property name="cm:sizeQuota"> <property name="cm:sizeQuota">
<type>d:long</type> <type>d:long</type>

View File

@@ -1933,4 +1933,22 @@
</property> </property>
</bean> </bean>
<bean id="patch.personUsagePatch" class="org.alfresco.repo.admin.patch.impl.PersonUsagePatch" parent="basePatch" >
<property name="id"><value>patch.personUsagePatch</value></property>
<property name="description"><value>patch.personUsagePatch.description</value></property>
<property name="fixesFromSchema"><value>0</value></property>
<property name="fixesToSchema"><value>3004</value></property>
<property name="targetSchema"><value>3005</value></property>
<!-- helper beans -->
<property name="nodeDaoService">
<ref bean="nodeDaoService"/>
</property>
<property name="personStoreUrl">
<value>${spaces.store}</value>
</property>
<property name="tenantService">
<ref bean="tenantService"/>
</property>
</bean>
</beans> </beans>

View File

@@ -19,4 +19,4 @@ version.build=@build-number@
# Schema number # Schema number
version.schema=3004 version.schema=3005

View File

@@ -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;
}
};
}

View File

@@ -716,6 +716,22 @@
(p1.string_value != 'System' OR (p1.string_value IS NULL AND n.audit_creator != 'System')) (p1.string_value != 'System' OR (p1.string_value IS NULL AND n.audit_creator != 'System'))
</sql-query> </sql-query>
<!-- note: for PersonUsagePatch only -->
<sql-query name="node.GetUsersWithoutUsageProp">
<return-scalar column="uuid" type="string"/>
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
</sql-query>
<sql-query name="node.GetUsersWithoutUsage"> <sql-query name="node.GetUsersWithoutUsage">
<return-scalar column="username" type="string"/> <return-scalar column="username" type="string"/>
<return-scalar column="uuid" type="string"/> <return-scalar column="uuid" type="string"/>

View File

@@ -503,6 +503,19 @@ public interface NodeDaoService
StoreRef storeRef, StoreRef storeRef,
ObjectArrayQueryCallback resultsCallback); 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 * Iterate over all person nodes to get users without a calculated usage
* *

View File

@@ -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_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_OLD = "node.GetContentUrlsForStoreOld";
private static final String QUERY_GET_CONTENT_URLS_FOR_STORE_NEW = "node.GetContentUrlsForStoreNew"; 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_WITHOUT_USAGE = "node.GetUsersWithoutUsage";
private static final String QUERY_GET_USERS_WITH_USAGE = "node.GetUsersWithUsage"; 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"; 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 // Done
} }
public void getUsersWithoutUsageProp(
final StoreRef storeRef,
final ObjectArrayQueryCallback resultsCallback)
{
final Pair<Long, QName> sizeCurrentPropQNamePair = qnameDAO.getQName(ContentModel.PROP_SIZE_CURRENT);
final Pair<Long, QName> 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( public void getUsersWithoutUsage(
final StoreRef storeRef, final StoreRef storeRef,
final ObjectArrayQueryCallback resultsCallback) final ObjectArrayQueryCallback resultsCallback)

View File

@@ -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 * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@@ -508,6 +508,7 @@ public class AuthenticationUtil implements InitializingBean
} }
AuthenticationUtil.setRunAsUser(uid); AuthenticationUtil.setRunAsUser(uid);
} }
logNDC(uid);
result = runAsWork.doWork(); result = runAsWork.doWork();
return result; return result;
} }
@@ -528,11 +529,14 @@ public class AuthenticationUtil implements InitializingBean
if (originalFullAuthentication == null) if (originalFullAuthentication == null)
{ {
AuthenticationUtil.clearCurrentSecurityContext(); AuthenticationUtil.clearCurrentSecurityContext();
logNDC(null);
} }
else else
{ {
AuthenticationUtil.setFullAuthentication(originalFullAuthentication); AuthenticationUtil.setFullAuthentication(originalFullAuthentication);
AuthenticationUtil.setRunAsAuthentication(originalRunAsAuthentication); AuthenticationUtil.setRunAsAuthentication(originalRunAsAuthentication);
logNDC(getUserName(originalFullAuthentication));
} }
} }
} }
@@ -599,6 +603,8 @@ public class AuthenticationUtil implements InitializingBean
{ {
NDC.remove(); NDC.remove();
if (userName != null)
{
if (isMtEnabled()) if (isMtEnabled())
{ {
String[] parts = splitUserTenant(userName); String[] parts = splitUserTenant(userName);
@@ -616,6 +622,7 @@ public class AuthenticationUtil implements InitializingBean
NDC.push("User:" + userName); NDC.push("User:" + userName);
} }
} }
}
private static String[] splitUserTenant(String userName) private static String[] splitUserTenant(String userName)
{ {