Author: bdelacretaz
Date: Fri Dec 20 10:03:35 2013
New Revision: 1552577
URL: http://svn.apache.org/r1552577
Log:
SLING-3295 - Add a scheduled replication rule, contributed by Tommaso Teofili,
thanks!
Added:
sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/rule/impl/ScheduleReplicateReplicationRule.java
sling/trunk/contrib/extensions/replication/src/test/java/org/apache/sling/replication/rule/impl/ScheduleReplicateReplicationRuleTest.java
Modified:
sling/trunk/contrib/extensions/replication/pom.xml
Modified: sling/trunk/contrib/extensions/replication/pom.xml
URL:
http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/replication/pom.xml?rev=1552577&r1=1552576&r2=1552577&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/replication/pom.xml (original)
+++ sling/trunk/contrib/extensions/replication/pom.xml Fri Dec 20 10:03:35 2013
@@ -116,6 +116,11 @@
<artifactId>org.apache.sling.commons.osgi</artifactId>
<version>2.2.0</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.commons.scheduler</artifactId>
+ <version>2.4.0</version>
+ </dependency>
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.jcr.api</artifactId>
Added:
sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/rule/impl/ScheduleReplicateReplicationRule.java
URL:
http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/rule/impl/ScheduleReplicateReplicationRule.java?rev=1552577&view=auto
==============================================================================
---
sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/rule/impl/ScheduleReplicateReplicationRule.java
(added)
+++
sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/rule/impl/ScheduleReplicateReplicationRule.java
Fri Dec 20 10:03:35 2013
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.replication.rule.impl;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.commons.scheduler.ScheduleOptions;
+import org.apache.sling.commons.scheduler.Scheduler;
+import org.apache.sling.replication.agent.AgentReplicationException;
+import org.apache.sling.replication.agent.ReplicationAgent;
+import org.apache.sling.replication.communication.ReplicationActionType;
+import org.apache.sling.replication.communication.ReplicationRequest;
+import org.apache.sling.replication.rule.ReplicationRule;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * {@link org.apache.sling.replication.rule.ReplicationRule} to schedule
replications on a certain {@link
org.apache.sling.replication.agent.ReplicationAgent}
+ */
+@Component(immediate = true)
+@Service(value = ReplicationRule.class)
+public class ScheduleReplicateReplicationRule implements ReplicationRule {
+ private static final String SIGNATURE = "scheduled {action} [on ${path}
]every {seconds} sec";
+
+ private static final String SIGNATURE_REGEX =
"(scheduled)\\s(add|delete|poll)+\\s((on)\\s(\\/\\w+)+\\s)?(every)\\s(\\d+)\\s(sec)";
+
+ private static final Pattern signaturePattern =
Pattern.compile(SIGNATURE_REGEX);
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ @Reference
+ private Scheduler scheduler;
+
+ public String getSignature() {
+ return SIGNATURE;
+ }
+
+ public boolean signatureMatches(String ruleString) {
+ return ruleString.matches(SIGNATURE_REGEX);
+ }
+
+ public void apply(String ruleString, ReplicationAgent agent) {
+ if (signatureMatches(ruleString)) {
+ Matcher matcher = signaturePattern.matcher(ruleString);
+ matcher.find();
+ String action = matcher.group(2);
+ ReplicationActionType actionType =
ReplicationActionType.fromName(action.toUpperCase());
+ String path = matcher.group(5); // can be null
+ int seconds = Integer.parseInt(matcher.group(7));
+ ScheduleOptions options = scheduler.NOW(-1, seconds);
+ options.name(agent.getName() + " " + ruleString);
+ scheduler.schedule(new ScheduledReplication(agent, actionType,
path), options);
+ }
+ }
+
+ public void undo(String ruleString, ReplicationAgent agent) {
+ if (signatureMatches(ruleString)) {
+ scheduler.unschedule(agent.getName() + " " + ruleString);
+ }
+ }
+
+ private class ScheduledReplication implements Runnable {
+ private final ReplicationAgent agent;
+ private final ReplicationActionType action;
+ private final String path;
+
+ public ScheduledReplication(ReplicationAgent agent,
ReplicationActionType action, String path) {
+ this.agent = agent;
+ this.action = action;
+ this.path = path != null ? path : "/";
+ }
+
+ public void run() {
+ try {
+ agent.send(new ReplicationRequest(System.currentTimeMillis(),
action, path));
+ } catch (AgentReplicationException e) {
+ if (log.isErrorEnabled()) {
+ log.error("failed scheduled replication {} on agent {} for
path {}", new Object[]{
+ action.name(), agent.getName(), path}, e);
+ }
+ }
+ }
+ }
+}
Added:
sling/trunk/contrib/extensions/replication/src/test/java/org/apache/sling/replication/rule/impl/ScheduleReplicateReplicationRuleTest.java
URL:
http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/replication/src/test/java/org/apache/sling/replication/rule/impl/ScheduleReplicateReplicationRuleTest.java?rev=1552577&view=auto
==============================================================================
---
sling/trunk/contrib/extensions/replication/src/test/java/org/apache/sling/replication/rule/impl/ScheduleReplicateReplicationRuleTest.java
(added)
+++
sling/trunk/contrib/extensions/replication/src/test/java/org/apache/sling/replication/rule/impl/ScheduleReplicateReplicationRuleTest.java
Fri Dec 20 10:03:35 2013
@@ -0,0 +1,167 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.replication.rule.impl;
+
+import java.lang.reflect.Field;
+import org.apache.sling.commons.scheduler.ScheduleOptions;
+import org.apache.sling.commons.scheduler.Scheduler;
+import org.apache.sling.replication.agent.ReplicationAgent;
+import org.junit.Test;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+/**
+ * Testcase for {@link
org.apache.sling.replication.rule.impl.ScheduleReplicateReplicationRule}
+ */
+public class ScheduleReplicateReplicationRuleTest {
+
+ @Test
+ public void testSignatureNotNull() throws Exception {
+ ScheduleReplicateReplicationRule scheduleReplicateReplicationRule =
new ScheduleReplicateReplicationRule();
+ assertNotNull(scheduleReplicateReplicationRule.getSignature());
+ }
+
+ @Test
+ public void testSignatureMatching() throws Exception {
+ ScheduleReplicateReplicationRule scheduleReplicateReplicationRule =
new ScheduleReplicateReplicationRule();
+ assertFalse(scheduleReplicateReplicationRule.signatureMatches(""));
+
assertTrue(scheduleReplicateReplicationRule.signatureMatches("scheduled poll on
/apps every 1 sec"));
+
assertTrue(scheduleReplicateReplicationRule.signatureMatches("scheduled add on
/system every 12 sec"));
+
assertTrue(scheduleReplicateReplicationRule.signatureMatches("scheduled delete
on /libs every 331 sec"));
+
assertTrue(scheduleReplicateReplicationRule.signatureMatches("scheduled poll
every 30 sec"));
+ }
+
+ @Test
+ public void testApplyWithNonMatchingString() throws Exception {
+ ScheduleReplicateReplicationRule scheduleReplicateReplicationRule =
new ScheduleReplicateReplicationRule();
+ String ruleString = "";
+ ReplicationAgent replicationAgent = mock(ReplicationAgent.class);
+ scheduleReplicateReplicationRule.apply(ruleString, replicationAgent);
+ }
+
+ @Test
+ public void testApplyWithMatchingString() throws Exception {
+ ScheduleReplicateReplicationRule scheduleReplicateReplicationRule =
new ScheduleReplicateReplicationRule();
+ Field schedulerField =
scheduleReplicateReplicationRule.getClass().getDeclaredField("scheduler");
+ schedulerField.setAccessible(true);
+ Scheduler scheduler = mock(Scheduler.class);
+ ScheduleOptions options = mock(ScheduleOptions.class);
+ when(scheduler.NOW(any(Integer.class),
any(Integer.class))).thenReturn(options);
+ schedulerField.set(scheduleReplicateReplicationRule, scheduler);
+
+ String ruleString = "scheduled add on /system every 12 sec";
+ ReplicationAgent replicationAgent = mock(ReplicationAgent.class);
+ scheduleReplicateReplicationRule.apply(ruleString, replicationAgent);
+ }
+
+ @Test
+ public void testApplyWithMatchingStringAndRegisteredContext() throws
Exception {
+ ScheduleReplicateReplicationRule scheduleReplicateReplicationRule =
new ScheduleReplicateReplicationRule();
+ Field schedulerField =
scheduleReplicateReplicationRule.getClass().getDeclaredField("scheduler");
+ schedulerField.setAccessible(true);
+ Scheduler scheduler = mock(Scheduler.class);
+ ScheduleOptions options = mock(ScheduleOptions.class);
+ when(scheduler.NOW(any(Integer.class),
any(Integer.class))).thenReturn(options);
+ schedulerField.set(scheduleReplicateReplicationRule, scheduler);
+
+ String ruleString = "scheduled add on /system every 12 sec";
+ ReplicationAgent replicationAgent = mock(ReplicationAgent.class);
+ scheduleReplicateReplicationRule.apply(ruleString, replicationAgent);
+ }
+
+ @Test
+ public void testApplyWithNonMatchingStringAndRegisteredContext() throws
Exception {
+ ScheduleReplicateReplicationRule scheduleReplicateReplicationRule =
new ScheduleReplicateReplicationRule();
+ Field schedulerField =
scheduleReplicateReplicationRule.getClass().getDeclaredField("scheduler");
+ schedulerField.setAccessible(true);
+ Scheduler scheduler = mock(Scheduler.class);
+ ScheduleOptions options = mock(ScheduleOptions.class);
+ when(scheduler.NOW(any(Integer.class),
any(Integer.class))).thenReturn(options);
+ schedulerField.set(scheduleReplicateReplicationRule, scheduler);
+
+ String ruleString = "scheduled add on /system every 12 sec";
+ ReplicationAgent replicationAgent = mock(ReplicationAgent.class);
+ scheduleReplicateReplicationRule.apply(ruleString, replicationAgent);
+ }
+
+ @Test
+ public void testUndoWithNonMatchingString() throws Exception {
+ ScheduleReplicateReplicationRule scheduleReplicateReplicationRule =
new ScheduleReplicateReplicationRule();
+ Field schedulerField =
scheduleReplicateReplicationRule.getClass().getDeclaredField("scheduler");
+ schedulerField.setAccessible(true);
+ Scheduler scheduler = mock(Scheduler.class);
+ ScheduleOptions options = mock(ScheduleOptions.class);
+ when(scheduler.NOW(any(Integer.class),
any(Integer.class))).thenReturn(options);
+ schedulerField.set(scheduleReplicateReplicationRule, scheduler);
+
+ String ruleString = "";
+ ReplicationAgent replicationAgent = mock(ReplicationAgent.class);
+ scheduleReplicateReplicationRule.undo(ruleString, replicationAgent);
+ }
+
+ @Test
+ public void testUndoWithMatchingString() throws Exception {
+ ScheduleReplicateReplicationRule scheduleReplicateReplicationRule =
new ScheduleReplicateReplicationRule();
+ Field schedulerField =
scheduleReplicateReplicationRule.getClass().getDeclaredField("scheduler");
+ schedulerField.setAccessible(true);
+ Scheduler scheduler = mock(Scheduler.class);
+ ScheduleOptions options = mock(ScheduleOptions.class);
+ when(scheduler.NOW(any(Integer.class),
any(Integer.class))).thenReturn(options);
+ schedulerField.set(scheduleReplicateReplicationRule, scheduler);
+
+ String ruleString = "scheduled add on /system every 12 sec";
+ ReplicationAgent replicationAgent = mock(ReplicationAgent.class);
+ scheduleReplicateReplicationRule.undo(ruleString, replicationAgent);
+ }
+
+ @Test
+ public void testUndoWithMatchingStringAndRegisteredContext() throws
Exception {
+ ScheduleReplicateReplicationRule scheduleReplicateReplicationRule =
new ScheduleReplicateReplicationRule();
+ Field schedulerField =
scheduleReplicateReplicationRule.getClass().getDeclaredField("scheduler");
+ schedulerField.setAccessible(true);
+ Scheduler scheduler = mock(Scheduler.class);
+ ScheduleOptions options = mock(ScheduleOptions.class);
+ when(scheduler.NOW(any(Integer.class),
any(Integer.class))).thenReturn(options);
+ schedulerField.set(scheduleReplicateReplicationRule, scheduler);
+
+ String ruleString = "scheduled add on /system every 12 sec";
+ ReplicationAgent replicationAgent = mock(ReplicationAgent.class);
+ scheduleReplicateReplicationRule.undo(ruleString, replicationAgent);
+ }
+
+ @Test
+ public void testUndoWithNonMatchingStringAndRegisteredContext() throws
Exception {
+ ScheduleReplicateReplicationRule scheduleReplicateReplicationRule =
new ScheduleReplicateReplicationRule();
+ Field schedulerField =
scheduleReplicateReplicationRule.getClass().getDeclaredField("scheduler");
+ schedulerField.setAccessible(true);
+ Scheduler scheduler = mock(Scheduler.class);
+ ScheduleOptions options = mock(ScheduleOptions.class);
+ when(scheduler.NOW(any(Integer.class),
any(Integer.class))).thenReturn(options);
+ schedulerField.set(scheduleReplicateReplicationRule, scheduler);
+
+ String ruleString = "scheduled add on /system every 12 sec";
+ ReplicationAgent replicationAgent = mock(ReplicationAgent.class);
+ scheduleReplicateReplicationRule.undo(ruleString, replicationAgent);
+ }
+}