/**
* Copyright (c) <2013> <Radware Ltd.> and others. All rights reserved.
*
* This program and the accompanying materials are made available under the terms of the Eclipse Public License
* v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html
* @author Kobi Samoray
* @author Gera Goft
* @version 0.1
*/
package org.opendaylight.defense4all.odl.controller;
import java.nio.charset.Charset;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.impl.client.DefaultHttpClient;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.opendaylight.defense4all.framework.core.ExceptionControlApp;
import org.opendaylight.defense4all.framework.core.FMHolder;
import org.opendaylight.defense4all.framework.core.HealthTracker;
import org.opendaylight.defense4all.odl.OdlOFC;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
public class Connector {
public interface JsonPreprocessor {
public String preProcess(String jsonStr);
}
private static Log log = LogFactory.getLog(Connector.class);
public OdlOFC odlOFC;
protected String restPrefix;
protected com.fasterxml.jackson.databind.ObjectMapper fasterxmlObjMapper;
protected RestTemplate restTemplate;
public Connector(OdlOFC odlOFC) {
if(odlOFC == null) {
log.error("Failed to create connector - null odlOFC passed");
throw new IllegalArgumentException("Null odlOFC");
}
fasterxmlObjMapper = new ObjectMapper();
fasterxmlObjMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // Ignore unknownfields
this.odlOFC = odlOFC;
}
public void init() throws ExceptionControlApp {
try {
restPrefix = "http://" + odlOFC.ipAddrString + ":" + Integer.toString(odlOFC.port);
// set authentication for rest template
AuthScope authScope = new AuthScope(odlOFC.hostname, odlOFC.port, AuthScope.ANY_REALM);
UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(odlOFC.username,odlOFC.password);
// DefaultHttpClient client = new DefaultHttpClient();
// client.getCredentialsProvider().setCredentials(authScope, credentials);
// HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(client);
// restTemplate = new RestTemplate(factory);
RestTemplateFactory.INSTANCE.setInsecureSsl(true);
restTemplate = RestTemplateFactory.INSTANCE.createRestTemplate(authScope, credentials);
if(restTemplate == null) throw new Exception("Failed to create restTemplate");
} catch (Throwable e) {
log.error("Failed to init connector to " + odlOFC.hostname, e);
FMHolder.get().getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE);
throw new ExceptionControlApp ("Failed to init connector to " + odlOFC.hostname, e);
}
}
protected synchronized <T> T getFromController(String urlPrefix, TypeReference<?> typeRef, JsonPreprocessor preProcessor)
throws RestClientException {
T t;
try {
String url = mkUrl(urlPrefix);
log.debug("Caller: "+getMethodName(2)+" Class:"+typeRef.getType().toString()+" Invoking restTemplate.getForObject"
+ "Calling - URL: "+url+" JSON: ");
String result = //restTemplate.getForObject(url, String.class);
restCallWithAutorization(url, "admin", "admin");
if(result == null) return null;
// Don't print it to log - it may contain non-printable chars
// log.debug("Caller: "+getMethodName(2)+" Class:"+typeRef.getType().toString()+" URL: "+url+" JSON: "+result.toString());
if(preProcessor != null)
result = preProcessor.preProcess(result);
t = fasterxmlObjMapper.readValue(result, typeRef);
} catch (Throwable e) {
log.error("Failed to get from controller " + odlOFC.hostname, e);
throw new RestClientException("Failed to get from controller " + odlOFC.hostname, e);
}
return t;
}
//TODO: organize and generalize (use ResponseEntity<T>, and factor out authorization header creation).
private String restCallWithAutorization(String url, final String username, final String password){
HttpHeaders httpHeaders = new HttpHeaders(){
{
String auth = username + ":" + password;
byte[] encodedAuth = Base64.encodeBase64(
auth.getBytes(Charset.forName("US-ASCII")) );
String authHeader = "Basic " + new String( encodedAuth );
set( "Authorization", authHeader );
}
};
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<Object>(httpHeaders), String.class);
String responseObject = response.getBody();
return responseObject;
}
protected synchronized void postToController(String urlPrefix, Object object) throws RestClientException {
try {
String url = mkUrl(urlPrefix);
log.debug("Caller: URL: " + url );
HttpEntity<String> entity = buildHttpEntityFromObject( object );
restTemplate.postForLocation(url, entity);
} catch (Throwable e) {
log.error("Failed to post to controller " + odlOFC.hostname, e);
throw new RestClientException("Failed to post to controller " + odlOFC.hostname, e);
}
}
protected synchronized void putToController(String urlPrefix, Object object) throws RestClientException {
try {
String url = mkUrl(urlPrefix);
log.debug("Caller: URL: " + url );
HttpEntity<String> entity = buildHttpEntityFromObject( object );
restTemplate.put(url, entity);
} catch (Throwable e) {
log.error("Failed to put to controller " + object + " to " + odlOFC.hostname, e);
throw new RestClientException("Failed to put to controller " + object + " to " + odlOFC.hostname, e);
}
}
private HttpEntity<String> buildHttpEntityFromObject( Object object) throws RestClientException {
String jsonStr;
try {
jsonStr = fasterxmlObjMapper.writeValueAsString(object);
} catch (Throwable e) {
String msg = "Failed to writeValueAsString " + object.toString() + " for controller " + odlOFC.hostname;
log.error(msg, e);
throw new RestClientException(msg, e);
}
log.debug("Caller: " + getMethodName(2) + " JSON: " + jsonStr);
HttpHeaders headers = new HttpHeaders(){
{
String username = "admin";
String password = "admin";
String auth = username + ":" + password;
byte[] encodedAuth = Base64.encodeBase64(
auth.getBytes(Charset.forName("US-ASCII")) );
String authHeader = "Basic " + new String( encodedAuth );
set( "Authorization", authHeader );
}
};
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<String>(jsonStr,headers);
return entity;
}
protected synchronized void putToController(String urlPrefix) throws RestClientException {
try {
String url = mkUrl(urlPrefix);
log.debug("Caller: " + getMethodName(2) + " URL: " + url + " JSON: ");
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
restTemplate.put(url, null);
} catch (Throwable e) {
log.error("Failed to put to controller " + odlOFC.hostname, e);
throw new RestClientException("Failed to put to controller " + odlOFC.hostname, e);
}
}
protected synchronized void delFromController(String urlPrefix) throws ExceptionInvalidState {
try {
String url = mkUrl(urlPrefix);
log.debug("Caller: " + getMethodName(2) + " URL: " + url);
restTemplate.delete(url);
} catch (Throwable e) {
log.error("Failed to put to controller " + odlOFC.hostname, e);
throw new RestClientException("Failed to put to controller " + odlOFC.hostname, e);
}
}
protected String mkUrl(String path) {
return restPrefix + path;
}
private static String getMethodName(final int depth) {
final StackTraceElement[] ste = Thread.currentThread().getStackTrace();
return ste[ste.length - 1 - depth].getMethodName();
}
}