fix for the apps-3129

This commit is contained in:
Sathish Kumar
2024-12-12 09:08:17 +05:30
parent 4b549bf474
commit 131f6e67da
10 changed files with 2574 additions and 2588 deletions

View File

@@ -93,15 +93,15 @@ public class RMv33HoldAuditEntryValuesPatchUnitTest
verify(mockedRecordsManagementQueryDAO, times(1)).updatePropertyStringValueEntity(deleteHoldPropertyStringValueEntity); verify(mockedRecordsManagementQueryDAO, times(1)).updatePropertyStringValueEntity(deleteHoldPropertyStringValueEntity);
assertEquals("Add To Hold", addToHoldPropertyStringValueEntity.getStringValue()); assertEquals("Add To Hold", addToHoldPropertyStringValueEntity.getStringValue());
assertEquals("add to hold", addToHoldPropertyStringValueEntity.getStringLower()); assertEquals("add to hold", addToHoldPropertyStringValueEntity.getStringEndLower());
assertEquals(Long.valueOf(770_786_109L), addToHoldPropertyStringValueEntity.getStringCrc()); assertEquals(Long.valueOf(770_786_109L), addToHoldPropertyStringValueEntity.getStringCrc());
assertEquals("Remove From Hold", removeFromHoldPropertyStringValueEntity.getStringValue()); assertEquals("Remove From Hold", removeFromHoldPropertyStringValueEntity.getStrRvingValue());
assertEquals("remove from hold", removeFromHoldPropertyStringValueEntity.getStringLower()); assertEquals("remove from hold", removeFromHoldPropertyStringValueEntity.getStringEndLower());
assertEquals(Long.valueOf(2_967_613_012L), removeFromHoldPropertyStringValueEntity.getStringCrc()); assertEquals(Long.valueOf(2_967_613_012L), removeFromHoldPropertyStringValueEntity.getStringCrc());
assertEquals("Delete Hold", deleteHoldPropertyStringValueEntity.getStringValue()); assertEquals("Delete Hold", deleteHoldPropertyStringValueEntity.getStringValue());
assertEquals("delete hold", deleteHoldPropertyStringValueEntity.getStringLower()); assertEquals("delete hold", deleteHoldPropertyStringValueEntity.getStringEndLower());
assertEquals(Long.valueOf(132_640_810L), deleteHoldPropertyStringValueEntity.getStringCrc()); assertEquals(Long.valueOf(132_640_810L), deleteHoldPropertyStringValueEntity.getStringCrc());
} }
@@ -122,6 +122,4 @@ public class RMv33HoldAuditEntryValuesPatchUnitTest
verify(mockedRecordsManagementQueryDAO, times(1)).getPropertyStringValueEntity("deleteHold"); verify(mockedRecordsManagementQueryDAO, times(1)).getPropertyStringValueEntity("deleteHold");
verify(mockedRecordsManagementQueryDAO, times(0)).updatePropertyStringValueEntity(any()); verify(mockedRecordsManagementQueryDAO, times(0)).updatePropertyStringValueEntity(any());
} }
} }

View File

@@ -909,14 +909,15 @@ public class AuditImpl implements Audit
public int getAuditEntriesCountByAppAndProperties(AuditService.AuditApplication auditApplication, AuditEntryQueryWalker propertyWalker) public int getAuditEntriesCountByAppAndProperties(AuditService.AuditApplication auditApplication, AuditEntryQueryWalker propertyWalker)
{ {
final String applicationName = auditApplication.getKey().substring(1);
AuditQueryParameters parameters = new AuditQueryParameters(); AuditQueryParameters parameters = new AuditQueryParameters();
parameters.setApplicationName(auditApplication.getName()); parameters.setApplicationName(applicationName);
parameters.setFromTime(propertyWalker.getFromTime()); parameters.setFromTime(propertyWalker.getFromTime());
parameters.setToTime(propertyWalker.getToTime()); parameters.setToTime(propertyWalker.getToTime());
parameters.setFromId(propertyWalker.getFromId()); parameters.setFromId(propertyWalker.getFromId());
parameters.setToId(propertyWalker.getToId()); parameters.setToId(propertyWalker.getToId());
parameters.setUser(propertyWalker.getCreatedByUser()); parameters.setUser(propertyWalker.getCreatedByUser());
return auditService.getAuditEntriesCountByAppAndProperties(parameters); return auditService.getAuditEntriesCountByAppAndProperties(applicationName, parameters);
} }
} }

View File

@@ -1,286 +1,287 @@
/* /*
* #%L * #%L
* Alfresco Repository * Alfresco Repository
* %% * %%
* Copyright (C) 2005 - 2024 Alfresco Software Limited * Copyright (C) 2005 - 2024 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of * If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is * the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms: * provided under the following open source license terms:
* *
* Alfresco is free software: you can redistribute it and/or modify * Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* Alfresco is distributed in the hope that it will be useful, * Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details. * GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L% * #L%
*/ */
package org.alfresco.repo.audit; package org.alfresco.repo.audit;
import java.io.Serializable; import java.io.Serializable;
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 org.alfresco.repo.audit.model.AuditApplication; import org.alfresco.repo.audit.model.AuditApplication;
import org.alfresco.repo.audit.model.AuditModelRegistry; import org.alfresco.repo.audit.model.AuditModelRegistry;
import org.alfresco.repo.audit.model._3.AuditPath; import org.alfresco.repo.audit.model._3.AuditPath;
import org.alfresco.service.cmr.audit.AuditQueryParameters; import org.alfresco.service.cmr.audit.AuditQueryParameters;
import org.alfresco.service.cmr.audit.AuditService.AuditQueryCallback; import org.alfresco.service.cmr.audit.AuditService.AuditQueryCallback;
/** /**
* The audit component. Used by the AuditService and AuditMethodInterceptor to insert audit entries. * The audit component. Used by the AuditService and AuditMethodInterceptor to insert audit entries.
* *
* @author Derek Hulley * @author Derek Hulley
*/ */
public interface AuditComponent public interface AuditComponent
{ {
/** /**
* Determines whether audit is globally enabled or disabled. * Determines whether audit is globally enabled or disabled.
* *
* @return Returns <code>true</code> if audit is enabled * @return Returns <code>true</code> if audit is enabled
* *
* @since 3.3 * @since 3.3
*/ */
public boolean isAuditEnabled(); public boolean isAuditEnabled();
/** /**
* Switch auditing on or off * Switch auditing on or off
* *
* @param enable <tt>true</tt> to enable auditing or <tt>false</tt> to disable * @param enable <tt>true</tt> to enable auditing or <tt>false</tt> to disable
* *
* @since 3.4 * @since 3.4
*/ */
public void setAuditEnabled(boolean enable); public void setAuditEnabled(boolean enable);
/** /**
* @param userAuditFilter UserAuditFilter * @param userAuditFilter UserAuditFilter
* *
* @since 4.2 * @since 4.2
*/ */
public void setUserAuditFilter(UserAuditFilter userAuditFilter); public void setUserAuditFilter(UserAuditFilter userAuditFilter);
/** /**
* Get all registered audit applications, whether active or not. * Get all registered audit applications, whether active or not.
* *
* @return Returns a map of registered audit applications keyed by name * @return Returns a map of registered audit applications keyed by name
* *
* @since 3.4 * @since 3.4
*/ */
public Map<String, AuditApplication> getAuditApplications(); public Map<String, AuditApplication> getAuditApplications();
/** /**
* Determine whether the audit infrastructure expects audit values to be passed in. * Determine whether the audit infrastructure expects audit values to be passed in.
* This is a helper method to allow optimizations in the client code. Reasons why * This is a helper method to allow optimizations in the client code. Reasons why
* this method might return <tt>false</tt> are: auditing is disabled; no audit applications * this method might return <tt>false</tt> are: auditing is disabled; no audit applications
* have been registered. Sometimes, depending on the log level, this method may always * have been registered. Sometimes, depending on the log level, this method may always
* return <tt>true</tt>. * return <tt>true</tt>.
* *
* *
* @return Returns <code>true</code> if the calling code (data producers) * @return Returns <code>true</code> if the calling code (data producers)
* should go ahead and generate the data for * should go ahead and generate the data for
* {@link #recordAuditValues(String, Map) recording}. * {@link #recordAuditValues(String, Map) recording}.
* *
* @since 3.3 * @since 3.3
*/ */
public boolean areAuditValuesRequired(); public boolean areAuditValuesRequired();
/** /**
* Determines if audit values are required based on whether there are any audit applications * Determines if audit values are required based on whether there are any audit applications
* registered to record data for the given path. This helper method gives data producers a * registered to record data for the given path. This helper method gives data producers a
* shortcut in the event that nothing would be recorded in any event. * shortcut in the event that nothing would be recorded in any event.
* *
* @param path the audit path * @param path the audit path
* @return Returns <tt>true</tt> if there is at least one audit application * @return Returns <tt>true</tt> if there is at least one audit application
* registered to handle the given path. * registered to handle the given path.
* *
* @since 3.4 * @since 3.4
*/ */
public boolean areAuditValuesRequired(String path); public boolean areAuditValuesRequired(String path);
/** /**
* Delete audit entries for the given application and time range * Delete audit entries for the given application and time range
* *
* @param applicationName the name of the application * @param applicationName the name of the application
* @param fromTime the start time of entries to remove (inclusive and optional) * @param fromTime the start time of entries to remove (inclusive and optional)
* @param toTime the end time of entries to remove (exclusive and optional) * @param toTime the end time of entries to remove (exclusive and optional)
* @return Returns the number of entries deleted * @return Returns the number of entries deleted
* *
* @since 3.2 * @since 3.2
*/ */
int deleteAuditEntries(String applicationName, Long fromTime, Long toTime); int deleteAuditEntries(String applicationName, Long fromTime, Long toTime);
/** /**
* Delete audit entries for the given application and id range * Delete audit entries for the given application and id range
* *
* @param applicationName the name of the application * @param applicationName the name of the application
* @param fromId the start time of entries to remove (inclusive and optional) * @param fromId the start time of entries to remove (inclusive and optional)
* @param toId the end time of entries to remove (exclusive and optional) * @param toId the end time of entries to remove (exclusive and optional)
* @return Returns the number of entries deleted * @return Returns the number of entries deleted
* *
* @since 5.2.2 * @since 5.2.2
*/ */
int deleteAuditEntriesByIdRange(String applicationName, Long fromId, Long toId); int deleteAuditEntriesByIdRange(String applicationName, Long fromId, Long toId);
/** /**
* Delete a discrete list of audit entries based on ID * Delete a discrete list of audit entries based on ID
* *
* @param auditEntryIds the audit entry IDs to delete * @param auditEntryIds the audit entry IDs to delete
* @return Returns the number of entries deleted * @return Returns the number of entries deleted
*/ */
int deleteAuditEntries(List<Long> auditEntryIds); int deleteAuditEntries(List<Long> auditEntryIds);
/** /**
* Check if an audit path is enabled. The path will be disabled if it or any higher * Check if an audit path is enabled. The path will be disabled if it or any higher
* path has been explicitly disabled. Any disabled path will not be processed when * path has been explicitly disabled. Any disabled path will not be processed when
* data is audited. * data is audited.
* *
* @param applicationName the name of the application being logged to * @param applicationName the name of the application being logged to
* @param path the audit path to check or <tt>null</tt> to assume the * @param path the audit path to check or <tt>null</tt> to assume the
* application's root path * application's root path
* @return Returns <tt>true</tt> if the audit path has been disabled * @return Returns <tt>true</tt> if the audit path has been disabled
* *
* @since 3.2 * @since 3.2
*/ */
boolean isAuditPathEnabled(String applicationName, String path); boolean isAuditPathEnabled(String applicationName, String path);
/** /**
* Enable auditing (if it is not already enabled) for all paths that contain the given path. * Enable auditing (if it is not already enabled) for all paths that contain the given path.
* The path is the path as originally logged and * The path is the path as originally logged and
* not the path that the generated data may contain - although this would be similarly * not the path that the generated data may contain - although this would be similarly
* enabled. * enabled.
* <p> * <p>
* If the enabled * If the enabled
* *
* @param applicationName the name of the application being logged to * @param applicationName the name of the application being logged to
* @param path the audit path to check or <tt>null</tt> to assume the * @param path the audit path to check or <tt>null</tt> to assume the
* application's root path * application's root path
* *
* @since 3.2 * @since 3.2
*/ */
void enableAudit(String applicationName, String path); void enableAudit(String applicationName, String path);
/** /**
* Disable auditing (if it is not already disabled) for all paths that contain the given path. * Disable auditing (if it is not already disabled) for all paths that contain the given path.
* The path is the path as originally logged and * The path is the path as originally logged and
* not the path that the generated data may contain - although this would be similarly * not the path that the generated data may contain - although this would be similarly
* disabled. * disabled.
* <p> * <p>
* If the path is <b>/x/y</b> then any data paths that start with <b>/x/y</b> will be stripped * If the path is <b>/x/y</b> then any data paths that start with <b>/x/y</b> will be stripped
* out <u>before</u> data generators and data recorders are applied. If the path represents * out <u>before</u> data generators and data recorders are applied. If the path represents
* the root path of the application, then auditing for that application is effectively disabled. * the root path of the application, then auditing for that application is effectively disabled.
* *
* @param applicationName the name of the application being logged to * @param applicationName the name of the application being logged to
* @param path the audit path to check or <tt>null</tt> to assume the * @param path the audit path to check or <tt>null</tt> to assume the
* application's root path * application's root path
* *
* @since 3.2 * @since 3.2
*/ */
void disableAudit(String applicationName, String path); void disableAudit(String applicationName, String path);
/** /**
* Remove all disabled paths i.e. enable all per-path based auditing. Auditing may still be * Remove all disabled paths i.e. enable all per-path based auditing. Auditing may still be
* disabled globally. This is primarily for test purposes; applications should know which * disabled globally. This is primarily for test purposes; applications should know which
* paths need {@link #enableAudit(String, String) enabling} or * paths need {@link #enableAudit(String, String) enabling} or
* {@link #disableAudit(String, String) disabled}. * {@link #disableAudit(String, String) disabled}.
* *
* @param applicationName the name of the application * @param applicationName the name of the application
* *
* @since 3.2 * @since 3.2
*/ */
void resetDisabledPaths(String applicationName); void resetDisabledPaths(String applicationName);
/** /**
* Create an audit entry for the given map of values. The map key is a path - starting with '/' * Create an audit entry for the given map of values. The map key is a path - starting with '/'
* ({@link AuditApplication#AUDIT_PATH_SEPARATOR}) - relative to the root path provided. * ({@link AuditApplication#AUDIT_PATH_SEPARATOR}) - relative to the root path provided.
* <p/> * <p/>
* The root path and value keys are combined to produce a map of data keyed by full path. This * The root path and value keys are combined to produce a map of data keyed by full path. This
* fully-pathed map is then passed through the * fully-pathed map is then passed through the
* {@link AuditModelRegistry#getAuditPathMapper() audit path mapper}. The result may yield data * {@link AuditModelRegistry#getAuditPathMapper() audit path mapper}. The result may yield data
* destined for several different * destined for several different
* {@link AuditModelRegistry#getAuditApplicationByKey(String) audit applications}. depending on * {@link AuditModelRegistry#getAuditApplicationByKey(String) audit applications}. depending on
* the data extraction and generation defined in the applications, values (or derived values) may * the data extraction and generation defined in the applications, values (or derived values) may
* be recorded against several audit entries (one per application represented). * be recorded against several audit entries (one per application represented).
* <p/> * <p/>
* The return values reflect what was actually persisted and is controlled by the data extractors * The return values reflect what was actually persisted and is controlled by the data extractors
* defined in the audit configuration. * defined in the audit configuration.
* <p/> * <p/>
* A new read-write transaction is started if there are values to write that there is not a viable * A new read-write transaction is started if there are values to write that there is not a viable
* transaction present. * transaction present.
* *
* @param rootPath a base path of {@link AuditPath} key entries concatenated with the path separator * @param rootPath a base path of {@link AuditPath} key entries concatenated with the path separator
* '/' ({@link AuditApplication#AUDIT_PATH_SEPARATOR}) * '/' ({@link AuditApplication#AUDIT_PATH_SEPARATOR})
* @param values the values to audit mapped by {@link AuditPath} key relative to root path * @param values the values to audit mapped by {@link AuditPath} key relative to root path
* (may be <tt>null</tt>) * (may be <tt>null</tt>)
* @return Returns the values that were actually persisted, keyed by their full path. * @return Returns the values that were actually persisted, keyed by their full path.
* @throws IllegalStateException if the transaction state could not be determined * @throws IllegalStateException if the transaction state could not be determined
* *
* @since 3.2 * @since 3.2
*/ */
Map<String, Serializable> recordAuditValues(String rootPath, Map<String, Serializable> values); Map<String, Serializable> recordAuditValues(String rootPath, Map<String, Serializable> values);
/** /**
* The same as {@link AuditComponent#recordAuditValues(String, Map)}, but with controlled usage of userFilter * The same as {@link AuditComponent#recordAuditValues(String, Map)}, but with controlled usage of userFilter
* *
* @param rootPath a base path of {@link AuditPath} key entries concatenated with the path separator * @param rootPath a base path of {@link AuditPath} key entries concatenated with the path separator
* '/' ({@link AuditApplication#AUDIT_PATH_SEPARATOR}) * '/' ({@link AuditApplication#AUDIT_PATH_SEPARATOR})
* @param values the values to audit mapped by {@link AuditPath} key relative to root path * @param values the values to audit mapped by {@link AuditPath} key relative to root path
* (may be <tt>null</tt>) * (may be <tt>null</tt>)
* @param useUserFilter if <tt>false</tt> the user filter is disabled. * @param useUserFilter if <tt>false</tt> the user filter is disabled.
* @return Returns the values that were actually persisted, keyed by their full path. * @return Returns the values that were actually persisted, keyed by their full path.
* @throws IllegalStateException if the transaction state could not be determined * @throws IllegalStateException if the transaction state could not be determined
*/ */
Map<String, Serializable> recordAuditValuesWithUserFilter(String rootPath, Map<String, Serializable> values, boolean useUserFilter); Map<String, Serializable> recordAuditValuesWithUserFilter(String rootPath, Map<String, Serializable> values, boolean useUserFilter);
/** /**
* Find audit entries using the given parameters * Find audit entries using the given parameters
* *
* @param callback the data callback per entry * @param callback the data callback per entry
* @param parameters the parameters for the query (may not be <tt>null</tt>) * @param parameters the parameters for the query (may not be <tt>null</tt>)
* @param maxResults the maximum number of results to retrieve (must be greater than 0) * @param maxResults the maximum number of results to retrieve (must be greater than 0)
* *
* @throws IllegalArgumentException if maxResults less or equal to zero * @throws IllegalArgumentException if maxResults less or equal to zero
* *
* @since 3.2 * @since 3.2
*/ */
void auditQuery(AuditQueryCallback callback, AuditQueryParameters parameters, int maxResults); void auditQuery(AuditQueryCallback callback, AuditQueryParameters parameters, int maxResults);
/** /**
* Issue an audit query to retrieve min / max audit record id for a given application. * Issue an audit query to retrieve min / max audit record id for a given application.
* *
* @param applicationName the name of the application * @param applicationName the name of the application
* @param extremes a list containing min/max or both * @param extremes a list containing min/max or both
* @return a map containing min/max and the associated value * @return a map containing min/max and the associated value
*/ */
HashMap<String, Long> getAuditMinMaxByApp(String applicationName, List<String> extremes); HashMap<String, Long> getAuditMinMaxByApp(String applicationName, List<String> extremes);
/** /**
* Issue an audit query to retrieve count of records for a given application. * Issue an audit query to retrieve count of records for a given application.
* *
* @param applicationName the name of the application * @param applicationName the name of the application
* @return a map containing min/max and the associated value * @return a map containing min/max and the associated value
*/ */
default int getAuditEntriesCountByApp(String applicationName) default int getAuditEntriesCountByApp(String applicationName)
{ {
return -1; return -1;
} }
/** /**
* Issue an audit query to retrieve count of records for a given application and properties * Issue an audit query to retrieve count of records for a given application and properties
* *
* @param parameters audit parameters provided by the <code>where</code> clause on the ReST API * @param applicationName the name of the application
* @return a map containing min/max and the associated value * @param parameters audit parameters provided by the <code>where</code> clause on the ReST API
*/ * @return a map containing min/max and the associated value
default int getAuditEntriesCountByAppAndProperties(AuditQueryParameters parameters) */
{ default int getAuditEntriesCountByAppAndProperties(String applicationName, AuditQueryParameters parameters)
return -1; {
} return -1;
} }
}

View File

@@ -1,197 +1,197 @@
/* /*
* #%L * #%L
* Alfresco Repository * Alfresco Repository
* %% * %%
* Copyright (C) 2005 - 2024 Alfresco Software Limited * Copyright (C) 2005 - 2024 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of * If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is * the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms: * provided under the following open source license terms:
* *
* Alfresco is free software: you can redistribute it and/or modify * Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* Alfresco is distributed in the hope that it will be useful, * Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details. * GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L% * #L%
*/ */
package org.alfresco.repo.audit; package org.alfresco.repo.audit;
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 java.util.TreeMap;
import org.alfresco.service.cmr.audit.AuditQueryParameters; import org.alfresco.service.cmr.audit.AuditQueryParameters;
import org.alfresco.service.cmr.audit.AuditService; import org.alfresco.service.cmr.audit.AuditService;
/** /**
* The implementation of the AuditService for application auditing. * The implementation of the AuditService for application auditing.
* *
* @author Derek Hulley * @author Derek Hulley
* @since 3.2 * @since 3.2
*/ */
public class AuditServiceImpl implements AuditService public class AuditServiceImpl implements AuditService
{ {
private AuditComponent auditComponent; private AuditComponent auditComponent;
public AuditServiceImpl() public AuditServiceImpl()
{ {
super(); super();
} }
public void setAuditComponent(AuditComponent auditComponent) public void setAuditComponent(AuditComponent auditComponent)
{ {
this.auditComponent = auditComponent; this.auditComponent = auditComponent;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
* @since 3.4 * @since 3.4
*/ */
public boolean isAuditEnabled() public boolean isAuditEnabled()
{ {
return auditComponent.isAuditEnabled(); return auditComponent.isAuditEnabled();
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
* @since 3.4 * @since 3.4
*/ */
@Override @Override
public void setAuditEnabled(boolean enable) public void setAuditEnabled(boolean enable)
{ {
auditComponent.setAuditEnabled(enable); auditComponent.setAuditEnabled(enable);
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
* @since 3.4 * @since 3.4
*/ */
@Override @Override
public Map<String, AuditApplication> getAuditApplications() public Map<String, AuditApplication> getAuditApplications()
{ {
Map<String, org.alfresco.repo.audit.model.AuditApplication> apps = auditComponent.getAuditApplications(); Map<String, org.alfresco.repo.audit.model.AuditApplication> apps = auditComponent.getAuditApplications();
Map<String, AuditApplication> ret = new TreeMap<String, AuditApplication>(); Map<String, AuditApplication> ret = new TreeMap<String, AuditApplication>();
for (String app : apps.keySet()) for (String app : apps.keySet())
{ {
String name = app; String name = app;
String key = org.alfresco.repo.audit.model.AuditApplication.AUDIT_PATH_SEPARATOR + apps.get(app).getApplicationKey(); String key = org.alfresco.repo.audit.model.AuditApplication.AUDIT_PATH_SEPARATOR + apps.get(app).getApplicationKey();
boolean enabled = auditComponent.isAuditPathEnabled(app, key); boolean enabled = auditComponent.isAuditPathEnabled(app, key);
AuditApplication auditApplication = new AuditApplication(name, key, enabled); AuditApplication auditApplication = new AuditApplication(name, key, enabled);
ret.put(name, auditApplication); ret.put(name, auditApplication);
} }
return ret; return ret;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
* @since 3.2 * @since 3.2
*/ */
public boolean isAuditEnabled(String applicationName, String path) public boolean isAuditEnabled(String applicationName, String path)
{ {
return auditComponent.isAuditPathEnabled(applicationName, path); return auditComponent.isAuditPathEnabled(applicationName, path);
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
* @since 3.2 * @since 3.2
*/ */
public void enableAudit(String applicationName, String path) public void enableAudit(String applicationName, String path)
{ {
auditComponent.enableAudit(applicationName, path); auditComponent.enableAudit(applicationName, path);
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
* @since 3.2 * @since 3.2
*/ */
public void disableAudit(String applicationName, String path) public void disableAudit(String applicationName, String path)
{ {
auditComponent.disableAudit(applicationName, path); auditComponent.disableAudit(applicationName, path);
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
* @since 3.2 * @since 3.2
*/ */
public int clearAudit(String applicationName) public int clearAudit(String applicationName)
{ {
Long now = Long.valueOf(System.currentTimeMillis()); Long now = Long.valueOf(System.currentTimeMillis());
return auditComponent.deleteAuditEntries(applicationName, null, now); return auditComponent.deleteAuditEntries(applicationName, null, now);
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
* @since 3.4 * @since 3.4
*/ */
@Override @Override
public int clearAudit(String applicationName, Long fromTime, Long toTime) public int clearAudit(String applicationName, Long fromTime, Long toTime)
{ {
toTime = (toTime == null) ? Long.valueOf(System.currentTimeMillis()) : toTime; toTime = (toTime == null) ? Long.valueOf(System.currentTimeMillis()) : toTime;
return auditComponent.deleteAuditEntries(applicationName, fromTime, toTime); return auditComponent.deleteAuditEntries(applicationName, fromTime, toTime);
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
* @since 5.2.2 * @since 5.2.2
*/ */
@Override @Override
public int clearAuditByIdRange(String applicationName, Long fromId, Long toId) public int clearAuditByIdRange(String applicationName, Long fromId, Long toId)
{ {
return auditComponent.deleteAuditEntriesByIdRange(applicationName, fromId, toId); return auditComponent.deleteAuditEntriesByIdRange(applicationName, fromId, toId);
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
* @since 3.4 * @since 3.4
*/ */
@Override @Override
public int clearAudit(List<Long> auditEntryIds) public int clearAudit(List<Long> auditEntryIds)
{ {
return auditComponent.deleteAuditEntries(auditEntryIds); return auditComponent.deleteAuditEntries(auditEntryIds);
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
* @since 3.3 * @since 3.3
*/ */
public void auditQuery(AuditQueryCallback callback, AuditQueryParameters parameters, int maxResults) public void auditQuery(AuditQueryCallback callback, AuditQueryParameters parameters, int maxResults)
{ {
auditComponent.auditQuery(callback, parameters, maxResults); auditComponent.auditQuery(callback, parameters, maxResults);
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public HashMap<String, Long> getAuditMinMaxByApp(String applicationName, List<String> extremes) public HashMap<String, Long> getAuditMinMaxByApp(String applicationName, List<String> extremes)
{ {
return auditComponent.getAuditMinMaxByApp(applicationName, extremes); return auditComponent.getAuditMinMaxByApp(applicationName, extremes);
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public int getAuditEntriesCountByApp(String applicationName) public int getAuditEntriesCountByApp(String applicationName)
{ {
return auditComponent.getAuditEntriesCountByApp(applicationName); return auditComponent.getAuditEntriesCountByApp(applicationName);
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override public int getAuditEntriesCountByAppAndProperties(AuditQueryParameters parameters) @Override public int getAuditEntriesCountByAppAndProperties(String applicationName, AuditQueryParameters parameters)
{ {
return auditComponent.getAuditEntriesCountByAppAndProperties(parameters); return auditComponent.getAuditEntriesCountByAppAndProperties(applicationName, parameters);
} }
} }

View File

@@ -1,123 +1,122 @@
/* /*
* #%L * #%L
* Alfresco Repository * Alfresco Repository
* %% * %%
* Copyright (C) 2005 - 2024 Alfresco Software Limited * Copyright (C) 2005 - 2024 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of * If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is * the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms: * provided under the following open source license terms:
* *
* Alfresco is free software: you can redistribute it and/or modify * Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* Alfresco is distributed in the hope that it will be useful, * Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details. * GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L% * #L%
*/ */
package org.alfresco.repo.domain; package org.alfresco.repo.domain;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.util.zip.CRC32; import java.util.zip.CRC32;
import org.alfresco.util.Pair; import org.alfresco.util.Pair;
/** /**
* Helper class to calculate CRC values for string persistence. * Helper class to calculate CRC values for string persistence.
* *
* @author Derek Hulley * @author Derek Hulley
* @since 3.2 * @since 3.2
*/ */
public class CrcHelper public class CrcHelper
{ {
public static final String EMPTY_STRING = ".empty"; public static final String EMPTY_STRING = ".empty";
/** /**
* Calculate a persistable, unique pair of values that can be persisted in a database unique * Calculate a persistable, unique pair of values that can be persisted in a database unique
* key and guarantee correct case-sensitivity. * key and guarantee correct case-sensitivity.
* <p> * <p>
* While the short-string version of the value is always lowercase, the CRC is * While the short-string version of the value is always lowercase, the CRC is
* calculated from the virgin string if case-sensitivity is enforced; in the case-insensitive * calculated from the virgin string if case-sensitivity is enforced; in the case-insensitive
* case, the CRC is calculated from a lowercase version of the string. * case, the CRC is calculated from a lowercase version of the string.
* <p> * <p>
* If the value is an empty string, then {@link #EMPTY_STRING} is used instead. This ensures * If the value is an empty string, then {@link #EMPTY_STRING} is used instead. This ensures
* that persisted values don't fall foul of the Oracle empty string comparison "behaviour" i.e * that persisted values don't fall foul of the Oracle empty string comparison "behaviour" i.e
* you should never persist an empty string in Oracle as it equates to a SQL <b>NULL</b>. * you should never persist an empty string in Oracle as it equates to a SQL <b>NULL</b>.
* *
* @param value the raw value that will be persisted * @param value the raw value that will be persisted
* @param dataLength the maximum number of characters that can be persisted * @param dataLength the maximum number of characters that can be persisted
* @param useCharsFromStart <tt>true</tt> if the shortened string value must be made from * @param useCharsFromStart <tt>true</tt> if the shortened string value must be made from
* the first characters of the string or <tt>false</tt> to use * the first characters of the string or <tt>false</tt> to use
* characters from the end of the string. * characters from the end of the string.
* @param caseSensitive <tt>true</tt> if the resulting pair must be case-sensitive or * @param caseSensitive <tt>true</tt> if the resulting pair must be case-sensitive or
* <tt>false</tt> if the pair must be case-insensitive. * <tt>false</tt> if the pair must be case-insensitive.
* @return Return the persistable pair. The result will never be <tt>null</tt>, * @return Return the persistable pair. The result will never be <tt>null</tt>,
* but the individual pair values will be <tt>null</tt> if the * but the individual pair values will be <tt>null</tt> if the
* value given is <tt>null</tt> * value given is <tt>null</tt>
*/ */
public static Pair<String, Long> getStringCrcPair( public static Pair<String, Long> getStringCrcPair(
String value, String value,
int dataLength, int dataLength,
boolean useCharsFromStart, boolean useCharsFromStart,
boolean caseSensitive) boolean caseSensitive)
{ {
String valueLowerCase; String valueLowerCase;
if (value == null) if (value == null)
{ {
return new Pair<String, Long>(null, null); return new Pair<String, Long>(null, null);
} }
else if (value.length() == 0) else if (value.length() == 0)
{ {
value = CrcHelper.EMPTY_STRING; value = CrcHelper.EMPTY_STRING;
valueLowerCase = value; valueLowerCase = value;
} }
else else
{ {
valueLowerCase = value.toLowerCase(); valueLowerCase = value.toLowerCase();
} }
Long valueCrc; Long valueCrc;
try try
{ {
CRC32 crc = new CRC32(); CRC32 crc = new CRC32();
if (caseSensitive) if (caseSensitive)
{ {
crc.update(value.getBytes("UTF-8")); crc.update(value.getBytes("UTF-8"));
} }
else else
{ {
crc.update(valueLowerCase.getBytes("UTF-8")); crc.update(valueLowerCase.getBytes("UTF-8"));
} }
valueCrc = crc.getValue(); valueCrc = crc.getValue();
} }
catch (UnsupportedEncodingException e) catch (UnsupportedEncodingException e)
{ {
throw new RuntimeException("UTF-8 encoding is not supported"); throw new RuntimeException("UTF-8 encoding is not supported");
} }
// Crc Value will change based on the case-sensitive, So we need to get the short value based on case-sensitive // Get the short value (case-sensitive or not)
String valueShort = null; String valueShort = null;
String currentValue = caseSensitive ? value : valueLowerCase; int valueLen = valueLowerCase.length();
int valueLen = currentValue.length(); if (valueLen < dataLength)
if (valueLen < dataLength) {
{ valueShort = valueLowerCase;
valueShort = currentValue; }
} else if (useCharsFromStart)
else if (useCharsFromStart) {
{ valueShort = valueLowerCase.substring(0, dataLength - 1);
valueShort = currentValue.substring(0, dataLength - 1); }
} else
else {
{ valueShort = valueLowerCase.substring(valueLen - dataLength);
valueShort = currentValue.substring(valueLen - dataLength); }
} return new Pair<String, Long>(valueShort, valueCrc);
return new Pair<String, Long>(valueShort, valueCrc); }
}
} }

View File

@@ -1,258 +1,259 @@
/* /*
* #%L * #%L
* Alfresco Repository * Alfresco Repository
* %% * %%
* Copyright (C) 2005 - 2024 Alfresco Software Limited * Copyright (C) 2005 - 2024 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of * If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is * the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms: * provided under the following open source license terms:
* *
* Alfresco is free software: you can redistribute it and/or modify * Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* Alfresco is distributed in the hope that it will be useful, * Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details. * GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L% * #L%
*/ */
package org.alfresco.repo.domain.audit; package org.alfresco.repo.domain.audit;
import java.io.Serializable; import java.io.Serializable;
import java.net.URL; import java.net.URL;
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.Set; import java.util.Set;
import org.alfresco.service.cmr.audit.AuditService.AuditQueryCallback; import org.alfresco.service.cmr.audit.AuditService.AuditQueryCallback;
import org.alfresco.service.cmr.repository.ContentData; import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.util.Pair; import org.alfresco.util.Pair;
/** /**
* DAO services for <b>alf_audit_XXX</b> tables. * DAO services for <b>alf_audit_XXX</b> tables.
* <p> * <p>
* The older methods are supported by a different implementation and will eventually * The older methods are supported by a different implementation and will eventually
* be deprecated and phased out. * be deprecated and phased out.
* *
* @author Derek Hulley * @author Derek Hulley
* @since 3.2 * @since 3.2
*/ */
public interface AuditDAO public interface AuditDAO
{ {
/* /*
* V3.2 methods after here only, please * V3.2 methods after here only, please
*/ */
/** /**
* Information about the audit application to be passed in an out of the interface. * Information about the audit application to be passed in an out of the interface.
* *
* @author Derek Hulley * @author Derek Hulley
* @since 3.2 * @since 3.2
*/ */
public static class AuditApplicationInfo public static class AuditApplicationInfo
{ {
private Long id; private Long id;
private String name; private String name;
private Long modelId; private Long modelId;
private Long disabledPathsId; private Long disabledPathsId;
@Override @Override
public String toString() public String toString()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("AuditApplicationInfo ") sb.append("AuditApplicationInfo ")
.append("[ id=").append(id) .append("[ id=").append(id)
.append(", name=").append(name) .append(", name=").append(name)
.append(", modelId=").append(modelId) .append(", modelId=").append(modelId)
.append(", disabledPathsId=").append(disabledPathsId) .append(", disabledPathsId=").append(disabledPathsId)
.append("]"); .append("]");
return sb.toString(); return sb.toString();
} }
public Long getId() public Long getId()
{ {
return id; return id;
} }
public void setId(Long id) public void setId(Long id)
{ {
this.id = id; this.id = id;
} }
public String getName() public String getName()
{ {
return name; return name;
} }
public void setname(String name) public void setname(String name)
{ {
this.name = name; this.name = name;
} }
public Long getModelId() public Long getModelId()
{ {
return modelId; return modelId;
} }
public void setModelId(Long modelId) public void setModelId(Long modelId)
{ {
this.modelId = modelId; this.modelId = modelId;
} }
public Long getDisabledPathsId() public Long getDisabledPathsId()
{ {
return disabledPathsId; return disabledPathsId;
} }
public void setDisabledPathsId(Long disabledPathsId) public void setDisabledPathsId(Long disabledPathsId)
{ {
this.disabledPathsId = disabledPathsId; this.disabledPathsId = disabledPathsId;
} }
} }
/** /**
* Creates a new audit model entry or finds an existing one * Creates a new audit model entry or finds an existing one
* *
* @param url the URL of the configuration * @param url the URL of the configuration
* @return Returns the ID of the config matching the input stream and the * @return Returns the ID of the config matching the input stream and the
* content storage details * content storage details
* @since 3.2 * @since 3.2
*/ */
Pair<Long, ContentData> getOrCreateAuditModel(URL url); Pair<Long, ContentData> getOrCreateAuditModel(URL url);
/** /**
* Get the audit application details. * Get the audit application details.
* *
* @param applicationName the name of the application * @param applicationName the name of the application
* @return Returns details of an existing application or <tt>null</tt> if it doesn't exist * @return Returns details of an existing application or <tt>null</tt> if it doesn't exist
* *
* @since 3.2 * @since 3.2
*/ */
AuditApplicationInfo getAuditApplication(String applicationName); AuditApplicationInfo getAuditApplication(String applicationName);
/** /**
* Creates a new audit application. The application name must be unique. * Creates a new audit application. The application name must be unique.
* *
* @param application the name of the application * @param application the name of the application
* @param modelId the ID of the model configuration * @param modelId the ID of the model configuration
* *
* @since 3.2 * @since 3.2
*/ */
AuditApplicationInfo createAuditApplication(String application, Long modelId); AuditApplicationInfo createAuditApplication(String application, Long modelId);
/** /**
* Update the audit application to refer to a new model. * Update the audit application to refer to a new model.
* If the model did not change, then nothing will be done. * If the model did not change, then nothing will be done.
* *
* @param id the ID of the audit application * @param id the ID of the audit application
* @param modelId the ID of the new model * @param modelId the ID of the new model
* *
* @since 3.2 * @since 3.2
*/ */
void updateAuditApplicationModel(Long id, Long modelId); void updateAuditApplicationModel(Long id, Long modelId);
/** /**
* Update the audit application to hold a new set of disabled paths. * Update the audit application to hold a new set of disabled paths.
* If the value did not change, then nothing will be done. * If the value did not change, then nothing will be done.
* *
* @param id the ID of the audit application * @param id the ID of the audit application
* @param disabledPaths the new disabled paths * @param disabledPaths the new disabled paths
* *
* @since 3.2 * @since 3.2
*/ */
void updateAuditApplicationDisabledPaths(Long id, Set<String> disabledPaths); void updateAuditApplicationDisabledPaths(Long id, Set<String> disabledPaths);
/** /**
* Delete audit entries for the application, possibly limiting the time range. * Delete audit entries for the application, possibly limiting the time range.
* *
* @param applicationId an existing audit application ID * @param applicationId an existing audit application ID
* @param fromTime the minimum entry time (inclusive, optional) * @param fromTime the minimum entry time (inclusive, optional)
* @param toTime the maximum entry time (exclusive, optional) * @param toTime the maximum entry time (exclusive, optional)
* @return Returns the number of entries deleted * @return Returns the number of entries deleted
* *
* @since 3.2 * @since 3.2
*/ */
int deleteAuditEntries(Long applicationId, Long fromTime, Long toTime); int deleteAuditEntries(Long applicationId, Long fromTime, Long toTime);
/** /**
* Delete audit entries for the application for given id range. * Delete audit entries for the application for given id range.
* *
* @param applicationId an existing audit application ID * @param applicationId an existing audit application ID
* @param fromId the minimum fromId (inclusive, optional) * @param fromId the minimum fromId (inclusive, optional)
* @param toId the maximum toId (exclusive, optional) * @param toId the maximum toId (exclusive, optional)
* @return Returns the number of entries deleted * @return Returns the number of entries deleted
* *
* @since 5.2.2 * @since 5.2.2
*/ */
int deleteAuditEntriesByIdRange(Long applicationId, Long fromId, Long toId); int deleteAuditEntriesByIdRange(Long applicationId, Long fromId, Long toId);
/** /**
* Delete a discrete list of audit entries. Duplicate entries are collapsed * Delete a discrete list of audit entries. Duplicate entries are collapsed
* and the number of entries deleted will match the count of unique IDs in * and the number of entries deleted will match the count of unique IDs in
* the list; otherwise a concurrency condition has occured and an exception * the list; otherwise a concurrency condition has occured and an exception
* will be generated. * will be generated.
* *
* @param auditEntryIds the IDs of all audit entries to delete * @param auditEntryIds the IDs of all audit entries to delete
* @return Returns the number of entries deleted * @return Returns the number of entries deleted
*/ */
int deleteAuditEntries(List<Long> auditEntryIds); int deleteAuditEntries(List<Long> auditEntryIds);
/** /**
* Create a new audit entry with the given map of values. * Create a new audit entry with the given map of values.
* *
* @param applicationId an existing audit application ID * @param applicationId an existing audit application ID
* @param time the time (ms since epoch) to log the entry against * @param time the time (ms since epoch) to log the entry against
* @param username the authenticated user (<tt>null</tt> if not present) * @param username the authenticated user (<tt>null</tt> if not present)
* @param values the values to record * @param values the values to record
* @return Returns the unique entry ID * @return Returns the unique entry ID
* *
* @since 3.2 * @since 3.2
*/ */
Long createAuditEntry(Long applicationId, long time, String username, Map<String, Serializable> values); Long createAuditEntry(Long applicationId, long time, String username, Map<String, Serializable> values);
/** /**
* 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 parameters the parameters for the query (may not be <tt>null</tt>) * @param parameters the parameters for the query (may not be <tt>null</tt>)
* @param maxResults the maximum number of results to retrieve (must be greater than 0) * @param maxResults the maximum number of results to retrieve (must be greater than 0)
* *
* @throws IllegalArgumentException if maxResults less or equal to zero * @throws IllegalArgumentException if maxResults less or equal to zero
*/ */
void findAuditEntries( void findAuditEntries(
AuditQueryCallback callback, AuditQueryCallback callback,
org.alfresco.service.cmr.audit.AuditQueryParameters parameters, org.alfresco.service.cmr.audit.AuditQueryParameters parameters,
int maxResults); int maxResults);
/** /**
* Issue an audit query to retrieve min / max audit record id for a given application. * Issue an audit query to retrieve min / max audit record id for a given application.
* *
* @param appId the database id of the application * @param appId the database id of the application
* @param extremes a list containing min/max or both * @param extremes a list containing min/max or both
* @return a map containing min/max and the associated value * @return a map containing min/max and the associated value
*/ */
HashMap<String, Long> getAuditMinMaxByApp(long appId, List<String> extremes); HashMap<String, Long> getAuditMinMaxByApp(long appId, List<String> extremes);
/** /**
* Issue an audit query to retrieve count of records for a given application. * Issue an audit query to retrieve count of records for a given application.
* *
* @param applicationId the database id of the application * @param applicationId the database id of the application
* @return a map containing min/max and the associated value * @return a map containing min/max and the associated value
*/ */
default int getAuditEntriesCountByApp(long applicationId) default int getAuditEntriesCountByApp(long applicationId)
{ {
return -1; return -1;
} }
/** /**
* Issue an audit query to retrieve count of records for a given application and properties * Issue an audit query to retrieve count of records for a given application and properties
* *
* @param parameters audit parameters provided by the <code>where</code> clause on the ReST API * @param applicationName name of the application to be queried
* @return a map containing min/max and the associated value * @param parameters audit parameters provided by the <code>where</code> clause on the ReST API
*/ * @return a map containing min/max and the associated value
default int getAuditEntriesCountByAppAndProperties(org.alfresco.service.cmr.audit.AuditQueryParameters parameters) */
{ default int getAuditEntriesCountByAppAndProperties(String applicationName, org.alfresco.service.cmr.audit.AuditQueryParameters parameters)
return -1; {
} return -1;
}
} }

View File

@@ -1,316 +1,315 @@
/* /*
* #%L * #%L
* Alfresco Repository * Alfresco Repository
* %% * %%
* Copyright (C) 2005 - 2024 Alfresco Software Limited * Copyright (C) 2005 - 2024 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of * If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is * the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms: * provided under the following open source license terms:
* *
* Alfresco is free software: you can redistribute it and/or modify * Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* Alfresco is distributed in the hope that it will be useful, * Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details. * GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L% * #L%
*/ */
package org.alfresco.repo.domain.audit.ibatis; package org.alfresco.repo.domain.audit.ibatis;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; 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.stream.Collectors; import java.util.stream.Collectors;
import org.alfresco.repo.domain.audit.AbstractAuditDAOImpl; import org.alfresco.repo.domain.audit.AbstractAuditDAOImpl;
import org.alfresco.repo.domain.audit.AuditApplicationEntity; import org.alfresco.repo.domain.audit.AuditApplicationEntity;
import org.alfresco.repo.domain.audit.AuditDeleteParameters; import org.alfresco.repo.domain.audit.AuditDeleteParameters;
import org.alfresco.repo.domain.audit.AuditEntryEntity; import org.alfresco.repo.domain.audit.AuditEntryEntity;
import org.alfresco.repo.domain.audit.AuditModelEntity; import org.alfresco.repo.domain.audit.AuditModelEntity;
import org.alfresco.repo.domain.audit.AuditQueryParameters; import org.alfresco.repo.domain.audit.AuditQueryParameters;
import org.alfresco.repo.domain.audit.AuditQueryResult; import org.alfresco.repo.domain.audit.AuditQueryResult;
import org.alfresco.repo.domain.propval.PropertyValueDAO.PropertyFinderCallback; import org.alfresco.repo.domain.propval.PropertyValueDAO.PropertyFinderCallback;
import org.alfresco.util.Pair; import org.alfresco.util.Pair;
import org.apache.ibatis.session.RowBounds; import org.apache.ibatis.session.RowBounds;
import org.mybatis.spring.SqlSessionTemplate; import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.dao.ConcurrencyFailureException; import org.springframework.dao.ConcurrencyFailureException;
/** /**
* iBatis-specific implementation of the DAO for <b>alf_audit_XXX</b> tables. * iBatis-specific implementation of the DAO for <b>alf_audit_XXX</b> tables.
* *
* @author Derek Hulley * @author Derek Hulley
* @since 3.2 * @since 3.2
*/ */
public class AuditDAOImpl extends AbstractAuditDAOImpl public class AuditDAOImpl extends AbstractAuditDAOImpl
{ {
private static final String SELECT_MODEL_BY_CRC = "alfresco.audit.select_AuditModelByCrc"; private static final String SELECT_MODEL_BY_CRC = "alfresco.audit.select_AuditModelByCrc";
private static final String INSERT_MODEL = "alfresco.audit.insert.insert_AuditModel"; private static final String INSERT_MODEL = "alfresco.audit.insert.insert_AuditModel";
private static final String SELECT_APPLICATION_BY_ID = "alfresco.audit.select_AuditApplicationById"; private static final String SELECT_APPLICATION_BY_ID = "alfresco.audit.select_AuditApplicationById";
private static final String SELECT_APPLICATION_BY_NAME_ID = "alfresco.audit.select_AuditApplicationByNameId"; private static final String SELECT_APPLICATION_BY_NAME_ID = "alfresco.audit.select_AuditApplicationByNameId";
private static final String INSERT_APPLICATION = "alfresco.audit.insert.insert_AuditApplication"; private static final String INSERT_APPLICATION = "alfresco.audit.insert.insert_AuditApplication";
private static final String UPDATE_APPLICATION = "alfresco.audit.update_AuditApplication"; private static final String UPDATE_APPLICATION = "alfresco.audit.update_AuditApplication";
private static final String DELETE_ENTRIES = "alfresco.audit.delete_AuditEntries"; private static final String DELETE_ENTRIES = "alfresco.audit.delete_AuditEntries";
private static final String DELETE_ENTRIES_BY_ID = "alfresco.audit.delete_AuditEntriesById"; private static final String DELETE_ENTRIES_BY_ID = "alfresco.audit.delete_AuditEntriesById";
private static final String INSERT_ENTRY = "alfresco.audit.insert.insert_AuditEntry"; private static final String INSERT_ENTRY = "alfresco.audit.insert.insert_AuditEntry";
private static final String SELECT_MINMAX_ENTRY_FOR_APP = "alfresco.audit.select_MinMaxAuditEntryId"; private static final String SELECT_MINMAX_ENTRY_FOR_APP = "alfresco.audit.select_MinMaxAuditEntryId";
private static final String SELECT_COUNT_ENTRIES_FOR_APP = "alfresco.audit.select_CountAuditEntryId"; private static final String SELECT_COUNT_ENTRIES_FOR_APP = "alfresco.audit.select_CountAuditEntryId";
private static final String SELECT_COUNT_ENTRIES_FOR_APP_WITH_PROPERTIES = "select_CountAuditEntryIdWithWhereClause"; private static final String SELECT_COUNT_ENTRIES_FOR_APP_WITH_PROPERTIES = "select_CountAuditEntryIdWithWhereClause";
@SuppressWarnings("unused") @SuppressWarnings("unused")
private static final String SELECT_ENTRIES_SIMPLE = "alfresco.audit.select_AuditEntriesSimple"; private static final String SELECT_ENTRIES_SIMPLE = "alfresco.audit.select_AuditEntriesSimple";
private static final String SELECT_ENTRIES_WITH_VALUES = "alfresco.audit.select_AuditEntriesWithValues"; private static final String SELECT_ENTRIES_WITH_VALUES = "alfresco.audit.select_AuditEntriesWithValues";
private static final String SELECT_ENTRIES_WITHOUT_VALUES = "alfresco.audit.select_AuditEntriesWithoutValues"; private static final String SELECT_ENTRIES_WITHOUT_VALUES = "alfresco.audit.select_AuditEntriesWithoutValues";
private SqlSessionTemplate template; private SqlSessionTemplate template;
public final void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) public final void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate)
{ {
this.template = sqlSessionTemplate; this.template = sqlSessionTemplate;
} }
@Override @Override
protected AuditModelEntity getAuditModelByCrc(long crc) protected AuditModelEntity getAuditModelByCrc(long crc)
{ {
AuditModelEntity entity = new AuditModelEntity(); AuditModelEntity entity = new AuditModelEntity();
entity.setContentCrc(crc); entity.setContentCrc(crc);
entity = template.selectOne( entity = template.selectOne(
SELECT_MODEL_BY_CRC, SELECT_MODEL_BY_CRC,
entity); entity);
// Done // Done
return entity; return entity;
} }
@Override @Override
protected AuditModelEntity createAuditModel(Long contentDataId, long crc) protected AuditModelEntity createAuditModel(Long contentDataId, long crc)
{ {
AuditModelEntity entity = new AuditModelEntity(); AuditModelEntity entity = new AuditModelEntity();
entity.setContentDataId(contentDataId); entity.setContentDataId(contentDataId);
entity.setContentCrc(crc); entity.setContentCrc(crc);
template.insert(INSERT_MODEL, entity); template.insert(INSERT_MODEL, entity);
return entity; return entity;
} }
@Override @Override
protected AuditApplicationEntity getAuditApplicationById(Long id) protected AuditApplicationEntity getAuditApplicationById(Long id)
{ {
Map<String, Object> params = new HashMap<String, Object>(11); Map<String, Object> params = new HashMap<String, Object>(11);
params.put("id", id); params.put("id", id);
AuditApplicationEntity entity = template.selectOne( AuditApplicationEntity entity = template.selectOne(
SELECT_APPLICATION_BY_ID, SELECT_APPLICATION_BY_ID,
params); params);
// Done // Done
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
{ {
logger.debug("Searched for audit application ID " + id + " and found: " + entity); logger.debug("Searched for audit application ID " + id + " and found: " + entity);
} }
return entity; return entity;
} }
@Override @Override
protected AuditApplicationEntity getAuditApplicationByName(String appName) protected AuditApplicationEntity getAuditApplicationByName(String appName)
{ {
// Resolve the name as a property ID // Resolve the name as a property ID
Pair<Long, Serializable> appNamePair = propertyValueDAO.getPropertyValue(appName); Pair<Long, Serializable> appNamePair = propertyValueDAO.getPropertyValue(appName);
if (appNamePair == null) if (appNamePair == null)
{ {
// There will be no results // There will be no results
return null; return null;
} }
Map<String, Object> params = new HashMap<String, Object>(11); Map<String, Object> params = new HashMap<String, Object>(11);
params.put("id", appNamePair.getFirst()); params.put("id", appNamePair.getFirst());
AuditApplicationEntity entity = template.selectOne( AuditApplicationEntity entity = template.selectOne(
SELECT_APPLICATION_BY_NAME_ID, SELECT_APPLICATION_BY_NAME_ID,
params); params);
// Done // Done
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
{ {
logger.debug("Searched for audit application '" + appName + "' and found: " + entity); logger.debug("Searched for audit application '" + appName + "' and found: " + entity);
} }
return entity; return entity;
} }
@Override @Override
protected AuditApplicationEntity createAuditApplication(Long appNameId, Long modelId, Long disabledPathsId) protected AuditApplicationEntity createAuditApplication(Long appNameId, Long modelId, Long disabledPathsId)
{ {
AuditApplicationEntity entity = new AuditApplicationEntity(); AuditApplicationEntity entity = new AuditApplicationEntity();
entity.setVersion((short)0); entity.setVersion((short)0);
entity.setApplicationNameId(appNameId); entity.setApplicationNameId(appNameId);
entity.setAuditModelId(modelId); entity.setAuditModelId(modelId);
entity.setDisabledPathsId(disabledPathsId); entity.setDisabledPathsId(disabledPathsId);
template.insert(INSERT_APPLICATION, entity); template.insert(INSERT_APPLICATION, entity);
return entity; return entity;
} }
@Override @Override
protected AuditApplicationEntity updateAuditApplication(AuditApplicationEntity entity) protected AuditApplicationEntity updateAuditApplication(AuditApplicationEntity entity)
{ {
AuditApplicationEntity updateEntity = new AuditApplicationEntity(); AuditApplicationEntity updateEntity = new AuditApplicationEntity();
updateEntity.setId(entity.getId()); updateEntity.setId(entity.getId());
updateEntity.setVersion(entity.getVersion()); updateEntity.setVersion(entity.getVersion());
updateEntity.incrementVersion(); updateEntity.incrementVersion();
updateEntity.setApplicationNameId(entity.getApplicationNameId()); updateEntity.setApplicationNameId(entity.getApplicationNameId());
updateEntity.setAuditModelId(entity.getAuditModelId()); updateEntity.setAuditModelId(entity.getAuditModelId());
updateEntity.setDisabledPathsId(entity.getDisabledPathsId()); updateEntity.setDisabledPathsId(entity.getDisabledPathsId());
int updated = template.update(UPDATE_APPLICATION, updateEntity); int updated = template.update(UPDATE_APPLICATION, updateEntity);
if (updated != 1) if (updated != 1)
{ {
// unexpected number of rows affected // unexpected number of rows affected
throw new ConcurrencyFailureException("Incorrect number of rows affected for updateAuditApplication: " + updateEntity + ": expected 1, actual " + updated); throw new ConcurrencyFailureException("Incorrect number of rows affected for updateAuditApplication: " + updateEntity + ": expected 1, actual " + updated);
} }
// Done // Done
return updateEntity; return updateEntity;
} }
public int deleteAuditEntries(Long applicationId, Long from, Long to) public int deleteAuditEntries(Long applicationId, Long from, Long to)
{ {
AuditDeleteParameters params = new AuditDeleteParameters(); AuditDeleteParameters params = new AuditDeleteParameters();
params.setAuditApplicationId(applicationId); params.setAuditApplicationId(applicationId);
params.setAuditFromTime(from); params.setAuditFromTime(from);
params.setAuditToTime(to); params.setAuditToTime(to);
return template.delete(DELETE_ENTRIES, params); return template.delete(DELETE_ENTRIES, params);
} }
public int deleteAuditEntriesByIdRange(Long applicationId, Long fromId, Long toId) public int deleteAuditEntriesByIdRange(Long applicationId, Long fromId, Long toId)
{ {
AuditDeleteParameters params = new AuditDeleteParameters(); AuditDeleteParameters params = new AuditDeleteParameters();
params.setAuditApplicationId(applicationId); params.setAuditApplicationId(applicationId);
params.setAuditFromId(fromId); params.setAuditFromId(fromId);
params.setAuditToId(toId); params.setAuditToId(toId);
return template.delete(DELETE_ENTRIES, params); return template.delete(DELETE_ENTRIES, params);
} }
@Override @Override
protected int deleteAuditEntriesImpl(List<Long> auditEntryIds) protected int deleteAuditEntriesImpl(List<Long> auditEntryIds)
{ {
AuditDeleteParameters params = new AuditDeleteParameters(); AuditDeleteParameters params = new AuditDeleteParameters();
params.setAuditEntryIds(auditEntryIds); params.setAuditEntryIds(auditEntryIds);
return template.delete(DELETE_ENTRIES_BY_ID, params); return template.delete(DELETE_ENTRIES_BY_ID, params);
} }
@Override @Override
protected AuditEntryEntity createAuditEntry(Long applicationId, long time, Long usernameId, Long valuesId) protected AuditEntryEntity createAuditEntry(Long applicationId, long time, Long usernameId, Long valuesId)
{ {
AuditEntryEntity entity = new AuditEntryEntity(); AuditEntryEntity entity = new AuditEntryEntity();
entity.setAuditApplicationId(applicationId); entity.setAuditApplicationId(applicationId);
entity.setAuditTime(time); entity.setAuditTime(time);
entity.setAuditUserId(usernameId); entity.setAuditUserId(usernameId);
entity.setAuditValuesId(valuesId); entity.setAuditValuesId(valuesId);
template.insert(INSERT_ENTRY, entity); template.insert(INSERT_ENTRY, entity);
return entity; return entity;
} }
public HashMap<String, Long> getAuditMinMaxByApp(long appId, List<String> extremes) public HashMap<String, Long> getAuditMinMaxByApp(long appId, List<String> extremes)
{ {
// Build parameters to be used in the query. Filter the duplicates when inserting into map // Build parameters to be used in the query. Filter the duplicates when inserting into map
Map<String, Object> params = extremes.stream().collect(Collectors.toMap(s -> s, s -> Boolean.TRUE, (s1, s2) -> s1)); Map<String, Object> params = extremes.stream().collect(Collectors.toMap(s -> s, s -> Boolean.TRUE, (s1, s2) -> s1));
params.put("auditAppId", appId); params.put("auditAppId", appId);
HashMap<String, Long> result = template.selectOne(SELECT_MINMAX_ENTRY_FOR_APP, params); HashMap<String, Long> result = template.selectOne(SELECT_MINMAX_ENTRY_FOR_APP, params);
return result; return result;
} }
@Override @Override
public int getAuditEntriesCountByApp(long applicationId) public int getAuditEntriesCountByApp(long applicationId)
{ {
Map<String, Object> params = new HashMap<>(); Map<String, Object> params = new HashMap<>();
params.put("auditAppId", applicationId); params.put("auditAppId", applicationId);
int result = template.selectOne(SELECT_COUNT_ENTRIES_FOR_APP, params); int result = template.selectOne(SELECT_COUNT_ENTRIES_FOR_APP, params);
return result; return result;
} }
@Override @Override
public int getAuditEntriesCountByAppAndProperties(org.alfresco.service.cmr.audit.AuditQueryParameters parameters) public int getAuditEntriesCountByAppAndProperties(String applicationName, org.alfresco.service.cmr.audit.AuditQueryParameters parameters)
{ {
AuditQueryParameters dbParameters = convertFromRestAuditQueryParameters(parameters); AuditQueryParameters dbParameters = convertFromRestAuditQueryParameters(parameters);
int result = template.selectOne(SELECT_COUNT_ENTRIES_FOR_APP_WITH_PROPERTIES, dbParameters); int result = template.selectOne(SELECT_COUNT_ENTRIES_FOR_APP_WITH_PROPERTIES, dbParameters);
return result; return result;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
protected void findAuditEntries( protected void findAuditEntries(
final AuditQueryRowHandler rowHandler, final AuditQueryRowHandler rowHandler,
int maxResults, int maxResults,
org.alfresco.service.cmr.audit.AuditQueryParameters restParameters) org.alfresco.service.cmr.audit.AuditQueryParameters restParameters)
{ {
AuditQueryParameters params = convertFromRestAuditQueryParameters(restParameters); AuditQueryParameters params = convertFromRestAuditQueryParameters(restParameters);
if (params==null) if (params==null)
{ {
return; return;
} }
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 Map<Long, AuditQueryResult> resultsByValueId = new HashMap<Long, AuditQueryResult>(173); 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)
{ {
// get the row // get the row
AuditQueryResult row = resultsByValueId.get(id); AuditQueryResult row = resultsByValueId.get(id);
try try
{ {
row.setAuditValue((Map<String, Serializable>) value); row.setAuditValue((Map<String, Serializable>) value);
} }
catch (ClassCastException e) catch (ClassCastException e)
{ {
// The handler will deal with the entry // The handler will deal with the entry
} }
} }
}; };
List<AuditQueryResult> rows = template.selectList(SELECT_ENTRIES_WITHOUT_VALUES, params, new RowBounds(0, maxResults)); List<AuditQueryResult> rows = template.selectList(SELECT_ENTRIES_WITHOUT_VALUES, params, new RowBounds(0, maxResults));
for (AuditQueryResult row : rows) for (AuditQueryResult row : rows)
{ {
resultsByValueId.put(row.getAuditValuesId(), row); resultsByValueId.put(row.getAuditValuesId(), row);
if (resultsByValueId.size() >= 100) if (resultsByValueId.size() >= 100)
{ {
// Fetch values for the results. The treemap is ordered. // Fetch values for the results. The treemap is ordered.
List<Long> valueIds = new ArrayList<Long>(resultsByValueId.keySet()); List<Long> valueIds = new ArrayList<Long>(resultsByValueId.keySet());
propertyValueDAO.getPropertiesByIds(valueIds, propertyFinderCallback); propertyValueDAO.getPropertiesByIds(valueIds, propertyFinderCallback);
// Clear and continue // Clear and continue
resultsByValueId.clear(); resultsByValueId.clear();
} }
} }
// Process any remaining results // Process any remaining results
if (resultsByValueId.size() > 0) if (resultsByValueId.size() > 0)
{ {
// Fetch values for the results. The treemap is ordered. // Fetch values for the results. The treemap is ordered.
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) // Now pass the filled-out results to the row handler (order-preserved)
for (AuditQueryResult row : rows) for (AuditQueryResult row : rows)
{ {
rowHandler.processResult(row); rowHandler.processResult(row);
} }
} }
else else
{ {
throw new IllegalArgumentException("maxResults must be greater than 0"); throw new IllegalArgumentException("maxResults must be greater than 0");
} }
} }
} }

View File

@@ -1,173 +1,159 @@
/* /*
* #%L * #%L
* Alfresco Repository * Alfresco Repository
* %% * %%
* Copyright (C) 2005 - 2024 Alfresco Software Limited * Copyright (C) 2005 - 2024 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of * If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is * the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms: * provided under the following open source license terms:
* *
* Alfresco is free software: you can redistribute it and/or modify * Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* Alfresco is distributed in the hope that it will be useful, * Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details. * GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L% * #L%
*/ */
package org.alfresco.repo.domain.propval; package org.alfresco.repo.domain.propval;
import org.alfresco.repo.domain.CrcHelper; import org.alfresco.repo.domain.CrcHelper;
import org.alfresco.util.EqualsHelper; import org.alfresco.util.EqualsHelper;
import org.alfresco.util.Pair; import org.alfresco.util.Pair;
/** /**
* Entity bean for <b>alf_prop_string_value</b> table. * Entity bean for <b>alf_prop_string_value</b> table.
* *
* @author Derek Hulley * @author Derek Hulley
* @since 3.2 * @since 3.2
*/ */
public class PropertyStringValueEntity public class PropertyStringValueEntity
{ {
public static final String EMPTY_STRING = ""; public static final String EMPTY_STRING = "";
public static final String EMPTY_STRING_REPLACEMENT = ".empty"; public static final String EMPTY_STRING_REPLACEMENT = ".empty";
private Long id; private Long id;
private String stringValue; private String stringValue;
private String stringEndLower; private String stringEndLower;
private Long stringCrc; private Long stringCrc;
private String stringLower;
public PropertyStringValueEntity()
public PropertyStringValueEntity() {
{ }
}
@Override
@Override public int hashCode()
public int hashCode() {
{ return (stringValue == null ? 0 : stringValue.hashCode());
return (stringValue == null ? 0 : stringValue.hashCode()); }
}
@Override
@Override public boolean equals(Object obj)
public boolean equals(Object obj) {
{ if (this == obj)
if (this == obj) {
{ return true;
return true; }
} else if (obj != null && obj instanceof PropertyStringValueEntity)
else if (obj != null && obj instanceof PropertyStringValueEntity) {
{ PropertyStringValueEntity that = (PropertyStringValueEntity) obj;
PropertyStringValueEntity that = (PropertyStringValueEntity) obj; return EqualsHelper.nullSafeEquals(this.stringValue, that.stringValue);
return EqualsHelper.nullSafeEquals(this.stringValue, that.stringValue); }
} else
else {
{ return false;
return false; }
} }
}
@Override
@Override public String toString()
public String toString() {
{ StringBuilder sb = new StringBuilder(512);
StringBuilder sb = new StringBuilder(512); sb.append("PropertyStringValueEntity")
sb.append("PropertyStringValueEntity") .append("[ ID=").append(id)
.append("[ ID=").append(id) .append(", stringValue=").append(stringValue)
.append(", stringValue=").append(stringValue) .append("]");
.append("]"); return sb.toString();
return sb.toString(); }
}
public Pair<Long, String> getEntityPair()
public Pair<Long, String> getEntityPair() {
{ if (stringValue != null && stringValue.equals(PropertyStringValueEntity.EMPTY_STRING_REPLACEMENT))
if (stringValue != null && stringValue.equals(PropertyStringValueEntity.EMPTY_STRING_REPLACEMENT)) {
{ return new Pair<Long, String>(id, PropertyStringValueEntity.EMPTY_STRING);
return new Pair<Long, String>(id, PropertyStringValueEntity.EMPTY_STRING); }
} else
else {
{ return new Pair<Long, String>(id, stringValue);
return new Pair<Long, String>(id, stringValue); }
} }
}
/**
/** * Set the string and string-end values
* Set the string and string-end values */
*/ public void setValue(String value)
public void setValue(String value) {
{ if (value == null)
if (value == null) {
{ throw new IllegalArgumentException("Null strings cannot be persisted");
throw new IllegalArgumentException("Null strings cannot be persisted"); }
} if (value != null && value.equals(PropertyStringValueEntity.EMPTY_STRING))
if (value != null && value.equals(PropertyStringValueEntity.EMPTY_STRING)) {
{ // Oracle: We can't insert empty strings into the column.
// Oracle: We can't insert empty strings into the column. value = PropertyStringValueEntity.EMPTY_STRING_REPLACEMENT;
value = PropertyStringValueEntity.EMPTY_STRING_REPLACEMENT; }
} stringValue = value;
stringValue = value; // Calculate the crc value from the original value
// Calculate the crc value from the original value Pair<String, Long> crcPair = CrcHelper.getStringCrcPair(value, 16, false, true);
Pair<String, Long> crcPair = CrcHelper.getStringCrcPair(value, 16, false, true); stringEndLower = crcPair.getFirst();
stringEndLower = crcPair.getFirst(); stringCrc = crcPair.getSecond();
stringCrc = crcPair.getSecond(); }
// Calculate the crc value with case-insensitive
Pair<String, Long> crcPairWithCaseInSensitive = CrcHelper.getStringCrcPair(value, 16, false, false); public Long getId()
stringLower = crcPairWithCaseInSensitive.getFirst(); {
} return id;
}
public Long getId()
{ public void setId(Long id)
return id; {
} this.id = id;
}
public void setId(Long id)
{ public String getStringValue()
this.id = id; {
} return stringValue;
}
public String getStringValue()
{ public void setStringValue(String stringValue)
return stringValue; {
} this.stringValue = stringValue;
}
public void setStringValue(String stringValue)
{ public String getStringEndLower()
this.stringValue = stringValue; {
} return stringEndLower;
}
public String getStringEndLower()
{ public void setStringEndLower(String stringEndLower)
return stringEndLower; {
} this.stringEndLower = stringEndLower;
}
public void setStringEndLower(String stringEndLower)
{ public Long getStringCrc()
this.stringEndLower = stringEndLower; {
} return stringCrc;
}
public Long getStringCrc()
{ public void setStringCrc(Long stringCrc)
return stringCrc; {
} this.stringCrc = stringCrc;
}
public void setStringCrc(Long stringCrc) }
{
this.stringCrc = stringCrc;
}
public String getStringLower()
{
return stringLower;
}
public void setStringLower(String stringLower)
{
this.stringLower = stringLower;
}
}

View File

@@ -1,266 +1,267 @@
/* /*
* #%L * #%L
* Alfresco Repository * Alfresco Repository
* %% * %%
* Copyright (C) 2005 - 2024 Alfresco Software Limited * Copyright (C) 2005 - 2024 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of * If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is * the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms: * provided under the following open source license terms:
* *
* Alfresco is free software: you can redistribute it and/or modify * Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* Alfresco is distributed in the hope that it will be useful, * Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details. * GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L% * #L%
*/ */
package org.alfresco.service.cmr.audit; package org.alfresco.service.cmr.audit;
import java.io.Serializable; import java.io.Serializable;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
* The public API by which applications can query the audit logs and enable or disable auditing. * The public API by which applications can query the audit logs and enable or disable auditing.
* *
* @author Derek Hulley * @author Derek Hulley
*/ */
public interface AuditService public interface AuditService
{ {
/** /**
* @return Returns <tt>true</tt> if auditing is globally enabled * @return Returns <tt>true</tt> if auditing is globally enabled
* *
* @since 3.4 * @since 3.4
*/ */
boolean isAuditEnabled(); boolean isAuditEnabled();
/** /**
* Enable or disable the global auditing state * Enable or disable the global auditing state
* *
* @param enable <tt>true</tt> to enable auditing globally or <tt>false</tt> to disable * @param enable <tt>true</tt> to enable auditing globally or <tt>false</tt> to disable
* *
* @since 3.4 * @since 3.4
*/ */
void setAuditEnabled(boolean enable); void setAuditEnabled(boolean enable);
/** /**
* Helper bean to carry information about an audit application. * Helper bean to carry information about an audit application.
* *
* @author Derek Hulley * @author Derek Hulley
* @since 3.4 * @since 3.4
*/ */
public static class AuditApplication public static class AuditApplication
{ {
private final String name; private final String name;
private final String key; private final String key;
private final boolean enabled; private final boolean enabled;
/** /**
* Constructor for final variables * Constructor for final variables
*/ */
public AuditApplication(String name, String key, boolean enabled) public AuditApplication(String name, String key, boolean enabled)
{ {
this.name = name; this.name = name;
this.key = key; this.key = key;
this.enabled = enabled; this.enabled = enabled;
} }
public String getName() public String getName()
{ {
return name; return name;
} }
public String getKey() public String getKey()
{ {
return key; return key;
} }
public boolean isEnabled() public boolean isEnabled()
{ {
return enabled; return enabled;
} }
} }
/** /**
* Get all registered audit applications * Get all registered audit applications
* *
* @return Returns a map of audit applications keyed by their name * @return Returns a map of audit applications keyed by their name
* *
* @since 3.4 * @since 3.4
*/ */
Map<String, AuditApplication> getAuditApplications(); Map<String, AuditApplication> getAuditApplications();
/** /**
* @param applicationName the name of the application to check * @param applicationName the name of the application to check
* @param path the path to check * @param path the path to check
* @return Returns <tt>true</tt> if auditing is enabled for the given path * @return Returns <tt>true</tt> if auditing is enabled for the given path
* *
* @since 3.2 * @since 3.2
*/ */
boolean isAuditEnabled(String applicationName, String path); boolean isAuditEnabled(String applicationName, String path);
/** /**
* Enable auditing for an application path * Enable auditing for an application path
* *
* @param applicationName the name of the application to check * @param applicationName the name of the application to check
* @param path the path to enable * @param path the path to enable
* *
* @since 3.2 * @since 3.2
*/ */
void enableAudit(String applicationName, String path); void enableAudit(String applicationName, String path);
/** /**
* Disable auditing for an application path * Disable auditing for an application path
* *
* @param applicationName the name of the application to check * @param applicationName the name of the application to check
* @param path the path to disable * @param path the path to disable
* *
* @since 3.2 * @since 3.2
*/ */
void disableAudit(String applicationName, String path); void disableAudit(String applicationName, String path);
/** /**
* Remove all audit entries for the given application * Remove all audit entries for the given application
* *
* @param applicationName the name of the application for which to remove entries * @param applicationName the name of the application for which to remove entries
* @return Returns the number of audit entries deleted * @return Returns the number of audit entries deleted
* *
* @since 3.2 * @since 3.2
* *
* @deprecated Use {@link #clearAudit(String, Long, Long)} * @deprecated Use {@link #clearAudit(String, Long, Long)}
*/ */
int clearAudit(String applicationName); int clearAudit(String applicationName);
/** /**
* Remove audit entries for the given application between the time ranges. If no start * Remove audit entries for the given application between the time ranges. If no start
* time is given then entries are deleted as far back as they exist. If no end time is * time is given then entries are deleted as far back as they exist. If no end time is
* given then entries are deleted up until the current time. * given then entries are deleted up until the current time.
* *
* @param applicationName the name of the application for which to remove entries * @param applicationName the name of the application for which to remove entries
* @param fromTime the start time of entries to remove (inclusive and optional) * @param fromTime the start time of entries to remove (inclusive and optional)
* @param toTime the end time of entries to remove (exclusive and optional) * @param toTime the end time of entries to remove (exclusive and optional)
* @return Returns the number of audit entries deleted * @return Returns the number of audit entries deleted
* *
* @since 3.4 * @since 3.4
*/ */
int clearAudit(String applicationName, Long fromTime, Long toTime); int clearAudit(String applicationName, Long fromTime, Long toTime);
/** /**
* Remove audit entries for the given application between the audit entry ids. * Remove audit entries for the given application between the audit entry ids.
* *
* @param applicationName the name of the application for which to remove entries * @param applicationName the name of the application for which to remove entries
* @param fromId the start time of entries to remove (inclusive and optional) * @param fromId the start time of entries to remove (inclusive and optional)
* @param toId the end time of entries to remove (exclusive and optional) * @param toId the end time of entries to remove (exclusive and optional)
* @return Returns the number of audit entries deleted * @return Returns the number of audit entries deleted
* *
* @since 5.2.2 * @since 5.2.2
*/ */
int clearAuditByIdRange(String applicationName, Long fromId, Long toId); int clearAuditByIdRange(String applicationName, Long fromId, Long toId);
/** /**
* Delete a discrete list of audit entries. * Delete a discrete list of audit entries.
* <p/> * <p/>
* This method should not be called <i>while</i> processing * This method should not be called <i>while</i> processing
* {@link #auditQuery(AuditQueryCallback, AuditQueryParameters, int) query results}. * {@link #auditQuery(AuditQueryCallback, AuditQueryParameters, int) query results}.
* *
* @param auditEntryIds the IDs of all audit entries to delete * @param auditEntryIds the IDs of all audit entries to delete
* @return Returns the number of audit entries deleted * @return Returns the number of audit entries deleted
* *
* @since 3.4 * @since 3.4
*/ */
int clearAudit(List<Long> auditEntryIds); int clearAudit(List<Long> auditEntryIds);
/** /**
* The interface that will be used to give query results to the calling code. * The interface that will be used to give query results to the calling code.
* *
* @since 3.2 * @since 3.2
*/ */
public static interface AuditQueryCallback public static interface AuditQueryCallback
{ {
/** /**
* Determines whether this callback requires the values argument to be populated when {@link #handleAuditEntry} * Determines whether this callback requires the values argument to be populated when {@link #handleAuditEntry}
* is called. * is called.
* *
* @return <code>true</code> if this callback requires the values argument to be populated * @return <code>true</code> if this callback requires the values argument to be populated
*/ */
boolean valuesRequired(); boolean valuesRequired();
/** /**
* Handle a row of audit entry data. * Handle a row of audit entry data.
* *
* @param entryId the unique audit entry ID * @param entryId the unique audit entry ID
* @param applicationName the name of the application * @param applicationName the name of the application
* @param user the user that logged the entry * @param user the user that logged the entry
* @param time the time of the entry * @param time the time of the entry
* @param values the values map as created * @param values the values map as created
* @return Return <tt>true</tt> to continue processing rows or <tt>false</tt> to stop * @return Return <tt>true</tt> to continue processing rows or <tt>false</tt> to stop
*/ */
boolean handleAuditEntry( boolean handleAuditEntry(
Long entryId, Long entryId,
String applicationName, String applicationName,
String user, String user,
long time, long time,
Map<String, Serializable> values); Map<String, Serializable> values);
/** /**
* Handle audit entry failures * Handle audit entry failures
* *
* @param entryId the entry ID * @param entryId the entry ID
* @param errorMsg the error message * @param errorMsg the error message
* @param error the exception causing the error (may be <tt>null</tt>) * @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 * @return Return <tt>true</tt> to continue processing rows or <tt>false</tt> to stop
*/ */
boolean handleAuditEntryError(Long entryId, String errorMsg, Throwable error); boolean handleAuditEntryError(Long entryId, String errorMsg, Throwable error);
} }
/** /**
* Issue an audit query using the given parameters and consuming results in the callback. * Issue an audit query using the given parameters and consuming results in the callback.
* Results are returned in entry order, corresponding to time order. * Results are returned in entry order, corresponding to time order.
* *
* @param callback the callback that will handle results * @param callback the callback that will handle results
* @param parameters the parameters for the query (may not be <tt>null</tt>) * @param parameters the parameters for the query (may not be <tt>null</tt>)
* @param maxResults the maximum number of results to retrieve (must be greater than 0) * @param maxResults the maximum number of results to retrieve (must be greater than 0)
* *
* @throws IllegalArgumentException if maxResults less or equal to zero * @throws IllegalArgumentException if maxResults less or equal to zero
* *
* @since 3.3 * @since 3.3
*/ */
void auditQuery(AuditQueryCallback callback, AuditQueryParameters parameters, int maxResults); void auditQuery(AuditQueryCallback callback, AuditQueryParameters parameters, int maxResults);
/** /**
* Issue an audit query to retrieve min / max audit record id for a given application. * Issue an audit query to retrieve min / max audit record id for a given application.
* *
* @param applicationName the name of the application * @param applicationName the name of the application
* @param extremes a list containing min/max or both * @param extremes a list containing min/max or both
* @return a map containing min/max and the associated value * @return a map containing min/max and the associated value
*/ */
HashMap<String, Long> getAuditMinMaxByApp(String applicationName, List<String> extremes); HashMap<String, Long> getAuditMinMaxByApp(String applicationName, List<String> extremes);
/** /**
* Issue an audit query to retrieve min / max audit record id for a given application. * Issue an audit query to retrieve min / max audit record id for a given application.
* *
* @param applicationName the name of the application * @param applicationName the name of the application
* @return a map containing min/max and the associated value * @return a map containing min/max and the associated value
*/ */
default int getAuditEntriesCountByApp(String applicationName) default int getAuditEntriesCountByApp(String applicationName)
{ {
return -1; return -1;
} }
/** /**
* Issue an audit query to retrieve min / max audit record id for a given application and properties * Issue an audit query to retrieve min / max audit record id for a given application and properties
* *
* @param parameters audit parameters provided by the <code>where</code> clause on the ReST API * @param applicationName the name of the application
* @return a map containing min/max and the associated value * @param parameters audit parameters provided by the <code>where</code> clause on the ReST API
*/ * @return a map containing min/max and the associated value
default int getAuditEntriesCountByAppAndProperties(AuditQueryParameters parameters) */
{ default int getAuditEntriesCountByAppAndProperties(String applicationName, AuditQueryParameters parameters)
return -1; {
} return -1;
} }
}