initial checkin
This commit is contained in:
commit
59147928d0
12
.gitignore
vendored
Normal file
12
.gitignore
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
# Maven
|
||||
target
|
||||
pom.xml.versionsBackup
|
||||
|
||||
# Eclipse
|
||||
.project
|
||||
.classpath
|
||||
.settings
|
||||
.vscode
|
||||
|
||||
# IDEA
|
||||
/.idea/
|
51
README.md
Normal file
51
README.md
Normal file
@ -0,0 +1,51 @@
|
||||
# Inteligr8 ACS Attribute Cleaner Platform Module Library
|
||||
|
||||
This is an Alfresco Content Services platform module that provides attribute service tools at the bootstrap and runtime of ACS.
|
||||
|
||||
# Features
|
||||
|
||||
You can enable this module by installing it and explicitly setting the following property:
|
||||
|
||||
```ini
|
||||
inteligr8.attrcleaner.enabled=true
|
||||
```
|
||||
|
||||
You may also change the log level of any output from this module using the following property (default is `info`):
|
||||
|
||||
```ini
|
||||
inteligr8.attrcleaner.log-level=info
|
||||
```
|
||||
|
||||
## Query
|
||||
|
||||
At startup, you can output the contents of the ACS attribute service by setting the scope of this feature (default is `jmx`):
|
||||
|
||||
```ini
|
||||
inteligr8.attrcleaner.feature.list.scope=jmx
|
||||
```
|
||||
|
||||
Here are the possible values:
|
||||
|
||||
| Scope | Description |
|
||||
| ---------------- | ----------- |
|
||||
| `none` | Do not list any attributes from the attribute service. |
|
||||
| `jmx` | List all JMX attributes (`.PropertyBackedBeans`) from the attribute service. |
|
||||
| `shard-registry` | List all shard registry attributes (`.SHARD_STATE` and `.SHARD_SUBSCRIPTION`) from the attribute service. |
|
||||
| `custom` | List all shard registry attributes in the attribute service that match the `inteligr8.attrcleaner.feature.list.keys` value. |
|
||||
|
||||
When using `custom`, you can query for certain keys using the following:
|
||||
|
||||
```ini
|
||||
inteligr8.attrcleaner.feature.list.keys=\.SHARD\_STATE,\.SHARD\_SUBSCRIPTION
|
||||
```
|
||||
|
||||
The keys are expected to be **comma delimited** and **regular expression** patterns.
|
||||
|
||||
# Clear
|
||||
|
||||
At startup, you can clear the contents of the ACS attribute service by setting the scope of this feature (defualt is `none`). See the section on *Query* for details. Everything is the same, except the property names are as follows:
|
||||
|
||||
```ini
|
||||
inteligr8.attrcleaner.feature.clear.scope=
|
||||
inteligr8.attrcleaner.feature.clear.keys=
|
||||
```
|
161
pom.xml
Normal file
161
pom.xml
Normal file
@ -0,0 +1,161 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.inteligr8.alfresco</groupId>
|
||||
<artifactId>attribute-cleaner-platform-module</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>Attribute Cleaner ACS Platform Module</name>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
<maven.compiler.release>11</maven.compiler.release>
|
||||
|
||||
<alfresco.sdk.version>5.2.0</alfresco.sdk.version>
|
||||
<alfresco.platform.version>7.4.2</alfresco.platform.version>
|
||||
<acs-platform.timeout>180000</acs-platform.timeout>
|
||||
<cxf.version>3.5.5</cxf.version>
|
||||
<jackson.version>2.15.0-rc1</jackson.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>acs-packaging</artifactId>
|
||||
<version>${alfresco.platform.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- alfresco-repository makes 'runtime' scope, but need it to compile -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.woodstox</groupId>
|
||||
<artifactId>woodstox-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<!-- Needed by this module, but provided by ACS -->
|
||||
<dependency>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-enterprise-repository</artifactId>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-elasticsearch-shared</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-repository</artifactId>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<!-- JDK 9+ Eclipse build issue -->
|
||||
<exclusion>
|
||||
<groupId>xpp3</groupId>
|
||||
<artifactId>xpp3</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jakarta.servlet</groupId>
|
||||
<artifactId>jakarta.servlet-api</artifactId>
|
||||
<version>4.0.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Included by pdfbox/aws; already provided by ACS -->
|
||||
<dependency>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Including for testing purposes only -->
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>4.11.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>io.repaint.maven</groupId>
|
||||
<artifactId>tiles-maven-plugin</artifactId>
|
||||
<version>2.36</version>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<tiles>
|
||||
<!-- Documentation: https://bitbucket.org/inteligr8/ootbee-beedk/src/stable/beedk-acs-platform-self-rad-tile -->
|
||||
<tile>com.inteligr8.ootbee:beedk-acs-platform-self-rad-tile:[1.0.0,2.0.0)</tile>
|
||||
<!-- Documentation: https://bitbucket.org/inteligr8/ootbee-beedk/src/stable/beedk-acs-search-rad-tile -->
|
||||
<tile>com.inteligr8.ootbee:beedk-acs-search-rad-tile:[1.0.1,2.0.0)</tile>
|
||||
<!-- Documentation: https://bitbucket.org/inteligr8/ootbee-beedk/src/stable/beedk-aps-rad-tile -->
|
||||
<!-- Not much point to this without the bootstrapped processes and task implementations
|
||||
<tile>com.inteligr8.ootbee:beedk-aps-rad-tile:[1.0.0,2.0.0)</tile>
|
||||
-->
|
||||
<!-- Documentation: https://bitbucket.org/inteligr8/ootbee-beedk/src/stable/beedk-acs-platform-module-tile -->
|
||||
<tile>com.inteligr8.ootbee:beedk-acs-platform-module-tile:[1.0.0,2.0.0)</tile>
|
||||
<!-- Documentation: https://bitbucket.org/inteligr8/ootbee-beedk/src/stable/beedk-acs-platform-self-it-tile
|
||||
<tile>com.inteligr8.ootbee:beedk-acs-platform-self-it-tile:[1.0.0,2.0.0)</tile> -->
|
||||
</tiles>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- avoids log4j dependency -->
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.13.0</version>
|
||||
</plugin>
|
||||
<!-- avoids struts dependency -->
|
||||
<plugin>
|
||||
<artifactId>maven-site-plugin</artifactId>
|
||||
<version>3.12.1</version>
|
||||
</plugin>
|
||||
<!-- Force use of a new maven-dependency-plugin that doesn't download struts dependency -->
|
||||
<plugin>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<version>3.7.1</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>windows-extended-timeout</id>
|
||||
<activation>
|
||||
<os>
|
||||
<family>windows</family>
|
||||
</os>
|
||||
</activation>
|
||||
<properties>
|
||||
<acs-share.timeout>1200000</acs-share.timeout>
|
||||
<acs-platform.timeout>2400000</acs-platform.timeout>
|
||||
</properties>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>alfresco-private</id>
|
||||
<url>https://artifacts.alfresco.com/nexus/content/groups/private</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
</project>
|
74
rad.ps1
Normal file
74
rad.ps1
Normal file
@ -0,0 +1,74 @@
|
||||
|
||||
function discoverArtifactId {
|
||||
$script:ARTIFACT_ID=(mvn -q -Dexpression=project"."artifactId -DforceStdout help:evaluate)
|
||||
}
|
||||
|
||||
function rebuild {
|
||||
echo "Rebuilding project ..."
|
||||
mvn process-classes
|
||||
}
|
||||
|
||||
function start_ {
|
||||
echo "Rebuilding project and starting Docker containers to support rapid application development ..."
|
||||
mvn -Drad process-classes
|
||||
}
|
||||
|
||||
function start_log {
|
||||
echo "Rebuilding project and starting Docker containers to support rapid application development ..."
|
||||
mvn -Drad "-Ddocker.showLogs" process-classes
|
||||
}
|
||||
|
||||
function stop_ {
|
||||
discoverArtifactId
|
||||
echo "Stopping Docker containers that supported rapid application development ..."
|
||||
docker container ls --filter name=${ARTIFACT_ID}-*
|
||||
echo "Stopping containers ..."
|
||||
docker container stop (docker container ls -q --filter name=${ARTIFACT_ID}-*)
|
||||
echo "Removing containers ..."
|
||||
docker container rm (docker container ls -aq --filter name=${ARTIFACT_ID}-*)
|
||||
}
|
||||
|
||||
function tail_logs {
|
||||
param (
|
||||
$container
|
||||
)
|
||||
|
||||
discoverArtifactId
|
||||
docker container logs -f (docker container ls -q --filter name=${ARTIFACT_ID}-${container})
|
||||
}
|
||||
|
||||
function list {
|
||||
discoverArtifactId
|
||||
docker container ls --filter name=${ARTIFACT_ID}-*
|
||||
}
|
||||
|
||||
switch ($args[0]) {
|
||||
"start" {
|
||||
start_
|
||||
}
|
||||
"start_log" {
|
||||
start_log
|
||||
}
|
||||
"stop" {
|
||||
stop_
|
||||
}
|
||||
"restart" {
|
||||
stop_
|
||||
start_
|
||||
}
|
||||
"rebuild" {
|
||||
rebuild
|
||||
}
|
||||
"tail" {
|
||||
tail_logs $args[1]
|
||||
}
|
||||
"containers" {
|
||||
list
|
||||
}
|
||||
default {
|
||||
echo "Usage: .\rad.ps1 [ start | start_log | stop | restart | rebuild | tail {container} | containers ]"
|
||||
}
|
||||
}
|
||||
|
||||
echo "Completed!"
|
||||
|
71
rad.sh
Normal file
71
rad.sh
Normal file
@ -0,0 +1,71 @@
|
||||
#!/bin/sh
|
||||
|
||||
discoverArtifactId() {
|
||||
ARTIFACT_ID=`mvn -q -Dexpression=project.artifactId -DforceStdout help:evaluate`
|
||||
}
|
||||
|
||||
rebuild() {
|
||||
echo "Rebuilding project ..."
|
||||
mvn process-classes
|
||||
}
|
||||
|
||||
start() {
|
||||
echo "Rebuilding project and starting Docker containers to support rapid application development ..."
|
||||
mvn -Drad process-classes
|
||||
}
|
||||
|
||||
start_log() {
|
||||
echo "Rebuilding project and starting Docker containers to support rapid application development ..."
|
||||
mvn -Drad -Ddocker.showLogs process-classes
|
||||
}
|
||||
|
||||
stop() {
|
||||
discoverArtifactId
|
||||
echo "Stopping Docker containers that supported rapid application development ..."
|
||||
docker container ls --filter name=${ARTIFACT_ID}-*
|
||||
echo "Stopping containers ..."
|
||||
docker container stop `docker container ls -q --filter name=${ARTIFACT_ID}-*`
|
||||
echo "Removing containers ..."
|
||||
docker container rm `docker container ls -aq --filter name=${ARTIFACT_ID}-*`
|
||||
}
|
||||
|
||||
tail_logs() {
|
||||
discoverArtifactId
|
||||
docker container logs -f `docker container ls -q --filter name=${ARTIFACT_ID}-$1`
|
||||
}
|
||||
|
||||
list() {
|
||||
discoverArtifactId
|
||||
docker container ls --filter name=${ARTIFACT_ID}-*
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
start
|
||||
;;
|
||||
start_log)
|
||||
start_log
|
||||
;;
|
||||
stop)
|
||||
stop
|
||||
;;
|
||||
restart)
|
||||
stop
|
||||
start
|
||||
;;
|
||||
rebuild)
|
||||
rebuild
|
||||
;;
|
||||
tail)
|
||||
tail_logs $2
|
||||
;;
|
||||
containers)
|
||||
list
|
||||
;;
|
||||
*)
|
||||
echo "Usage: ./rad.sh [ start | start_log | stop | restart | rebuild | tail {container} | containers ]"
|
||||
exit 1
|
||||
esac
|
||||
|
||||
echo "Completed!"
|
||||
|
@ -0,0 +1,220 @@
|
||||
package com.inteligr8.alfresco.attrclean;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.alfresco.service.cmr.attributes.AttributeService;
|
||||
import org.alfresco.service.cmr.attributes.AttributeService.AttributeQueryCallback;
|
||||
import org.alfresco.util.PropertyCheck;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.event.Level;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.extensions.surf.util.AbstractLifecycleBean;
|
||||
|
||||
public abstract class AbstractBootstrapService extends AbstractLifecycleBean implements BootstrapService {
|
||||
|
||||
public enum Scope {
|
||||
None,
|
||||
JMX,
|
||||
ShardRegistry,
|
||||
Custom;
|
||||
|
||||
static Scope caseInsensitiveValueOf(String value) {
|
||||
for (Scope scope : Scope.values())
|
||||
if (scope.toString().equalsIgnoreCase(value))
|
||||
return scope;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
private final Pattern rootKeyPattern = Pattern.compile("(.+)/.*");
|
||||
|
||||
@Autowired
|
||||
@Qualifier("attributeService")
|
||||
private AttributeService attributeService;
|
||||
|
||||
@Value("${inteligr8.attrcleaner.enabled}")
|
||||
private boolean enabled;
|
||||
|
||||
@Value("${inteligr8.attrcleaner.log-level}")
|
||||
private String logLevelRaw;
|
||||
|
||||
protected Level logLevel;
|
||||
protected Scope scope;
|
||||
protected Map<String, List<Pattern>> keyPatterns;
|
||||
|
||||
protected abstract String getRawScope();
|
||||
|
||||
protected abstract String getRawKeys();
|
||||
|
||||
@Override
|
||||
protected void onBootstrap(ApplicationEvent aevent) {
|
||||
if (!this.enabled) {
|
||||
this.logger.info("Inteligr8 Attribute Cleaner module is disabled");
|
||||
return;
|
||||
}
|
||||
|
||||
this.logger.info("Inteligr8 Attribute Cleaner {} bootstrapping", this.getClass().getSimpleName());
|
||||
|
||||
if (this.validateAndNormalize())
|
||||
this.execute();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onShutdown(ApplicationEvent aevent) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validateAndNormalize() {
|
||||
this.logLevel = Level.valueOf(this.logLevelRaw.toUpperCase());
|
||||
PropertyCheck.mandatory(this, "inteligr8.attrcleaner.log-level", this.logLevel);
|
||||
|
||||
this.scope = Scope.caseInsensitiveValueOf(this.getRawScope().replace("-", ""));
|
||||
this.logger.trace("Attribute cleaner {} scope is {}", this.getClass().getSimpleName(), this.scope);
|
||||
if (this.scope == null)
|
||||
throw new IllegalArgumentException();
|
||||
|
||||
if (Scope.None.equals(this.scope)) {
|
||||
this.logger.debug("Attribute cleaner {} feature is off", this.getClass().getSimpleName());
|
||||
return false;
|
||||
}
|
||||
|
||||
this.keyPatterns = new LinkedHashMap<>();
|
||||
|
||||
for (String keyRaw : this.getRawKeys().split(",")) {
|
||||
this.logger.trace("Attribute cleaner {} key: {}", this.getClass().getSimpleName(), keyRaw);
|
||||
|
||||
if (keyRaw.length() == 0) {
|
||||
this.logger.debug("Skipping empty key");
|
||||
continue;
|
||||
}
|
||||
|
||||
Matcher matcher = this.rootKeyPattern.matcher(keyRaw);
|
||||
if (!matcher.find()) {
|
||||
this.logger.warn("Key must have a root element; skipping: {}", keyRaw);
|
||||
continue;
|
||||
}
|
||||
|
||||
String rootKey = matcher.group(1).replace("\\.", ".");
|
||||
|
||||
Pattern keyPattern = Pattern.compile(keyRaw);
|
||||
this.logger.debug("Validated key pattern: {} => {}", rootKey, keyPattern);
|
||||
this.putAddToList(this.keyPatterns, rootKey, keyPattern);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
Map<Serializable[], Serializable> attributes = null;
|
||||
|
||||
switch (this.scope) {
|
||||
case None:
|
||||
throw new IllegalArgumentException();
|
||||
case JMX:
|
||||
attributes = this.queryJmx();
|
||||
break;
|
||||
case ShardRegistry:
|
||||
attributes = this.queryShardRegistry();
|
||||
break;
|
||||
case Custom:
|
||||
attributes = this.queryCustom();
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
this.logger.atLevel(this.logLevel).log("Queried {} Attributes: ", attributes.size());
|
||||
for (Entry<Serializable[], Serializable> entry : attributes.entrySet()) {
|
||||
this.execute(entry);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void execute(Entry<Serializable[], Serializable> entry);
|
||||
|
||||
private Map<Serializable[], Serializable> queryJmx() {
|
||||
return this.queryAttrs(".PropertyBackedBeans");
|
||||
}
|
||||
|
||||
private Map<Serializable[], Serializable> queryShardRegistry() {
|
||||
Map<Serializable[], Serializable> attributes = new LinkedHashMap<>();
|
||||
attributes.putAll(this.queryAttrs(".SHARD_STATE"));
|
||||
attributes.putAll(this.queryAttrs(".SHARD_SUBSCRIPTION"));
|
||||
return attributes;
|
||||
}
|
||||
|
||||
private Map<Serializable[], Serializable> queryCustom() {
|
||||
Map<Serializable[], Serializable> attributes = new LinkedHashMap<>();
|
||||
|
||||
AttributeQueryCallback aqc = new AttributeQueryCallback() {
|
||||
@Override
|
||||
public boolean handleAttribute(Long attrId, Serializable value, Serializable[] keys) {
|
||||
String keysAsStr = StringUtils.stripEnd(StringUtils.join(keys, "/"), "/");
|
||||
for (Entry<String, List<Pattern>> patterns : keyPatterns.entrySet()) {
|
||||
for (Pattern pattern : patterns.getValue()) {
|
||||
if (pattern.matcher(keysAsStr).matches()) {
|
||||
logger.debug("{} matches attribute: {}", pattern, keysAsStr);
|
||||
attributes.put(keys, value);
|
||||
} else {
|
||||
logger.trace("{} does not match attribute: {}", pattern, keysAsStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
for (String rootKey : this.keyPatterns.keySet()) {
|
||||
this.logger.debug("Querying for attributes with root key: {}", rootKey);
|
||||
this.attributeService.getAttributes(aqc, rootKey);
|
||||
}
|
||||
|
||||
return attributes;
|
||||
}
|
||||
|
||||
private Map<Serializable[], Serializable> queryAttrs(Serializable... selectKeys) {
|
||||
Map<Serializable[], Serializable> attributes = new LinkedHashMap<>();
|
||||
|
||||
AttributeQueryCallback aqc = new AttributeQueryCallback() {
|
||||
@Override
|
||||
public boolean handleAttribute(Long attrId, Serializable value, Serializable[] keys) {
|
||||
logger.trace("Found attribute: {}", Arrays.toString(keys));
|
||||
attributes.put(keys, value);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
this.logger.debug("Querying for attributes with keys: {}", Arrays.toString(selectKeys));
|
||||
this.attributeService.getAttributes(aqc, selectKeys);
|
||||
|
||||
return attributes;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <K, CV extends Collection<V>, V> void putAddToList(Map<K, CV> map, K key, V value) {
|
||||
CV c = map.get(key);
|
||||
if (c == null) {
|
||||
c = (CV) new LinkedList<V>();
|
||||
map.put(key, c);
|
||||
}
|
||||
c.add(value);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package com.inteligr8.alfresco.attrclean;
|
||||
|
||||
public interface BootstrapService {
|
||||
|
||||
boolean validateAndNormalize();
|
||||
|
||||
void execute();
|
||||
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package com.inteligr8.alfresco.attrclean;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.alfresco.service.cmr.attributes.AttributeService;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Order(value = -10) // higher than average
|
||||
public class ClearBootstrapService extends AbstractBootstrapService {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(ClearBootstrapService.class);
|
||||
|
||||
@Autowired
|
||||
@Qualifier("attributeService")
|
||||
private AttributeService attributeService;
|
||||
|
||||
@Value("${inteligr8.attrcleaner.feature.clear.scope}")
|
||||
private String scopeRaw;
|
||||
|
||||
@Value("${inteligr8.attrcleaner.feature.clear.keys}")
|
||||
private String keysRaw;
|
||||
|
||||
@Override
|
||||
public String getRawScope() {
|
||||
return this.scopeRaw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRawKeys() {
|
||||
return this.keysRaw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Entry<Serializable[], Serializable> entry) {
|
||||
String keysAsStr = StringUtils.join(entry.getKey(), "/");
|
||||
this.logger.debug(" Removing: {}", keysAsStr);
|
||||
this.attributeService.removeAttribute(entry.getKey());
|
||||
this.logger.warn(" Removed: {}", keysAsStr);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package com.inteligr8.alfresco.attrclean;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.alfresco.service.cmr.attributes.AttributeService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Order(value = -100) // higher than average
|
||||
public class ListBootstrapService extends AbstractBootstrapService {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Autowired
|
||||
@Qualifier("attributeService")
|
||||
private AttributeService attributeService;
|
||||
|
||||
@Value("${inteligr8.attrcleaner.feature.list.scope}")
|
||||
private String scopeRaw;
|
||||
|
||||
@Value("${inteligr8.attrcleaner.feature.list.keys}")
|
||||
private String keysRaw;
|
||||
|
||||
@Override
|
||||
public String getRawScope() {
|
||||
return this.scopeRaw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRawKeys() {
|
||||
return this.keysRaw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Entry<Serializable[], Serializable> entry) {
|
||||
this.logger.atLevel(this.logLevel).log(" {}: {}", entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
|
||||
inteligr8.attrcleaner.enabled=false
|
||||
inteligr8.attrcleaner.log-level=info
|
||||
|
||||
# list attributes: `none` | `jmx` | `shard-registry` | `custom`
|
||||
inteligr8.attrcleaner.feature.list.scope=jmx
|
||||
# when `custom`, what attributes to list
|
||||
# supports regex; e.g.: \.PropertyBackedBeans/.*
|
||||
inteligr8.attrcleaner.feature.list.keys=
|
||||
|
||||
# clear attributes: `none` | `jmx` | `shard-registry` | `custom`
|
||||
inteligr8.attrcleaner.feature.clear.scope=none
|
||||
# when `custom`, what attributes to clear
|
||||
# supports regex; e.g.: \.PropertyBackedBeans/.*
|
||||
inteligr8.attrcleaner.feature.clear.keys=
|
@ -0,0 +1,3 @@
|
||||
|
||||
logger.inteligr8-jmx.name=com.inteligr8.alfresco.jmx
|
||||
logger.inteligr8-jmx.level=INFO
|
@ -0,0 +1,16 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
|
||||
<!-- Use this file for beans to be loaded in whatever order Alfresco/Spring decides -->
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
|
||||
|
||||
<!-- Enable Spring annotation scanning for classes in package -->
|
||||
<context:component-scan base-package="com.inteligr8.alfresco.jmx"
|
||||
name-generator="org.springframework.context.annotation.FullyQualifiedAnnotationBeanNameGenerator">
|
||||
<context:include-filter type="assignable" expression="com.inteligr8.alfresco.jmx.BootstrapService" />
|
||||
</context:component-scan>
|
||||
|
||||
</beans>
|
@ -0,0 +1,16 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
|
||||
<!-- Use this file for beans to be loaded in whatever order Alfresco/Spring decides -->
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
|
||||
|
||||
<!-- Enable Spring annotation scanning for classes aps-public-rest-api -->
|
||||
<context:component-scan base-package="com.inteligr8.alfresco.jmx"
|
||||
name-generator="org.springframework.context.annotation.FullyQualifiedAnnotationBeanNameGenerator">
|
||||
<context:exclude-filter type="assignable" expression="com.inteligr8.alfresco.jmx.BootstrapService" />
|
||||
</context:component-scan>
|
||||
|
||||
</beans>
|
@ -0,0 +1,4 @@
|
||||
module.id=${project.groupId}.${project.artifactId}
|
||||
module.title=${project.name}
|
||||
module.description=${project.description}
|
||||
module.version=${project.version}
|
Loading…
x
Reference in New Issue
Block a user