/* * RHQ Management Platform * Copyright (C) 2005-2008 Red Hat, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as * published by the Free Software Foundation, and/or the GNU Lesser * General Public License, version 2.1, also 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 and the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU General Public License * and the GNU Lesser General Public License along with this program; * if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package org.rhq.plugins.platform.content; import java.io.BufferedReader; import java.io.IOException; import java.io.StringReader; import java.util.HashSet; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.rhq.core.domain.content.PackageDetailsKey; import org.rhq.core.domain.content.PackageType; import org.rhq.core.domain.content.transfer.ResourcePackageDetails; import org.rhq.core.system.ProcessExecution; import org.rhq.core.system.ProcessExecutionResults; import org.rhq.core.system.SystemInfo; /** * Handles discovering RPMs installed on a Linux system. * * @author Jason Dobies */ public class RpmPackageDiscoveryDelegate { // Static -------------------------------------------- private static SystemInfo systemInfo; /** * Holds the full file name of the RPM executable if found. Will contain <code>null</code> if there is no RPM * executable on the system. */ private static String rpmExecutable; // Public -------------------------------------------- public static void checkExecutables() { // Make sure rpm is actually on the system ProcessExecution processExecution = new ProcessExecution("/usr/bin/which"); processExecution.setArguments(new String[] { "rpm" }); processExecution.setCaptureOutput(true); ProcessExecutionResults executionResults = systemInfo.executeProcess(processExecution); String capturedOutput = executionResults.getCapturedOutput(); rpmExecutable = (((capturedOutput == null) || "".equals(capturedOutput)) ? null : capturedOutput.trim()); } public static void setSystemInfo(SystemInfo systemInfo) { RpmPackageDiscoveryDelegate.systemInfo = systemInfo; } public static Set<ResourcePackageDetails> discoverPackages(PackageType type) throws IOException { Log log = LogFactory.getLog(RpmPackageDiscoveryDelegate.class); Set<ResourcePackageDetails> packages = new HashSet<ResourcePackageDetails>(); if (rpmExecutable == null) { return packages; } /* Sample output from: rpm -qa * xorg-x11-fonts-ethiopic-7.2-3.fc8 bitmap-fonts-0.3-5.1.2.fc7 bluez-utils-cups-3.20-4.fc8 * * In short, it's a list of installed packages. */ ProcessExecution listRpmsProcess = new ProcessExecution(rpmExecutable); listRpmsProcess.setArguments(new String[] { "-qa" }); listRpmsProcess.setCaptureOutput(true); ProcessExecutionResults executionResults = systemInfo.executeProcess(listRpmsProcess); String capturedOutput = executionResults.getCapturedOutput(); // Process the resulting output if (capturedOutput == null) { return packages; } BufferedReader rpmNameReader = new BufferedReader(new StringReader(capturedOutput)); String rpmName; while ((rpmName = rpmNameReader.readLine()) != null) { String name = null; String version = null; String architectureName = null; try { // Execute RPM query for each RPM ProcessExecution rpmQuery = new ProcessExecution(rpmExecutable); rpmQuery .setArguments(new String[] { "-q", "--qf", "%{NAME}\\n%{VERSION}.%{RELEASE}\\n%{ARCH}\\n%{INSTALLTIME}\\n%{FILEMD5S}\\n%{GROUP}\\n%{FILENAMES}\\n%{SIZE}\\n%{LICENSE}\\n%{DESCRIPTION}", rpmName }); rpmQuery.setCaptureOutput(true); ProcessExecutionResults rpmDataResults = systemInfo.executeProcess(rpmQuery); String rpmData = rpmDataResults.getCapturedOutput(); BufferedReader rpmDataReader = new BufferedReader(new StringReader(rpmData)); name = rpmDataReader.readLine(); version = rpmDataReader.readLine(); architectureName = rpmDataReader.readLine(); String installTimeString = rpmDataReader.readLine(); String md5 = rpmDataReader.readLine(); String category = rpmDataReader.readLine(); String fileName = rpmDataReader.readLine(); String sizeString = rpmDataReader.readLine(); String license = rpmDataReader.readLine(); StringBuffer description = new StringBuffer(); String descriptionTemp; while ((descriptionTemp = rpmDataReader.readLine()) != null) { description.append(descriptionTemp); } Long fileSize = null; if (sizeString != null) { try { fileSize = Long.parseLong(sizeString); } catch (NumberFormatException e) { log.warn("Could not parse file size: " + sizeString); } } Long installTime = null; if (installTimeString != null) { try { installTime = Long.parseLong(installTimeString); installTime *= 1000L; // RPM returns epoch seconds, we need epoch millis } catch (NumberFormatException e) { log.debug("Could not parse package install time"); } } // There may be multiple file names. For now, just ignore the package (I'll find a better way // to deal with this going forward). There will be a blank space in the fileName attribute, so // just abort if we see that if ((fileName == null) || fileName.equals("")) { continue; } PackageDetailsKey key = new PackageDetailsKey(name, version, "rpm", architectureName); ResourcePackageDetails packageDetails = new ResourcePackageDetails(key); packageDetails.setClassification(category); packageDetails.setDisplayName(name); packageDetails.setFileName(fileName); if (!md5.startsWith("00000000000000000000000000000000")) { if (md5.length() <= 32) { packageDetails.setMD5(md5); } else { packageDetails.setSHA256(md5); // md5's can only be 32 chars, anything more and we assume its a SHA256 } } packageDetails.setFileSize(fileSize); packageDetails.setLicenseName(license); packageDetails.setLongDescription(description.toString()); packageDetails.setInstallationTimestamp(installTime); packages.add(packageDetails); } catch (Exception e) { log.error("Error creating resource package. RPM Name: " + rpmName + " Version: " + version + " Architecture: " + architectureName); } } return packages; } }