/* * 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.InputStream; import java.util.HashMap; import java.util.List; import java.util.Map; import org.jdom.Element; import org.jdom.Namespace; import org.jdom.input.SAXBuilder; import org.jdom.output.Format; import org.jdom.output.XMLOutputter; /** * The Repodata object is used to read yum metadata. * * @author jortel */ public class Repodata { /** * Yum metadata files types. * * @author jortel */ enum Meta { primary, filelists, other }; /** * A yum reader used to access the repo. */ private final RepoReader reader; /** * A SAX builder. */ private SAXBuilder builder = new SAXBuilder(); /** * The location mapping of metadata types to hrefs. */ private Map<Meta, String> locations = new HashMap<Meta, String>(); /** * A meta document cache. Ensures that metadata files are only read/parsed once. */ private Map<Meta, Element> documents = new HashMap<Meta, Element>(); /** * Namespaces */ public static final Namespace yumns = Namespace.getNamespace("http://linux.duke.edu/metadata/common"); public static final Namespace repons = Namespace.getNamespace("http://linux.duke.edu/metadata/repo"); public static final Namespace rpmns = Namespace.getNamespace("rpm", "http://linux.duke.edu/metadata/rpm"); /** * Constructor. Initializes the object and refreshes the metadata caches. * * @param reader An initialized reader used to access the repo. * * @see refresh(). */ public Repodata(RepoReader reader) { this.reader = reader; } /** * Refresh the repo's metadata. * * <p/>1) Clear all cached data. * * <p/>2) Read and process repomd.xml * * @throws Exception */ public void refresh() throws Exception { clear(); Element repomd = getRepomd(); for (Meta t : Meta.values()) { locations.put(t, getLocation(repomd, t)); } } /** * Clear caches. */ public void clear() { locations.clear(); documents.clear(); } /** * Get the object's reader. * * @return The object's reader. */ public RepoReader getReader() { return reader; } /** * Get and parse the repo's <i>repomd.xml</i> file. * * @return The root repomd node. * * @throws Exception On all errors. */ public Element getRepomd() throws Exception { InputStream istr = reader.openStream("repodata/repomd.xml"); return builder.build(istr).getRootElement(); } /** * Get the node for the specified metadata type. The node is returned from the cache when already cached. Otherwise, * it is read/parsed and stored in the cache. * * @param type A metadata type. * * @return The requested node. * * @throws Exception On all errors. */ public Element getMetadata(Meta type) throws Exception { Element node = documents.get(type); InputStream istr = null; try { if (node == null) { String href = locations.get(type); istr = reader.openStream(href); node = builder.build(istr).getRootElement(); documents.put(type, node); } } finally { if (istr != null) { istr.close(); } } return node; } /** * A utility for getting an XML (string representation) for the specified metadata type. * * @param type A type of metadata. * * @return A XML string. * * @throws Exception On all errors. */ public String toString(Meta type) throws Exception { return toString(getMetadata(type)); } /** * Get the <location href=""/> value from the repomd node for the specified yum metadata type. * * @param repomd A repomd node. * @param type The yum metadata type. * * @return The href for the specified type when found, else "". */ @SuppressWarnings("unchecked") private String getLocation(Element repomd, Meta type) { String href = ""; for (Element e : (List<Element>) repomd.getChildren()) { String typeAttribute = e.getAttributeValue("type"); if (typeAttribute != null && typeAttribute.equals(type.name())) { Element location = e.getChild("location", repons); href = location.getAttributeValue("href"); break; } } return href; } /** * Utility for converting an XML fragment into a string. * * @param e An element to convert. * * @return A string representation of the specified element. */ public static String toString(Element e) { Format format = Format.getPrettyFormat(); XMLOutputter p = new XMLOutputter(format); return p.outputString(e); } }