Author: amitj
Date: Wed Jun 24 04:25:58 2015
New Revision: 1687171
URL: http://svn.apache.org/r1687171
Log:
OAK-2962: SegmentNodeStoreService fails to handle empty strings in the OSGi
configuration
Patch from Francesco Mari
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/osgi/OsgiUtil.java
(with props)
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/osgi/OsgiUtilTest.java
(with props)
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/osgi/package-info.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreService.java
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/osgi/OsgiUtil.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/osgi/OsgiUtil.java?rev=1687171&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/osgi/OsgiUtil.java
(added)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/osgi/OsgiUtil.java
Wed Jun 24 04:25:58 2015
@@ -0,0 +1,100 @@
+/*
+ * 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.osgi;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.service.component.ComponentContext;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Utility methods to use in an OSGi environment.
+ */
+public class OsgiUtil {
+
+ private OsgiUtil() {
+ // Prevent instantiation.
+ }
+
+ /**
+ * Looks a property up by name in a component context. Returns {@code null}
+ * if the property is not found or if the property is found but it is an
+ * empty string.
+ *
+ * @param context Component context.
+ * @param name Name of the property.
+ * @return The property value serialized as a string, or {@code null}.
+ */
+ public static String lookup(ComponentContext context, String name) {
+ return
asString(checkNotNull(context).getProperties().get(checkNotNull(name)));
+ }
+
+ /**
+ * Looks a property up by name in the set of framework properties. Returns
+ * {@code null} if the property is not found or if the property is found
but
+ * it is an empty string.
+ *
+ * @param context Component context.
+ * @param name Name of the property.
+ * @return The property value serialized as a string, or {@code null}.
+ */
+ public static String lookup(BundleContext context, String name) {
+ return asString(checkNotNull(context).getProperty(checkNotNull(name)));
+ }
+
+ /**
+ * Looks a property up by name in the component context first, falling back
+ * in the framework properties if not found. Returns {@code null} if the
+ * property is not found or if the property is found but it is an empty
+ * string.
+ *
+ * @param context Component context.
+ * @param name Name of the property.
+ * @return The property value serialized as a string, or {@code null}.
+ */
+ public static String fallbackLookup(ComponentContext context, String name)
{
+ String fromComponent = lookup(context, name);
+
+ if (fromComponent != null) {
+ return fromComponent;
+ }
+
+ String fromFramework = lookup(context.getBundleContext(), name);
+
+ if (fromFramework != null) {
+ return fromFramework;
+ }
+
+ return null;
+ }
+
+ private static String asString(Object value) {
+ if (value == null) {
+ return null;
+ }
+
+ String string = value.toString().trim();
+
+ if (string.isEmpty()) {
+ return null;
+ }
+
+ return string;
+ }
+
+}
Propchange:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/osgi/OsgiUtil.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/osgi/package-info.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/osgi/package-info.java?rev=1687171&r1=1687170&r2=1687171&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/osgi/package-info.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/osgi/package-info.java
Wed Jun 24 04:25:58 2015
@@ -14,9 +14,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-@Version("1.0")
+@Version("1.1")
@Export(optional = "provide:=true")
package org.apache.jackrabbit.oak.osgi;
import aQute.bnd.annotation.Version;
-import aQute.bnd.annotation.Export;
\ No newline at end of file
+import aQute.bnd.annotation.Export;
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreService.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreService.java?rev=1687171&r1=1687170&r2=1687171&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreService.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreService.java
Wed Jun 24 04:25:58 2015
@@ -21,6 +21,7 @@ import static java.util.Collections.empt
import static org.apache.jackrabbit.oak.commons.PropertiesUtil.toBoolean;
import static org.apache.jackrabbit.oak.commons.PropertiesUtil.toInteger;
import static org.apache.jackrabbit.oak.commons.PropertiesUtil.toLong;
+import static org.apache.jackrabbit.oak.osgi.OsgiUtil.fallbackLookup;
import static
org.apache.jackrabbit.oak.plugins.segment.compaction.CompactionStrategy.CLEANUP_DEFAULT;
import static
org.apache.jackrabbit.oak.plugins.segment.compaction.CompactionStrategy.CLONE_BINARIES_DEFAULT;
import static
org.apache.jackrabbit.oak.plugins.segment.compaction.CompactionStrategy.FORCE_AFTER_FAIL_DEFAULT;
@@ -272,7 +273,7 @@ public class SegmentNodeStoreService ext
@Activate
private void activate(ComponentContext context) throws IOException {
this.context = context;
- this.customBlobStore = Boolean.parseBoolean(lookup(context,
CUSTOM_BLOB_STORE));
+ this.customBlobStore = Boolean.parseBoolean(fallbackLookup(context,
CUSTOM_BLOB_STORE));
if (blobStore == null && customBlobStore) {
log.info("BlobStore use enabled. SegmentNodeStore would be
initialized when BlobStore would be available");
@@ -283,7 +284,7 @@ public class SegmentNodeStoreService ext
public void registerNodeStore() throws IOException {
if (registerSegmentStore()) {
- boolean standby = toBoolean(lookup(context, STANDBY), false);
+ boolean standby = toBoolean(fallbackLookup(context, STANDBY),
false);
providerRegistration = context.getBundleContext().registerService(
SegmentStoreProvider.class.getName(), this, null);
if (!standby) {
@@ -304,56 +305,56 @@ public class SegmentNodeStoreService ext
Dictionary<?, ?> properties = context.getProperties();
name = String.valueOf(properties.get(NAME));
- String directory = lookup(context, DIRECTORY);
+ String directory = fallbackLookup(context, DIRECTORY);
if (directory == null) {
directory = "tarmk";
}else{
directory = FilenameUtils.concat(directory, "segmentstore");
}
- String mode = lookup(context, MODE);
+ String mode = fallbackLookup(context, MODE);
if (mode == null) {
mode = System.getProperty(MODE,
System.getProperty("sun.arch.data.model", "32"));
}
- String size = lookup(context, SIZE);
+ String size = fallbackLookup(context, SIZE);
if (size == null) {
size = System.getProperty(SIZE, "256");
}
- String cache = lookup(context, CACHE);
+ String cache = fallbackLookup(context, CACHE);
if (cache == null) {
cache = System.getProperty(CACHE);
}
- boolean pauseCompaction = toBoolean(lookup(context, PAUSE_COMPACTION),
+ boolean pauseCompaction = toBoolean(fallbackLookup(context,
PAUSE_COMPACTION),
PAUSE_DEFAULT);
boolean cloneBinaries = toBoolean(
- lookup(context, COMPACTION_CLONE_BINARIES),
+ fallbackLookup(context, COMPACTION_CLONE_BINARIES),
CLONE_BINARIES_DEFAULT);
- long cleanupTs = toLong(lookup(context, COMPACTION_CLEANUP_TIMESTAMP),
+ long cleanupTs = toLong(fallbackLookup(context,
COMPACTION_CLEANUP_TIMESTAMP),
TIMESTAMP_DEFAULT);
- int retryCount = toInteger(lookup(context, COMPACTION_RETRY_COUNT),
+ int retryCount = toInteger(fallbackLookup(context,
COMPACTION_RETRY_COUNT),
RETRY_COUNT_DEFAULT);
- boolean forceCommit = toBoolean(lookup(context,
COMPACTION_FORCE_AFTER_FAIL),
+ boolean forceCommit = toBoolean(fallbackLookup(context,
COMPACTION_FORCE_AFTER_FAIL),
FORCE_AFTER_FAIL_DEFAULT);
- final int lockWaitTime = toInteger(lookup(context,
COMPACTION_LOCK_WAIT_TIME),
+ final int lockWaitTime = toInteger(fallbackLookup(context,
COMPACTION_LOCK_WAIT_TIME),
COMPACTION_LOCK_WAIT_TIME_DEFAULT);
- boolean persistCompactionMap = toBoolean(lookup(context,
PERSIST_COMPACTION_MAP),
+ boolean persistCompactionMap = toBoolean(fallbackLookup(context,
PERSIST_COMPACTION_MAP),
PERSIST_COMPACTION_MAP_DEFAULT);
- String cleanup = lookup(context, COMPACTION_CLEANUP);
+ String cleanup = fallbackLookup(context, COMPACTION_CLEANUP);
if (cleanup == null) {
cleanup = CLEANUP_DEFAULT.toString();
}
- String memoryThresholdS = lookup(context, COMPACTION_MEMORY_THRESHOLD);
+ String memoryThresholdS = fallbackLookup(context,
COMPACTION_MEMORY_THRESHOLD);
byte memoryThreshold = MEMORY_THRESHOLD_DEFAULT;
if (memoryThresholdS != null) {
memoryThreshold = Byte.valueOf(memoryThresholdS);
}
- final long blobGcMaxAgeInSecs = toLong(lookup(context,
PROP_BLOB_GC_MAX_AGE), DEFAULT_BLOB_GC_MAX_AGE);
+ final long blobGcMaxAgeInSecs = toLong(fallbackLookup(context,
PROP_BLOB_GC_MAX_AGE), DEFAULT_BLOB_GC_MAX_AGE);
OsgiWhiteboard whiteboard = new
OsgiWhiteboard(context.getBundleContext());
gcMonitor = new GCMonitorTracker();
@@ -443,16 +444,6 @@ public class SegmentNodeStoreService ext
return true;
}
- private static String lookup(ComponentContext context, String property) {
- if (context.getProperties().get(property) != null) {
- return context.getProperties().get(property).toString();
- }
- if (context.getBundleContext().getProperty(property) != null) {
- return context.getBundleContext().getProperty(property);
- }
- return null;
- }
-
@Deactivate
public synchronized void deactivate() {
unregisterNodeStore();
Added:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/osgi/OsgiUtilTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/osgi/OsgiUtilTest.java?rev=1687171&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/osgi/OsgiUtilTest.java
(added)
+++
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/osgi/OsgiUtilTest.java
Wed Jun 24 04:25:58 2015
@@ -0,0 +1,202 @@
+/*
+ * 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.osgi;
+
+import org.junit.Test;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.component.ComponentContext;
+
+import java.util.Dictionary;
+
+import static org.apache.jackrabbit.oak.osgi.OsgiUtil.fallbackLookup;
+import static org.apache.jackrabbit.oak.osgi.OsgiUtil.lookup;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+public class OsgiUtilTest {
+
+ @Test(expected = NullPointerException.class)
+ public void testComponentLookupWithNullContext() {
+ lookup((ComponentContext) null, "name");
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testComponentLookupWithNullName() {
+ lookup(mock(ComponentContext.class), null);
+ }
+
+ @Test
+ public void testComponentLookupWithNotFoundValue() {
+ Dictionary properties = mock(Dictionary.class);
+ doReturn(null).when(properties).get("name");
+
+ ComponentContext context = mock(ComponentContext.class);
+ doReturn(properties).when(context).getProperties();
+
+ assertNull(lookup(context, "name"));
+ }
+
+ @Test
+ public void testComponentLookupWithEmptyString() {
+ Dictionary properties = mock(Dictionary.class);
+ doReturn("").when(properties).get("name");
+
+ ComponentContext context = mock(ComponentContext.class);
+ doReturn(properties).when(context).getProperties();
+
+ assertNull(lookup(context, "name"));
+ }
+
+ @Test
+ public void testComponentLookupWithNonTrimmedString() {
+ Dictionary properties = mock(Dictionary.class);
+ doReturn(" ").when(properties).get("name");
+
+ ComponentContext context = mock(ComponentContext.class);
+ doReturn(properties).when(context).getProperties();
+
+ assertNull(lookup(context, "name"));
+ }
+
+ @Test
+ public void testComponentLookupWithNonStringValue() {
+ Dictionary properties = mock(Dictionary.class);
+ doReturn(42).when(properties).get("name");
+
+ ComponentContext context = mock(ComponentContext.class);
+ doReturn(properties).when(context).getProperties();
+
+ assertEquals("42", lookup(context, "name"));
+ }
+
+ @Test
+ public void testComponentLookupWithStringValue() {
+ Dictionary properties = mock(Dictionary.class);
+ doReturn(" value ").when(properties).get("name");
+
+ ComponentContext context = mock(ComponentContext.class);
+ doReturn(properties).when(context).getProperties();
+
+ assertEquals("value", lookup(context, "name"));
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testFrameworkLookupWithNullContext() {
+ lookup((BundleContext) null, "name");
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testFrameworkLookupWithNullName() {
+ lookup(mock(BundleContext.class), null);
+ }
+
+ @Test
+ public void testFrameworkLookupWithNotFoundValue() {
+ BundleContext context = mock(BundleContext.class);
+ doReturn(null).when(context).getProperty("name");
+
+ assertNull(lookup(context, "name"));
+ }
+
+ @Test
+ public void testFrameworkLookupWithEmptyString() {
+ BundleContext context = mock(BundleContext.class);
+ doReturn("").when(context).getProperty("name");
+
+ assertNull(lookup(context, "name"));
+ }
+
+ @Test
+ public void testFrameworkLookupWithNonTrimmedString() {
+ BundleContext context = mock(BundleContext.class);
+ doReturn(" ").when(context).getProperty("name");
+
+ assertNull(lookup(context, "name"));
+ }
+
+ @Test
+ public void testFrameworkLookupWith() {
+ BundleContext context = mock(BundleContext.class);
+ doReturn(" value ").when(context).getProperty("name");
+
+ assertEquals("value", lookup(context, "name"));
+ }
+
+ @Test
+ public void testFallbackLookupWithNotFoundValue() {
+ Dictionary dictionary = mock(Dictionary.class);
+ doReturn(null).when(dictionary).get("name");
+
+ BundleContext bundleContext = mock(BundleContext.class);
+ doReturn(null).when(bundleContext).getProperty("name");
+
+ ComponentContext componentContext = mock(ComponentContext.class);
+ doReturn(dictionary).when(componentContext).getProperties();
+ doReturn(bundleContext).when(componentContext).getBundleContext();
+
+ assertNull(fallbackLookup(componentContext, "name"));
+ }
+
+ @Test
+ public void testFallbackLookupWithValueInComponent() {
+ Dictionary dictionary = mock(Dictionary.class);
+ doReturn("value").when(dictionary).get("name");
+
+ BundleContext bundleContext = mock(BundleContext.class);
+ doReturn(null).when(bundleContext).getProperty("name");
+
+ ComponentContext componentContext = mock(ComponentContext.class);
+ doReturn(dictionary).when(componentContext).getProperties();
+ doReturn(bundleContext).when(componentContext).getBundleContext();
+
+ assertEquals("value", fallbackLookup(componentContext, "name"));
+ }
+
+ @Test
+ public void testFallbackLookupWithValueInFramework() {
+ Dictionary dictionary = mock(Dictionary.class);
+ doReturn(null).when(dictionary).get("name");
+
+ BundleContext bundleContext = mock(BundleContext.class);
+ doReturn("value").when(bundleContext).getProperty("name");
+
+ ComponentContext componentContext = mock(ComponentContext.class);
+ doReturn(dictionary).when(componentContext).getProperties();
+ doReturn(bundleContext).when(componentContext).getBundleContext();
+
+ assertEquals("value", fallbackLookup(componentContext, "name"));
+ }
+
+ @Test
+ public void testFallbackLookupWithValueInComponentAndFramework() {
+ Dictionary dictionary = mock(Dictionary.class);
+ doReturn("value").when(dictionary).get("name");
+
+ BundleContext bundleContext = mock(BundleContext.class);
+ doReturn("ignored").when(bundleContext).getProperty("name");
+
+ ComponentContext componentContext = mock(ComponentContext.class);
+ doReturn(dictionary).when(componentContext).getProperties();
+ doReturn(bundleContext).when(componentContext).getBundleContext();
+
+ assertEquals("value", fallbackLookup(componentContext, "name"));
+ }
+
+}
Propchange:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/osgi/OsgiUtilTest.java
------------------------------------------------------------------------------
svn:eol-style = native