org.hydracache.client.http.HttpHydraCacheClient.java Source code

Java tutorial

Introduction

Here is the source code for org.hydracache.client.http.HttpHydraCacheClient.java

Source

/*
 * Copyright 2008 the original author or authors.
 *
 * Licensed 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.hydracache.client.http;

import java.io.DataInputStream;
import java.io.IOException;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
import org.apache.commons.httpclient.methods.PutMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.log4j.Logger;
import org.hydracache.client.HydraCacheClient;
import org.hydracache.data.hashing.HashFunction;
import org.hydracache.data.hashing.NativeHashFunction;
import org.hydracache.data.partitioning.NodePartition;
import org.hydracache.io.Buffer;
import org.hydracache.protocol.data.codec.DefaultProtocolDecoder;
import org.hydracache.protocol.data.codec.DefaultProtocolEncoder;
import org.hydracache.protocol.data.codec.ProtocolDecoder;
import org.hydracache.protocol.data.codec.ProtocolEncoder;
import org.hydracache.protocol.data.marshaller.MessageMarshallerFactory;
import org.hydracache.protocol.data.message.BlobDataMessage;
import org.hydracache.protocol.data.message.DataMessage;
import org.hydracache.server.Identity;
import org.hydracache.server.IdentityMarshaller;
import org.hydracache.server.data.storage.Data;
import org.hydracache.server.data.versioning.IncrementVersionFactory;
import org.hydracache.server.harmony.core.Substance;

/**
 * Simple HTTP-based client that connects to a node partition.
 * 
 * @author Tan Quach (tquach@jointsource.com)
 * @since 1.0
 */
public class HttpHydraCacheClient implements HydraCacheClient {

    private static final String PROTOCOL = "http://";

    private static final Logger logger = Logger.getLogger(HttpHydraCacheClient.class);

    private final NodePartition<Identity> nodePartition;

    private HashFunction hashFunction;

    private HttpClient httpClient;

    private ProtocolEncoder<DataMessage> protocolEncoder;

    private ProtocolDecoder<DataMessage> protocolDecoder;

    /**
     * Construct a client instance referencing an existing {@link NodePartition}
     * .
     * 
     * @param connection
     *            The connection to the {@link Substance}.
     */
    public HttpHydraCacheClient(NodePartition<Identity> nodePartition) {
        this.nodePartition = nodePartition;
        this.hashFunction = new NativeHashFunction();
        this.httpClient = new HttpClient();

        IncrementVersionFactory versionMarshaller = new IncrementVersionFactory();
        versionMarshaller.setIdentityMarshaller(new IdentityMarshaller());

        protocolEncoder = new DefaultProtocolEncoder(new MessageMarshallerFactory(versionMarshaller));

        protocolDecoder = new DefaultProtocolDecoder(new MessageMarshallerFactory(versionMarshaller));
    }

    /**
     * @param httpClient
     *            the httpClient to set
     */
    public void setHttpClient(HttpClient httpClient) {
        this.httpClient = httpClient;
    }

    /**
     * @param hashFunction
     *            the hashFunction to set
     */
    public void setHashFunction(HashFunction hashFunction) {
        this.hashFunction = hashFunction;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.hydracache.connector.HydraCacheClient#get(java.lang.String)
     */
    @Override
    public Data get(Object key) {
        Identity identity = nodePartition.get(key);
        String uri = constructUri(key, identity);

        Data data = null;
        try {
            GetMethod getMethod = new GetMethod(uri);

            int responseCode = httpClient.executeMethod(getMethod);
            validateResponseCode(responseCode);

            DataMessage dataMessage = protocolDecoder
                    .decode(new DataInputStream(getMethod.getResponseBodyAsStream()));
            data = dataMessage.getData();

        } catch (IOException ioe) {
            logger.error("Cannot retrieve data.", ioe);
        }

        return data;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.hydracache.connector.HydraCacheClient#put(java.lang.String,
     * org.hydracache.server.data.storage.Data)
     */
    @Override
    public void put(Object key, Data data) {
        Identity identity = nodePartition.get(key);
        String uri = constructUri(key, identity);

        try {
            PutMethod putMethod = new PutMethod(uri);
            Buffer buffer = Buffer.allocate();
            protocolEncoder.encode(new BlobDataMessage(data), buffer.asDataOutpuStream());

            RequestEntity requestEntity = new InputStreamRequestEntity(buffer.asDataInputStream());
            putMethod.setRequestEntity(requestEntity);

            validateResponseCode(httpClient.executeMethod(putMethod));
        } catch (IOException ioe) {
            logger.error("Cannot write to connection.", ioe);
        }
    }

    /**
     * Validate the response code
     * 
     * @param executeMethod
     * @throws IOException
     */
    private void validateResponseCode(int rc) throws IOException {
        if (rc != HttpStatus.SC_OK && rc != HttpStatus.SC_CREATED)
            throw new IOException("Error HTTP response received: " + rc);
    }

    /**
     * @param key
     * @param identity
     * @return
     */
    private String constructUri(Object key, Identity identity) {
        StringBuffer uri = new StringBuffer();
        uri.append(PROTOCOL).append(identity.getAddress().getHostName()).append(":").append(identity.getPort())
                .append("/").append(hashFunction.hash(key));
        return uri.toString();
    }

}