com.getperka.flatpack.client.impl.RequestBase Maven / Gradle / Ivy
/*
* #%L
* FlatPack Client
* %%
* Copyright (C) 2012 Perka Inc.
* %%
* 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.
* #L%
*/
package com.getperka.flatpack.client.impl;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URLEncoder;
import java.util.Collections;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.getperka.flatpack.client.Request;
import com.getperka.flatpack.util.FlatPackCollections;
abstract class RequestBase, X> implements Request {
private static final Pattern pathArgPattern = Pattern.compile("[{][^}]*[}]");
private final ApiBase api;
private final Object[] args;
private Object entity;
private Map headers = Collections.emptyMap();
private final String method;
private final String path;
private Map queryParams = Collections.emptyMap();
private final boolean hasPayload;
protected RequestBase(ApiBase api, String method, String path, boolean hasPayload, Object... args) {
this.api = api;
this.args = args;
this.method = method;
this.path = path;
this.hasPayload = hasPayload;
}
@Override
public X execute() throws IOException {
String replacedPath = path;
// Replace all {foo} in the path with the args
Matcher m = pathArgPattern.matcher(replacedPath);
int index = 0;
while (m.find() && index < args.length) {
replacedPath = m.replaceFirst(args[index++].toString());
m = pathArgPattern.matcher(replacedPath);
}
StringBuilder sb = new StringBuilder(replacedPath);
// Now add query parameters
if (!queryParams.isEmpty()) {
sb.append("?");
boolean needsAmp = false;
for (Map.Entry entry : queryParams.entrySet()) {
if (needsAmp) {
sb.append("&");
} else {
needsAmp = true;
}
sb.append(entry.getKey()).append("=")
.append(URLEncoder.encode(entry.getValue().toString(), "UTF8"));
}
}
URI sendTo = api.getServerBase().resolve(sb.toString());
HttpURLConnection conn = (HttpURLConnection) sendTo.toURL().openConnection();
conn.setDoOutput(hasPayload);
conn.setRequestMethod(method);
for (Map.Entry entry : headers.entrySet()) {
conn.setRequestProperty(entry.getKey(), entry.getValue().toString());
}
conn = api.filter(conn);
writeEntity(conn);
return execute(conn);
}
public Object getEntity() {
return entity;
}
@Override
public R header(String name, Object value) {
if (headers.isEmpty()) {
headers = FlatPackCollections.mapForIteration();
}
headers.put(name, value);
return as();
}
@Override
public R queryParameter(String name, Object value) {
if (queryParams.isEmpty()) {
queryParams = FlatPackCollections.mapForIteration();
}
queryParams.put(name, value);
return as();
}
public void setEntity(Object entity) {
this.entity = entity;
}
@SuppressWarnings("unchecked")
protected R as() {
return (R) this;
}
protected abstract X execute(HttpURLConnection response) throws IOException;
protected ApiBase getApi() {
return api;
}
/**
* Returns {@code true} for a 2XX series response code.
*/
protected boolean isOk(int statusCode) {
return statusCode >= 200 && statusCode < 300;
}
protected abstract void writeEntity(HttpURLConnection connection) throws IOException;
}