mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Fixed MOB-1656: Audit Log: Log ordering is incorrect for "Last N" results
- Added option to have results in either ascending or descending order - RM uses descending listings where the query results are limited git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@16628 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -201,6 +201,14 @@
|
|||||||
sp_mpl.value_prop_id = #searchValueId#
|
sp_mpl.value_prop_id = #searchValueId#
|
||||||
</isNotNull>
|
</isNotNull>
|
||||||
</dynamic>
|
</dynamic>
|
||||||
|
<isEqual property="forward" compareProperty="forwardTrue">
|
||||||
|
order by
|
||||||
|
entry.id asc
|
||||||
|
</isEqual>
|
||||||
|
<isNotEqual property="forward" compareProperty="forwardTrue">
|
||||||
|
order by
|
||||||
|
entry.id desc
|
||||||
|
</isNotEqual>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<!-- Get audit entries -->
|
<!-- Get audit entries -->
|
||||||
@@ -242,6 +250,14 @@
|
|||||||
sp_mpl.value_prop_id = #searchValueId#
|
sp_mpl.value_prop_id = #searchValueId#
|
||||||
</isNotNull>
|
</isNotNull>
|
||||||
</dynamic>
|
</dynamic>
|
||||||
|
<isEqual property="forward" compareProperty="forwardTrue">
|
||||||
|
order by
|
||||||
|
entry.id asc
|
||||||
|
</isEqual>
|
||||||
|
<isNotEqual property="forward" compareProperty="forwardTrue">
|
||||||
|
order by
|
||||||
|
entry.id desc
|
||||||
|
</isNotEqual>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
</sqlMap>
|
</sqlMap>
|
@@ -188,6 +188,8 @@ public interface AuditComponent
|
|||||||
* Get the audit entries that match the given criteria.
|
* Get the audit entries that match the given criteria.
|
||||||
*
|
*
|
||||||
* @param callback the callback that will handle results
|
* @param callback the callback that will handle results
|
||||||
|
* @param forward <tt>true</tt> for results to ordered from first to last,
|
||||||
|
* or <tt>false</tt> to order from last to first
|
||||||
* @param applicationName if not <tt>null</tt>, find entries logged against this application
|
* @param applicationName if not <tt>null</tt>, find entries logged against this application
|
||||||
* @param user if not <tt>null</tt>, find entries logged against this user
|
* @param user if not <tt>null</tt>, find entries logged against this user
|
||||||
* @param from the start search time (<tt>null</tt> to start at the beginning)
|
* @param from the start search time (<tt>null</tt> to start at the beginning)
|
||||||
@@ -198,6 +200,7 @@ public interface AuditComponent
|
|||||||
*/
|
*/
|
||||||
void auditQuery(
|
void auditQuery(
|
||||||
AuditQueryCallback callback,
|
AuditQueryCallback callback,
|
||||||
|
boolean forward,
|
||||||
String applicationName, String user, Long from, Long to,
|
String applicationName, String user, Long from, Long to,
|
||||||
int maxResults);
|
int maxResults);
|
||||||
|
|
||||||
@@ -205,6 +208,8 @@ public interface AuditComponent
|
|||||||
* Get the audit entries that match the given criteria.
|
* Get the audit entries that match the given criteria.
|
||||||
*
|
*
|
||||||
* @param callback the callback that will handle results
|
* @param callback the callback that will handle results
|
||||||
|
* @param forward <tt>true</tt> for results to ordered from first to last,
|
||||||
|
* or <tt>false</tt> to order from last to first
|
||||||
* @param applicationName if not <tt>null</tt>, find entries logged against this application
|
* @param applicationName if not <tt>null</tt>, find entries logged against this application
|
||||||
* @param user if not <tt>null</tt>, find entries logged against this user
|
* @param user if not <tt>null</tt>, find entries logged against this user
|
||||||
* @param from the start search time (<tt>null</tt> to start at the beginning)
|
* @param from the start search time (<tt>null</tt> to start at the beginning)
|
||||||
@@ -217,6 +222,7 @@ public interface AuditComponent
|
|||||||
*/
|
*/
|
||||||
void auditQuery(
|
void auditQuery(
|
||||||
AuditQueryCallback callback,
|
AuditQueryCallback callback,
|
||||||
|
boolean forward,
|
||||||
String applicationName, String user, Long from, Long to,
|
String applicationName, String user, Long from, Long to,
|
||||||
String searchKey, Serializable searchValue,
|
String searchKey, Serializable searchValue,
|
||||||
int maxResults);
|
int maxResults);
|
||||||
|
@@ -1323,6 +1323,7 @@ public class AuditComponentImpl implements AuditComponent
|
|||||||
*/
|
*/
|
||||||
public void auditQuery(
|
public void auditQuery(
|
||||||
AuditQueryCallback callback,
|
AuditQueryCallback callback,
|
||||||
|
boolean forward,
|
||||||
String applicationName,
|
String applicationName,
|
||||||
String user,
|
String user,
|
||||||
Long from,
|
Long from,
|
||||||
@@ -1338,7 +1339,8 @@ public class AuditComponentImpl implements AuditComponent
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auditDAO.findAuditEntries(callback, applicationName, user, from, to, maxResults);
|
auditDAO.findAuditEntries(
|
||||||
|
callback, forward, applicationName, user, from, to, maxResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1346,6 +1348,7 @@ public class AuditComponentImpl implements AuditComponent
|
|||||||
*/
|
*/
|
||||||
public void auditQuery(
|
public void auditQuery(
|
||||||
AuditQueryCallback callback,
|
AuditQueryCallback callback,
|
||||||
|
boolean forward,
|
||||||
String applicationName,
|
String applicationName,
|
||||||
String user,
|
String user,
|
||||||
Long from,
|
Long from,
|
||||||
@@ -1362,6 +1365,7 @@ public class AuditComponentImpl implements AuditComponent
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auditDAO.findAuditEntries(callback, applicationName, user, from, to, searchKey, searchValue, maxResults);
|
auditDAO.findAuditEntries(
|
||||||
|
callback, forward, applicationName, user, from, to, searchKey, searchValue, maxResults);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -35,6 +35,7 @@ import java.util.Map;
|
|||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
import org.alfresco.repo.audit.model.AuditApplication;
|
import org.alfresco.repo.audit.model.AuditApplication;
|
||||||
import org.alfresco.repo.audit.model.AuditModelException;
|
import org.alfresco.repo.audit.model.AuditModelException;
|
||||||
import org.alfresco.repo.audit.model.AuditModelRegistry;
|
import org.alfresco.repo.audit.model.AuditModelRegistry;
|
||||||
@@ -328,11 +329,16 @@ public class AuditComponentTest extends TestCase
|
|||||||
rowCount.setValue(rowCount.intValue() + 1);
|
rowCount.setValue(rowCount.intValue() + 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean handleAuditEntryError(Long entryId, String errorMsg, Throwable error)
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException(errorMsg, error);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
sb.delete(0, sb.length());
|
sb.delete(0, sb.length());
|
||||||
rowCount.setValue(0);
|
rowCount.setValue(0);
|
||||||
auditComponent.auditQuery(callback, APPLICATION_ACTIONS_TEST, null, null, null, -1);
|
auditComponent.auditQuery(callback, true, APPLICATION_ACTIONS_TEST, null, null, null, -1);
|
||||||
assertTrue("Expected some data", rowCount.intValue() > 0);
|
assertTrue("Expected some data", rowCount.intValue() > 0);
|
||||||
logger.debug(sb.toString());
|
logger.debug(sb.toString());
|
||||||
int allResults = rowCount.intValue();
|
int allResults = rowCount.intValue();
|
||||||
@@ -340,21 +346,21 @@ public class AuditComponentTest extends TestCase
|
|||||||
// Limit by count
|
// Limit by count
|
||||||
sb.delete(0, sb.length());
|
sb.delete(0, sb.length());
|
||||||
rowCount.setValue(0);
|
rowCount.setValue(0);
|
||||||
auditComponent.auditQuery(callback, APPLICATION_ACTIONS_TEST, null, null, null, 1);
|
auditComponent.auditQuery(callback, true, APPLICATION_ACTIONS_TEST, null, null, null, 1);
|
||||||
assertEquals("Expected to limit data", 1, rowCount.intValue());
|
assertEquals("Expected to limit data", 1, rowCount.intValue());
|
||||||
logger.debug(sb.toString());
|
logger.debug(sb.toString());
|
||||||
|
|
||||||
// Limit by time and query up to and excluding the 'before' time
|
// Limit by time and query up to and excluding the 'before' time
|
||||||
sb.delete(0, sb.length());
|
sb.delete(0, sb.length());
|
||||||
rowCount.setValue(0);
|
rowCount.setValue(0);
|
||||||
auditComponent.auditQuery(callback, APPLICATION_ACTIONS_TEST, null, null, beforeTime, -1);
|
auditComponent.auditQuery(callback, true, APPLICATION_ACTIONS_TEST, null, null, beforeTime, -1);
|
||||||
logger.debug(sb.toString());
|
logger.debug(sb.toString());
|
||||||
int resultsBefore = rowCount.intValue();
|
int resultsBefore = rowCount.intValue();
|
||||||
|
|
||||||
// Limit by time and query from and including the 'before' time
|
// Limit by time and query from and including the 'before' time
|
||||||
sb.delete(0, sb.length());
|
sb.delete(0, sb.length());
|
||||||
rowCount.setValue(0);
|
rowCount.setValue(0);
|
||||||
auditComponent.auditQuery(callback, APPLICATION_ACTIONS_TEST, null, beforeTime, null, -1);
|
auditComponent.auditQuery(callback, true, APPLICATION_ACTIONS_TEST, null, beforeTime, null, -1);
|
||||||
logger.debug(sb.toString());
|
logger.debug(sb.toString());
|
||||||
int resultsAfter = rowCount.intValue();
|
int resultsAfter = rowCount.intValue();
|
||||||
|
|
||||||
@@ -364,13 +370,13 @@ public class AuditComponentTest extends TestCase
|
|||||||
|
|
||||||
sb.delete(0, sb.length());
|
sb.delete(0, sb.length());
|
||||||
rowCount.setValue(0);
|
rowCount.setValue(0);
|
||||||
auditComponent.auditQuery(callback, APPLICATION_ACTIONS_TEST, user, null, null, -1);
|
auditComponent.auditQuery(callback, true, APPLICATION_ACTIONS_TEST, user, null, null, -1);
|
||||||
assertTrue("Expected some data for specific user", rowCount.intValue() > 0);
|
assertTrue("Expected some data for specific user", rowCount.intValue() > 0);
|
||||||
logger.debug(sb.toString());
|
logger.debug(sb.toString());
|
||||||
|
|
||||||
sb.delete(0, sb.length());
|
sb.delete(0, sb.length());
|
||||||
rowCount.setValue(0);
|
rowCount.setValue(0);
|
||||||
auditComponent.auditQuery(callback, APPLICATION_ACTIONS_TEST, "Numpty", null, null, -1);
|
auditComponent.auditQuery(callback, true, APPLICATION_ACTIONS_TEST, "Numpty", null, null, -1);
|
||||||
assertTrue("Expected no data for bogus user", rowCount.intValue() == 0);
|
assertTrue("Expected no data for bogus user", rowCount.intValue() == 0);
|
||||||
logger.debug(sb.toString());
|
logger.debug(sb.toString());
|
||||||
|
|
||||||
@@ -483,12 +489,17 @@ public class AuditComponentTest extends TestCase
|
|||||||
;
|
;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean handleAuditEntryError(Long entryId, String errorMsg, Throwable error)
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException(errorMsg, error);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
auditService.clearAudit(APPLICATION_API_TEST);
|
auditService.clearAudit(APPLICATION_API_TEST);
|
||||||
results.clear();
|
results.clear();
|
||||||
sb.delete(0, sb.length());
|
sb.delete(0, sb.length());
|
||||||
auditService.auditQuery(auditQueryCallback, APPLICATION_API_TEST, null, null, null, -1);
|
auditService.auditQuery(auditQueryCallback, true, APPLICATION_API_TEST, null, null, null, -1);
|
||||||
logger.debug(sb.toString());
|
logger.debug(sb.toString());
|
||||||
assertTrue("There should be no audit entries for the API test after a clear", results.isEmpty());
|
assertTrue("There should be no audit entries for the API test after a clear", results.isEmpty());
|
||||||
|
|
||||||
@@ -522,7 +533,7 @@ public class AuditComponentTest extends TestCase
|
|||||||
// Check that the call was audited
|
// Check that the call was audited
|
||||||
results.clear();
|
results.clear();
|
||||||
sb.delete(0, sb.length());
|
sb.delete(0, sb.length());
|
||||||
auditService.auditQuery(auditQueryCallback, APPLICATION_API_TEST, null, null, null, -1);
|
auditService.auditQuery(auditQueryCallback, true, APPLICATION_API_TEST, null, null, null, -1);
|
||||||
logger.debug(sb.toString());
|
logger.debug(sb.toString());
|
||||||
assertFalse("Did not get any audit results after successful login", results.isEmpty());
|
assertFalse("Did not get any audit results after successful login", results.isEmpty());
|
||||||
|
|
||||||
@@ -539,7 +550,7 @@ public class AuditComponentTest extends TestCase
|
|||||||
}
|
}
|
||||||
results.clear();
|
results.clear();
|
||||||
sb.delete(0, sb.length());
|
sb.delete(0, sb.length());
|
||||||
auditService.auditQuery(auditQueryCallback, APPLICATION_API_TEST, null, null, null, -1);
|
auditService.auditQuery(auditQueryCallback, true, APPLICATION_API_TEST, null, null, null, -1);
|
||||||
logger.debug(sb.toString());
|
logger.debug(sb.toString());
|
||||||
assertFalse("Did not get any audit results after failed login", results.isEmpty());
|
assertFalse("Did not get any audit results after failed login", results.isEmpty());
|
||||||
}
|
}
|
||||||
|
@@ -173,13 +173,15 @@ public class AuditServiceImpl implements AuditService
|
|||||||
*/
|
*/
|
||||||
public void auditQuery(
|
public void auditQuery(
|
||||||
AuditQueryCallback callback,
|
AuditQueryCallback callback,
|
||||||
|
boolean forward,
|
||||||
String applicationName, String user, Long from, Long to,
|
String applicationName, String user, Long from, Long to,
|
||||||
int maxResults)
|
int maxResults)
|
||||||
|
|
||||||
{
|
{
|
||||||
ParameterCheck.mandatory("callback", callback);
|
ParameterCheck.mandatory("callback", callback);
|
||||||
|
|
||||||
auditComponent.auditQuery(callback, applicationName, user, from, to, maxResults);
|
auditComponent.auditQuery(
|
||||||
|
callback, forward, applicationName, user, from, to, maxResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -188,6 +190,7 @@ public class AuditServiceImpl implements AuditService
|
|||||||
*/
|
*/
|
||||||
public void auditQuery(
|
public void auditQuery(
|
||||||
AuditQueryCallback callback,
|
AuditQueryCallback callback,
|
||||||
|
boolean forward,
|
||||||
String applicationName, String user, Long from, Long to,
|
String applicationName, String user, Long from, Long to,
|
||||||
String searchKey, Serializable searchValue,
|
String searchKey, Serializable searchValue,
|
||||||
int maxResults)
|
int maxResults)
|
||||||
@@ -195,6 +198,7 @@ public class AuditServiceImpl implements AuditService
|
|||||||
{
|
{
|
||||||
ParameterCheck.mandatory("callback", callback);
|
ParameterCheck.mandatory("callback", callback);
|
||||||
|
|
||||||
auditComponent.auditQuery(callback, applicationName, user, from, to, searchKey, searchValue, maxResults);
|
auditComponent.auditQuery(
|
||||||
|
callback, forward, applicationName, user, from, to, searchKey, searchValue, maxResults);
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -740,6 +740,7 @@ public class HibernateAuditDAO extends HibernateDaoSupport implements AuditDAO,
|
|||||||
*/
|
*/
|
||||||
public void findAuditEntries(
|
public void findAuditEntries(
|
||||||
AuditQueryCallback callback,
|
AuditQueryCallback callback,
|
||||||
|
boolean forward,
|
||||||
String applicationName, String user, Long from, Long to,
|
String applicationName, String user, Long from, Long to,
|
||||||
int maxResults)
|
int maxResults)
|
||||||
{
|
{
|
||||||
@@ -754,6 +755,7 @@ public class HibernateAuditDAO extends HibernateDaoSupport implements AuditDAO,
|
|||||||
*/
|
*/
|
||||||
public void findAuditEntries(
|
public void findAuditEntries(
|
||||||
AuditQueryCallback callback,
|
AuditQueryCallback callback,
|
||||||
|
boolean forward,
|
||||||
String applicationName, String user, Long from, Long to,
|
String applicationName, String user, Long from, Long to,
|
||||||
String searchKey, Serializable searchValue,
|
String searchKey, Serializable searchValue,
|
||||||
int maxResults)
|
int maxResults)
|
||||||
|
@@ -383,7 +383,10 @@ public abstract class AbstractAuditDAOImpl implements AuditDAO
|
|||||||
if (auditValuesPair == null)
|
if (auditValuesPair == null)
|
||||||
{
|
{
|
||||||
// Ignore
|
// Ignore
|
||||||
logger.warn("Audit entry not joined to audit properties: " + row);
|
more = callback.handleAuditEntryError(
|
||||||
|
row.getAuditEntryId(),
|
||||||
|
"Audit entry not joined to audit properties: " + row,
|
||||||
|
null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auditValues = (Map<String, Serializable>) auditValuesPair.getSecond();
|
auditValues = (Map<String, Serializable>) auditValuesPair.getSecond();
|
||||||
@@ -397,17 +400,26 @@ public abstract class AbstractAuditDAOImpl implements AuditDAO
|
|||||||
}
|
}
|
||||||
catch (ClassCastException e)
|
catch (ClassCastException e)
|
||||||
{
|
{
|
||||||
logger.warn("Audit entry not linked to a Map<String, Serializable> value: " + row);
|
more = callback.handleAuditEntryError(
|
||||||
|
row.getAuditEntryId(),
|
||||||
|
"Audit entry not linked to a Map<String, Serializable> value: " + row,
|
||||||
|
e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
catch (Throwable e)
|
catch (Throwable e)
|
||||||
{
|
{
|
||||||
logger.warn("Audit entry unable to extract audited values: " + row, e);
|
more = callback.handleAuditEntryError(
|
||||||
|
row.getAuditEntryId(),
|
||||||
|
"Audit entry unable to extract audited values: " + row,
|
||||||
|
e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (auditValues == null)
|
if (auditValues == null)
|
||||||
{
|
{
|
||||||
logger.warn("Audit entry incompletely joined to audit properties: " + row);
|
more = callback.handleAuditEntryError(
|
||||||
|
row.getAuditEntryId(),
|
||||||
|
"Audit entry incompletely joined to audit properties: " + row,
|
||||||
|
null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -430,25 +442,28 @@ public abstract class AbstractAuditDAOImpl implements AuditDAO
|
|||||||
|
|
||||||
public void findAuditEntries(
|
public void findAuditEntries(
|
||||||
AuditQueryCallback callback,
|
AuditQueryCallback callback,
|
||||||
|
boolean forward,
|
||||||
String applicationName, String user, Long from, Long to,
|
String applicationName, String user, Long from, Long to,
|
||||||
int maxResults)
|
int maxResults)
|
||||||
{
|
{
|
||||||
AuditQueryRowHandler rowHandler = new AuditQueryRowHandler(callback);
|
AuditQueryRowHandler rowHandler = new AuditQueryRowHandler(callback);
|
||||||
findAuditEntries(rowHandler, applicationName, user, from, to, maxResults, null, null);
|
findAuditEntries(rowHandler, forward, applicationName, user, from, to, maxResults, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void findAuditEntries(
|
public void findAuditEntries(
|
||||||
AuditQueryCallback callback,
|
AuditQueryCallback callback,
|
||||||
|
boolean forward,
|
||||||
String applicationName, String user, Long from, Long to,
|
String applicationName, String user, Long from, Long to,
|
||||||
String searchKey, Serializable searchValue,
|
String searchKey, Serializable searchValue,
|
||||||
int maxResults)
|
int maxResults)
|
||||||
{
|
{
|
||||||
AuditQueryRowHandler rowHandler = new AuditQueryRowHandler(callback);
|
AuditQueryRowHandler rowHandler = new AuditQueryRowHandler(callback);
|
||||||
findAuditEntries(rowHandler, applicationName, user, from, to, maxResults, searchKey, searchValue);
|
findAuditEntries(rowHandler, forward, applicationName, user, from, to, maxResults, searchKey, searchValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void findAuditEntries(
|
protected abstract void findAuditEntries(
|
||||||
AuditQueryRowHandler rowHandler,
|
AuditQueryRowHandler rowHandler,
|
||||||
|
boolean forward,
|
||||||
String applicationName, String user, Long from, Long to, int maxResults,
|
String applicationName, String user, Long from, Long to, int maxResults,
|
||||||
String searchKey, Serializable searchValue);
|
String searchKey, Serializable searchValue);
|
||||||
}
|
}
|
||||||
|
@@ -207,6 +207,8 @@ public interface AuditDAO
|
|||||||
* Find audit entries using the given parameters, any of which may be null
|
* Find audit entries using the given parameters, any of which may be null
|
||||||
*
|
*
|
||||||
* @param callback the data callback per entry
|
* @param callback the data callback per entry
|
||||||
|
* @param forward <tt>true</tt> for results to ordered from first to last,
|
||||||
|
* or <tt>false</tt> to order from last to first
|
||||||
* @param applicationName the name of the application to search against (optional)
|
* @param applicationName the name of the application to search against (optional)
|
||||||
* @param user the user to search for (optional)
|
* @param user the user to search for (optional)
|
||||||
* @param from the minimum entry time (optional)
|
* @param from the minimum entry time (optional)
|
||||||
@@ -215,6 +217,7 @@ public interface AuditDAO
|
|||||||
*/
|
*/
|
||||||
void findAuditEntries(
|
void findAuditEntries(
|
||||||
AuditQueryCallback callback,
|
AuditQueryCallback callback,
|
||||||
|
boolean forward,
|
||||||
String applicationName, String user, Long from, Long to, int maxResults);
|
String applicationName, String user, Long from, Long to, int maxResults);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -230,6 +233,7 @@ public interface AuditDAO
|
|||||||
*/
|
*/
|
||||||
void findAuditEntries(
|
void findAuditEntries(
|
||||||
AuditQueryCallback callback,
|
AuditQueryCallback callback,
|
||||||
|
boolean forward,
|
||||||
String applicationName, String user, Long from, Long to,
|
String applicationName, String user, Long from, Long to,
|
||||||
String searchKey, Serializable searchValue,
|
String searchKey, Serializable searchValue,
|
||||||
int maxResults);
|
int maxResults);
|
||||||
|
@@ -28,10 +28,12 @@ import java.io.File;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
import org.alfresco.repo.content.transform.AbstractContentTransformerTest;
|
import org.alfresco.repo.content.transform.AbstractContentTransformerTest;
|
||||||
import org.alfresco.repo.domain.audit.AuditDAO.AuditApplicationInfo;
|
import org.alfresco.repo.domain.audit.AuditDAO.AuditApplicationInfo;
|
||||||
import org.alfresco.repo.domain.contentdata.ContentDataDAO;
|
import org.alfresco.repo.domain.contentdata.ContentDataDAO;
|
||||||
@@ -43,6 +45,7 @@ import org.alfresco.service.cmr.repository.ContentData;
|
|||||||
import org.alfresco.service.transaction.TransactionService;
|
import org.alfresco.service.transaction.TransactionService;
|
||||||
import org.alfresco.util.ApplicationContextHelper;
|
import org.alfresco.util.ApplicationContextHelper;
|
||||||
import org.alfresco.util.Pair;
|
import org.alfresco.util.Pair;
|
||||||
|
import org.apache.commons.lang.mutable.MutableInt;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -182,11 +185,13 @@ public class AuditDAOTest extends TestCase
|
|||||||
return appName;
|
return appName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAuditQuery() throws Exception
|
public synchronized void testAuditQuery() throws Exception
|
||||||
{
|
{
|
||||||
// Some entries
|
// Some entries
|
||||||
doAuditEntryImpl(1);
|
doAuditEntryImpl(1);
|
||||||
|
|
||||||
|
final MutableInt count = new MutableInt(0);
|
||||||
|
final LinkedList<Long> timestamps = new LinkedList<Long>();
|
||||||
// Find everything, but look for a specific key
|
// Find everything, but look for a specific key
|
||||||
final AuditQueryCallback callback = new AuditQueryCallback()
|
final AuditQueryCallback callback = new AuditQueryCallback()
|
||||||
{
|
{
|
||||||
@@ -197,20 +202,55 @@ public class AuditDAOTest extends TestCase
|
|||||||
long time,
|
long time,
|
||||||
Map<String, Serializable> values)
|
Map<String, Serializable> values)
|
||||||
{
|
{
|
||||||
System.out.println(values);
|
count.setValue(count.intValue() + 1);
|
||||||
|
timestamps.add(time);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean handleAuditEntryError(Long entryId, String errorMsg, Throwable error)
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException(errorMsg, error);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
RetryingTransactionCallback<Void> findCallback = new RetryingTransactionCallback<Void>()
|
RetryingTransactionCallback<Void> findCallback = new RetryingTransactionCallback<Void>()
|
||||||
{
|
{
|
||||||
public Void execute() throws Throwable
|
public Void execute() throws Throwable
|
||||||
{
|
{
|
||||||
auditDAO.findAuditEntries(callback, null, null, null, null, "/a/b/c", null, -1);
|
auditDAO.findAuditEntries(callback, true, null, null, null, null, "/a/b/c", null, 2);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
count.setValue(0);
|
||||||
|
timestamps.clear();
|
||||||
txnHelper.doInTransaction(findCallback);
|
txnHelper.doInTransaction(findCallback);
|
||||||
|
assertTrue("Expected at least one result", count.intValue() > 0);
|
||||||
|
|
||||||
|
// Make sure that the last two entries are in forward order (ascending time)
|
||||||
|
Long lastTimestamp = timestamps.removeLast();
|
||||||
|
Long secondLastTimeStamp = timestamps.removeLast();
|
||||||
|
assertTrue("The timestamps should be in ascending order", lastTimestamp.compareTo(secondLastTimeStamp) > 0);
|
||||||
|
|
||||||
|
// Make sure that the last two entries differ in time
|
||||||
|
wait(1000L);
|
||||||
|
|
||||||
|
// Search in reverse order
|
||||||
|
doAuditEntryImpl(1);
|
||||||
|
RetryingTransactionCallback<Void> findReverseCallback = new RetryingTransactionCallback<Void>()
|
||||||
|
{
|
||||||
|
public Void execute() throws Throwable
|
||||||
|
{
|
||||||
|
auditDAO.findAuditEntries(callback, false, null, null, null, null, "/a/b/c", null, 2);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
timestamps.clear();
|
||||||
|
txnHelper.doInTransaction(findReverseCallback);
|
||||||
|
|
||||||
|
// Make sure that the last two entries are in reverse order (descending time)
|
||||||
|
lastTimestamp = timestamps.removeLast();
|
||||||
|
secondLastTimeStamp = timestamps.removeLast();
|
||||||
|
assertTrue("The timestamps should be in descending order", lastTimestamp.compareTo(secondLastTimeStamp) < 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAuditDeleteEntries() throws Exception
|
public void testAuditDeleteEntries() throws Exception
|
||||||
@@ -227,6 +267,11 @@ public class AuditDAOTest extends TestCase
|
|||||||
fail("Expected no results. All entries should have been removed.");
|
fail("Expected no results. All entries should have been removed.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean handleAuditEntryError(Long entryId, String errorMsg, Throwable error)
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException(errorMsg, error);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Some entries
|
// Some entries
|
||||||
@@ -239,7 +284,7 @@ public class AuditDAOTest extends TestCase
|
|||||||
Long appId = auditDAO.getAuditApplication(appName).getId();
|
Long appId = auditDAO.getAuditApplication(appName).getId();
|
||||||
auditDAO.deleteAuditEntries(appId, null, null);
|
auditDAO.deleteAuditEntries(appId, null, null);
|
||||||
// There should be no entries
|
// There should be no entries
|
||||||
auditDAO.findAuditEntries(noResultsCallback, appName, null, null, null, -1);
|
auditDAO.findAuditEntries(noResultsCallback, true, appName, null, null, null, -1);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -34,7 +34,7 @@ import java.util.Date;
|
|||||||
*/
|
*/
|
||||||
public class AuditQueryParameters
|
public class AuditQueryParameters
|
||||||
{
|
{
|
||||||
private Long auditEntryId;
|
private boolean forward;
|
||||||
private Long auditAppNameId;
|
private Long auditAppNameId;
|
||||||
private Long auditUserId;
|
private Long auditUserId;
|
||||||
private Long auditFromTime;
|
private Long auditFromTime;
|
||||||
@@ -51,25 +51,30 @@ public class AuditQueryParameters
|
|||||||
{
|
{
|
||||||
StringBuilder sb = new StringBuilder(512);
|
StringBuilder sb = new StringBuilder(512);
|
||||||
sb.append("AuditEntryParameters")
|
sb.append("AuditEntryParameters")
|
||||||
.append("[ auditEntryId=").append(auditEntryId)
|
.append("[ forward=").append(forward)
|
||||||
.append(", auditAppNameId=").append(auditAppNameId)
|
.append(", auditAppNameId=").append(auditAppNameId)
|
||||||
.append(", auditUserId=").append(auditUserId)
|
.append(", auditUserId=").append(auditUserId)
|
||||||
.append(", auditFromTime").append(auditFromTime == null ? null : new Date(auditFromTime))
|
.append(", auditFromTime=").append(auditFromTime == null ? null : new Date(auditFromTime))
|
||||||
.append(", auditToTime").append(auditToTime == null ? null : new Date(auditToTime))
|
.append(", auditToTime=").append(auditToTime == null ? null : new Date(auditToTime))
|
||||||
.append(", searchKeyId").append(searchKeyId)
|
.append(", searchKeyId=").append(searchKeyId)
|
||||||
.append(", searchValueId").append(searchValueId)
|
.append(", searchValueId=").append(searchValueId)
|
||||||
.append("]");
|
.append("]");
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getAuditEntryId()
|
public boolean isForward()
|
||||||
{
|
{
|
||||||
return auditEntryId;
|
return forward;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAuditEntryId(Long entryId)
|
public void setForward(boolean forward)
|
||||||
{
|
{
|
||||||
this.auditEntryId = entryId;
|
this.forward = forward;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isForwardTrue()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getAuditAppNameId()
|
public Long getAuditAppNameId()
|
||||||
|
@@ -29,7 +29,6 @@ import java.util.ArrayList;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
|
||||||
|
|
||||||
import org.alfresco.ibatis.RollupRowHandler;
|
import org.alfresco.ibatis.RollupRowHandler;
|
||||||
import org.alfresco.repo.domain.audit.AbstractAuditDAOImpl;
|
import org.alfresco.repo.domain.audit.AbstractAuditDAOImpl;
|
||||||
@@ -194,6 +193,7 @@ public class AuditDAOImpl extends AbstractAuditDAOImpl
|
|||||||
@Override
|
@Override
|
||||||
protected void findAuditEntries(
|
protected void findAuditEntries(
|
||||||
final AuditQueryRowHandler rowHandler,
|
final AuditQueryRowHandler rowHandler,
|
||||||
|
boolean forward,
|
||||||
String appName, String user, Long from, Long to, int maxResults,
|
String appName, String user, Long from, Long to, int maxResults,
|
||||||
String searchKey, Serializable searchValue)
|
String searchKey, Serializable searchValue)
|
||||||
{
|
{
|
||||||
@@ -244,12 +244,13 @@ public class AuditDAOImpl extends AbstractAuditDAOImpl
|
|||||||
}
|
}
|
||||||
params.setSearchValueId(searchValuePair.getFirst());
|
params.setSearchValueId(searchValuePair.getFirst());
|
||||||
}
|
}
|
||||||
|
params.setForward(forward);
|
||||||
|
|
||||||
if (maxResults > 0)
|
if (maxResults > 0)
|
||||||
{
|
{
|
||||||
// Query without getting the values. We gather all the results and batch-fetch the audited
|
// Query without getting the values. We gather all the results and batch-fetch the audited
|
||||||
// values afterwards.
|
// values afterwards.
|
||||||
final TreeMap<Long, AuditQueryResult> resultsByValueId = new TreeMap<Long, AuditQueryResult>();
|
final Map<Long, AuditQueryResult> resultsByValueId = new HashMap<Long, AuditQueryResult>(173);
|
||||||
PropertyFinderCallback propertyFinderCallback = new PropertyFinderCallback()
|
PropertyFinderCallback propertyFinderCallback = new PropertyFinderCallback()
|
||||||
{
|
{
|
||||||
public void handleProperty(Long id, Serializable value)
|
public void handleProperty(Long id, Serializable value)
|
||||||
@@ -264,7 +265,6 @@ public class AuditDAOImpl extends AbstractAuditDAOImpl
|
|||||||
{
|
{
|
||||||
// The handler will deal with the entry
|
// The handler will deal with the entry
|
||||||
}
|
}
|
||||||
rowHandler.processResult(row);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -288,6 +288,11 @@ public class AuditDAOImpl extends AbstractAuditDAOImpl
|
|||||||
List<Long> valueIds = new ArrayList<Long>(resultsByValueId.keySet());
|
List<Long> valueIds = new ArrayList<Long>(resultsByValueId.keySet());
|
||||||
propertyValueDAO.getPropertiesByIds(valueIds, propertyFinderCallback);
|
propertyValueDAO.getPropertiesByIds(valueIds, propertyFinderCallback);
|
||||||
}
|
}
|
||||||
|
// Now pass the filled-out results to the row handler (order-preserved)
|
||||||
|
for (AuditQueryResult row : rows)
|
||||||
|
{
|
||||||
|
rowHandler.processResult(row);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@@ -168,12 +168,24 @@ public interface AuditService
|
|||||||
String user,
|
String user,
|
||||||
long time,
|
long time,
|
||||||
Map<String, Serializable> values);
|
Map<String, Serializable> values);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle audit entry failures
|
||||||
|
*
|
||||||
|
* @param entryId the entry ID
|
||||||
|
* @param errorMsg the error message
|
||||||
|
* @param error the exception causing the error (may be <tt>null</tt>)
|
||||||
|
* @return Return <tt>true</tt> to continue processing rows or <tt>false</tt> to stop
|
||||||
|
*/
|
||||||
|
boolean handleAuditEntryError(Long entryId, String errorMsg, Throwable error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the audit entries that match the given criteria.
|
* Get the audit entries that match the given criteria.
|
||||||
*
|
*
|
||||||
* @param callback the callback that will handle results
|
* @param callback the callback that will handle results
|
||||||
|
* @param forward <tt>true</tt> for results to ordered from first to last,
|
||||||
|
* or <tt>false</tt> to order from last to first
|
||||||
* @param applicationName if not <tt>null</tt>, find entries logged against this application
|
* @param applicationName if not <tt>null</tt>, find entries logged against this application
|
||||||
* @param user if not <tt>null</tt>, find entries logged against this user
|
* @param user if not <tt>null</tt>, find entries logged against this user
|
||||||
* @param from the start search time (<tt>null</tt> to start at the beginning)
|
* @param from the start search time (<tt>null</tt> to start at the beginning)
|
||||||
@@ -184,6 +196,7 @@ public interface AuditService
|
|||||||
*/
|
*/
|
||||||
void auditQuery(
|
void auditQuery(
|
||||||
AuditQueryCallback callback,
|
AuditQueryCallback callback,
|
||||||
|
boolean forward,
|
||||||
String applicationName, String user, Long from, Long to,
|
String applicationName, String user, Long from, Long to,
|
||||||
int maxResults);
|
int maxResults);
|
||||||
|
|
||||||
@@ -191,6 +204,8 @@ public interface AuditService
|
|||||||
* Get the audit entries that match the given criteria.
|
* Get the audit entries that match the given criteria.
|
||||||
*
|
*
|
||||||
* @param callback the callback that will handle results
|
* @param callback the callback that will handle results
|
||||||
|
* @param forward <tt>true</tt> for results to ordered from first to last,
|
||||||
|
* or <tt>false</tt> to order from last to first
|
||||||
* @param applicationName if not <tt>null</tt>, find entries logged against this application
|
* @param applicationName if not <tt>null</tt>, find entries logged against this application
|
||||||
* @param user if not <tt>null</tt>, find entries logged against this user
|
* @param user if not <tt>null</tt>, find entries logged against this user
|
||||||
* @param from the start search time (<tt>null</tt> to start at the beginning)
|
* @param from the start search time (<tt>null</tt> to start at the beginning)
|
||||||
@@ -203,6 +218,7 @@ public interface AuditService
|
|||||||
*/
|
*/
|
||||||
void auditQuery(
|
void auditQuery(
|
||||||
AuditQueryCallback callback,
|
AuditQueryCallback callback,
|
||||||
|
boolean forward,
|
||||||
String applicationName, String user, Long from, Long to,
|
String applicationName, String user, Long from, Long to,
|
||||||
String searchKey, Serializable searchValue,
|
String searchKey, Serializable searchValue,
|
||||||
int maxResults);
|
int maxResults);
|
||||||
|
Reference in New Issue
Block a user