/**
* 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.jbi;
import java.io.File;
import java.io.FileInputStream;
import java.net.URI;
import java.util.Properties;
import java.util.StringTokenizer;
import javax.jbi.JBIException;
import javax.jbi.component.Component;
import javax.jbi.component.ComponentContext;
import javax.jbi.component.ComponentLifeCycle;
import javax.jbi.component.ServiceUnitManager;
import javax.jbi.messaging.MessageExchange;
import javax.jbi.servicedesc.ServiceEndpoint;
import javax.management.MBeanInfo;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.fusesource.cloudmix.agent.AgentPoller;
import org.fusesource.cloudmix.agent.InstallerAgent;
import org.fusesource.cloudmix.agent.RestGridClient;
import org.fusesource.cloudmix.agent.security.DialogPasswordProvider;
import org.fusesource.cloudmix.agent.security.FilePasswordProvider;
import org.fusesource.cloudmix.agent.security.PasswordProvider;
public class AgentComponent implements ComponentLifeCycle, Component {
private static final Log LOGGER = LogFactory.getLog(AgentComponent.class);
private static final String CONFIG_PROP_FILE = "agent.properties.file";
private static final String CONFIG_REPO_URI = "agent.repository.uri";
private static final String CONFIG_ID = InstallerAgent.PERSISTABLE_PROPERTY_AGENT_ID;
private static final String CONFIG_NAME = InstallerAgent.PERSISTABLE_PROPERTY_AGENT_NAME;
private static final String CONFIG_PROFILE = InstallerAgent.PERSISTABLE_PROPERTY_PROFILE_ID;
private static final String CONFIG_MBEAN_NAME = "agent.deployservice.mbean";
private static final String CONFIG_AGENT_USER = "agent.user";
private static final String CONFIG_AGENT_PASSWORD_PROV = "agent.password.provider";
private static final String CONFIG_AGENT_PASSWORD_FILE = "agent.password.file";
private static final String CONFIG_AGENT_TYPE = "agent.type";
private static final String CONFIG_AGENT_LINK = "agent.link";
private static final String CONFIG_AGENT_PACKAGES = "agent.packages";
private static final String CONFIG_AGENT_MBEAN_CONTAINER = "agent.mbean.container";
private static final String DEFAULT_PROP_FILE = "conf/agent.properties";
private static final String DEFAULT_CONTAINER_TYPE = "smx3";
private static final String DEFAULT_REPO_URI = "http://localhost:9091/controller";
private static final String DEFAULT_PROFILE = "default";
private static final String DEFAULT_AGENT_USER = "Agent";
private static final String DEFAULT_AGENT_PASSWORD = "agent";
private static final String DEFAULT_AGENT_PASSWORD_PROV = "file";
private static final String DEFAULT_AGENT_PASSWORD_FILE = "conf/agent.password";
private static final String FILE_PROVIDER = "file";
private static final String DIALOG_PROVIDER = "dialog";
private static final String DEFAULT_MBEAN_NAME = "org.apache.servicemix:"
+ "ContainerName=ServiceMix,"
+ "Type=SystemService,"
+ "Name=DeploymentService";
private static final String DEFAULT_PACKAGES = "jbi";
private static final String DEFAULT_AGENT_MBEAN_CONTAINER = "ServiceMix";
private static final int MAX_FEATURES = 25;
private static final long INITIAL_POLLING_DELAY = 5000;
private static final long POLLING_PERIOD = 1000;
private RestGridClient gridClient = new RestGridClient();
private JBIInstallerAgent agent = new JBIInstallerAgent();
private AgentPoller poller = new AgentPoller();
private MBeanServer mbeanServer;
private ObjectName mbeanName;
public AgentComponent() {
// Complete
}
public ObjectName getExtensionMBeanName() {
// Complete
return null;
}
public void init(ComponentContext ctx) throws JBIException {
LOGGER.info("initialising agent");
StringBuilder sb =
new StringBuilder()
.append("\n")
.append("CloudMix Agent JBI Service Assembly Deployer\n");
try {
Properties properties = System.getProperties();
String agentPropertiesFile = getConfig(System.getProperties(),
CONFIG_PROP_FILE,
DEFAULT_PROP_FILE);
Properties newProperties = loadProperties(agentPropertiesFile);
if (newProperties != null) {
properties = newProperties;
}
String agentUser = getConfig(properties, CONFIG_AGENT_USER, DEFAULT_AGENT_USER);
PasswordProvider provider = null;
String providerType = getConfig(properties, CONFIG_AGENT_PASSWORD_PROV, DEFAULT_AGENT_PASSWORD_PROV);
if (FILE_PROVIDER.equals(providerType)) {
FilePasswordProvider fpp = new FilePasswordProvider();
fpp.setPasswordFile(getConfig(properties, CONFIG_AGENT_PASSWORD_FILE, DEFAULT_AGENT_PASSWORD_FILE));
provider = fpp;
} else if (DIALOG_PROVIDER.equals(providerType)) {
DialogPasswordProvider dpp = new DialogPasswordProvider();
dpp.setUsername(agentUser);
provider = dpp;
} else {
throw new RuntimeException("Unknown password provider " + providerType);
}
String agentId = getConfig(properties, CONFIG_ID, null);
String agentName = getConfig(properties, CONFIG_NAME, null);
String agentProfile = getConfig(properties, CONFIG_PROFILE, DEFAULT_PROFILE);
String anMbeanName = getConfig(properties, CONFIG_MBEAN_NAME, DEFAULT_MBEAN_NAME);
String rootUri = getConfig(properties, CONFIG_REPO_URI, DEFAULT_REPO_URI);
String agentType = getConfig(properties, CONFIG_AGENT_TYPE, DEFAULT_CONTAINER_TYPE);
String agentLink = getConfig(properties, CONFIG_AGENT_LINK, null);
String[] supportPackageTypes = getConfigList(properties, CONFIG_AGENT_PACKAGES, DEFAULT_PACKAGES);
String mbeanContainer = getConfig(properties,
CONFIG_AGENT_MBEAN_CONTAINER,
DEFAULT_AGENT_MBEAN_CONTAINER);
mbeanServer = ctx.getMBeanServer();
ObjectName oname = validateMbean(mbeanServer, anMbeanName);
if (oname == null) {
throw new JBIException("DeploymentService MBean not available using name " + anMbeanName);
}
gridClient.setRootUri(new URI(rootUri));
gridClient.setUsername(agentUser);
gridClient.setPasswordProvider(provider);
agent.setAgentId(agentId);
agent.setAgentName(agentName);
agent.setDetailsPropertyFilePath(agentPropertiesFile);
agent.setMBeanServer(mbeanServer);
agent.setMBeanName(oname);
agent.setMaxFeatures(MAX_FEATURES);
agent.setProfile(agentProfile);
agent.setClient(gridClient);
agent.setContainerType(agentType);
agent.setSupportPackageTypes(supportPackageTypes);
agent.setAgentLink(agentLink);
agent.init();
sb.append("\nConfiguration:")
.append("\n Agent ID: " + agentId == null ? "unassigned yet" : agentId)
.append("\n Agent Name: " + agentName == null ? "unassigned yet" : agentName)
.append("\n Agent profile: " + agentProfile)
.append("\n Repository URI: " + rootUri)
.append("\n Agent user: " + agentUser)
.append("\n Agent type: " + agent.getContainerType())
.append("\n Agent link: " + agentLink)
.append("\n Agent mbean name: " + anMbeanName)
.append("\n Package types: ");
for (String packageType : supportPackageTypes) {
sb.append(packageType).append(" ");
}
poller.setInitialPollingDelay(INITIAL_POLLING_DELAY);
poller.setPollingPeriod(POLLING_PERIOD);
poller.setAgent(agent);
mbeanServer = ctx.getMBeanServer();
AgentMBean agentMBean = new Agent(agent, gridClient, poller);
registerMBean(agentMBean, ctx.getMBeanNames().getJmxDomainName(),
mbeanContainer);
sb.append("\n");
LOGGER.info(sb.toString());
} catch (JBIException e) {
throw e;
} catch (Exception e) {
LOGGER.error("Failed to initialise agent. Exception " + e);
throw new JBIException(e);
}
}
public void shutDown() throws JBIException {
LOGGER.info("shutting down agent");
if (mbeanName != null) {
try {
mbeanServer.unregisterMBean(mbeanName);
} catch (Exception e) {
LOGGER.warn("Exception unregistering agent mbean " + e);
}
}
}
public void start() throws JBIException {
LOGGER.info("starting agent");
// TODO: need to support restarting agent.
try {
poller.afterPropertiesSet();
} catch (Exception e) {
LOGGER.warn("Exception " + e + " starting agent poller");
}
}
public void stop() throws JBIException {
LOGGER.info("stopping agent");
try {
LOGGER.info("destroying poller");
agent.setClient(null);
poller.destroy();
} catch (Exception e) {
LOGGER.warn("Exception destroying poller; " + e);
}
}
public ComponentLifeCycle getLifeCycle() {
return this;
}
public Document getServiceDescription(ServiceEndpoint se) {
// Complete
return null;
}
public ServiceUnitManager getServiceUnitManager() {
// Complete
return null;
}
public boolean isExchangeWithConsumerOkay(ServiceEndpoint se,
MessageExchange me) {
// Complete
return false;
}
public boolean isExchangeWithProviderOkay(ServiceEndpoint se,
MessageExchange me) {
// Complete
return false;
}
public ServiceEndpoint resolveEndpointReference(DocumentFragment df) {
// Complete
return null;
}
private Properties loadProperties(String file) {
try {
if (file == null || "".equals(file)) {
return null;
}
File f = new File(file);
if (!f.exists()) {
LOGGER.warn("properties file " + file + " does not exist");
return null;
}
Properties properties = new Properties();
LOGGER.info("Loading properties from file " + f);
properties.load(new FileInputStream(f));
return properties;
} catch (Exception e) {
LOGGER.warn("error loading properties file " + file + ", exception " + e);
return null;
}
}
private String getConfig(Properties properties, String name, String defaultValue) {
String value = properties.getProperty(name);
if (value == null) {
value = defaultValue;
}
LOGGER.debug(" Property " + name + " = " + defaultValue);
return value;
}
private String[] getConfigList(Properties properties, String name, String defaultValue) {
String value = properties.getProperty(name);
if (value == null) {
value = defaultValue;
}
StringTokenizer tokeniser = new StringTokenizer(value, ",");
int arraySize = tokeniser.countTokens();
String[] array = new String[arraySize];
for (int i = 0; i < arraySize; i++) {
String item = (String) tokeniser.nextElement();
array[i] = item.trim();
}
return array;
}
private void registerMBean(AgentMBean agentMBean, String domainName,
String containerName) {
try {
String name = domainName
+ ":ContainerName=" + containerName
+ ",Type=ServiceGrid,Name=Agent";
mbeanName = new ObjectName(name);
LOGGER.info("registering agent mbean with name " + mbeanName);
mbeanServer.registerMBean(agentMBean, mbeanName);
} catch (Exception e) {
LOGGER.warn("Exception registering mbean " + e);
}
}
private ObjectName validateMbean(MBeanServer anMbeanServer, String anMbeanName) {
try {
ObjectName oname = new ObjectName(anMbeanName);
MBeanInfo info = anMbeanServer.getMBeanInfo(oname);
if (info != null) {
LOGGER.info("Successfully accesses Deployment Service mbean");
LOGGER.info("Description: " + info.getDescription());
return oname;
}
} catch (Exception e) {
LOGGER.debug("Exception getting DeploymentService mbean " + e);
}
LOGGER.error("Cannot resolve DeploymentService MBean using name " + anMbeanName);
return null;
}
}