/*******************************************************************************
* This file is part of OpenNMS(R).
*
* Copyright (C) 2009-2011 The OpenNMS Group, Inc.
* OpenNMS(R) is Copyright (C) 1999-2011 The OpenNMS Group, Inc.
*
* OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
*
* OpenNMS(R) is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* OpenNMS(R) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenNMS(R). If not, see:
* http://www.gnu.org/licenses/
*
* For more information contact:
* OpenNMS(R) Licensing <license@opennms.org>
* http://www.opennms.org/
* http://www.opennms.com/
*******************************************************************************/
package org.opennms.netmgt.provision.detector.bsf.client;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.bsf.BSFException;
import org.apache.bsf.BSFManager;
import org.apache.bsf.util.IOUtils;
import org.opennms.core.utils.LogUtils;
import org.opennms.netmgt.provision.detector.bsf.request.BSFRequest;
import org.opennms.netmgt.provision.detector.bsf.response.BSFResponse;
import org.opennms.netmgt.provision.support.Client;
/**
* <p>BSFClient class.</p>
*
* @author Alejandro Galue <agalue@opennms.org>
* @version $Id: $
*/
public class BSFClient implements Client<BSFRequest, BSFResponse> {
private String m_serviceName;
private String m_fileName;
private String m_langClass;
private String m_bsfEngine;
private String[] m_fileExtensions = {};
private String m_runType = "eval";
private HashMap<String,String> m_results;
/**
* <p>close</p>
*/
public void close() {
}
/** {@inheritDoc} */
public void connect(final InetAddress address, final int port, final int timeout) throws IOException, Exception {
m_results = new HashMap<String,String>();
BSFManager bsfManager = new BSFManager();
File file = new File(m_fileName);
Map<String,Object> map = getParametersMap();
try {
if (m_langClass == null) {
m_langClass = BSFManager.getLangFromFilename(m_fileName);
}
if (m_bsfEngine != null && m_langClass != null && m_fileExtensions.length > 0 ) {
BSFManager.registerScriptingEngine(m_langClass, m_bsfEngine, m_fileExtensions);
}
if (file.exists() && file.canRead()) {
String code = IOUtils.getStringFromReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
// Declare some beans that can be used inside the script
bsfManager.declareBean("map", map, Map.class);
bsfManager.declareBean("ip_addr", address.getHostAddress(), String.class);
// TODO: I'm not sure how to deal with it on detectors. Is the node exists before running detectors? If so, I need NodeDao here.
// bsfManager.declareBean("node_id",svc.getNodeId(),int.class );
// bsfManager.declareBean("node_label", svc.getNodeLabel(), String.class);
bsfManager.declareBean("svc_name", m_serviceName, String.class);
bsfManager.declareBean("results", m_results, HashMap.class);
for (final Entry<String, Object> entry : map.entrySet()) {
bsfManager.declareBean(entry.getKey(), entry.getValue(), String.class);
}
LogUtils.infof(this, "Executing %s for %s", m_langClass, file.getAbsoluteFile());
if ("eval".equals(m_runType)) {
m_results.put("status", bsfManager.eval(m_langClass, "BSFDetector", 0, 0, code).toString());
} else if ("exec".equals(m_runType)) {
bsfManager.exec(m_langClass, "BSFDetector", 0, 0, code);
} else {
LogUtils.warnf(this, "Invalid run-type parameter value '%s' for service '%s'. Only 'eval' and 'exec' are supported.", m_runType, m_serviceName);
throw new RuntimeException("Invalid run-type '" + m_runType + "'");
}
if ("exec".equals(m_runType) && !m_results.containsKey("status")) {
LogUtils.warnf(this, "The exec script '%s' for service '%s' never put a 'status' entry in the 'results' bean. Exec scripts should put this entry with a value of 'OK' for up.", m_fileName, m_serviceName);
}
} else {
LogUtils.warnf(this, "Cannot locate or read BSF script file '%s'. Marking service '%s' down.", m_fileName, m_serviceName);
}
} catch (BSFException e) {
m_results.clear();
LogUtils.warnf(this, e, "BSFDetector poll for service '%s' failed with BSFException: %s", m_serviceName, e.getMessage());
} catch (FileNotFoundException e) {
m_results.clear();
LogUtils.warnf(this, "Could not find BSF script file '%s'. Marking service '%s' down.", m_fileName, m_serviceName);
} catch (IOException e) {
m_results.clear();
LogUtils.warnf(this, e, "BSFDetector poll for service '%s' failed with IOException: %s", m_serviceName, e.getMessage());
} catch (Throwable e) {
m_results.clear();
LogUtils.warnf(this, e, "BSFDetector poll for service '%s' failed with unexpected throwable: %s", m_serviceName, e.getMessage());
} finally {
bsfManager.terminate();
}
}
/**
* <p>receiveBanner</p>
*
* @return a {@link org.opennms.netmgt.provision.detector.bsf.response.BSFResponse} object.
* @throws java.io.IOException if any.
* @throws java.lang.Exception if any.
*/
public BSFResponse receiveBanner() throws IOException, Exception {
LogUtils.debugf(this, "Results: %s", m_results);
final BSFResponse response = new BSFResponse(m_results);
return response;
}
/**
* <p>sendRequest</p>
*
* @param request a {@link org.opennms.netmgt.provision.detector.bsf.request.BSFRequest} object.
* @return a {@link org.opennms.netmgt.provision.detector.bsf.response.BSFResponse} object.
* @throws java.io.IOException if any.
* @throws java.lang.Exception if any.
*/
public BSFResponse sendRequest(final BSFRequest request) throws IOException, Exception {
return null;
}
public String getServiceName() {
return m_serviceName;
}
public void setServiceName(String serviceName) {
this.m_serviceName = serviceName;
}
public String getFileName() {
return m_fileName;
}
public void setFileName(String fileName) {
this.m_fileName = fileName;
}
public String getLangClass() {
return m_langClass;
}
public void setLangClass(String langClass) {
this.m_langClass = langClass;
}
public String getBsfEngine() {
return m_bsfEngine;
}
public void setBsfEngine(String bsfEngine) {
this.m_bsfEngine = bsfEngine;
}
public String[] getFileExtensions() {
return m_fileExtensions;
}
public void setFileExtensions(String[] fileExtensions) {
this.m_fileExtensions = fileExtensions;
}
public String getRunType() {
return m_runType;
}
public void setRunType(String runType) {
this.m_runType = runType;
}
private Map<String,Object> getParametersMap() {
final Map<String,Object> map = new HashMap<String,Object>();
map.put("file-name", getFileName());
map.put("lang-class", getLangClass());
map.put("bsf-engine", getBsfEngine());
map.put("file-extensions", getFileExtensions());
map.put("run-type", getRunType());
return Collections.unmodifiableMap(map);
}
}