/* * RHQ Management Platform * Copyright (C) 2005-2011 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.core.clientapi.descriptor; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.rhq.core.domain.plugin.Plugin; import org.rhq.core.clientapi.descriptor.plugin.PluginDescriptor; import org.rhq.core.clientapi.descriptor.plugin.Help; import org.rhq.core.util.MessageDigestGenerator; import java.net.URL; import java.io.IOException; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.JarInputStream; import java.util.jar.Manifest; import java.util.jar.Attributes; /** * Transforms some input into a {@link org.rhq.core.domain.plugin.Plugin} object. */ public class PluginTransformer { private static final Log LOG = LogFactory.getLog(PluginTransformer.class); /** * Takes the given plugin descriptor and plugin JAR file URL and converts them into a * {@link org.rhq.core.domain.plugin.Plugin} object. This method does not set the <code>content</code> property * of the plugin. * * @param pluginDescriptor The plugin descriptor from which to create the plugin * @param pluginURL The URL of the plugin JAR file from which to create the plugin * @return A new plugin object create from the descriptor and plugin URL * @throws PluginTransformException if any IO errors occur trying to read the JAR file or if a version not in the * plugin descriptor or in the plugin JAR manifest */ public Plugin toPlugin(PluginDescriptor pluginDescriptor, URL pluginURL) { try { Plugin plugin = new Plugin(); plugin.setName(pluginDescriptor.getName()); if (pluginDescriptor.getDisplayName() == null) { plugin.setDisplayName(pluginDescriptor.getName()); } else { plugin.setDisplayName(pluginDescriptor.getDisplayName()); } plugin.setAmpsVersion(getAmpsVersion(pluginDescriptor)); plugin.setDescription(pluginDescriptor.getDescription()); plugin.setPath(pluginURL.getPath()); plugin.setMtime(pluginURL.openConnection().getLastModified()); plugin.setHelp(getHelp(pluginDescriptor)); plugin.setMd5(getMd5(pluginURL)); plugin.setVersion(getVersion(pluginDescriptor, pluginURL)); return plugin; } catch (IOException e) { throw new PluginTransformException("Failed to create plugin.", e); } } private String getAmpsVersion(PluginDescriptor pluginDescriptor) { if (pluginDescriptor.getAmpsVersion() == null) { return "2.0"; } return pluginDescriptor.getAmpsVersion(); } private String getHelp(PluginDescriptor pluginDescriptor) { Help help = pluginDescriptor.getHelp(); if (help == null || help.getContent().isEmpty()) { return null; } return help.getContent().get(0).toString(); } private String getMd5(URL pluginURL) throws IOException { return MessageDigestGenerator.getDigestString(pluginURL); } String getVersion(PluginDescriptor pluginDescriptor, URL pluginURL) throws IOException { String version = pluginDescriptor.getVersion(); if (version == null) { version = getVersionFromPluginJarManifest(pluginURL); } if (version == null) { throw new PluginTransformException("No version is defined for plugin jar [" + pluginURL + "]. A version must be defined either via the MANIFEST.MF '" + Attributes.Name.IMPLEMENTATION_VERSION + "' attribute or via the plugin descriptor 'version' attribute."); } return version; } private String getVersionFromPluginJarManifest(URL pluginJarUrl) throws IOException { JarInputStream jarInputStream = new JarInputStream(pluginJarUrl.openStream()); Manifest manifest = jarInputStream.getManifest(); if (manifest == null) { // BZ 682116 (ips, 03/25/11): The manifest file is not in the standard place as the 2nd entry of the JAR, // but we want to be flexible and support JARs that have a manifest file somewhere else, so scan the entire // JAR for one. JarEntry jarEntry; while((jarEntry = jarInputStream.getNextJarEntry()) != null) { if (JarFile.MANIFEST_NAME.equalsIgnoreCase(jarEntry.getName())) { manifest = new Manifest(jarInputStream); break; } } } try { jarInputStream.close(); } catch (IOException e) { LOG.error("Failed to close plugin jar input stream for plugin jar [" + pluginJarUrl + "].", e); } if (manifest != null) { Attributes attributes = manifest.getMainAttributes(); return attributes.getValue(Attributes.Name.IMPLEMENTATION_VERSION); } else { return null; } } }