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

com.fasterxml.clustermate.client.jdk.BaseJdkHttpAccessor Maven / Gradle / Ivy

Go to download

ClusterMate NetworkClient implementation built on default JDK-provided HTTP client (HTTPUrlConnection)

There is a newer version: 0.10.5
Show newest version
package com.fasterxml.clustermate.client.jdk;

import java.io.*;
import java.net.HttpURLConnection;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.storemate.shared.util.BufferRecycler;
import com.fasterxml.clustermate.api.*;
import com.fasterxml.clustermate.client.*;
import com.fasterxml.clustermate.client.cluster.ClusterServerNodeImpl;
import com.fasterxml.clustermate.std.JdkHttpClientPathBuilder;

/**
 * Intermediate base class used by accessors that use
 * Async HTTP Client library for HTTP Access.
 */
public abstract class BaseJdkHttpAccessor<
    K extends EntryKey,
    P extends Enum

// Path enumeration > extends Loggable { /** * Not sure what is optimal chunk size, but 16k sounds like * a reasonable starting point. */ protected final static int CHUNK_SIZE = 16 * 1024; /** * We can reuse read buffers as they are somewhat costly to * allocate, reallocate all the time. */ final protected static BufferRecycler _bufferRecycler = new BufferRecycler(CHUNK_SIZE); protected final ObjectMapper _mapper; protected final RequestPathStrategy

_pathFinder; protected final P _endpoint; protected EntryKeyConverter _keyConverter; @SuppressWarnings("unchecked") protected BaseJdkHttpAccessor(StoreClientConfig storeConfig, P endpoint) { super(); _mapper = storeConfig.getJsonMapper(); _endpoint = endpoint; _pathFinder = (RequestPathStrategy

) storeConfig.getPathStrategy(); _keyConverter = storeConfig.getKeyConverter(); } /* /********************************************************************** /* Simple HTTP helper methods /********************************************************************** */ protected long parseLongHeader(HttpURLConnection conn, String headerName) { String lenStr = conn.getHeaderField(headerName); if (lenStr == null) { return -1L; } lenStr = lenStr.trim(); if (lenStr.length() == 0) { return -1L; } try { return Long.parseLong(lenStr.trim()); } catch (NumberFormatException e) { String desc = (lenStr == null) ? "null" : "\""+lenStr+"\""; throw new IllegalArgumentException("Bad numeric value for header '"+headerName+"': "+desc); } } /* /********************************************************************** /* HTTP Request helpers /********************************************************************** */ /** * Helper method that encapsulates logic of setting various connection * settings, and then forcing sending of the request. */ protected int sendRequest(String method, HttpURLConnection conn, JdkHttpClientPathBuilder path, long timeoutMsecs) throws IOException { return initRequest(method, conn, path, timeoutMsecs).getResponseCode(); } protected HttpURLConnection initRequest(String method, HttpURLConnection conn, JdkHttpClientPathBuilder path, long timeoutMsecs) throws IOException { conn.setRequestMethod(method); // not optimal, will have to do: conn.setConnectTimeout((int) timeoutMsecs); conn.setReadTimeout((int) timeoutMsecs); path.addHeaders(conn); return conn; } protected JdkHttpClientPathBuilder addChecksum(JdkHttpClientPathBuilder path, int checksum) { return path.addParameter(ClusterMateConstants.QUERY_PARAM_CHECKSUM, (checksum == 0) ? "0" : String.valueOf(checksum)); } /* /********************************************************************** /* HTTP Response helpers /********************************************************************** */ /** * Helper method that takes care of processing state based on any * standard headers we might pick up */ protected void handleHeaders(ClusterServerNode server, HttpURLConnection conn, long requestTime) { String versionStr = conn.getHeaderField(ClusterMateConstants.CUSTOM_HTTP_HEADER_LAST_CLUSTER_UPDATE); if (versionStr != null && (versionStr = versionStr.trim()).length() > 0) { try { long l = Long.parseLong(versionStr); long responseTime = System.currentTimeMillis(); ((ClusterServerNodeImpl) server).updateLastClusterUpdateAvailable(l, requestTime, responseTime); } catch (Exception e) { logWarn("Invalid Cluster version String '"+versionStr+"' received from " +server.getAddress()); } } } protected ContentType findContentType(HttpURLConnection conn, ContentType defaultType) { String ctStr = conn.getContentType(); if (ctStr != null) { ctStr = ctStr.trim(); if (ctStr.length() > 0) { ContentType ct = ContentType.findType(ctStr); if (ct == null) { logWarn("Unrecognized Content-Type ('"+ctStr+"'); defaulting to: "+defaultType); } return ct; } } return defaultType; } /* /********************************************************************** /* HTTP content handling /********************************************************************** */ protected long copy(InputStream in, OutputStream out, boolean closeInput) throws IOException { final BufferRecycler.Holder bufferHolder = _bufferRecycler.getHolder(); final byte[] copyBuffer = bufferHolder.borrowBuffer(); try { long total = 0L; int count; while ((count = in.read(copyBuffer)) > 0) { out.write(copyBuffer, 0, count); total += count; } return total; } finally { bufferHolder.returnBuffer(copyBuffer); if (closeInput) { try { in.close(); } catch (IOException e0) { logError("Failed to close input: "+e0.getMessage()); } } } } protected void drain(HttpURLConnection conn, int statusCode) { try { if (statusCode >= 300) { // error drain(conn.getErrorStream()); } else { drain(conn.getInputStream()); } } catch (IOException e) { this.logWarn(e, "Problems closing response stream when draining"); } } protected void drain(InputStream in) { try { while (in.skip(8000) > 0) { } } catch (IOException e) { this.logWarn(e, "Problems draining stream"); } finally { try { in.close(); } catch (IOException e2) { this.logWarn(e2, "Problems closing response stream after draining"); } } } protected String getExcerpt(HttpURLConnection conn, int statusCode, int maxLen) { InputStream in = null; try { in = (statusCode >= 300) ? conn.getErrorStream() : conn.getInputStream(); if (in == null) { return "[N/A]"; } // NOTE: StoreMate has IOUtil, but won't take max length return getExcerpt(in, maxLen); } catch (Exception e) { return "[N/A due to error: "+e.getMessage()+"]"; } finally { if (in != null) { try { in.close(); } catch (IOException e2) { this.logWarn(e2, "Problems closing response stream after draining"); } } } } protected String getExcerpt(InputStream in, int maxLen) throws IOException { char[] buf = new char[maxLen]; int offset = 0; InputStreamReader r = new InputStreamReader(in, "UTF-8"); while (offset < buf.length) { int count = r.read(buf, offset, buf.length-offset); if (count <= 0) { break; } offset += count; } return new String(buf, 0, offset); } /* /********************************************************************** /* Other /********************************************************************** */ protected static Throwable _unwrap(Throwable t) { while (t.getCause() != null) { t = t.getCause(); } return t; } protected byte[] fromBase64(String b64str) { return _mapper.convertValue(b64str, byte[].class); } protected String toBase64(byte[] data) { return _mapper.convertValue(data, String.class); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy