/* * 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.yum; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.zip.GZIPOutputStream; import org.jdom.Element; import org.jdom.output.XMLOutputter; import org.rhq.core.domain.content.PackageDetails; import org.rhq.enterprise.server.plugin.pc.content.ContentProviderPackageDetails; import org.rhq.enterprise.server.plugin.pc.content.ContentProviderPackageDetailsKey; import org.rhq.enterprise.server.plugins.yum.Repodata.Meta; /** * The Repo is a proxy for a local or remote yum repository. * * @author jortel */ public class Repo { /** * A repodata object used to access the yum repo's content. */ private Repodata repodata; /** * Constructor. * * @param reader An initialized repo reader. */ public Repo(RepoReader reader) { repodata = new Repodata(reader); } /** * Connect to the yum repo. * * @throws Exception On connection error. */ public void connect() throws Exception { repodata.refresh(); } /** * Disconnect and reset object. */ public void disconnect() { repodata.clear(); } /** * Get a string representation of metadata entry contained within the primary.xml for the specified package by name. * * @param pkgname A fully qualified package name. * * @return A <i>string</i> XML fragment when found, else null. * * @throws Exception On all errors. */ public String getPackageMetadataString(String pkgname) throws Exception { return Repodata.toString(getPackageMetadata(pkgname)); } /** * Get the metadata entry contained within the primary.xml for the specified package by name. * * @param pkgname A fully qualified package name. * * @return A node containing the packages metadata when found, else null. * * @throws Exception On all errors. */ @SuppressWarnings("unchecked") public Element getPackageMetadata(String pkgname) throws Exception { Element primary = repodata.getMetadata(Meta.primary); for (Element p : (List<Element>) primary.getChildren("package", Repodata.yumns)) { if (p.getChildText("name", Repodata.yumns).equals(pkgname)) { return p; } } return null; } /** * Get a list of {@link org.rhq.core.domain.content.PackageDetails } for all packages contained with the yum repo. * * @return A list of package details. * * @throws Exception On all errors. */ @SuppressWarnings("unchecked") public List<ContentProviderPackageDetails> getPackageDetails() throws Exception { List<ContentProviderPackageDetails> list = new ArrayList<ContentProviderPackageDetails>(); Element primary = repodata.getMetadata(Meta.primary); for (Element p : (List<Element>) primary.getChildren("package", Repodata.yumns)) { list.add(getDetails(p)); } return list; } /** * Get a {@link org.rhq.core.domain.content.PackageDetails } for the specified package by name. * * @param pkgname A fully qualified package name. * * @return The found package detail when found, else null. * * @throws Exception On all errors. */ public PackageDetails getPackageDetails(String pkgname) throws Exception { return getDetails(getPackageMetadata(pkgname)); } /** * Open and return an input stream for the specified package (bit) by name. * * @param pkgname A fully qualified package name. * * @return An open input stream that <b>must</b> be closed by the caller. * * @throws Exception On all erorrs. */ public InputStream openPackageStream(String pkgname) throws Exception { String location = packageLocation(pkgname); return repodata.getReader().openStream(location); } /** * Get the location (href) of the specified package. * * @param pkgname A fully qualified package name. * * @return The <i>href</i> of the specified package if found, else null. * * @throws Exception On all errors. */ public String packageLocation(String pkgname) throws Exception { Element p = getPackageMetadata(pkgname); return p.getChild("location", Repodata.yumns).getAttributeValue("href"); } /** * Encode the <i>version</i> element into an internal version representation. This representation is the * {epoch}.{ver}.{rel} formatted string. * * @param version A primary.xml version node. * * @return An encoded string representation of the rpm's version. */ private String encodeVersion(Element p) { Element version = p.getChild("version", Repodata.yumns); StringBuilder sb = new StringBuilder(); sb.append(version.getAttributeValue("epoch")); sb.append('.'); sb.append(version.getAttributeValue("ver")); sb.append('.'); sb.append(version.getAttributeValue("rel")); return sb.toString(); } /** * Get the filename from the specified package node. * * @param p A (primary.xml) package node. * * @return The package file name. */ private String filename(Element p) { String[] parts = location(p).split("[/\\\\]"); return parts[parts.length - 1]; } /** * Get the package file date. * * @param p A (primary.xml) package node. * * @return The package's file date. */ private Long filedate(Element p) { String date = p.getChild("time", Repodata.yumns).getAttributeValue("file"); return Long.parseLong(date); } private String location(Element p) { return p.getChild("location", Repodata.yumns).getAttributeValue("href"); } /** * Create and return a {@link org.rhq.core.domain.content.PackageDetails } object of rthe specified (primary.xml) * package node. * * @param p A primary.xml package node. * * @return A {@link org.rhq.core.domain.content.PackageDetails } object. */ private ContentProviderPackageDetails getDetails(Element p) throws Exception { String name = p.getChildText("name", Repodata.yumns); String displayVersion = encodeVersion(p); String sha256 = p.getChildText("checksum", Repodata.yumns); String version = "[sha256=" + sha256 + "]"; String arch = p.getChildText("arch", Repodata.yumns); ContentProviderPackageDetailsKey key = new ContentProviderPackageDetailsKey(name, version, "rpm", arch, "Linux", "Platforms"); ContentProviderPackageDetails pkg = new ContentProviderPackageDetails(key); String filename = filename(p); pkg.setDisplayName(filename); pkg.setShortDescription(p.getChildText("summary", Repodata.yumns)); pkg.setLongDescription(p.getChildText("description", Repodata.yumns)); pkg.setFileName(filename); pkg.setFileSize(Long.parseLong(p.getChild("size", Repodata.yumns).getAttributeValue("package"))); pkg.setFileCreatedDate(filedate(p)); pkg.setLicenseName(p.getChild("format", Repodata.yumns).getChildText("license", Repodata.rpmns)); pkg.setSHA256(p.getChildText("checksum", Repodata.yumns)); pkg.setDisplayVersion(displayVersion); pkg.setLocation(location(p)); pkg.setMetadata(gzip(p)); return pkg; } /** * Compress (using gzip) a string representation of the node. * * @param p A package element. * * @return A gzipped string representation of the node. * * @throws IOException */ private byte[] gzip(Element p) throws IOException { XMLOutputter printer = new XMLOutputter(); ByteArrayOutputStream zipped = new ByteArrayOutputStream(); GZIPOutputStream gzip = new GZIPOutputStream(zipped); try { printer.output(p, gzip); } finally { gzip.close(); } return zipped.toByteArray(); } }