All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.basho.riak.client.http.RiakClient Maven / Gradle / Ivy

/*
 * This file is provided 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 com.basho.riak.client.http;

import com.basho.riak.client.http.request.IndexRequest;
import com.basho.riak.client.http.request.MapReduceBuilder;
import com.basho.riak.client.http.request.RequestMeta;
import com.basho.riak.client.http.request.RiakWalkSpec;
import com.basho.riak.client.http.response.*;
import com.basho.riak.client.http.util.ClientHelper;
import com.basho.riak.client.http.util.Constants;
import org.apache.http.client.HttpClient;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.util.Map;
import java.util.Set;

/**
 * Primary interface for interacting with Riak via HTTP.
 */
public class RiakClient {

    private ClientHelper helper;

    /* (non-Javadoc)
     * @see com.basho.riak.client.HttpRiakClient#getConfig()
     */
    public RiakConfig getConfig() {
        return helper.getConfig();
    }

    public RiakClient(RiakConfig config) {
        this(config, null);
    }

    public RiakClient(RiakConfig config, String clientId) {
        helper = new ClientHelper(config, clientId);
    }

    public RiakClient(String url) {
        this(new RiakConfig(url), null);
    }

    public RiakClient(String url, String clientId) {
        this(new RiakConfig(url), clientId);
    }

    // Package protected constructor used for testing
    RiakClient(ClientHelper helper) {
        this.helper = helper;
    }

    /* (non-Javadoc)
     * @see com.basho.riak.client.HttpRiakClient#setBucketSchema(java.lang.String, com.basho.riak.client.RiakBucketInfo, com.basho.riak.client.request.RequestMeta)
     */
    public HttpResponse setBucketSchema(String bucket, RiakBucketInfo bucketInfo, RequestMeta meta) {
        JSONObject schema = null;
        try {
            schema = new JSONObject().put(Constants.FL_SCHEMA, bucketInfo.getSchema());
        } catch (JSONException unreached) {
            throw new IllegalStateException("wrapping valid json should be valid", unreached);
        }

        return helper.setBucketSchema(bucket, schema, meta);
    }

    /* (non-Javadoc)
     * @see com.basho.riak.client.HttpRiakClient#setBucketSchema(java.lang.String, com.basho.riak.client.RiakBucketInfo)
     */
    public HttpResponse setBucketSchema(String bucket, RiakBucketInfo bucketInfo) {
        return setBucketSchema(bucket, bucketInfo, null);
    }

    /* (non-Javadoc)
     * @see com.basho.riak.client.HttpRiakClient#getBucketSchema(java.lang.String, com.basho.riak.client.request.RequestMeta)
     */
    public BucketResponse getBucketSchema(String bucket, RequestMeta meta) {
        HttpResponse r = helper.getBucketSchema(bucket, meta);
        try {
            return getBucketResponse(r);
        } catch (JSONException e) {
            try {
                return new BucketResponse(helper.toss(new RiakResponseRuntimeException(r, e)));
            } catch (Exception e1) {
                throw new IllegalStateException(
                                                "helper.toss() returns a unsuccessful result, so BucketResponse shouldn't try to parse it or throw");
            }
        } catch (IOException e) {
            try {
                return new BucketResponse(helper.toss(new RiakIORuntimeException(e)));
            } catch (Exception e1) {
                throw new IllegalStateException(
                                                "helper.toss() returns a unsuccessful result, so BucketResponse shouldn't try to read it or throw");
            }
        }
    }

    public HttpResponse resetBucketSchema(String bucket) {
        return helper.resetBucketSchema(bucket);
    }
    
    /* (non-Javadoc)
     * @see com.basho.riak.client.HttpRiakClient#getBucketSchema(java.lang.String)
     */
    public BucketResponse getBucketSchema(String bucket) {
        return getBucketSchema(bucket, null);
    }

    /* (non-Javadoc)
     * @see com.basho.riak.client.HttpRiakClient#listBucket(java.lang.String, com.basho.riak.client.request.RequestMeta)
     */
    public BucketResponse listBucket(String bucket, RequestMeta meta) {
        return listBucket(bucket, meta, false);
    }

    /* (non-Javadoc)
     * @see com.basho.riak.client.HttpRiakClient#listBucket(java.lang.String)
     */
    public BucketResponse listBucket(String bucket) {
        return listBucket(bucket, null);
    }

    /* (non-Javadoc)
     * @see com.basho.riak.client.HttpRiakClient#streamBucket(java.lang.String, com.basho.riak.client.request.RequestMeta)
     */
    public BucketResponse streamBucket(String bucket, RequestMeta meta) {
        return listBucket(bucket, meta, true);
    }

    /* (non-Javadoc)
     * @see com.basho.riak.client.HttpRiakClient#streamBucket(java.lang.String)
     */
    public BucketResponse streamBucket(String bucket) {
        return streamBucket(bucket, null);
    }

    BucketResponse listBucket(String bucket, RequestMeta meta, boolean streamResponse) {
        HttpResponse r = helper.listBucket(bucket, meta, streamResponse);
        try {
            return getBucketResponse(r);
        } catch (JSONException e) {
            try {
                return new BucketResponse(helper.toss(new RiakResponseRuntimeException(r, e)));
            } catch (Exception e1) {
                throw new IllegalStateException(
                                                "helper.toss() returns a unsuccessful result, so BucketResponse shouldn't try to parse it or throw");
            }
        } catch (IOException e) {
            try {
                return new BucketResponse(helper.toss(new RiakIORuntimeException(e)));
            } catch (Exception e1) {
                throw new IllegalStateException(
                                                "helper.toss() returns a unsuccessful result, so BucketResponse shouldn't try to read it or throw");
            }
        }
    }

    /* (non-Javadoc)
     * @see com.basho.riak.client.HttpRiakClient#store(com.basho.riak.client.RiakObject, com.basho.riak.client.request.RequestMeta)
     */
    public StoreResponse store(RiakObject object, RequestMeta meta) {
        if (meta == null) {
            meta = new RequestMeta();
        }
        if (meta.getQueryParam(Constants.QP_RETURN_BODY) == null) {
            meta.setQueryParam(Constants.QP_RETURN_BODY, "true");
        }

        setAcceptHeader(meta);
        HttpResponse r = helper.store(object, meta);
        return new StoreResponse(new FetchResponse(r, this));
    }

    /**
     * Ensure that Accept header includes
     * {@link Constants#CTYPE_MULTIPART_MIXED} so that we may parse siblings
     * correctly.
     * 
     * @param meta
     */
    private void setAcceptHeader(RequestMeta meta) {
        String accept = meta.getHeader(Constants.HDR_ACCEPT);
        if (accept == null) {
            meta.setHeader(Constants.HDR_ACCEPT, Constants.CTYPE_ANY + ", " + Constants.CTYPE_MULTIPART_MIXED);
        } else {
            meta.setHeader(Constants.HDR_ACCEPT, accept + ", " + Constants.CTYPE_MULTIPART_MIXED);
        }
    }

    /* (non-Javadoc)
     * @see com.basho.riak.client.HttpRiakClient#store(com.basho.riak.client.RiakObject)
     */
    public StoreResponse store(RiakObject object) {
        return store(object, null);
    }

    /**
     * Fetch metadata (e.g. vclock, last modified, vtag) for the
     * {@link RiakObject} stored at bucket and key.
     * 

* NOTE: if there a sibling values (HTTP status code 300), then a full * {@link RiakClient#fetch(String, String, RequestMeta)} is executed as well * to get all meta values. Examine the {@link FetchResponse#hasSiblings()} * value to determine if you need to perform conflict resolution. *

* * @param bucket * The bucket containing the {@link RiakObject} to fetch. * @param key * The key of the {@link RiakObject} to fetch. * @param meta * Extra metadata to attach to the request such as an r- value * for the request, HTTP headers, and other query parameters. See * {@link RequestMeta#readParams(int)}. * * @return {@link FetchResponse} containing HTTP response information and a * {@link RiakObject} containing only metadata and no value. * * @throws RiakIORuntimeException * If an error occurs during communication with the Riak server. * @throws RiakResponseRuntimeException * If the Riak server returns a malformed response. */ public FetchResponse fetchMeta(String bucket, String key, RequestMeta meta) { try { if (meta == null) { meta = new RequestMeta(); } setAcceptHeader(meta); HttpResponse resp = helper.fetchMeta(bucket, key, meta); if (resp.getStatusCode() != 300) { return getFetchResponse(resp); } else { return fetch(bucket, key, meta); } } catch (RiakResponseRuntimeException e) { return new FetchResponse(helper.toss(e), this); } } /* (non-Javadoc) * @see com.basho.riak.client.HttpRiakClient#fetchMeta(java.lang.String, java.lang.String) */ public FetchResponse fetchMeta(String bucket, String key) { return fetchMeta(bucket, key, null); } public FetchResponse fetch(String bucket, String key, RequestMeta meta) { return fetch(bucket, key, meta, false); } public FetchResponse fetch(String bucket, String key) { return fetch(bucket, key, null, false); } /** * Similar to fetch(), except the HTTP connection is left open for * successful responses, and the Riak response is provided as a stream. * The user must remember to call {@link FetchResponse#close()} on the * return value. * * @param bucket * The bucket containing the {@link RiakObject} to fetch. * @param key * The key of the {@link RiakObject} to fetch. * @param meta * Extra metadata to attach to the request such as an r value * for the request, HTTP headers, and other query parameters. See * RequestMeta.readParams(). * * @return A streaming {@link FetchResponse} containing HTTP response * information and the response stream. The HTTP connection must be * closed manually by the user by calling * {@link FetchResponse#close()}. */ public FetchResponse stream(String bucket, String key, RequestMeta meta) { return fetch(bucket, key, meta, true); } public FetchResponse stream(String bucket, String key) { return fetch(bucket, key, null, true); } FetchResponse fetch(String bucket, String key, RequestMeta meta, boolean streamResponse) { if (meta == null) { meta = new RequestMeta(); } setAcceptHeader(meta); HttpResponse r = helper.fetch(bucket, key, meta, streamResponse); try { return getFetchResponse(r); } catch (RiakResponseRuntimeException e) { return new FetchResponse(helper.toss(e), this); } } /* (non-Javadoc) * @see com.basho.riak.client.HttpRiakClient#stream(java.lang.String, java.lang.String, com.basho.riak.client.response.StreamHandler, com.basho.riak.client.request.RequestMeta) */ public boolean stream(String bucket, String key, StreamHandler handler, RequestMeta meta) throws IOException { return helper.stream(bucket, key, handler, meta); } /* (non-Javadoc) * @see com.basho.riak.client.HttpRiakClient#delete(java.lang.String, java.lang.String, com.basho.riak.client.request.RequestMeta) */ public HttpResponse delete(String bucket, String key, RequestMeta meta) { return helper.delete(bucket, key, meta); } /* (non-Javadoc) * @see com.basho.riak.client.HttpRiakClient#delete(java.lang.String, java.lang.String) */ public HttpResponse delete(String bucket, String key) { return delete(bucket, key, null); } /* (non-Javadoc) * @see com.basho.riak.client.HttpRiakClient#walk(java.lang.String, java.lang.String, java.lang.String, com.basho.riak.client.request.RequestMeta) */ public WalkResponse walk(String bucket, String key, String walkSpec, RequestMeta meta) { HttpResponse r = helper.walk(bucket, key, walkSpec, meta); try { return getWalkResponse(r); } catch (RiakResponseRuntimeException e) { return new WalkResponse(helper.toss(e), this); } } /* (non-Javadoc) * @see com.basho.riak.client.HttpRiakClient#walk(java.lang.String, java.lang.String, java.lang.String) */ public WalkResponse walk(String bucket, String key, String walkSpec) { return walk(bucket, key, walkSpec, null); } /* (non-Javadoc) * @see com.basho.riak.client.HttpRiakClient#walk(java.lang.String, java.lang.String, com.basho.riak.client.request.RiakWalkSpec) */ public WalkResponse walk(String bucket, String key, RiakWalkSpec walkSpec) { return walk(bucket, key, walkSpec.toString(), null); } /* (non-Javadoc) * @see com.basho.riak.client.HttpRiakClient#mapReduce(java.lang.String, com.basho.riak.client.request.RequestMeta) */ public MapReduceResponse mapReduce(String job, RequestMeta meta) { HttpResponse r = helper.mapReduce(job, meta); try { return getMapReduceResponse(r); } catch (JSONException e) { helper.toss(new RiakResponseRuntimeException(r, e)); return null; } } /* (non-Javadoc) * @see com.basho.riak.client.HttpRiakClient#mapReduce(java.lang.String) */ public MapReduceResponse mapReduce(String job) { return mapReduce(job, null); } /* (non-Javadoc) * @see com.basho.riak.client.HttpRiakClient#mapReduceOverBucket(java.lang.String) */ public MapReduceBuilder mapReduceOverBucket(String bucket) { return new MapReduceBuilder(this).setBucket(bucket); } /** * Same as {@link RiakClient#mapReduceOverBucket(String)}, except over a set * of objects instead of a bucket. * * @param objects * A set of objects represented as a map of { bucket : [ list of * keys in bucket ] } * * @return A {@link MapReduceBuilder} to build the map reduce job */ public MapReduceBuilder mapReduceOverObjects(Map> objects) { return new MapReduceBuilder(this).setRiakObjects(objects); } /** * Same as {@link RiakClient#mapReduceOverBucket(String)}, except over a * riak-search query instead of a bucket. * * @param bucket * The bucket to perform the riak-search over * @param search * The query that riak-search will execute * @return A {@link MapReduceBuilder} to build the map reduce job */ public MapReduceBuilder mapReduceOverSearch(String bucket, String search) { return new MapReduceBuilder(this).setBucket(bucket).setSearch(search); } /* (non-Javadoc) * @see com.basho.riak.client.HttpRiakClient#getExceptionHandler() */ public RiakExceptionHandler getExceptionHandler() { return helper.getExceptionHandler(); } /* (non-Javadoc) * @see com.basho.riak.client.HttpRiakClient#setExceptionHandler(com.basho.riak.client.response.RiakExceptionHandler) */ public void setExceptionHandler(RiakExceptionHandler exceptionHandler) { helper.setExceptionHandler(exceptionHandler); } /* (non-Javadoc) * @see com.basho.riak.client.HttpRiakClient#getHttpClient() */ public HttpClient getHttpClient() { return helper.getHttpClient(); } /* (non-Javadoc) * @see com.basho.riak.client.HttpRiakClient#getClientId() */ public byte[] getClientId() { return helper.getClientId(); } /* (non-Javadoc) * @see com.basho.riak.client.HttpRiakClient#setClientId(java.lang.String) */ public void setClientId(String clientId) { helper.setClientId(clientId); } // Encapsulate response creation so it can be stubbed for testing BucketResponse getBucketResponse(HttpResponse r) throws JSONException, IOException { return new BucketResponse(r); } FetchResponse getFetchResponse(HttpResponse r) throws RiakResponseRuntimeException { return new FetchResponse(r, this); } WalkResponse getWalkResponse(HttpResponse r) throws RiakResponseRuntimeException { return new WalkResponse(r, this); } MapReduceResponse getMapReduceResponse(HttpResponse r) throws JSONException { return new MapReduceResponse(r); } /** * Fetch a list of all the buckets in Riak * * @return a {@link ListBucketsResponse} * @throws IOException * @throws JSONException */ public ListBucketsResponse listBuckets(boolean streaming) { HttpResponse r = helper.listBuckets(streaming); try { return new ListBucketsResponse(r); } catch (JSONException e) { try { return new ListBucketsResponse(helper.toss(new RiakResponseRuntimeException(r, e))); } catch (Exception e1) { throw new IllegalStateException( "helper.toss() returns a unsuccessful result, so BucketResponse shouldn't try to parse it or throw"); } } catch (IOException e) { try { return new ListBucketsResponse(helper.toss(new RiakIORuntimeException(e))); } catch (Exception e1) { throw new IllegalStateException( "helper.toss() returns a unsuccessful result, so BucketResponse shouldn't try to read it or throw"); } } } /** * GET Riak's ping resource. * * @return an {@link HttpResponse} with the result of GET */ public HttpResponse ping() { return helper.ping(); } /** * GET Riak's /stats (status) resource. * * @return an {@link HttpResponse} with the result of GET */ public HttpResponse stats() { return helper.stats(); } /** * Fetch the keys for index with value * * @param bucket * the bucket * @param indexName * the name of the index (e.g. 'user_bin') * @param value * the value of the index * @return an {@link IndexResponse} */ public IndexResponse index(String bucket, String indexName, String value) { return makeIndexResponse(helper.fetchIndex(bucket, indexName, new String[] { value })); } /** * Fetch the keys for index with value * * @param bucket * the bucket * @param indexName * index name (e.g. 'age_int') * @param value * an int for the index value * @return {@link IndexResponse} */ public IndexResponse index(String bucket, String indexName, long value) { return makeIndexResponse(helper.fetchIndex(bucket, indexName, new long[] { value })); } /** * A range index query matching a binary index from start to * end * * @param bucket * the bucket * @param indexName * the index (e.g. 'username_bin') * @param start * the start value in a range (e.g 'a') * @param end * the end value in a range (e.g. 'z') * @return an {@link IndexResponse} */ public IndexResponse index(String bucket, String indexName, String start, String end) { return makeIndexResponse(helper.fetchIndex(bucket, indexName, new String[] { start, end })); } /** * A range index query matching a int index from start to * end * * @param bucket * the bucket * @param indexName * the index (e.g. 'age_int') * @param start * the start value in a range (e.g 16) * @param end * the end value in a range (e.g. 32) * @return an {@link IndexResponse} */ public IndexResponse index(String bucket, String indexName, long start, long end) { return makeIndexResponse(helper.fetchIndex(bucket, indexName, new long[] { start, end })); } /** * Create an {@link IndexResponse} from the given {@link HttpResponse} * * @param r * an {@link HttpResponse} from an index query * @return an {@link IndexResponse} */ private IndexResponse makeIndexResponse(HttpResponse r) { try { return new IndexResponse(r); } catch (JSONException e) { try { return new IndexResponse(helper.toss(new RiakResponseRuntimeException(r, e))); } catch (Exception e1) { throw new IllegalStateException( "helper.toss() returns a unsuccessful result, so BucketResponse shouldn't try to parse it or throw"); } } } public IndexResponseV2 index(IndexRequest request) { HttpResponse r = helper.fetchIndex(request); try { return new IndexResponseV2(request, r); } catch (JSONException e) { try { return new IndexResponseV2(request, helper.toss(new RiakResponseRuntimeException(r, e))); } catch (Exception e1) { throw new IllegalStateException("helper.toss() returns a unsuccessful result, so IndexResponseV2 shouldn't try to parse it or throw"); } } } public Long incrementCounter(String bucket, String counter, long increment, RequestMeta meta) { if (null == meta) { meta = new RequestMeta(); } setAcceptHeader(meta); HttpResponse r = helper.incrementCounter(bucket, counter, increment, meta); return parseCounterResponse(r); } public Long fetchCounter(String bucket, String counter, RequestMeta meta) { if (null == meta) { meta = new RequestMeta(); } setAcceptHeader(meta); HttpResponse r = helper.fetchCounter(bucket, counter, meta); return parseCounterResponse(r); } private Long parseCounterResponse(HttpResponse resp) { if (resp.isError() && resp.getStatusCode() != 404) { helper.toss(new RiakResponseRuntimeException(resp)); return null; } else if (resp.getStatusCode() == 404) { return null; } else { if (resp.getBodyAsString() != null) { return Long.parseLong(resp.getBodyAsString()); } else { // An increment without returnvalue will return an empty result return null; } } } public void shutdown() { } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy