Java tutorial
/* * 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.autoinventory; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.io.PrintStream; import java.text.DateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hyperic.hq.appdef.shared.AIPlatformValue; import org.hyperic.hq.appdef.shared.AIServerExtValue; import org.hyperic.hq.appdef.shared.AIServerValue; import org.hyperic.hq.product.ServerResource; import org.hyperic.util.StringUtil; import org.hyperic.util.StringifiedException; public class ScanState { private static HashMap installdirExcludes = new HashMap(); private static List installdirExcludesPrefixes = new ArrayList(); private static final Log _log = LogFactory.getLog(ScanState.class); static { loadInstalldirExcludes(); } private DateFormat dateFmt = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM); private ScanStateCore _core; /** ScanMethodClassName->ScanMethod */ private Map _scanMethods = null; private boolean _isDefaultScan = false; public ScanState() { _core = new ScanStateCore(); } public ScanState(ScanStateCore core) { _core = core; } public ScanStateCore getCore() { return _core; } public void setCore(ScanStateCore core) { _core = core; } public boolean getIsDefaultScan() { return _isDefaultScan; } public void setIsDefaultScan(boolean b) { _isDefaultScan = b; } public boolean getAreServersIncluded() { return _core.getAreServersIncluded(); } public void setAreServersIncluded(boolean b) { _core.setAreServersIncluded(b); } public long getStartTime() { return _core.getStartTime(); } /** * @return the formatted start time */ public String getStartTimeStr() { if (getStartTime() == 0) return "00/00/00 00:00:00"; return dateFmt.format(new Long(getStartTime())); } public void setStartTime(long startTime) { _core.setStartTime(startTime); } public long getEndTime() { return _core.getEndTime(); } public String getEndTimeStr() { if (getEndTime() == 0) return "00/00/00 00:00:00"; return dateFmt.format(new Long(getEndTime())); } public void setEndTime(long endTime) { _core.setEndTime(endTime); } /** * @return the formatted relapsed time */ public String getElapsedTimeStr() { long end = 0; // if the start time is zero, return no elapsed time if (getStartTime() == 0) return StringUtil.formatDuration(0); if (getEndTime() == 0) end = (new Date()).getTime(); else end = getEndTime(); return StringUtil.formatDuration(end - getStartTime()); } public boolean getIsDone() { return _core.getIsDone(); } public void setIsDone() { _core.setIsDone(true); } public boolean getIsInterrupted() { return _core.getIsInterrupted(); } public void setIsInterrupted() { _core.setIsInterrupted(true); } public StringifiedException getGlobalException() { return _core.getGlobalException(); } public void setGlobalException(Throwable _globalException) { _core.setGlobalException(new StringifiedException(_globalException)); } /** * Tell the scan state what scan methods will be run. * @param scanMethods An array of ScanMethod class names that * represent the ScanMethods that will be run in this scan. */ public void setScanMethods(String[] scanMethods) throws AutoinventoryException { // Walk thru the list and construct the ScanMethodState[] array ScanMethodState[] smStates = new ScanMethodState[scanMethods.length]; for (int i = 0; i < scanMethods.length; i++) { smStates[i] = new ScanMethodState(); smStates[i].setMethodClass(scanMethods[i]); } _core.setScanMethodStates(smStates); setupMethodHash(); } /** * Setup our internal hash of ScanMethodClassName->ScanMethod */ protected void setupMethodHash() throws AutoinventoryException { _scanMethods = new HashMap(); ScanMethodState[] smStates = _core.getScanMethodStates(); if (smStates == null) return; ScanMethod method; String methodClass; for (int i = 0; i < smStates.length; i++) { methodClass = smStates[i].getMethodClass(); try { method = (ScanMethod) Class.forName(methodClass).newInstance(); } catch (Exception e) { throw new AutoinventoryException(methodClass + ": error instantiating: " + e, e); } _scanMethods.put(methodClass, method); } } public boolean completedOK() { return _core.getIsDone() && (!hasExceptions()) && (!_core.getIsInterrupted()); } public boolean hasExceptions() { ScanMethodState[] smStates = _core.getScanMethodStates(); StringifiedException[] exceptions; for (int i = 0; i < smStates.length; i++) { exceptions = smStates[i].getExceptions(); if (exceptions != null && exceptions.length > 0) { return true; } } return false; } public void initStartTime() { _core.setStartTime(System.currentTimeMillis()); } public void initEndTime() { _core.setEndTime(System.currentTimeMillis()); } public long getScanDuration() { long startTime = _core.getStartTime(); long endTime = _core.getEndTime(); if (endTime == 0) { if (startTime == 0) { return 0; } return System.currentTimeMillis() - startTime; } return endTime - startTime; } public AIPlatformValue getPlatform() { return _core.getPlatform(); } public void setPlatform(AIPlatformValue platform) { _core.setPlatform(platform); } public String getCertDN() { return _core.getPlatform().getCertdn(); } public void setCertDN(String certDN) { _core.setCertDN(certDN); } public void addScanException(ScanMethod scanMethod, Throwable t) { ScanMethodState smState = findSMState("addScanException", scanMethod); smState.addException(new StringifiedException(t)); } public void addScanExceptions(ScanMethod scanMethod, Throwable[] t) { ScanMethodState smState = findSMState("addScanException", scanMethod); smState.addExceptions(t); } public void setScanStatus(ScanMethod scanMethod, String status) { ScanMethodState smState = findSMState("addScanException", scanMethod); smState.setStatus(status); } public ScanMethodState[] getScanMethodStates() { ScanMethodState[] smStates = _core.getScanMethodStates(); return smStates; } //XXX temporary during refactoring private AIServerValue getServerValue(Object o) { AIServerValue server; if (o instanceof AIServerValue) { server = (AIServerValue) o; } else { server = (AIServerValue) ((ServerResource) o).getResource(); } if (!server.cTimeHasBeenSet()) { server.setCTime(new Long(System.currentTimeMillis())); } return server; } private List excludeServers(List servers) { if (installdirExcludes.size() == 0) { return servers; } ArrayList includes = new ArrayList(); for (int i = 0; i < servers.size(); i++) { Object server = servers.get(i); String installpath = getServerValue(server).getInstallPath(); boolean exclude = false; if (installdirExcludes.get(installpath) != null) { continue; } for (int j = 0; j < installdirExcludesPrefixes.size(); j++) { String prefix = (String) installdirExcludesPrefixes.get(j); if (installpath.startsWith(prefix)) { exclude = true; break; } } if (!exclude) { includes.add(server); } } return includes; } /** * Add servers to the list of servers detected for a particular * scan method. * @param scanMethod The scan method to add servers to. * @param servers A List of AIServer objects representing * the servers (and their services) that were detected and should be * added and associated with the given scan method. */ public void addServers(ScanMethod scanMethod, List servers) { servers = excludeServers(servers); if (servers.isEmpty()) { return; } ScanMethodState smState = findSMState("addServers", scanMethod); AIServerValue[] newServers; AIServerValue[] existingServers = smState.getServers(); if (existingServers == null) { newServers = new AIServerValue[servers.size()]; for (int i = 0; i < newServers.length; i++) { newServers[i] = getServerValue(servers.get(i)); } } else { List<AIServerValue> allServers = new ArrayList<AIServerValue>(Arrays.asList(existingServers)); //Get rid of any servers we have already discovered (by autoinventoryidentifier). //ServerDetectors are ordered, so first one should always win for (Iterator iterator = servers.iterator(); iterator.hasNext();) { AIServerValue server = getServerValue(iterator.next()); String identifier = server.getAutoinventoryIdentifier(); boolean newIdentifier = true; for (AIServerValue existingServer : existingServers) { if (existingServer.getAutoinventoryIdentifier().equals(identifier)) { newIdentifier = false; break; } } if (newIdentifier) { allServers.add(server); } } newServers = allServers.toArray(new AIServerValue[allServers.size()]); } smState.setServers(newServers); } /** * For debugging purposes, print out the servers that were * detected. */ public void printServers() { ScanMethodState[] smStates = _core.getScanMethodStates(); AIServerValue[] servers; for (int i = 0; i < smStates.length; i++) { System.err.println("Detected by: " + smStates[i].getMethodClass()); servers = smStates[i].getServers(); for (i = 0; i < servers.length; i++) { System.err.println("\t" + servers[i]); } } } /** * For debugging purposes, print stack traces for all exceptions */ public void printStackTraces() { ScanMethodState[] smStates = _core.getScanMethodStates(); StringifiedException[] exc; for (int i = 0; i < smStates.length; i++) { exc = smStates[i].getExceptions(); if (exc != null && exc.length > 0) { System.err.println("Exceptions for method " + smStates[i].getMethodClass() + ":"); for (int j = 0; j < exc.length; j++) { System.err.println("\n" + exc[j].getStackTrace()); } } } } /** * For debugging and command-line use, pretty-print full status info. * @param out The stream to write to. */ public void printFullStatus(PrintStream out) throws AutoinventoryException { StringifiedException globalEx = _core.getGlobalException(); ScanMethodState[] smStates = _core.getScanMethodStates(); if (globalEx != null) { out.println("Severe failure: " + globalEx); out.println(globalEx.getStackTrace()); } if (smStates == null) { out.println("scan not yet started."); return; } printMainStatus(out); for (int i = 0; i < smStates.length; i++) { printMethodStatus(smStates[i], out); } } public void printMainStatus(PrintStream out) { out.print("\nOVERALL STATUS: "); String status = null; if (_core.getIsInterrupted()) { status = "interrupted before normal completion"; } else if (_core.getIsDone()) { status = "completed"; } else { status = "scan in progress"; } if (_core.getGlobalException() != null) { status += ", however a general scanning error occurred"; } else if (hasExceptions()) { status += " successfully, however one or more scan methods had errors"; } else if (_core.getIsDone()) { status += " successfully with no errors"; } out.println(status); String duration = StringUtil.formatDuration(getScanDuration()); out.println("Run time: " + duration); AIPlatformValue platform = _core.getPlatform(); if (platform != null) { out.println("\nPlatform Detected:"); out.println("\t" + platform); out.println("\tIP addresses: " + StringUtil.arrayToString(platform.getAIIpValues())); } else { out.println("\nNo Platform Detected!"); } } public void printMethodStatus(ScanMethodState smState, PrintStream out) throws AutoinventoryException { ScanMethod method = findScanMethod(smState.getMethodClass()); out.println("\n" + method.getName() + ":"); // Print exception (if any) StringifiedException[] t = smState.getExceptions(); String status = smState.getStatus(); if (t != null && t.length > 0) { out.println("\t* SCAN FAILED: "); if (status != null) { out.println("\t* Last status before failure: " + status); } else { out.println("\t* No status message available."); } for (int i = 0; i < t.length; i++) { out.println("\t* " + t[i].toString()); out.println("\t* Stack Trace:"); out.println(t[i].getStackTrace()); } } else { if (status == null) { out.println("\t* Status: unknown"); } else { out.println("\t* Status: " + status); } } // PRINT SERVERS DETECTED AIServerValue[] servers = smState.getServers(); if (servers == null || servers.length == 0) { out.println("\t* No Servers Detected"); } else { out.println("\t* Detected Servers:"); for (int i = 0; i < servers.length; i++) { out.println("\t" + servers[i]); } } out.println("\n"); } public String toString() { if (_core == null) return "[ScanState]"; return _core.toString(); } /** * Get the set of all servers detected in this autoinventory scan. * This is the method that reconciles the fact that multiple scan methods * may have discovered the same server. We assemble the list of all * servers by iterating over each scan method in order of authority level. * The scan methods with the highest authority level have their servers * added first. Scan methods with lower authority levels will have their * servers added as long as they have a different autoinventory ID from * ones discovered by methods with higher authority levels. * @return A Set of AIServerValue objects. The Set uniqueness * is based on the server autoinventory identifier, which is * usually the same as the install path. */ public Set getAllServers() throws AutoinventoryException { // allServers will guarantee uniqueness on the AIID. Set allServers = new TreeSet(COMPARE_AIID); // Put all the scan methods in a list Map scanMethods = getScanMethodMap(); Iterator iter = scanMethods.keySet().iterator(); List smList = new ArrayList(); while (iter.hasNext()) { smList.add(scanMethods.get(iter.next())); } // Sort the scan methods by authority level. Collections.sort(smList, COMPARE_AUTH); // Iterate over the scan methods AIServerValue[] servers; String methodClass; ScanMethod method; ScanMethodState smState; for (int i = 0; i < smList.size(); i++) { method = (ScanMethod) smList.get(i); smState = findSMState("getAllServers", method); methodClass = smState.getMethodClass(); servers = smState.getServers(); if (servers != null) { for (int j = 0; j < servers.length; j++) { if (!allServers.add(servers[j])) { if (_log != null) { _log.info("Server not added because another scan " + "method already detected it:" + servers[j]); } } } } } Map mServers = new HashMap(); //look for servers with the same Metric Connect HashCode //for example, two JBoss servers with different installpath //but the same config: jnp://localhost:1099 for (Iterator allIter = allServers.iterator(); allIter.hasNext();) { Object o = allIter.next(); if (!(o instanceof AIServerExtValue)) { continue; } AIServerExtValue server = (AIServerExtValue) o; if (!server.getAutoEnable()) { continue; } int hashCode = server.getMetricConnectHashCode(); if (hashCode == 0) { continue; } Integer key = new Integer(hashCode); AIServerExtValue cServer = (AIServerExtValue) mServers.get(key); if (cServer == null) { //based on ScanImpl authority, the first server //found is the most likely to be running. mServers.put(key, server); } else { //found a server with the same connect config //turn off AutoEnable server.setAutoEnable(false); //disable metric collection server.unsetMeasurementConfig(); if (_log != null) { _log.info("Turning off AutoEnable for server " + server.getName() + " [" + server.getInstallPath() + "]" + ", has the same metric connect config as " + cServer.getName() + " [" + cServer.getInstallPath() + "]"); } } } return allServers; } protected ScanMethodState findSMState(String caller, ScanMethod scanMethod) { ScanMethodState[] smStates = _core.getScanMethodStates(); String smClassName = scanMethod.getClass().getName(); for (int i = 0; i < smStates.length; i++) { if (smStates[i].getMethodClass().equals(smClassName)) { return smStates[i]; } } throw new IllegalArgumentException("Error finding smState: " + smClassName + ", caller=" + caller); } protected ScanMethod findScanMethod(String methodClass) throws AutoinventoryException { Map scanMethods = getScanMethodMap(); ScanMethod m = (ScanMethod) scanMethods.get(methodClass); if (m != null) return m; throw new IllegalArgumentException("ScanMethod not found: " + methodClass); } private Map getScanMethodMap() throws AutoinventoryException { if (_scanMethods == null) setupMethodHash(); return _scanMethods; } public boolean isSameState(ScanState other) throws AutoinventoryException { // Compare platform attributes AIPlatformValue p1, p2; p1 = getPlatform(); p2 = other.getPlatform(); if (!AICompare.compareAIPlatforms(p1, p2)) return false; Set servers1, servers2; servers1 = getAllServers(); servers2 = other.getAllServers(); if (!AICompare.compareAIServers(servers1, servers2)) return false; return true; } private static Comparator COMPARE_AIID = new ServerComparator_AIID(); static class ServerComparator_AIID implements Comparator { public ServerComparator_AIID() { } public int compare(Object o1, Object o2) { if (o1 instanceof AIServerValue && o2 instanceof AIServerValue) { return ((AIServerValue) o2).getAutoinventoryIdentifier() .compareTo(((AIServerValue) o1).getAutoinventoryIdentifier()); } return 0; // all other object are "equal" } public boolean equals(Object o) { return false; } } private static Comparator COMPARE_AUTH = new ServerComparator_AuthLevel(); static class ServerComparator_AuthLevel implements Comparator { public ServerComparator_AuthLevel() { } public int compare(Object o1, Object o2) { if (o1 instanceof ScanMethod && o2 instanceof ScanMethod) { return ((ScanMethod) o2).getAuthorityLevel() - ((ScanMethod) o1).getAuthorityLevel(); } return 0; // all other object are "equal" } public boolean equals(Object o) { return false; } } //any installpath found in ~/.hq/installdir.excludes //will not be reported by AI private static void loadInstalldirExcludes() { String path = System.getProperty("user.home") + File.separator + ".hq" + File.separator + "installdir.excludes"; File excludes = new File(path); if (!excludes.exists()) { return; } FileReader is = null; try { is = new FileReader(excludes); BufferedReader in = new BufferedReader(is); String line; while ((line = in.readLine()) != null) { line = line.trim(); if (line.length() == 0) { continue; } if (line.charAt(0) == '#') { continue; } if (line.endsWith("*")) { line = line.substring(0, line.length() - 1); installdirExcludesPrefixes.add(line); } installdirExcludes.put(line, Boolean.TRUE); } } catch (IOException e) { e.printStackTrace(); } finally { if (is != null) { try { is.close(); } catch (IOException e) { } } } } }