Author: mreutegg
Date: Thu Jul  9 13:00:47 2020
New Revision: 1879706

URL: http://svn.apache.org/viewvc?rev=1879706&view=rev
Log:
OAK-9132: Feature toggles

Commit proposal

Added:
    
jackrabbit/oak/trunk/oak-core-spi/src/main/java/org/apache/jackrabbit/oak/spi/toggle/
    
jackrabbit/oak/trunk/oak-core-spi/src/main/java/org/apache/jackrabbit/oak/spi/toggle/Feature.java
   (with props)
    
jackrabbit/oak/trunk/oak-core-spi/src/main/java/org/apache/jackrabbit/oak/spi/toggle/FeatureToggle.java
   (with props)
    
jackrabbit/oak/trunk/oak-core-spi/src/main/java/org/apache/jackrabbit/oak/spi/toggle/package-info.java
   (with props)
    
jackrabbit/oak/trunk/oak-core-spi/src/test/java/org/apache/jackrabbit/oak/spi/toggle/
    
jackrabbit/oak/trunk/oak-core-spi/src/test/java/org/apache/jackrabbit/oak/spi/toggle/FeatureToggleTest.java
   (with props)
Modified:
    jackrabbit/oak/trunk/oak-core-spi/pom.xml

Modified: jackrabbit/oak/trunk/oak-core-spi/pom.xml
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core-spi/pom.xml?rev=1879706&r1=1879705&r2=1879706&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core-spi/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-core-spi/pom.xml Thu Jul  9 13:00:47 2020
@@ -58,6 +58,7 @@
               org.apache.jackrabbit.oak.spi.namespace,
               org.apache.jackrabbit.oak.spi.nodetype,
               org.apache.jackrabbit.oak.spi.observation,
+              org.apache.jackrabbit.oak.spi.toggle,
               org.apache.jackrabbit.oak.spi.version,
               org.apache.jackrabbit.oak.spi.whiteboard,
               org.apache.jackrabbit.oak.stats
@@ -174,6 +175,11 @@
       <classifier>tests</classifier>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.apache.sling</groupId>
+      <artifactId>org.apache.sling.testing.osgi-mock</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
 </project>

Added: 
jackrabbit/oak/trunk/oak-core-spi/src/main/java/org/apache/jackrabbit/oak/spi/toggle/Feature.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core-spi/src/main/java/org/apache/jackrabbit/oak/spi/toggle/Feature.java?rev=1879706&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core-spi/src/main/java/org/apache/jackrabbit/oak/spi/toggle/Feature.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core-spi/src/main/java/org/apache/jackrabbit/oak/spi/toggle/Feature.java
 Thu Jul  9 13:00:47 2020
@@ -0,0 +1,83 @@
+/*
+ * 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.jackrabbit.oak.spi.toggle;
+
+import java.io.Closeable;
+import java.util.Collections;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.jackrabbit.oak.spi.whiteboard.Registration;
+import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
+
+/**
+ * A feature toggle to control new functionality. The default state of a 
feature
+ * is {@code false} and can be controlled by third party code discovering
+ * {@link FeatureToggle}s on the {@link Whiteboard}. Every feature is
+ * linked to a feature toggle and allows to control the state of the feature
+ * toggle via {@link FeatureToggle#setEnabled(boolean)}. Creating a new feature
+ * involves registering a feature toggle on the {@link Whiteboard} and
+ * potentially comes with some overhead (e.g. when the whiteboard is based on
+ * OSGi). Therefore, client code should not create a new feature, check the
+ * state and then immediately release/close it again. Instead a feature should
+ * be acquired initially, checked at runtime whenever needed and finally
+ * released when the client component is destroyed.
+ */
+public final class Feature implements Closeable {
+
+    private final AtomicBoolean value;
+
+    private final Registration registration;
+
+    private Feature(AtomicBoolean value, Registration registration) {
+        this.value = value;
+        this.registration = registration;
+    }
+
+    /**
+     * Creates a new {@link Feature} with the given name and registers the
+     * corresponding {@link FeatureToggle} on the {@link Whiteboard}.
+     * Client code must call {@link Feature#close()} when the toggle is
+     * not used anymore.
+     *
+     * @param name the name of the feature toggle.
+     * @param whiteboard the whiteboard where to register the feature toggle.
+     * @return the feature toggle.
+     */
+    public static Feature newFeature(String name, Whiteboard whiteboard) {
+        AtomicBoolean value = new AtomicBoolean();
+        FeatureToggle adapter = new FeatureToggle(name, value);
+        return new Feature(value, whiteboard.register(
+                FeatureToggle.class, adapter, Collections.emptyMap()));
+    }
+
+    /**
+     * @return the current state of this feature.
+     */
+    public boolean isEnabled() {
+        return value.get();
+    }
+
+    /**
+     * Releases resources for this feature toggle.
+     */
+    @Override
+    public void close() {
+        this.registration.unregister();
+    }
+}

Propchange: 
jackrabbit/oak/trunk/oak-core-spi/src/main/java/org/apache/jackrabbit/oak/spi/toggle/Feature.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
jackrabbit/oak/trunk/oak-core-spi/src/main/java/org/apache/jackrabbit/oak/spi/toggle/FeatureToggle.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core-spi/src/main/java/org/apache/jackrabbit/oak/spi/toggle/FeatureToggle.java?rev=1879706&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core-spi/src/main/java/org/apache/jackrabbit/oak/spi/toggle/FeatureToggle.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core-spi/src/main/java/org/apache/jackrabbit/oak/spi/toggle/FeatureToggle.java
 Thu Jul  9 13:00:47 2020
@@ -0,0 +1,69 @@
+/*
+ * 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.jackrabbit.oak.spi.toggle;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
+
+/**
+ * A feature toggle is registered with the {@link Whiteboard} and can be
+ * discovered by third party code to control the state of feature toggles.
+ */
+public final class FeatureToggle {
+
+    private final String name;
+
+    private final AtomicBoolean state;
+
+    /**
+     * Create a new adapter with a given name and value.
+     *
+     * @param name the name of the feature toggle.
+     * @param state the state for the feature toggle.
+     */
+    public FeatureToggle(String name, AtomicBoolean state) {
+        this.name = name;
+        this.state = state;
+    }
+
+    /**
+     * @return the name of the feature toggle.
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * @return the current state of this feature toggle.
+     */
+    public boolean isEnabled() {
+        return state.get();
+    }
+
+    /**
+     * Changes the state of the feature toggle.
+     *
+     * @param state the new state of the feature toggle.
+     * @return the previous state.
+     */
+    public boolean setEnabled(boolean state) {
+        return this.state.getAndSet(state);
+    }
+}

Propchange: 
jackrabbit/oak/trunk/oak-core-spi/src/main/java/org/apache/jackrabbit/oak/spi/toggle/FeatureToggle.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
jackrabbit/oak/trunk/oak-core-spi/src/main/java/org/apache/jackrabbit/oak/spi/toggle/package-info.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core-spi/src/main/java/org/apache/jackrabbit/oak/spi/toggle/package-info.java?rev=1879706&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core-spi/src/main/java/org/apache/jackrabbit/oak/spi/toggle/package-info.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core-spi/src/main/java/org/apache/jackrabbit/oak/spi/toggle/package-info.java
 Thu Jul  9 13:00:47 2020
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+@Version("1.0.0")
+package org.apache.jackrabbit.oak.spi.toggle;
+
+import org.osgi.annotation.versioning.Version;
\ No newline at end of file

Propchange: 
jackrabbit/oak/trunk/oak-core-spi/src/main/java/org/apache/jackrabbit/oak/spi/toggle/package-info.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
jackrabbit/oak/trunk/oak-core-spi/src/test/java/org/apache/jackrabbit/oak/spi/toggle/FeatureToggleTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core-spi/src/test/java/org/apache/jackrabbit/oak/spi/toggle/FeatureToggleTest.java?rev=1879706&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core-spi/src/test/java/org/apache/jackrabbit/oak/spi/toggle/FeatureToggleTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core-spi/src/test/java/org/apache/jackrabbit/oak/spi/toggle/FeatureToggleTest.java
 Thu Jul  9 13:00:47 2020
@@ -0,0 +1,105 @@
+/*
+ * 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.jackrabbit.oak.spi.toggle;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.jackrabbit.oak.osgi.OsgiWhiteboard;
+import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUtils;
+import org.apache.sling.testing.mock.osgi.junit.OsgiContext;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static org.apache.jackrabbit.oak.spi.toggle.Feature.newFeature;
+import static org.hamcrest.CoreMatchers.hasItems;
+import static org.hamcrest.Matchers.empty;
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+public class FeatureToggleTest {
+
+    @Rule
+    public final OsgiContext context = new OsgiContext();
+
+    private final OsgiWhiteboard whiteboard = new 
OsgiWhiteboard(context.bundleContext());
+
+    @Test
+    public void disabledByDefault() {
+        try (Feature feature = newFeature("my.toggle", whiteboard)) {
+            assertFalse(feature.isEnabled());
+        }
+    }
+
+    @Test
+    public void register() {
+        try (Feature feature = newFeature("my.toggle", whiteboard)) {
+            assertFalse(feature.isEnabled());
+            List<FeatureToggle> toggles = getFeatureToggles();
+            assertEquals(1, toggles.size());
+            FeatureToggle toggle = toggles.get(0);
+            assertEquals("my.toggle", toggle.getName());
+
+            assertFalse(toggle.setEnabled(true));
+            assertTrue(toggle.isEnabled());
+            assertTrue(feature.isEnabled());
+
+            assertTrue(toggle.setEnabled(true));
+            assertTrue(toggle.setEnabled(false));
+            assertFalse(toggle.isEnabled());
+            assertFalse(feature.isEnabled());
+        }
+    }
+
+    @Test
+    public void registerMultiple() {
+        try (Feature f1 = newFeature("my.t1", whiteboard);
+             Feature f2 = newFeature("my.t2", whiteboard)) {
+            assertFalse(f1.isEnabled());
+            assertFalse(f2.isEnabled());
+            List<FeatureToggle> toggles = getFeatureToggles();
+            assertEquals(2, toggles.size());
+            List<String> toggleNames = new ArrayList<>();
+            for (FeatureToggle adapter : toggles) {
+                toggleNames.add(adapter.getName());
+            }
+            assertThat(toggleNames, hasItems("my.t1", "my.t2"));
+        }
+    }
+
+    @Test
+    public void unregisterOnClose() {
+        List<FeatureToggle> toggles;
+        try (Feature feature = newFeature("my.toggle", whiteboard)) {
+            assertFalse(feature.isEnabled());
+            toggles = getFeatureToggles();
+            assertEquals(1, toggles.size());
+        }
+        toggles = getFeatureToggles();
+        assertThat(toggles, is(empty()));
+    }
+
+    private List<FeatureToggle> getFeatureToggles() {
+        return WhiteboardUtils.getServices(
+                whiteboard, FeatureToggle.class);
+    }
+}

Propchange: 
jackrabbit/oak/trunk/oak-core-spi/src/test/java/org/apache/jackrabbit/oak/spi/toggle/FeatureToggleTest.java
------------------------------------------------------------------------------
    svn:eol-style = native


Reply via email to