Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
168 changes: 90 additions & 78 deletions src/main/java/nl/stil4m/transmission/rpc/RpcClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import nl.stil4m.transmission.http.RequestExecutorException;

import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
Expand All @@ -16,82 +18,92 @@

public class RpcClient {

private final RpcConfiguration configuration;
private final ObjectMapper objectMapper;
private final Map<String, String> headers;
private final DefaultHttpClient defaultHttpClient = new DefaultHttpClient();

private final RequestExecutor requestExecutor;

public RpcClient(RpcConfiguration configuration, ObjectMapper objectMapper) {
this.requestExecutor = new RequestExecutor(objectMapper, configuration, defaultHttpClient);
this.configuration = configuration;
this.objectMapper = objectMapper;
headers = new HashMap<>();
}

public <T, V> void execute(RpcCommand<T, V> command, Map<String, String> h) throws RpcException {
try {
executeCommandInner(command, h);
} catch (RequestExecutorException | IOException e) {
throw new RpcException(e);
} catch (InvalidResponseStatus e) {
setup();
try {
executeCommandInner(command, h);
} catch (Exception | RequestExecutorException | InvalidResponseStatus inner) {
throw new RpcException(inner);
}
}
}

private <T, V> void executeCommandInner(RpcCommand<T, V> command, Map<String, String> h) throws RequestExecutorException, InvalidResponseStatus, IOException, RpcException {
for (Map.Entry<String, String> entry : h.entrySet()) {
requestExecutor.removeAllHeaders();
requestExecutor.configureHeader(entry.getKey(), entry.getValue());
}

RpcRequest<T> request = command.buildRequestPayload();
RpcResponse<V> response = requestExecutor.execute(request, RpcResponse.class, 200);

Map args = (Map) response.getArguments();
String stringValue = objectMapper.writeValueAsString(args);
response.setArguments((V) objectMapper.readValue(stringValue, command.getArgumentsObject()));
if (!command.getTag().equals(response.getTag())) {
throw new RpcException(String.format("Invalid response tag. Expected %d, but got %d", command.getTag(), request.getTag()));
}
command.setResponse(response);

if (!"success".equals(response.getResult())) {
throw new RpcException("Rpc Command Failed: " + response.getResult(), command);
}
}

private void setup() throws RpcException {
try {
DefaultHttpClient defaultHttpClient = getClient();
HttpPost httpPost = createPost();
HttpResponse result = defaultHttpClient.execute(httpPost);
putSessionHeader(result);
EntityUtils.consume(result.getEntity());
} catch (IOException e) {
throw new RpcException(e);
}
}

protected HttpPost createPost() {
return new HttpPost(configuration.getHost());
}

protected DefaultHttpClient getClient() {
return defaultHttpClient;
}

public void executeWithHeaders(RpcCommand command) throws RpcException {
execute(command, headers);
}

private void putSessionHeader(HttpResponse result) {
headers.put("X-Transmission-Session-Id", result.getFirstHeader("X-Transmission-Session-Id").getValue());
}
private final RpcConfiguration configuration;
private final ObjectMapper objectMapper;
private final Map<String, String> headers;
private final DefaultHttpClient defaultHttpClient = new DefaultHttpClient();

private final RequestExecutor requestExecutor;

public RpcClient(RpcConfiguration configuration, ObjectMapper objectMapper) {
this.requestExecutor = new RequestExecutor(objectMapper, configuration, defaultHttpClient);
this.configuration = configuration;
this.objectMapper = objectMapper;
headers = new HashMap<>();

if (configuration.getUsername() != null && configuration.getPassword() != null) {

getClient().getCredentialsProvider() //
.setCredentials(new AuthScope(configuration.getHost().getHost(), configuration.getHost().getPort()),
new UsernamePasswordCredentials(configuration.getUsername(), configuration.getPassword()));

}
}

public <T, V> void execute(RpcCommand<T, V> command, Map<String, String> h) throws RpcException {
try {
executeCommandInner(command, h);
} catch (RequestExecutorException | IOException e) {
throw new RpcException(e);
} catch (InvalidResponseStatus e) {
setup();
try {
executeCommandInner(command, h);
} catch (Exception | RequestExecutorException | InvalidResponseStatus inner) {
throw new RpcException(inner);
}
}
}

private <T, V> void executeCommandInner(RpcCommand<T, V> command, Map<String, String> h)
throws RequestExecutorException, InvalidResponseStatus, IOException, RpcException {
for (Map.Entry<String, String> entry : h.entrySet()) {
requestExecutor.removeAllHeaders();
requestExecutor.configureHeader(entry.getKey(), entry.getValue());
}

RpcRequest<T> request = command.buildRequestPayload();
RpcResponse<V> response = requestExecutor.execute(request, RpcResponse.class, 200);

Map args = (Map) response.getArguments();
String stringValue = objectMapper.writeValueAsString(args);
response.setArguments((V) objectMapper.readValue(stringValue, command.getArgumentsObject()));
if (!command.getTag().equals(response.getTag())) {
throw new RpcException(
String.format("Invalid response tag. Expected %d, but got %d", command.getTag(), request.getTag()));
}
command.setResponse(response);

if (!"success".equals(response.getResult())) {
throw new RpcException("Rpc Command Failed: " + response.getResult(), command);
}
}

private void setup() throws RpcException {
try {
DefaultHttpClient defaultHttpClient = getClient();
HttpPost httpPost = createPost();
HttpResponse result = defaultHttpClient.execute(httpPost);
putSessionHeader(result);
EntityUtils.consume(result.getEntity());
} catch (IOException e) {
throw new RpcException(e);
}
}

protected HttpPost createPost() {
return new HttpPost(configuration.getHost());
}

protected DefaultHttpClient getClient() {
return defaultHttpClient;
}

public void executeWithHeaders(RpcCommand command) throws RpcException {
execute(command, headers);
}

private void putSessionHeader(HttpResponse result) {
headers.put("X-Transmission-Session-Id", result.getFirstHeader("X-Transmission-Session-Id").getValue());
}
}
20 changes: 19 additions & 1 deletion src/main/java/nl/stil4m/transmission/rpc/RpcConfiguration.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,30 @@
public class RpcConfiguration implements HostConfiguration {

private URI host;

private String username = null;
private String password = null;

public URI getHost() {
return host;
}

public void setHost(URI host) {
this.host = host;
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}
}