Java tutorial
/* * 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.raw.http; import static com.basho.riak.client.raw.http.ConversionUtil.convert; import java.io.IOException; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import org.apache.http.HttpStatus; import com.basho.riak.client.IRiakObject; import com.basho.riak.client.bucket.BucketProperties; import com.basho.riak.client.cap.ClientId; import com.basho.riak.client.http.RiakClient; import com.basho.riak.client.http.request.RequestMeta; import com.basho.riak.client.http.response.BucketResponse; import com.basho.riak.client.http.response.FetchResponse; import com.basho.riak.client.http.response.HttpResponse; import com.basho.riak.client.http.response.IndexResponse; import com.basho.riak.client.http.response.ListBucketsResponse; import com.basho.riak.client.http.response.MapReduceResponse; import com.basho.riak.client.http.response.StoreResponse; import com.basho.riak.client.http.response.WithBodyResponse; import com.basho.riak.client.query.MapReduceResult; import com.basho.riak.client.query.NodeStats; import com.basho.riak.client.query.WalkResult; import com.basho.riak.client.raw.DeleteMeta; import com.basho.riak.client.raw.FetchMeta; import com.basho.riak.client.raw.MatchFoundException; import com.basho.riak.client.raw.ModifiedException; import com.basho.riak.client.raw.RawClient; import com.basho.riak.client.raw.RiakResponse; import com.basho.riak.client.raw.StoreMeta; import com.basho.riak.client.raw.Transport; import com.basho.riak.client.raw.query.LinkWalkSpec; import com.basho.riak.client.raw.query.MapReduceSpec; import com.basho.riak.client.raw.query.MapReduceTimeoutException; import com.basho.riak.client.raw.query.indexes.IndexQuery; import com.basho.riak.client.raw.query.indexes.IndexWriter; import com.basho.riak.client.util.CharsetUtils; import org.codehaus.jackson.map.ObjectMapper; /** * Adapts the http.{@link RiakClient} to the new {@link RawClient} interface. * * @author russell * */ public class HTTPClientAdapter implements RawClient { private final RiakClient client; /** * Create an instance of the adapter that delegates all API calls to <code>client</code> * @param client the {@link RiakClient} to delegate to. */ public HTTPClientAdapter(final RiakClient client) { this.client = client; } /** * Convenience constructor that delegates to * {@link RiakClient#RiakClient(String)} to create a {@link RiakClient} to * adapt * * @param url * of the riak REST interface */ public HTTPClientAdapter(String url) { this(new RiakClient(url)); } /** * NOTE: returns the values *if* siblings are present * * @see com.basho.riak.client.raw.RawClient#head(java.lang.String, * java.lang.String) */ public RiakResponse head(String bucket, String key, FetchMeta fetchMeta) throws IOException { if (bucket == null || bucket.trim().equals("")) { throw new IllegalArgumentException( "bucket must not be null and bucket.getName() must not be null or empty " + "or just whitespace."); } if (key == null || key.trim().equals("")) { throw new IllegalArgumentException("Key cannot be null or empty or just whitespace"); } if (fetchMeta == null) { fetchMeta = FetchMeta.head(); } else { fetchMeta = new FetchMeta(fetchMeta.getR(), fetchMeta.getPr(), fetchMeta.getNotFoundOK(), fetchMeta.getBasicQuorum(), true, fetchMeta.getReturnDeletedVClock(), fetchMeta.getIfModifiedSince(), fetchMeta.getIfModifiedVClock()); } RequestMeta rm = convert(fetchMeta); FetchResponse resp = client.fetchMeta(bucket, key, rm); return handleBodyResponse(resp); } /* * (non-Javadoc) * * @see * com.basho.riak.client.raw.RawClient#fetch(com.basho.riak.newapi.bucket * .Bucket, java.lang.String) */ public RiakResponse fetch(String bucket, String key) throws IOException { if (bucket == null || bucket.trim().equals("")) { throw new IllegalArgumentException( "bucket must not be null and bucket.getName() must not be null or empty " + "or just whitespace."); } if (key == null || key.trim().equals("")) { throw new IllegalArgumentException("Key cannot be null or empty or just whitespace"); } FetchResponse resp = client.fetch(bucket, key); return handleBodyResponse(resp); } /* * (non-Javadoc) * * @see * com.basho.riak.client.raw.RawClient#fetch(com.basho.riak.newapi.bucket * .Bucket, java.lang.String, int) */ public RiakResponse fetch(String bucket, String key, int readQuorum) throws IOException { if (bucket == null || bucket.trim().equals("")) { throw new IllegalArgumentException( "bucket must not be null and bucket.getName() must not be null or empty " + "or just whitespace."); } if (key == null || key.trim().equals("")) { throw new IllegalArgumentException("Key cannot be null or empty or just whitespace"); } FetchResponse resp = client.fetch(bucket, key, RequestMeta.readParams(readQuorum)); return handleBodyResponse(resp); } /* * (non-Javadoc) * * @see com.basho.riak.client.raw.RawClient#fetch(java.lang.String, * java.lang.String, com.basho.riak.client.raw.FetchMeta) */ public RiakResponse fetch(String bucket, String key, FetchMeta fetchMeta) throws IOException { if (bucket == null || bucket.trim().equals("")) { throw new IllegalArgumentException( "bucket must not be null and bucket.getName() must not be null or empty " + "or just whitespace."); } if (key == null || key.trim().equals("")) { throw new IllegalArgumentException("Key cannot be null or empty or just whitespace"); } RequestMeta rm = convert(fetchMeta); FetchResponse resp = client.fetch(bucket, key, rm); return handleBodyResponse(resp); } /** * For all those fetch/store methods that may return an actual data payload. * @param resp a {@link WithBodyResponse} * @return a {@link RiakResponse} with the data items copied from <code>resp</code> * @see ConversionUtil#convert(java.util.Collection) */ private RiakResponse handleBodyResponse(WithBodyResponse resp) { boolean unmodified = resp.getStatusCode() == HttpStatus.SC_NOT_MODIFIED; RiakResponse response = RiakResponse.empty(unmodified); IRiakObject[] values = new IRiakObject[] {}; if (resp.hasSiblings()) { values = convert(resp.getSiblings()); } else if (resp.hasObject() && !unmodified) { values = new IRiakObject[] { convert(resp.getObject()) }; } if (values.length > 0) { response = new RiakResponse(CharsetUtils.utf8StringToBytes(resp.getVclock()), values); } else { if (resp.getVclock() != null) { // a deleted vclock response = new RiakResponse(CharsetUtils.utf8StringToBytes(resp.getVclock())); } } return response; } /* * (non-Javadoc) * * @see * com.basho.riak.client.raw.RawClient#store(com.basho.riak.newapi.RiakObject * , com.basho.riak.client.raw.StoreMeta) */ public RiakResponse store(IRiakObject object, StoreMeta storeMeta) throws IOException { if (object == null || object.getBucket() == null) { throw new IllegalArgumentException("cannot store a null RiakObject, or a RiakObject without a bucket"); } RiakResponse response = RiakResponse.empty(); com.basho.riak.client.http.RiakObject riakObject = convert(object, client); RequestMeta requestMeta = convert(storeMeta); StoreResponse resp = client.store(riakObject, requestMeta); if (!resp.isSuccess()) { if (resp.getStatusCode() == HttpStatus.SC_PRECONDITION_FAILED) { if (storeMeta.hasIfNoneMatch() && storeMeta.getIfNoneMatch()) { throw new MatchFoundException(); } else if (storeMeta.hasIfNotModified() && storeMeta.getIfNotModified()) { throw new ModifiedException(); } } throw new IOException(resp.getStatusCode() + " " + resp.getBodyAsString()); } if (storeMeta.hasReturnBody() && storeMeta.getReturnBody()) { response = handleBodyResponse(resp); } else if (storeMeta.hasReturnHead() && storeMeta.getReturnHead()) { // fake a returnHead by doing a head fetch now FetchResponse fr = client.fetchMeta(object.getBucket(), object.getKey()); response = handleBodyResponse(fr); } return response; } /* * (non-Javadoc) * * @see * com.basho.riak.client.raw.RawClient#store(com.basho.riak.newapi.RiakObject * ) */ public void store(IRiakObject object) throws IOException { store(object, StoreMeta.empty()); } /* * (non-Javadoc) * * @see * com.basho.riak.client.raw.RawClient#delete(com.basho.riak.newapi.bucket * .Bucket, java.lang.String) */ public void delete(String bucket, String key) throws IOException { HttpResponse resp = client.delete(bucket, key); if (!resp.isSuccess()) { throw new IOException(resp.getBodyAsString()); } } /* * (non-Javadoc) * * @see * com.basho.riak.client.raw.RawClient#delete(com.basho.riak.newapi.bucket * .Bucket, java.lang.String, int) */ public void delete(String bucket, String key, int deleteQuorum) throws IOException { HttpResponse resp = client.delete(bucket, key, RequestMeta.deleteParams(deleteQuorum)); if (!resp.isSuccess()) { throw new IOException(resp.getBodyAsString()); } } /* (non-Javadoc) * @see com.basho.riak.client.raw.RawClient#delete(java.lang.String, java.lang.String, com.basho.riak.client.raw.DeleteMeta) */ public void delete(String bucket, String key, DeleteMeta deleteMeta) throws IOException { HttpResponse resp = client.delete(bucket, key, convert(deleteMeta)); if (!resp.isSuccess()) { throw new IOException(resp.getBodyAsString()); } } /* * (non-Javadoc) * * @see com.basho.riak.client.raw.RawClient#listBuckets() */ public Set<String> listBuckets() throws IOException { final ListBucketsResponse lbr = client.listBuckets(); if (!lbr.isSuccess()) { throw new IOException("List Buckets failed with status code: " + lbr.getStatusCode()); } return new HashSet<String>(lbr.getBuckets()); } /* * (non-Javadoc) * * @see com.basho.riak.client.raw.RawClient#fetchBucket(java.lang.String) */ public BucketProperties fetchBucket(String bucketName) throws IOException { if (bucketName == null || bucketName.trim().equals("")) { throw new IllegalArgumentException("bucketName cannot be null, empty or all whitespace"); } BucketResponse response = client.getBucketSchema(bucketName, null); return convert(response); } /* * (non-Javadoc) * * @see com.basho.riak.client.raw.RawClient#updateBucket(java.lang.String, * com.basho.riak.newapi.bucket.BucketProperties) */ public void updateBucket(String name, BucketProperties bucketProperties) throws IOException { HttpResponse response = client.setBucketSchema(name, convert(bucketProperties)); if (!response.isSuccess()) { throw new IOException(response.getBodyAsString()); } } /* * (non-Javadoc) * * @see * com.basho.riak.client.raw.RawClient#fetchBucketKeys(java.lang.String) */ public Iterable<String> listKeys(String bucketName) throws IOException { final BucketResponse bucketResponse = client.streamBucket(bucketName); if (bucketResponse.isSuccess()) { final KeySource keyStream = new KeySource(bucketResponse); return new Iterable<String>() { public Iterator<String> iterator() { return keyStream; } }; } else { throw new IOException("stream keys for bucket " + bucketName + " failed with response code : " + bucketResponse.getStatusCode() + ", body: " + bucketResponse.getBodyAsString()); } } /* * (non-Javadoc) * * @see * com.basho.riak.client.raw.RawClient#linkWalk(com.basho.riak.client.raw.query.LinkWalkSpec) */ public WalkResult linkWalk(final LinkWalkSpec linkWalkSpec) throws IOException { final String walkSpecString = convert(linkWalkSpec); return convert(client.walk(linkWalkSpec.getStartBucket(), linkWalkSpec.getStartKey(), walkSpecString)); } /* * (non-Javadoc) * * @see * com.basho.riak.client.raw.RawClient#mapReduce(com.basho.riak.newapi.query * .MapReduceSpec) */ public MapReduceResult mapReduce(MapReduceSpec spec) throws IOException, MapReduceTimeoutException { MapReduceResponse resp = client.mapReduce(spec.getJSON()); return convert(resp); } /* * (non-Javadoc) * * @see com.basho.riak.client.raw.RawClient#generateAndSetClientId() */ public byte[] generateAndSetClientId() throws IOException { setClientId(ClientId.generate()); return client.getClientId(); } /* * (non-Javadoc) * * @see com.basho.riak.client.raw.RawClient#setClientId(byte[]) */ public void setClientId(byte[] clientId) throws IOException { if (clientId == null || clientId.length != 4) { throw new IllegalArgumentException( "clientId must be 4 bytes. generateAndSetClientId() can do this for you"); } client.setClientId(CharsetUtils.asString(clientId, CharsetUtils.ISO_8859_1)); } /* * (non-Javadoc) * * @see com.basho.riak.client.raw.RawClient#getClientId() */ public byte[] getClientId() throws IOException { return client.getClientId(); } /* (non-Javadoc) * @see com.basho.riak.client.raw.RawClient#ping() */ public void ping() throws IOException { HttpResponse resp = client.ping(); if (!resp.isSuccess()) { throw new IOException(resp.getBodyAsString()); } } /* * (non-Javadoc) * * @see * com.basho.riak.client.raw.RawClient#fetchIndex(com.basho.riak.client. * raw.query.IndexQuery) */ public List<String> fetchIndex(IndexQuery indexQuery) throws IOException { final ResultCapture<IndexResponse> res = new ResultCapture<IndexResponse>(); IndexWriter executor = new IndexWriter() { public void write(String bucket, String index, String from, String to) throws IOException { res.capture(client.index(bucket, index, from, to)); } public void write(final String bucket, final String index, final String value) throws IOException { res.capture(client.index(bucket, index, value)); } public void write(final String bucket, final String index, final int value) throws IOException { res.capture(client.index(bucket, index, value)); } public void write(final String bucket, final String index, final int from, final int to) throws IOException { res.capture(client.index(bucket, index, from, to)); } }; indexQuery.write(executor); return convert(res.get()); } /* (non-Javadoc) * @see com.basho.riak.client.raw.RawClient#getTransport() */ public Transport getTransport() { return Transport.HTTP; } public void shutdown() { client.shutdown(); } /* (non-Javadoc) * @see com.basho.riak.client.raw.RawClient#stats() */ public NodeStats stats() throws IOException { HttpResponse r = client.stats(); if (!r.isSuccess()) { throw new IOException("stats failed with status code: " + r.getStatusCode()); } else { try { return new ObjectMapper().readValue(r.getBodyAsString(), NodeStats.class); } catch (IOException e) { throw new IOException("Could not parse stats JSON response, body: " + r.getBodyAsString(), e); } } } }