Java tutorial
/* * 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 as published by * the Free Software Foundation version 2 of the License. * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.rhq.enterprise.server.plugins.rhnhosted; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.zip.GZIPOutputStream; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.xmlrpc.XmlRpcException; import org.rhq.enterprise.server.plugin.pc.content.AdvisoryBugDetails; import org.rhq.enterprise.server.plugin.pc.content.AdvisoryCVEDetails; import org.rhq.enterprise.server.plugin.pc.content.AdvisoryDetails; import org.rhq.enterprise.server.plugin.pc.content.AdvisoryPackageDetails; import org.rhq.enterprise.server.plugin.pc.content.ContentProviderPackageDetails; import org.rhq.enterprise.server.plugin.pc.content.ContentProviderPackageDetailsKey; import org.rhq.enterprise.server.plugin.pc.content.DistributionDetails; import org.rhq.enterprise.server.plugin.pc.content.DistributionFileDetails; import org.rhq.enterprise.server.plugin.pc.content.ThreadUtil; import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnChannelFamilyType; import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnChannelType; import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnErratumBugType; import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnErratumType; import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnKickstartFileType; import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnKickstartableTreeType; import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnPackageType; import org.rhq.enterprise.server.plugins.rhnhosted.xmlrpc.RhnComm; import org.rhq.enterprise.server.plugins.rhnhosted.xmlrpc.RhnDownloader; /** * @author pkilambi * */ public class RHNHelper { private final String baseurl; private final RhnComm rhndata; private final RhnDownloader rhndownload; private final String systemid; private final String distributionType; private final Log log = LogFactory.getLog(RHNHelper.class); /** * Constructor. * * @param baseurl The base url to connect to hosted * @param systemIdIn systemId to use for auth */ public RHNHelper(String baseurl, String systemIdIn) { this.baseurl = baseurl; this.rhndata = new RhnComm(baseurl); this.rhndownload = new RhnDownloader(baseurl); this.systemid = systemIdIn; this.distributionType = "kickstart"; } public boolean checkSystemId(String systemId) throws IOException, XmlRpcException { return this.rhndata.checkSystemId(systemId); } public List<DistributionDetails> getDistributionMetaData(List<String> labels) throws IOException, XmlRpcException { log.debug("getDistributionMetaData(" + labels + " invoked"); List<DistributionDetails> distros = new ArrayList<DistributionDetails>(); List<RhnKickstartableTreeType> ksTreeTypes = rhndata.getKickstartTreeMetadata(this.systemid, labels); for (RhnKickstartableTreeType ksTree : ksTreeTypes) { log.debug("Forming DistributionDetails(" + ksTree.getLabel() + ", " + ksTree.getBasePath() + " , " + distributionType); DistributionDetails details = new DistributionDetails(ksTree.getLabel(), ksTree.getBasePath(), distributionType); distros.add(details); List<RhnKickstartFileType> ksFiles = ksTree.getRhnKickstartFiles().getRhnKickstartFile(); for (RhnKickstartFileType ksFile : ksFiles) { if (log.isDebugEnabled()) { log.debug("RHNHelper::getDistributionMetaData<ksLabel=" + ksTree.getLabel() + "> current file = " + ksFile.getRelativePath() + ", md5sum = " + ksFile.getMd5Sum() + ", lastModified = " + ksFile.getLastModified() + ", fileSize = " + ksFile.getFileSize()); } Long lastMod = Long.parseLong(ksFile.getLastModified()); DistributionFileDetails dFile = new DistributionFileDetails(ksFile.getRelativePath(), lastMod, ksFile.getMd5Sum()); Long fileSize = Long.parseLong(ksFile.getFileSize()); dFile.setFileSize(fileSize); details.addFile(dFile); } } return distros; } public List<AdvisoryDetails> getAdvisoryMetadata(List<String> advisoryList, String repoName) throws XmlRpcException, IOException, InterruptedException { List<AdvisoryDetails> erratadetails = new ArrayList<AdvisoryDetails>(); List<RhnErratumType> errata = rhndata.getErrataMetadata(this.systemid, advisoryList); for (RhnErratumType erratum : errata) { ThreadUtil.checkInterrupted(); log.debug("Forming AdvisoryDetails(" + erratum.getAdvisory()); AdvisoryDetails details = new AdvisoryDetails(erratum.getAdvisory(), erratum.getRhnErratumAdvisoryType(), erratum.getRhnErratumSynopsis()); details.setDescription(erratum.getRhnErratumDescription()); details.setSolution(erratum.getRhnErratumSolution()); details.setTopic(erratum.getRhnErratumTopic()); details.setIssue_date(getLongForDate(erratum.getRhnErratumIssueDate())); details.setUpdate_date(getLongForDate(erratum.getRhnErratumUpdateDate())); details.setAdvisory_name(erratum.getRhnErratumAdvisoryName()); details.setAdvisory_rel(erratum.getRhnErratumAdvisoryRel()); String cvestr = erratum.getCveNames(); String[] cves = cvestr.split(" "); log.debug("list of cves " + cvestr + cves.toString()); for (String cve : cves) { if (log.isDebugEnabled()) { log.debug("RHNHelper::getAdvisoryMetaData<Advisory=" + erratum.getAdvisory() + "> CVEs<" + cve + ">"); } AdvisoryCVEDetails acve = new AdvisoryCVEDetails(cve); details.addCVE(acve); } List<RhnErratumBugType> ebugs = erratum.getRhnErratumBugs().getRhnErratumBug(); if (ebugs != null) { for (RhnErratumBugType ebug : ebugs) { if (log.isDebugEnabled()) { log.debug("RHNHelper::getAdvisoryMetaData<Advisory=" + erratum.getAdvisory() + "> Bugs<" + ebug + ">"); } AdvisoryBugDetails dbug = new AdvisoryBugDetails(ebug.getRhnErratumBugId()); details.addBug(dbug); } } String pkgs = erratum.getPackages(); String[] pkgIds = pkgs.split(" "); //try { List<AdvisoryPackageDetails> apkgdetails = new ArrayList<AdvisoryPackageDetails>(); List<RhnPackageType> pkgdetails = rhndata.getPackageMetadata(this.systemid, Arrays.asList(pkgIds)); for (RhnPackageType pkgd : pkgdetails) { if (log.isDebugEnabled()) { log.debug("RHNHelper::getAdvisoryMetaData<Advisory=" + erratum.getAdvisory() + "> Package<" + pkgd + ">"); } String name = pkgd.getName(); String version = pkgd.getVersion(); String arch = pkgd.getPackageArch(); String release = pkgd.getRelease(); String rpmname = constructRpmDisplayName(name, version, release, arch); AdvisoryPackageDetails apkgd = new AdvisoryPackageDetails(name, version, arch, rpmname); apkgdetails.add(apkgd); } details.addPkgs(apkgdetails); //} catch (Exception e) { // e.printStackTrace(); // } erratadetails.add(details); } return erratadetails; } /** * Extract the package metadata for all available packages to sync * @param packageIds Valid package ids for getPackageMatadata call to fetch from hosted * @param channelName channel name of passed in package ids * @return A list of package detail objects * @throws Exception On all errors */ public List<ContentProviderPackageDetails> getPackageDetails(List packageIds, String channelName) throws Exception { log.debug("getPackageDetails() for " + packageIds.size() + " packageIds on channel " + channelName); int skippedPackages = 0; int pkgNoName = 0; List<ContentProviderPackageDetails> pdlist = new ArrayList<ContentProviderPackageDetails>(); List<RhnPackageType> pkgs = rhndata.getPackageMetadata(this.systemid, packageIds); log.debug(pkgs.size() + " packages were returned from getPackageMetadata()."); for (RhnPackageType pkg : pkgs) { try { ContentProviderPackageDetails details = getDetails(pkg, channelName); pdlist.add(details); } catch (Exception e) { if (pkg != null) { if (StringUtils.isBlank(pkg.getName())) { log.debug("getPackageDetails skipping package with no name."); pkgNoName++; continue; } } log.warn("Caught exception with getDetails() of package: " + pkg.getName() + " : " + e); log.warn("Package: id = " + pkg.getId() + " getSourceRpm() = " + pkg.getSourceRpm() + ", getDescription() = " + pkg.getRhnPackageDescription()); // something went wrong while constructing the pkg object. // Proceed to next and get as many packages as we can. skippedPackages++; continue; } } log.info("We skipped: " + skippedPackages + " packages. " + "We also skipped " + pkgNoName + " packages because they had no name"); log.info("getPackageDetails was called with a list of package ids size = " + packageIds.size() + " we have fetched metadata for " + pdlist.size() + " packages"); return pdlist; } /** * Extract the package details for each rpm metadata fetched * * @param p an rpm package metadata object * @param channelName channel name * * @return ContentProviderPackageDetails pkg object */ private ContentProviderPackageDetails getDetails(RhnPackageType p, String channelName) throws IOException { String name = p.getName(); String version = p.getVersion(); String arch = p.getPackageArch(); String downloadName = constructRpmDownloadName(name, version, p.getRelease(), p.getEpoch(), arch); String displayName = constructRpmDisplayName(name, version, p.getRelease(), arch); ContentProviderPackageDetailsKey key = new ContentProviderPackageDetailsKey(name, version, "rpm", arch, "Linux", "Platforms"); ContentProviderPackageDetails pkg = new ContentProviderPackageDetails(key); pkg.setDisplayName(name); pkg.setShortDescription(p.getRhnPackageSummary()); pkg.setLongDescription(p.getRhnPackageDescription()); pkg.setFileName(displayName); pkg.setFileSize(new Long(p.getPackageSize())); pkg.setFileCreatedDate(new Long(p.getLastModified())); pkg.setLicenseName("license"); pkg.setMD5(p.getMd5Sum()); pkg.setLocation(constructPackageUrl(channelName, downloadName)); String metadata = PrimaryXML.createPackageXML(p); byte[] gzippedMetadata = gzip(metadata.getBytes()); pkg.setMetadata(gzippedMetadata); return pkg; } /** * Get List of packagesIds for Given Channels * @param channelName channel name * @return List of all package ids associated to the channel * @throws IOException on io errors on systemid reads * @throws XmlRpcException on xmlrpc faults */ public List<String> getChannelPackages(String channelName) throws IOException, XmlRpcException { log.debug("getChannelPackages(" + channelName + ")"); ArrayList<String> allPackages = new ArrayList(); List<RhnChannelType> channels = rhndata.getChannels(this.systemid, Arrays.asList(channelName)); for (RhnChannelType channel : channels) { String packages = channel.getPackages(); String[] pkgIds = packages.split(" "); if (pkgIds.length > 1) { allPackages.addAll(Arrays.asList(pkgIds)); } } return allPackages; } /** * Get List of errataIds for Given Channels * @param channelName channel name * @return List of all errata ids associated to the channel * @throws IOException on io errors on systemid reads * @throws XmlRpcException on xmlrpc faults */ public List<String> getChannelAdvisory(String channelName) throws IOException, XmlRpcException { log.debug("getChannelAdvisory(" + channelName + ")"); ArrayList<String> allAdvisory = new ArrayList(); List<RhnChannelType> channels = rhndata.getChannels(this.systemid, Arrays.asList(channelName)); for (RhnChannelType channel : channels) { String errata = channel.getChannelErrata(); String[] errataIds = errata.split(" "); if (errataIds.length > 1) { allAdvisory.addAll(Arrays.asList(errataIds)); } } return allAdvisory; } /** * Get a list of all Syncable Channels based on entitled channel families * @return A list of channel labels * @throws IOException on systemid reads * @throws XmlRpcException on xmlrpc faults */ public List<String> getSyncableChannels() throws IOException, XmlRpcException { log.debug("getSyncableChannels()"); ArrayList<String> allchannels = new ArrayList<String>(); String[] ignoredChannelFamiliesArray = { "education", "k12ltsp", "rh-public", "rhel-devsuite", "rhel-gfs" }; List<String> ignoredChannelFamilies = Arrays.asList(ignoredChannelFamiliesArray); log.debug("Ignoring expired channel families :"); log.debug(ignoredChannelFamilies.toString()); List<RhnChannelFamilyType> cfts = rhndata.getChannelFamilies(this.systemid); for (RhnChannelFamilyType cf : cfts) { if (ignoredChannelFamilies.contains(cf.getLabel())) { continue; } String channeldata = cf.getChannelLabels(); String[] clabels = channeldata.split(" "); if (clabels.length > 1) { allchannels.addAll(Arrays.asList(clabels)); } } return allchannels; } /** * * @return returns list of all possible kickstart labels from all possible channels * @throws IOException * @throws XmlRpcException */ public List<String> getSyncableKickstartLabels() throws IOException, XmlRpcException { log.debug("getSyncableKickstartLabels() - no channels passed, will use all available channels"); List<String> allChannels = getSyncableChannels(); return getSyncableKickstartLabels(allChannels); } /** * * @param channelName channel name * @return kickstart labels part of the passed in channel name * @throws IOException * @throws XmlRpcException */ public List<String> getSyncableKickstartLabels(String channelName) throws IOException, XmlRpcException { log.debug("getSyncableKickstartLabels(" + channelName + ")"); List<String> names = new ArrayList<String>(); names.add(channelName); return getSyncableKickstartLabels(names); } /** * * @param channelLabels list of channel names to restrict return data to * @return kickstart labels from the passed in list of channel names * @throws IOException * @throws XmlRpcException */ public List<String> getSyncableKickstartLabels(List<String> channelLabels) throws IOException, XmlRpcException { log.debug("getSyncableKickstartLabels(" + channelLabels + ")"); List<String> ksLabels = new ArrayList<String>(); List<RhnChannelType> rct = rhndata.getChannels(this.systemid, channelLabels); for (RhnChannelType ct : rct) { String ksTrees = ct.getKickstartableTrees(); String[] trees = ksTrees.split(" "); ksLabels.addAll(Arrays.asList(trees)); } return ksLabels; } /** * Open an input stream to specifed relative url. Prepends the baseurl to the <i>url</i> and opens and opens and * input stream. Files with a .gz suffix will be unziped (inline). * * @param location A url that is relative to the <i>baseurl</i> and references a file within the repo. * * @return An open input stream that <b>must</b> be closed by the caller. * * @throws IOException On io errors. * * @throws XmlRpcException On all errors. */ public InputStream openStream(String location) throws IOException, XmlRpcException { log.info("File being fetched from: " + location); return rhndownload.getFileStream(this.systemid, location); } /** * Constructs a downloadable url for package downloads. * @param channelName channel label to be synced. * @param rpmName rpm file name * @return a valid url location to fetch the rpm from. */ public String constructPackageUrl(String channelName, String rpmName) { return constructPackageUrl(baseurl, channelName, rpmName); } static public String constructPackageUrl(String baseurl, String channelName, String rpmName) { String appendurl = "/SAT/$RHN/" + channelName + "/getPackage/" + rpmName; return baseurl + appendurl; } /** * Constructs a downloadable url for package downloads. * @param channelName channel label to be synced. * @param ksTreeLabel kickstart tree label name * @param ksFilePath path to kickstart file * @return a valid url location to fetch the rpm from. */ public String constructKickstartFileUrl(String channelName, String ksTreeLabel, String ksFilePath) { return constructKickstartFileUrl(baseurl, channelName, ksTreeLabel, ksFilePath); } static public String constructKickstartFileUrl(String baseurl, String channelName, String ksTreeLabel, String ksFilePath) { String appendurl = "/SAT/$RHN/" + channelName + "/getKickstartFile/" + ksTreeLabel + "/" + ksFilePath; return baseurl + appendurl; } /** * Method to construct an rpm format filename for download url * @param name rpm package name * @param version rpm package version * @param release rpm package release * @param epoch rpm package epoch * @param arch rpm package arch * @return an rpm package name string */ static public String constructRpmDownloadName(String name, String version, String release, String epoch, String arch) { String releaseepoch = release + ":" + epoch; return name + "-" + version + "-" + releaseepoch + "." + arch + ".rpm"; } /** * construct a legitimate rpm name to display * @param name * @param version * @param release * @param arch * @return rpm name String */ static public String constructRpmDisplayName(String name, String version, String release, String arch) { return name + "-" + version + "-" + release + "." + arch + ".rpm"; } private byte[] gzip(byte[] input) throws IOException { ByteArrayOutputStream zipped = new ByteArrayOutputStream(); GZIPOutputStream gzip = new GZIPOutputStream(zipped); try { gzip.write(input); } finally { gzip.close(); } return zipped.toByteArray(); } private long getLongForDate(String dateIn) { return Long.parseLong(dateIn); } /* * (non-Javadoc) @see java.lang.Object#toString() */ @Override public String toString() { return baseurl; } }