/**
* Copyright (C) 2008 Progress Software, Inc. All rights reserved.
* http://fusesource.com
*
* The software in this package is published under the terms of the AGPL license
* a copy of which has been included with this distribution in the license.txt file.
*/
package org.fusesource.cloudmix.agent;
import java.io.InputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.fusesource.cloudmix.agent.logging.LogRecord;
import org.fusesource.cloudmix.common.GridClient;
import org.fusesource.cloudmix.common.GridClients;
import org.fusesource.cloudmix.common.ProcessClient;
import org.fusesource.cloudmix.common.URIs;
import org.fusesource.cloudmix.common.dto.AgentDetails;
import org.fusesource.cloudmix.common.dto.AgentDetailsList;
import org.fusesource.cloudmix.common.dto.FeatureDetails;
import org.fusesource.cloudmix.common.dto.FeatureDetailsList;
import org.fusesource.cloudmix.common.dto.ProfileDetails;
import org.fusesource.cloudmix.common.dto.ProfileDetailsList;
import org.fusesource.cloudmix.common.dto.ProfileStatus;
import org.fusesource.cloudmix.common.dto.ProvisioningHistory;
import org.fusesource.cloudmix.common.dto.Resource;
import org.fusesource.cloudmix.common.dto.ResourceList;
import org.fusesource.cloudmix.common.dto.StringList;
import org.fusesource.cloudmix.common.util.ObjectHelper;
/**
* @version $Revision: 61256 $
*/
public class RestGridClient extends RestClientSupport implements GridClient {
private static final transient Log LOG = LogFactory.getLog(RestGridClient.class);
private URI agentsUri;
private URI featuresUri;
private URI profilesUri;
public RestGridClient() {
}
public RestGridClient(String rootUri) {
this(URIs.createURI(rootUri));
}
public RestGridClient(URI rootUri) {
setRootUri(rootUri);
}
public String addAgentDetails(AgentDetails agentDetails) {
WebResource.Builder agentsResource = resource(getAgentsUri()).type("application/xml");
ClientResponse response = agentsResource.post(ClientResponse.class, agentDetails);
URI location = response.getLocation();
if (location == null) {
throw new IllegalArgumentException("No Location header returned from response!");
}
String path = location.getPath();
// The agent id is the last part of that path..
path = path.substring(path.lastIndexOf("/") + 1);
return path;
}
public void updateAgentDetails(String agentId, AgentDetails agentDetails) {
WebResource.Builder resource = resource(append(getAgentsUri(), "/", agentId)).accept("application/xml");
getTemplate().put(resource, agentDetails);
}
public List<LogRecord> getLogRecords(Map<String, List<String>> queries) {
WebResource.Builder resource = resource(append(getRootUri(), "/log")).accept("application/xml");
assert resource != null;
// TODO: how to tell Jersey to get List<LogRecord> ?
return Collections.emptyList();
}
public AgentDetails getAgentDetails(String agentId) {
WebResource.Builder resource = resource(append(getAgentsUri(), "/", agentId)).accept("application/xml");
return getTemplate().get(resource, AgentDetails.class);
}
public List<AgentDetails> getAllAgentDetails() {
WebResource.Builder resource = resource(getAgentsUri()).accept("application/xml");
AgentDetailsList answer = getTemplate().get(resource, AgentDetailsList.class);
if (answer == null) {
// TODO just return empty list?
return new ArrayList<AgentDetails>();
} else {
return answer.getAgents();
}
}
public InputStream getInputStream() {
WebResource.Builder resource = resource(getRootUri()).accept("*/*");
return resource.get(InputStream.class);
}
public void removeAgentDetails(String agentId) {
WebResource.Builder resource = resource(append(getAgentsUri(), "/", agentId)).accept("application/xml");
getTemplate().delete(resource);
}
public ProvisioningHistory getAgentHistory(String agentId) {
WebResource.Builder resource = resource(append(getAgentsUri(), "/", agentId, "/history")).accept("application/xml");
return getTemplate().get(resource, ProvisioningHistory.class);
}
public ProvisioningHistory pollAgentHistory(String agentId) {
WebResource.Builder resource = resource(append(getAgentsUri(), "/", agentId, "/history")).accept("application/xml");
LOG.debug("polling agent history, agent id: " + agentId);
LOG.debug("polling agent history, resource: " + resource);
return getTemplate().poll(resource, ProvisioningHistory.class);
}
public List<FeatureDetails> getFeatures() {
WebResource.Builder resource = resource(getFeaturesUri()).accept("application/xml");
FeatureDetailsList answer = getTemplate().get(resource, FeatureDetailsList.class);
if (answer == null) {
// TODO just return empty list?
return new ArrayList<FeatureDetails>();
} else {
return answer.getFeatures();
}
}
public void addFeature(FeatureDetails feature) {
String id = feature.getId();
ObjectHelper.notNull(id, "FeatureDetails.id");
WebResource.Builder resource = resource(append(getFeaturesUri(), "/", id)).type("application/xml");
getTemplate().put(resource, feature);
}
public void removeFeature(String id) {
ObjectHelper.notNull(id, "feature.id");
WebResource.Builder resource = resource(append(getFeaturesUri(), "/", id)).type("application/xml");
getTemplate().delete(resource);
}
public FeatureDetails getFeature(String featureId) {
ObjectHelper.notNull(featureId, "featureId");
WebResource.Builder resource = resource(append(getFeaturesUri(), "/", featureId)).accept("application/xml");
return getTemplate().get(resource, FeatureDetails.class);
}
public void removeFeature(FeatureDetails feature) {
String id = feature.getId();
ObjectHelper.notNull(id, "feature.id");
removeFeature(id);
}
public void addAgentToFeature(String featureId, String agentId, Map<String, String> cfgOverridesProps) {
WebResource.Builder resource = resource(append(getFeaturesUri(), "/", featureId, "/agents/", agentId)).type("application/xml");
getTemplate().put(resource);
}
public void removeAgentFromFeature(String featureId, String agentId) {
WebResource.Builder resource = resource(append(getFeaturesUri(), "/", featureId, "/agents/", agentId)).type("application/xml");
getTemplate().delete(resource);
}
public List<String> getAgentsAssignedToFeature(String id) {
ObjectHelper.notNull(id, "feature.id");
WebResource.Builder resource = resource(append(getFeaturesUri(), "/", id, "/agents")).accept("application/xml");
StringList answer = getTemplate().get(resource, StringList.class);
if (answer == null) {
// TODO just return empty list?
return new ArrayList<String>();
}
return answer.getValues();
}
public List<? extends ProcessClient> getProcessClientsForFeature(String featureId) {
List<RestProcessClient> answer = new ArrayList<RestProcessClient>();
List<AgentDetails> list = Collections.emptyList();
for (int i = 0; i < 10; i++) {
list = GridClients.getAgentDetailsAssignedToFeature(this, featureId);
if (!list.isEmpty()) {
break;
}
LOG.debug("Retrying...");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// ignore
}
}
for (AgentDetails agentDetails : list) {
String href = agentDetails.getHref();
if (href != null && href.contains("://")) {
// lets get the processes for this feature
if (!href.endsWith("/")) {
href = href + "/";
}
String uri = href + "features/" + featureId;
LOG.debug("About to test feature URI: " + uri);
//System.out.println("Found: " + resource(new URI(uri)).accept("text/xml").get(String.class));
ResourceList resourceList = resource(URIs.createURI(uri)).accept("text/xml").get(ResourceList.class);
if (resourceList != null) {
LOG.debug(uri + " Found: " + resourceList);
List<Resource> resources = resourceList.getResources();
for (Resource resource : resources) {
RestProcessClient client = createProcessClient(agentDetails, featureId, resource);
if (client != null) {
answer.add(client);
}
}
} else {
LOG.warn("No ResourceList found for " + uri);
}
} else {
LOG.warn("Ignoring agent " + agentDetails + " due to bad href " + href);
}
}
return answer;
}
private RestProcessClient createProcessClient(AgentDetails agentDetails, String featureId, Resource resource) {
String agentHref = agentDetails.getHref();
String resourceHref = resource.getHref();
//Make sure we don't end up with a double slash
if (resourceHref.startsWith("/") && agentHref.endsWith("/")) {
resourceHref = resourceHref.substring(1);
}
return new RestProcessClient(agentHref + resourceHref);
}
public ProfileDetails getProfile(String id) {
WebResource.Builder resource = resource(append(getProfilesUri(), "/", id)).accept("application/xml");
return getTemplate().get(resource, ProfileDetails.class);
}
public ProfileStatus getProfileStatus(String id) {
WebResource.Builder resource = resource(append(getProfilesUri(), "/", id, "/status")).accept("application/xml");
return getTemplate().get(resource, ProfileStatus.class);
}
public List<ProfileDetails> getProfiles() {
WebResource.Builder resource = resource(getProfilesUri()).accept("application/xml");
ProfileDetailsList answer = getTemplate().get(resource, ProfileDetailsList.class);
if (answer == null) {
// TODO just return empty list?
return new ArrayList<ProfileDetails>();
} else {
return answer.getProfiles();
}
}
public void addProfile(ProfileDetails profile) {
String id = profile.getId();
WebResource.Builder resource = resource(append(getProfilesUri(), "/", id)).type("application/xml");
int status = getTemplate().put(resource, profile);
System.out.println("updating profile " + profile + " status " + status);
}
public void removeProfile(ProfileDetails profile) {
String id = profile.getId();
ObjectHelper.notNull(id, "profile.id");
removeProfile(id);
}
public void removeProfile(String id) {
ObjectHelper.notNull(id, "profile.id");
WebResource.Builder resource = resource(append(getProfilesUri(), "/", id)).type("application/xml");
getTemplate().delete(resource);
}
public Properties getProperties(String profileId) {
ObjectHelper.notNull(profileId, "profile.id");
WebResource.Builder resource = resource(append(getProfilesUri(), "/", profileId, "/properties")).accept("application/xml");
return getTemplate().get(resource, Properties.class);
}
// Properties
//-------------------------------------------------------------------------
public URI getAgentsUri() {
if (agentsUri == null) {
agentsUri = getRootUri().resolve("agents");
LOG.debug("agents URI : " + agentsUri);
}
return agentsUri;
}
public URI getFeaturesUri() {
if (featuresUri == null) {
featuresUri = getRootUri().resolve("features");
}
return featuresUri;
}
public URI getProfilesUri() {
if (profilesUri == null) {
profilesUri = getRootUri().resolve("profiles");
}
return profilesUri;
}
}