You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2017/11/07 09:55:49 UTC
[sling-org-apache-sling-nosql-couchbase-client] 01/14: SLING-4381
couchbase client
This is an automated email from the ASF dual-hosted git repository.
rombert pushed a commit to annotated tag org.apache.sling.nosql.couchbase-client-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-nosql-couchbase-client.git
commit a587659c476c21147dc79a82c34055c9030f4773
Author: Stefan Seifert <ss...@apache.org>
AuthorDate: Wed May 20 13:48:32 2015 +0000
SLING-4381 couchbase client
git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/nosql/couchbase-client@1680570 13f79535-47bb-0310-9956-ffa450edef68
---
pom.xml | 131 +++++++++++++++++++
.../nosql/couchbase/client/CouchbaseClient.java | 63 +++++++++
.../sling/nosql/couchbase/client/CouchbaseKey.java | 79 ++++++++++++
.../couchbase/client/impl/CouchbaseClientImpl.java | 141 +++++++++++++++++++++
.../nosql/couchbase/client/impl/CouchbaseUtil.java | 63 +++++++++
.../sling/nosql/couchbase/client/package-info.java | 24 ++++
.../nosql/couchbase/client/CouchbaseKeyTest.java | 44 +++++++
7 files changed, 545 insertions(+)
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..d0a4ba9
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>sling</artifactId>
+ <version>22</version>
+ <relativePath/>
+ </parent>
+
+ <artifactId>org.apache.sling.nosql.couchbase-client</artifactId>
+ <version>0.5.0-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <name>Apache Sling NoSQL Couchbase Client</name>
+ <description>Couchbase client provider using Couchbase SDK 2.</description>
+
+ <scm>
+ <connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/contrib/nosql/couchbase-client</connection>
+ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/sling/trunk/contrib/nosql/couchbase-client</developerConnection>
+ <url>http://svn.apache.org/viewvc/sling/trunk/contrib/nosql/couchbase-client</url>
+ </scm>
+
+ <properties>
+ <sling.java.version>7</sling.java.version>
+ <couchbase.client.version>2.1.3</couchbase.client.version>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>com.couchbase.client</groupId>
+ <artifactId>java-client</artifactId>
+ <version>${couchbase.client.version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.commons.osgi</artifactId>
+ <version>2.2.2</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ <version>3.3.2</version>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <!-- Do not inline jars, include as jar files -->
+ <Embed-Dependency>*;scope=compile|runtime;inline=false;groupId=com.couchbase.*</Embed-Dependency>
+ <Embed-Transitive>true</Embed-Transitive>
+ <!-- use _exportcontents instead of Export-Package to avoid conflict with Embed-Dependency an inline=true -->
+ <_exportcontents>
+ com.couchbase.client.java.*;version=${couchbase.client.version},
+ org.apache.sling.nosql.couchbase.client;version=${project.version}
+ </_exportcontents>
+ <Import-Package>
+ com.barchart.udt.*;resolution:=optional,
+ com.google.protobuf.*;resolution:=optional,
+ com.jcraft.jzlib.*;resolution:=optional,
+ com.sun.*;resolution:=optional,
+ gnu.io.*;resolution:=optional,
+ javassist.*;resolution:=optional,
+ org.apache.tomcat.*;resolution:=optional,
+ org.bouncycastle.*;resolution:=optional,
+ org.eclipse.jetty.*;resolution:=optional,
+ org.jboss.*;resolution:=optional,
+ rx.internal.*;resolution:=optional,
+ sun.misc.*;resolution:=optional,
+ sun.security.*;resolution:=optional,
+ *
+ </Import-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-scr-plugin</artifactId>
+ </plugin>
+
+ </plugins>
+ </build>
+
+</project>
diff --git a/src/main/java/org/apache/sling/nosql/couchbase/client/CouchbaseClient.java b/src/main/java/org/apache/sling/nosql/couchbase/client/CouchbaseClient.java
new file mode 100644
index 0000000..f6751a2
--- /dev/null
+++ b/src/main/java/org/apache/sling/nosql/couchbase/client/CouchbaseClient.java
@@ -0,0 +1,63 @@
+/*
+ * 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.nosql.couchbase.client;
+
+import aQute.bnd.annotation.ProviderType;
+
+import com.couchbase.client.java.AsyncBucket;
+import com.couchbase.client.java.Bucket;
+
+/**
+ * Provides access to a preconfigured couchbase client.
+ * Multiple clients can be registered for different buckets; they can be filtered by the 'clientId' OSGi property.
+ */
+@ProviderType
+public interface CouchbaseClient {
+
+ /**
+ * OSGi property for filtering the configured couchbase clients.
+ */
+ String CLIENT_ID_PROPERTY = "clientId";
+
+ /**
+ * @return ID to uniquely identify the couchbase client if multiple are defined.
+ */
+ String getClientId();
+
+ /**
+ * @return true if Couchbase caching is enabled and configured properly.
+ */
+ boolean isEnabled();
+
+ /**
+ * @return the name of the couchbase bucket to use for caching
+ */
+ String getBucketName();
+
+ /**
+ * @return Default bucket as configured for the couchbase client provider.
+ */
+ Bucket getBucket();
+
+ /**
+ * @return Default asynchronous bucket as configured for the couchbase client provider.
+ */
+ AsyncBucket getAsyncBucket();
+
+}
diff --git a/src/main/java/org/apache/sling/nosql/couchbase/client/CouchbaseKey.java b/src/main/java/org/apache/sling/nosql/couchbase/client/CouchbaseKey.java
new file mode 100644
index 0000000..e495ffc
--- /dev/null
+++ b/src/main/java/org/apache/sling/nosql/couchbase/client/CouchbaseKey.java
@@ -0,0 +1,79 @@
+/*
+ * 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.nosql.couchbase.client;
+
+import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import aQute.bnd.annotation.ProviderType;
+
+/**
+ * Builds couchbase keys. Cuts them off and replaces the remaining part with a hash if too long.
+ */
+@ProviderType
+public final class CouchbaseKey {
+
+ static final int MAX_KEY_LENGTH = 250;
+
+ private CouchbaseKey() {
+ // static methods only
+ }
+
+ /**
+ * Builds a key for a couchbase document with the given prefix that does not
+ * exceed the max. length for couchbase keys.
+ * @param key Full key
+ * @param cacheKeyPrefix Prefix to add before the key
+ * @return Valid key for couchbase
+ */
+ public static String build(String key, String keyPrefix) {
+ String cacheKey = keyPrefix + key;
+
+ if (cacheKey.length() < MAX_KEY_LENGTH) {
+ return cacheKey;
+ }
+
+ int charactersToKeep = MAX_KEY_LENGTH - keyPrefix.length() - 41;
+
+ String toKeep = key.substring(0, charactersToKeep);
+ String toHash = key.substring(charactersToKeep);
+
+ String hash = calculateHash(toHash);
+
+ return keyPrefix + toKeep + "#" + hash;
+ }
+
+ private static String calculateHash(String message) {
+ try {
+ MessageDigest digest = MessageDigest.getInstance("SHA-1");
+ digest.update(message.getBytes("UTF-8"));
+ byte[] digestBytes = digest.digest();
+
+ return javax.xml.bind.DatatypeConverter.printHexBinary(digestBytes).toLowerCase();
+ }
+ catch (NoSuchAlgorithmException ex) {
+ throw new RuntimeException("Failed to create sha1 Hash from " + message, ex);
+ }
+ catch (UnsupportedEncodingException ex) {
+ throw new RuntimeException("Failed to create sha1 Hash from " + message, ex);
+ }
+ }
+
+}
diff --git a/src/main/java/org/apache/sling/nosql/couchbase/client/impl/CouchbaseClientImpl.java b/src/main/java/org/apache/sling/nosql/couchbase/client/impl/CouchbaseClientImpl.java
new file mode 100644
index 0000000..a12a61f
--- /dev/null
+++ b/src/main/java/org/apache/sling/nosql/couchbase/client/impl/CouchbaseClientImpl.java
@@ -0,0 +1,141 @@
+/*
+ * 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.nosql.couchbase.client.impl;
+
+import java.util.Map;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.ConfigurationPolicy;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.commons.osgi.PropertiesUtil;
+import org.apache.sling.nosql.couchbase.client.CouchbaseClient;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.couchbase.client.java.AsyncBucket;
+import com.couchbase.client.java.Bucket;
+import com.couchbase.client.java.Cluster;
+
+/**
+ * Default implementation of {@link CouchbaseClient}.
+ */
+@Component(immediate = true, metatype = true,
+ name="org.apache.sling.nosql.couchbase.client.CouchbaseClient.factory.config",
+ label = "Apache Sling NoSQL Couchbase Client",
+ description = "Provides access to a preconfigured couchbase client.",
+ configurationFactory = true, policy = ConfigurationPolicy.REQUIRE)
+@Service(CouchbaseClient.class)
+@Property(name = "webconsole.configurationFactory.nameHint",
+ value = "{" + CouchbaseClientImpl.CLIENT_ID_PROPERTY + "}: {" + CouchbaseClientImpl.CACHE_BUCKET_NAME_PROPERTY + "}")
+public class CouchbaseClientImpl implements CouchbaseClient {
+
+ @Property(label = "Client ID", description = "ID to uniquely identify the couchbase client if multiple are defined.")
+ static final String CLIENT_ID_PROPERTY = CouchbaseClient.CLIENT_ID_PROPERTY;
+
+ @Property(label = "Enabled", description = "Enable or disable couchbase caching.", boolValue = CouchbaseClientImpl.ENABLED_PROPERTY_DEFAULT)
+ static final String ENABLED_PROPERTY = "enabled";
+ private static final boolean ENABLED_PROPERTY_DEFAULT = true;
+
+ @Property(label = "Couchbase Hosts", description = "Couchbase cluster host list.", cardinality = Integer.MAX_VALUE)
+ static final String COUCHBASE_HOSTS_PROPERTY = "couchbaseHosts";
+
+ @Property(label = "Bucket Name", description = "Couchbase bucket name")
+ static final String CACHE_BUCKET_NAME_PROPERTY = "bucketName";
+
+ @Property(label = "Bucket Password", description = "Couchbase bucket password")
+ static final String CACHE_BUCKET_PASSWORD_PROPERTY = "bucketPassword";
+
+ private static final Logger log = LoggerFactory.getLogger(CouchbaseClientImpl.class);
+
+ private String clientId;
+ private boolean enabled;
+ private String bucketName;
+ private Cluster cluster;
+ private Bucket bucket;
+
+ @Activate
+ private void activate(Map<String, Object> config) {
+ clientId = PropertiesUtil.toString(config.get(CLIENT_ID_PROPERTY), null);
+ enabled = PropertiesUtil.toBoolean(config.get(ENABLED_PROPERTY), ENABLED_PROPERTY_DEFAULT);
+ if (!enabled) {
+ log.info("Couchbase caching for client '{}' is disabled by configuration.", clientId);
+ return;
+ }
+
+ String[] couchbaseHosts = PropertiesUtil.toStringArray(config.get(COUCHBASE_HOSTS_PROPERTY));
+ if (couchbaseHosts == null || couchbaseHosts.length == 0) {
+ enabled = false;
+ log.warn("No couchbase host configured, client '{}' is disabled.", clientId);
+ return;
+ }
+
+ bucketName = PropertiesUtil.toString(config.get(CACHE_BUCKET_NAME_PROPERTY), null);
+ String bucketPassword = PropertiesUtil.toString(config.get(CACHE_BUCKET_PASSWORD_PROPERTY), null);
+ if (bucketName == null) {
+ enabled = false;
+ log.warn("No couchbase bucket name configured, client '{}' is disabled.", clientId);
+ return;
+ }
+
+ try {
+ cluster = CouchbaseUtil.createCluster(couchbaseHosts);
+ bucket = CouchbaseUtil.openBucket(cluster, bucketName, bucketPassword);
+ }
+ catch (Throwable ex) {
+ enabled = false;
+ log.error("Unable to connect to couchbase cluster or open couchbase bucket, client '" + clientId + "' is disabled.", ex);
+ }
+ }
+
+ @Deactivate
+ private void deactivate() {
+ if (bucket != null) {
+ bucket.close();
+ bucket = null;
+ }
+ if (cluster != null) {
+ cluster.disconnect();
+ cluster = null;
+ }
+ }
+
+ public String getClientId() {
+ return clientId;
+ }
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public String getBucketName() {
+ return bucketName;
+ }
+
+ public Bucket getBucket() {
+ return bucket;
+ }
+
+ public AsyncBucket getAsyncBucket() {
+ return bucket.async();
+ }
+
+}
diff --git a/src/main/java/org/apache/sling/nosql/couchbase/client/impl/CouchbaseUtil.java b/src/main/java/org/apache/sling/nosql/couchbase/client/impl/CouchbaseUtil.java
new file mode 100644
index 0000000..523870c
--- /dev/null
+++ b/src/main/java/org/apache/sling/nosql/couchbase/client/impl/CouchbaseUtil.java
@@ -0,0 +1,63 @@
+/*
+ * 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.nosql.couchbase.client.impl;
+
+import com.couchbase.client.java.Bucket;
+import com.couchbase.client.java.Cluster;
+import com.couchbase.client.java.CouchbaseCluster;
+import com.couchbase.client.java.env.CouchbaseEnvironment;
+import com.couchbase.client.java.env.DefaultCouchbaseEnvironment;
+
+/**
+ * Manages couchbase environment.
+ */
+final class CouchbaseUtil {
+
+ private static final CouchbaseEnvironment COUCHBASE_ENVIRONMENT = DefaultCouchbaseEnvironment.builder().build();
+
+ private CouchbaseUtil() {
+ // static methods only
+ }
+
+ /**
+ * Create new couchbase cluster.
+ * @param hostNames Multiple hosts
+ * @return Couchbase cluster
+ */
+ public static Cluster createCluster(String... hostNames) {
+ return CouchbaseCluster.create(COUCHBASE_ENVIRONMENT, hostNames);
+ }
+
+ /**
+ * Open couchbase bucket.
+ * @param cluster Couchbase cluster
+ * @param bucketName Bucker name
+ * @param bucketPassword Bucker password (optional)
+ * @return Couchbase bucket
+ */
+ public static Bucket openBucket(Cluster cluster, String bucketName, String bucketPassword) {
+ if (bucketPassword == null) {
+ return cluster.openBucket(bucketName, bucketPassword);
+ }
+ else {
+ return cluster.openBucket(bucketName);
+ }
+ }
+
+}
diff --git a/src/main/java/org/apache/sling/nosql/couchbase/client/package-info.java b/src/main/java/org/apache/sling/nosql/couchbase/client/package-info.java
new file mode 100644
index 0000000..537c719
--- /dev/null
+++ b/src/main/java/org/apache/sling/nosql/couchbase/client/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+/**
+ * Couchbase Client Provider
+ */
+@aQute.bnd.annotation.Version("0.5.0")
+package org.apache.sling.nosql.couchbase.client;
+
diff --git a/src/test/java/org/apache/sling/nosql/couchbase/client/CouchbaseKeyTest.java b/src/test/java/org/apache/sling/nosql/couchbase/client/CouchbaseKeyTest.java
new file mode 100644
index 0000000..cd1a68b
--- /dev/null
+++ b/src/test/java/org/apache/sling/nosql/couchbase/client/CouchbaseKeyTest.java
@@ -0,0 +1,44 @@
+/*
+ * 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.nosql.couchbase.client;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.commons.lang3.StringUtils;
+import org.junit.Test;
+
+public class CouchbaseKeyTest {
+
+ private static final String PREFIX = "prefix:";
+
+ @Test
+ public void testShortKey() {
+ String key = CouchbaseKey.build("/short/key", PREFIX);
+ assertEquals(PREFIX + "/short/key", key);
+ }
+
+ @Test
+ public void testLongKey() {
+ String key = CouchbaseKey.build("/long/key/" + StringUtils.repeat("/aaa", 500), PREFIX);
+ assertTrue(StringUtils.startsWith(key, PREFIX + "/long/key/"));
+ assertEquals(CouchbaseKey.MAX_KEY_LENGTH, key.length());
+ }
+
+}
--
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.