/*
* Copyright (c) 2015 EMC Corporation
* All Rights Reserved
*/
package com.emc.cloud.platform.clientlib;
import java.lang.reflect.InvocationTargetException;
import java.util.Collections;
import javax.xml.bind.JAXBElement;
import org.apache.commons.beanutils.BeanUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.Assert;
import com.emc.cloud.platform.ucs.in.model.AaaLogin;
import com.emc.cloud.platform.ucs.in.model.AaaLogout;
import com.emc.cloud.platform.ucs.in.model.ObjectFactory;
import com.emc.cloud.platform.ucs.model.ext.OutStatus;
public class ClientHttpMethodsImpl implements ClientHttpMethods, InitializingBean, ApplicationContextAware {
@Autowired
ApplicationContext applicationContext;
private String httpReqFactoryBeanRef;
private ClientHttpRequestFactory requestFactory;
String serviceURI;
private ObjectFactory objectFactory = new ObjectFactory();
/**
* @return the httpReqFactoryBeanRef
*/
public String getHttpReqFactoryBeanRef() {
return httpReqFactoryBeanRef;
}
/**
* @param httpReqFactoryBeanRef the httpReqFactoryBeanRef to set
*/
public void setHttpReqFactoryBeanRef(String httpReqFactoryBeanRef) {
this.httpReqFactoryBeanRef = httpReqFactoryBeanRef;
}
public ClientHttpMethodsImpl(String serviceURI, String username, String password) throws ClientGeneralException {
this.serviceURI = serviceURI;
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(username, password));
}
private Authentication endpointLogin(String serviceURI, String username, String password) throws ClientGeneralException {
Authentication authentication = null;
ClientHttpRequest httpRequest = requestFactory.create();
AaaLogin aaaLogin = new AaaLogin();
aaaLogin.setInName(username);
aaaLogin.setInPassword(password);
com.emc.cloud.platform.ucs.out.model.AaaLogin response = httpRequest.httpPostXMLObject(getServiceURI(),
objectFactory.createAaaLogin(aaaLogin), com.emc.cloud.platform.ucs.out.model.AaaLogin.class);
if (response != null && response.getOutCookie() != null && !response.getOutCookie().isEmpty()) {
authentication = new UsernamePasswordAuthenticationToken(username, password, Collections.EMPTY_LIST);
((UsernamePasswordAuthenticationToken) authentication).setDetails(response);
SecurityContextHolder.getContext().setAuthentication(authentication);
} else {
throw new ClientGeneralException(ClientMessageKeys.UNAUTHORIZED, new String[] { getServiceURI(), "",
"Unable to authenticate username/credentials pair" });
}
return authentication;
}
/*
* Delegate such that there is only one injection required in the services
*/
public String getServiceURI() {
return this.serviceURI;
}
public void setServiceURI(String serviceURI) {
this.serviceURI = serviceURI;
}
private static final Logger LOGGER = LoggerFactory.getLogger(ClientHttpMethodsImpl.class);
// =======================================================================================
// Entity routines
// =======================================================================================
public <T> T postEntity(JAXBElement<?> jaxbElement, Class<T> returnType) throws ClientGeneralException {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
Assert.notNull(authentication, "No credentials provided for call");
if (authentication instanceof UsernamePasswordAuthenticationToken && !authentication.isAuthenticated()) {
Assert.notNull(authentication.getName(), "No username provided for call");
Assert.notNull(authentication.getCredentials(), "No password provided for call");
authentication = endpointLogin(getServiceURI(), authentication.getName(), authentication.getCredentials().toString());
}
T result = null;
try {
ClientHttpRequest httpRequest = requestFactory.create();
if (authentication instanceof UsernamePasswordAuthenticationToken && authentication.isAuthenticated()) {
com.emc.cloud.platform.ucs.out.model.AaaLogin loginResponse = (com.emc.cloud.platform.ucs.out.model.AaaLogin) authentication
.getDetails();
try {
if (loginResponse != null) {
BeanUtils.setProperty(jaxbElement.getValue(), "cookie", loginResponse.getOutCookie());
}
} catch (IllegalAccessException e) {
LOGGER.error("Unable to set the cookie on object type: " + jaxbElement.getValue(), e);
throw new ClientGeneralException(ClientMessageKeys.MODEL_EXCEPTION);
} catch (InvocationTargetException e) {
LOGGER.error("Unable to set the cookie on object type: " + jaxbElement.getValue(), e);
throw new ClientGeneralException(ClientMessageKeys.MODEL_EXCEPTION);
}
}
result = httpRequest.httpPostXMLObject(getServiceURI(), jaxbElement, returnType);
} catch (ClientGeneralException e) {
LOGGER.debug(e.getLocalizedMessage(), e);
throw e;
}
return result;
}
@Override
public void afterPropertiesSet() throws Exception {
requestFactory = (ClientHttpRequestFactory) applicationContext.getBean(httpReqFactoryBeanRef);
if (requestFactory == null) {
throw new IllegalArgumentException("httpMethods object requires non-null requestFactory");
}
}
@Override
public void setApplicationContext(ApplicationContext arg0)
throws BeansException {
this.applicationContext = arg0;
}
@Override
public void close() throws ClientGeneralException {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null) {
/**
* No-op - There's no security context to log out!
*/
return;
} else if (authentication instanceof UsernamePasswordAuthenticationToken) {
endpointLogout(authentication);
}
}
private void endpointLogout(Authentication authentication) throws ClientGeneralException {
if (authentication == null) {
return;
}
Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication);
Assert.isTrue(authentication.isAuthenticated());
Assert.isTrue(authentication.getDetails() != null);
Assert.isInstanceOf(com.emc.cloud.platform.ucs.out.model.AaaLogin.class, authentication.getDetails());
AaaLogout aaaLogout = new AaaLogout();
aaaLogout.setInCookie(((com.emc.cloud.platform.ucs.out.model.AaaLogin) authentication.getDetails()).getOutCookie());
ClientHttpRequest httpRequest = requestFactory.create();
com.emc.cloud.platform.ucs.out.model.AaaLogout response = httpRequest.httpPostXMLObject(getServiceURI(),
objectFactory.createAaaLogout(aaaLogout), com.emc.cloud.platform.ucs.out.model.AaaLogout.class);
if (OutStatus.SUCCESS.getValue().equals(response.getOutStatus())) {
return;
} else {
throw new ClientGeneralException(ClientMessageKeys.SECURITY_EXCEPTION, new String[] { "Unable to log out session : "
+ authentication.getDetails() });
}
}
}