You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2019/03/18 07:03:58 UTC

[syncope] 01/01: [SYNCOPE-1448] Relying on Spring's concurrency checks

This is an automated email from the ASF dual-hosted git repository.

ilgrosso pushed a commit to branch SYNCOPE-1448_alternative-fix
in repository https://gitbox.apache.org/repos/asf/syncope.git

commit 44bf731faea371d0439286386b453d38b80c6832
Author: Francesco Chicchiriccò <il...@apache.org>
AuthorDate: Mon Mar 18 08:03:40 2019 +0100

    [SYNCOPE-1448] Relying on Spring's concurrency checks
---
 .../syncope/core/spring/ImplementationManager.java |  60 ++++++++----
 .../core/spring/ImplementationManagerTest.java     | 106 +++++++++++++++++++++
 2 files changed, 146 insertions(+), 20 deletions(-)

diff --git a/core/spring/src/main/java/org/apache/syncope/core/spring/ImplementationManager.java b/core/spring/src/main/java/org/apache/syncope/core/spring/ImplementationManager.java
index b3e050a..85a7662 100644
--- a/core/spring/src/main/java/org/apache/syncope/core/spring/ImplementationManager.java
+++ b/core/spring/src/main/java/org/apache/syncope/core/spring/ImplementationManager.java
@@ -70,10 +70,14 @@ public final class ImplementationManager {
                         reportlet = (Reportlet) ApplicationContextProvider.getBeanFactory().
                                 getSingleton(reportletClass.getName());
                     } else {
-                        reportlet = (Reportlet) ApplicationContextProvider.getBeanFactory().
-                                createBean(reportletClass, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, false);
-                        ApplicationContextProvider.getBeanFactory().
-                                registerSingleton(reportletClass.getName(), reportlet);
+                        try {
+                            reportlet = (Reportlet) ApplicationContextProvider.getBeanFactory().
+                                    createBean(reportletClass, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, false);
+                            ApplicationContextProvider.getBeanFactory().
+                                    registerSingleton(reportletClass.getName(), reportlet);
+                        } catch (IllegalStateException e) {
+                            LOG.warn("While attempting to register {}", reportletClass.getName(), e);
+                        }
                     }
                     reportlet.setConf(reportletConf);
                 }
@@ -104,10 +108,14 @@ public final class ImplementationManager {
                         rule = (AccountRule) ApplicationContextProvider.getBeanFactory().
                                 getSingleton(ruleClass.getName());
                     } else {
-                        rule = (AccountRule) ApplicationContextProvider.getBeanFactory().
-                                createBean(ruleClass, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, false);
-                        ApplicationContextProvider.getBeanFactory().
-                                registerSingleton(ruleClass.getName(), rule);
+                        try {
+                            rule = (AccountRule) ApplicationContextProvider.getBeanFactory().
+                                    createBean(ruleClass, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, false);
+                            ApplicationContextProvider.getBeanFactory().
+                                    registerSingleton(ruleClass.getName(), rule);
+                        } catch (IllegalStateException e) {
+                            LOG.warn("While attempting to register {}", ruleClass.getName(), e);
+                        }
                     }
                     rule.setConf(ruleConf);
                 }
@@ -138,10 +146,14 @@ public final class ImplementationManager {
                         rule = (PasswordRule) ApplicationContextProvider.getBeanFactory().
                                 getSingleton(ruleClass.getName());
                     } else {
-                        rule = (PasswordRule) ApplicationContextProvider.getBeanFactory().
-                                createBean(ruleClass, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, false);
-                        ApplicationContextProvider.getBeanFactory().
-                                registerSingleton(ruleClass.getName(), rule);
+                        try {
+                            rule = (PasswordRule) ApplicationContextProvider.getBeanFactory().
+                                    createBean(ruleClass, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, false);
+                            ApplicationContextProvider.getBeanFactory().
+                                    registerSingleton(ruleClass.getName(), rule);
+                        } catch (IllegalStateException e) {
+                            LOG.warn("While attempting to register {}", ruleClass.getName(), e);
+                        }
                     }
                     rule.setConf(ruleConf);
                 }
@@ -173,10 +185,14 @@ public final class ImplementationManager {
                         rule = (PullCorrelationRule) ApplicationContextProvider.getBeanFactory().
                                 getSingleton(ruleClass.getName());
                     } else {
-                        rule = (PullCorrelationRule) ApplicationContextProvider.getBeanFactory().
-                                createBean(ruleClass, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, false);
-                        ApplicationContextProvider.getBeanFactory().
-                                registerSingleton(ruleClass.getName(), rule);
+                        try {
+                            rule = (PullCorrelationRule) ApplicationContextProvider.getBeanFactory().
+                                    createBean(ruleClass, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, false);
+                            ApplicationContextProvider.getBeanFactory().
+                                    registerSingleton(ruleClass.getName(), rule);
+                        } catch (IllegalStateException e) {
+                            LOG.warn("While attempting to register {}", ruleClass.getName(), e);
+                        }
                     }
                     rule.setConf(ruleConf);
                 }
@@ -208,10 +224,14 @@ public final class ImplementationManager {
                         rule = (PushCorrelationRule) ApplicationContextProvider.getBeanFactory().
                                 getSingleton(ruleClass.getName());
                     } else {
-                        rule = (PushCorrelationRule) ApplicationContextProvider.getBeanFactory().
-                                createBean(ruleClass, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, false);
-                        ApplicationContextProvider.getBeanFactory().
-                                registerSingleton(ruleClass.getName(), rule);
+                        try {
+                            rule = (PushCorrelationRule) ApplicationContextProvider.getBeanFactory().
+                                    createBean(ruleClass, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, false);
+                            ApplicationContextProvider.getBeanFactory().
+                                    registerSingleton(ruleClass.getName(), rule);
+                        } catch (IllegalStateException e) {
+                            LOG.warn("While attempting to register {}", ruleClass.getName(), e);
+                        }
                     }
                     rule.setConf(ruleConf);
                 }
diff --git a/core/spring/src/test/java/org/apache/syncope/core/spring/ImplementationManagerTest.java b/core/spring/src/test/java/org/apache/syncope/core/spring/ImplementationManagerTest.java
new file mode 100644
index 0000000..359d484
--- /dev/null
+++ b/core/spring/src/test/java/org/apache/syncope/core/spring/ImplementationManagerTest.java
@@ -0,0 +1,106 @@
+/*
+ * 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.syncope.core.spring;
+
+import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.apache.syncope.common.lib.policy.DefaultPasswordRuleConf;
+import org.apache.syncope.core.persistence.api.dao.PasswordRule;
+import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
+import org.apache.syncope.core.spring.security.TestImplementation;
+import org.junit.jupiter.api.Test;
+import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
+import java.time.Duration;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.stream.Collectors;
+
+@SpringJUnitConfig(locations = { "classpath:springTest.xml" })
+class ImplementationManagerTest {
+
+    private DefaultPasswordRuleConf createBaseDefaultPasswordRuleConf() {
+        DefaultPasswordRuleConf baseDefaultPasswordRuleConf = new DefaultPasswordRuleConf();
+        baseDefaultPasswordRuleConf.setAlphanumericRequired(false);
+        baseDefaultPasswordRuleConf.setDigitRequired(false);
+        baseDefaultPasswordRuleConf.setLowercaseRequired(false);
+        baseDefaultPasswordRuleConf.setMaxLength(1000);
+        baseDefaultPasswordRuleConf.setMinLength(8);
+        baseDefaultPasswordRuleConf.setMustEndWithAlpha(false);
+        baseDefaultPasswordRuleConf.setMustEndWithDigit(false);
+        baseDefaultPasswordRuleConf.setMustEndWithNonAlpha(false);
+        baseDefaultPasswordRuleConf.setMustStartWithAlpha(false);
+        baseDefaultPasswordRuleConf.setMustStartWithDigit(false);
+        baseDefaultPasswordRuleConf.setMustStartWithNonAlpha(false);
+        baseDefaultPasswordRuleConf.setMustntEndWithAlpha(false);
+        baseDefaultPasswordRuleConf.setMustntEndWithDigit(false);
+        baseDefaultPasswordRuleConf.setMustntEndWithNonAlpha(false);
+        baseDefaultPasswordRuleConf.setMustntStartWithAlpha(false);
+        baseDefaultPasswordRuleConf.setMustntStartWithDigit(false);
+        baseDefaultPasswordRuleConf.setMustntStartWithNonAlpha(false);
+        baseDefaultPasswordRuleConf.setNonAlphanumericRequired(false);
+        baseDefaultPasswordRuleConf.setUppercaseRequired(false);
+        return baseDefaultPasswordRuleConf;
+    }
+
+    @Test
+    public void concurrentPasswordRuleBuilding() {
+        assertTimeoutPreemptively(Duration.ofSeconds(30), () -> {
+            TestImplementation implementation = new TestImplementation();
+            implementation.setBody(POJOHelper.serialize(createBaseDefaultPasswordRuleConf()));
+            ReentrantLock lock = new ReentrantLock();
+            lock.lock();
+            AtomicInteger runningThreads = new AtomicInteger(0);
+            AtomicInteger errorCount = new AtomicInteger(0);
+            List<String> errorMessages = Collections.synchronizedList(new LinkedList<>());
+            for (int i = 0; i < 10; i++) {
+                runningThreads.incrementAndGet();
+                new Thread(() -> {
+                    try {
+                        while (lock.isLocked()) {
+                            Thread.yield();
+                        }
+                        Optional<PasswordRule> passwordRule;
+                        try {
+                            passwordRule = ImplementationManager.buildPasswordRule(implementation);
+                            passwordRule.orElseThrow();
+                        } catch (Exception e) {
+                            errorMessages.add(e.getLocalizedMessage());
+                            errorCount.incrementAndGet();
+                        }
+                    } finally {
+                        runningThreads.decrementAndGet();
+                    }
+                }).start();
+            }
+            lock.unlock();
+            while (runningThreads.get() > 0) {
+                Thread.yield();
+            }
+
+            assertTrue(
+                    errorMessages.isEmpty(),
+                    errorMessages.stream().collect(Collectors.joining(System.lineSeparator())));
+        });
+    }
+}