/* * NOTE: This copyright does *not* cover user programs that use HQ * program services by normal system calls through the application * program interfaces provided as part of the Hyperic Plug-in Development * Kit or the Hyperic Client Development Kit - this is merely considered * normal use of the program, and does *not* fall under the heading of * "derived work". * * Copyright (C) [2004, 2005, 2006], Hyperic, Inc. * This file is part of HQ. * * HQ is free software; you can redistribute it and/or modify * it under the terms version 2 of the GNU General Public License as * published by the Free Software Foundation. This program 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 this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA. */ package org.hyperic.hq.plugin.informix; import java.io.File; import java.io.IOException; import java.sql.Connection; import java.sql.DriverManager; import java.sql.Statement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import org.hyperic.hq.product.AutoServerDetector; import org.hyperic.hq.product.FileServerDetector; import org.hyperic.hq.product.PluginException; import org.hyperic.hq.product.RegistryServerDetector; import org.hyperic.hq.product.ServerDetector; import org.hyperic.hq.product.ServerResource; import org.hyperic.hq.product.ServiceResource; import org.hyperic.util.config.ConfigResponse; import org.hyperic.util.file.FileUtil; import org.hyperic.util.jdbc.DBUtil; import org.hyperic.sigar.win32.RegistryKey; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class InformixServerDetector extends ServerDetector implements FileServerDetector, RegistryServerDetector, AutoServerDetector { private static final boolean DEBUG = InformixPluginUtil.DEBUG; static final String PROP_DBNAME = InformixPluginUtil.PROP_DBNAME, PROP_TABLENAME = InformixPluginUtil.PROP_TABLENAME, JDBC_DRIVER = InformixPluginUtil.JDBC_DRIVER, PROP_CHUNK = InformixPluginUtil.PROP_CHUNK, PROP_TABLE = InformixMeasurementPlugin.PROP_TABLE, PROP_URL = InformixMeasurementPlugin.PROP_URL, PROP_USER = InformixMeasurementPlugin.PROP_USER, PROP_PASSWORD = InformixMeasurementPlugin.PROP_PASSWORD; private Log log = LogFactory.getLog("InformixServerDetector"); private static final String INFORMIX_VERSION = "(Informix)"; //likely will only work w/ linux due to permissions //and setting of argv[0] to the full binary path. //State.Name == 'postgres' on OSX, 'postmaster' elsewhere private static final String PTQL_QUERY = "State.Name.re=oninit,State.Name.Pne=$1,Args.0.re=.*oninit$"; // Table discovery query private static final String TABLE_QUERY = "select dbsname, tabname from sysptprof"; // Data Chunk discovery query private static final String CHUNK_QUERY = "select name datachunk from sysdbstab"; // Resource types and versions static final String SERVER_NAME = "Informix", TABLE = "Table", INDEX = "Index", VERSION_10 = "10.0"; private static List getServerProcessList() { ArrayList servers = new ArrayList(); long[] pids = getPids(PTQL_QUERY); for (int i=0; i<pids.length; i++) { String exe = getProcExe(pids[i]); if (exe == null) continue; File binary = new File(exe); if (!binary.isAbsolute()) continue; servers.add(binary.getAbsolutePath()); } return servers; } public List getServerResources(ConfigResponse platformConfig) throws PluginException { List servers = new ArrayList(); List paths = getServerProcessList(); for (int i=0; i<paths.size(); i++) { String dir = (String)paths.get(i); List found = getServerList(dir); if (!found.isEmpty()) servers.addAll(found); } return servers; } public List getServerResources(ConfigResponse platformConfig, String path) throws PluginException { // Normal file scan return getServerList(path); } public List getServerResources (ConfigResponse platformConfig, String path, RegistryKey current) throws PluginException { return getServerList(path); } public List getServerList(String path) throws PluginException { ConfigResponse productConfig = new ConfigResponse(); productConfig.setValue("hostname", "localhost"); productConfig.setValue("port", "3500"); productConfig.setValue("servername", "test_shm"); productConfig.setValue(PROP_USER, "informix"); productConfig.setValue(PROP_PASSWORD, "sainformix"); List servers = new ArrayList(); // Only check the binaries if they match the path we expect if (path.indexOf("oninit") == -1) return servers; String installdir = getParentDir(path, 2); ServerResource server = createServerResource(installdir); String version = getTypeInfo().getVersion(); // Set custom properties ConfigResponse cprop = new ConfigResponse(); cprop.setValue("version", version); server.setCustomProperties(cprop); server.setProductConfig(productConfig); server.setMeasurementConfig(); server.setName(SERVER_NAME+" "+version); servers.add(server); return servers; } protected List discoverServices(ConfigResponse config) throws PluginException { String url = config.getValue(PROP_URL); String user = config.getValue(PROP_USER); String pass = config.getValue(PROP_PASSWORD); try { Class.forName(JDBC_DRIVER); } catch (ClassNotFoundException e) { // No driver. Should not happen. String msg = "Unable to load JDBC "+"Driver: "+e.getMessage(); throw new PluginException(msg); } List rtn = new ArrayList(); Connection conn = null; Statement stmt = null; ResultSet rs = null; try { conn = DriverManager.getConnection(url, user, pass); // Discover all Informix DB tables. stmt = conn.createStatement(); setTableServices(rtn, conn, stmt); setChunkServices(rtn, conn, stmt); } catch (SQLException e) { String msg = "Error querying for services: "+e.getMessage(); throw new PluginException(msg); } finally { DBUtil.closeJDBCObjects(this.log, conn, stmt, rs); } return rtn; } private void setChunkServices(List services, Connection conn, Statement stmt) throws SQLException { ResultSet rs = null; try { rs = stmt.executeQuery(CHUNK_QUERY); while (rs != null && rs.next()) { String chunkName = rs.getString(1).trim(); ServiceResource service = new ServiceResource(); service.setType(this, "DBSpace"); service.setServiceName("chunk="+chunkName); ConfigResponse productConfig = new ConfigResponse(); productConfig.setValue(PROP_CHUNK, chunkName); service.setProductConfig(productConfig); service.setMeasurementConfig(); service.setControlConfig(); services.add(service); } } finally { if (rs != null) rs.close(); } } private void setTableServices(List services, Connection conn, Statement stmt) throws SQLException { ResultSet rs = null; try { rs = stmt.executeQuery(TABLE_QUERY); while (rs != null && rs.next()) { String tablename = rs.getString(2).trim(), dbname = rs.getString(1).trim(); if (!isValidTablename(tablename)) continue; ServiceResource service = new ServiceResource(); service.setType(this, TABLE); service.setServiceName("dbname="+dbname+", tablename="+tablename); ConfigResponse productConfig = new ConfigResponse(); productConfig.setValue(PROP_TABLE, tablename); productConfig.setValue(PROP_DBNAME, dbname); service.setProductConfig(productConfig); service.setMeasurementConfig(); service.setControlConfig(); services.add(service); } } finally { if (rs != null) rs.close(); } } private boolean isValidTablename(String tablename) { return (tablename.matches("[A-Za-z_][A-Za-z0-9_]*")) ? true : false; } }