Merge pull request #3 from sagarmiglani/SLING-11620

SLING-11620 - Synchronization issue in Webconsole Security Provider
diff --git a/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/ServicesListener.java b/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/ServicesListener.java
index 5c60215..0225e12 100644
--- a/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/ServicesListener.java
+++ b/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/ServicesListener.java
@@ -67,6 +67,9 @@
     /** The listener for the authenticator. */
     private final Listener authListener;
 
+    /** Shared lock object */
+    private final Object lock = new Object();
+
     enum State {
         NONE,
         PROVIDER_JCR,
@@ -140,27 +143,28 @@
     /**
      * Notify of service changes from the listeners.
      */
-    public synchronized void notifyChange() {
+    public void notifyChange() {
         // check if all services are available
-        
-        final Object authSupport = this.authSupportListener.getService();
-        final Object authenticator = this.authListener.getService();
-        final Object repository = this.repositoryListener.getService();
+        synchronized (lock) {
+            final Object authSupport = this.authSupportListener.getService();
+            final Object authenticator = this.authListener.getService();
+            final Object repository = this.repositoryListener.getService();
 
-        final State targetState = this.getTargetState(authSupport != null && authenticator != null, repository != null);
-        if ( this.registrationState != targetState ) {
-            if ( targetState != State.PROVIDER_JCR ) {
-                this.unregisterProviderJcr();
-            } 
-            if ( targetState != State.PROVIDER_SLING ) {
-                this.unregisterProviderSling();
+            final State targetState = this.getTargetState(authSupport != null && authenticator != null, repository != null);
+            if ( this.registrationState != targetState ) {
+                if ( targetState != State.PROVIDER_JCR ) {
+                    this.unregisterProviderJcr();
+                }
+                if ( targetState != State.PROVIDER_SLING ) {
+                    this.unregisterProviderSling();
+                }
+                if ( targetState == State.PROVIDER_JCR ) {
+                    this.registerProviderJcr(repository);
+                } else if ( targetState == State.PROVIDER_SLING ) {
+                    this.registerProviderSling(authSupport, authenticator);
+                }
+                this.registrationState = targetState;
             }
-            if ( targetState == State.PROVIDER_JCR ) {
-                this.registerProviderJcr(repository);
-            } else if ( targetState == State.PROVIDER_SLING ) {
-                this.registerProviderSling(authSupport, authenticator);
-            }
-            this.registrationState = targetState;
         }
     }
 
@@ -259,47 +263,53 @@
         /**
          * Return the service (if available)
          */
-        public synchronized Object getService() {
-            return this.service;
+        public Object getService() {
+            synchronized (lock) {
+                return this.service;
+            }
         }
 
         /**
          * Try to get the service and notify the change.
          */
-        private synchronized void retainService(final ServiceReference<?> ref) {
-            boolean hadService = this.service != null;
-            boolean getService = this.reference == null;
-            if ( !getService ) {
-                final int result = this.reference.compareTo(ref);
-                if ( result < 0 ) {
-                    bundleContext.ungetService(this.reference);
-                    this.service = null;
-                    getService = true;
+        private void retainService(final ServiceReference<?> ref) {
+            synchronized (lock) {
+                boolean hadService = this.service != null;
+                boolean getService = this.reference == null;
+                if ( !getService ) {
+                    final int result = this.reference.compareTo(ref);
+                    if ( result < 0 ) {
+                        bundleContext.ungetService(this.reference);
+                        this.service = null;
+                        getService = true;
+                    }
                 }
-            }
-            if ( getService ) {
-                this.reference = ref;
-                this.service = bundleContext.getService(this.reference);
-                if ( this.service == null ) {
-                    this.reference = null;
-                } else {
+                if ( getService ) {
+                    this.reference = ref;
+                    this.service = bundleContext.getService(this.reference);
+                    if ( this.service == null ) {
+                        this.reference = null;
+                    } else {
+                        notifyChange();
+                    }
+                }
+                if ( hadService && this.service == null ) {
                     notifyChange();
                 }
             }
-            if ( hadService && this.service == null ) {
-                notifyChange();
-            }
         }
 
         /**
          * Try to release the service and notify the change.
          */
-        private synchronized void releaseService(final ServiceReference<?> ref) {
-            if ( this.reference != null && this.reference.compareTo(ref) == 0) {
-                this.service = null;
-                bundleContext.ungetService(this.reference);
-                this.reference = null;
-                notifyChange();
+        private void releaseService(final ServiceReference<?> ref) {
+            synchronized (lock) {
+                if ( this.reference != null && this.reference.compareTo(ref) == 0) {
+                    this.service = null;
+                    bundleContext.ungetService(this.reference);
+                    this.reference = null;
+                    notifyChange();
+                }
             }
         }