modules/core/client-api/src/main/java/org/rhq/core/clientapi/descriptor/PluginTransformException.java
| 48 +
modules/core/client-api/src/main/java/org/rhq/core/clientapi/descriptor/PluginTransformer.java
| 124 ++++
modules/core/client-api/src/test/java/org/rhq/core/clientapi/descriptor/PluginTransformerTest.java
| 303 ++++++++++
modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainerConfiguration.java
| 16
modules/core/plugin-container/src/main/java/org/rhq/core/pc/plugin/PluginManager.java
| 83 ++
modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/PluginUpdate.java
| 3
modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml
| 3
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ProductPluginDeployer.java
| 16
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
| 46 -
9 files changed, 599 insertions(+), 43 deletions(-)
New commits:
commit 81923849f08cf1267a63938a3a11f89bace50061
Merge: 370de38... 58bea15...
Author: John Sanda <john(a)localhost.localdomain>
Date: Fri Oct 30 17:01:21 2009 -0400
Merge branch 'raw-config' of
ssh://git.fedorahosted.org/git/rhq/rhq into
raw-config
commit 370de388b6e3b3f0b88f7e2a2a5f7dfc325f7b41
Author: John Sanda <john(a)localhost.localdomain>
Date: Fri Oct 30 16:46:22 2009 -0400
[US 403] Adding ampsVersion to UI in plugin details page and updating logic for
setting ampsVersion for exisitng plugins
For any pre-existing plugin whose ampsVersion is undefined or less than 2.1, the
ampsVersion will be set to 2.0. This logic has been added to ProductPluginDeployer.
diff --git
a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml
b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml
index 3c8a1f3..e1aef90 100644
---
a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml
+++
b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml
@@ -49,6 +49,9 @@
<h:outputLabel styleClass="BlockLabel"
value="Version:"/>
<h:outputText styleClass="BlockContent"
value="#{InstalledPluginUIBean.plugin.version}"/>
+ <h:outputLabel styleClass="BlockLabel" value="AMPS
Version:"/>
+ <h:outputText styleClass="BlockContent"
value="#{InstalledPluginUIBean.plugin.ampsVersion}"/>
+
<h:outputLabel styleClass="BlockLabel"
value="Enabled:"/>
<h:outputText
value="#{InstalledPluginUIBean.plugin.enabled}"/>
diff --git
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ProductPluginDeployer.java
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ProductPluginDeployer.java
index 6a73c7f..3c54d3c 100644
---
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ProductPluginDeployer.java
+++
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ProductPluginDeployer.java
@@ -485,7 +485,7 @@ public class ProductPluginDeployer {
plugin.setDisplayName((displayName != null) ? displayName : pluginName);
plugin.setEnabled(true);
plugin.setDescription(pluginDescriptor.getDescription());
- plugin.setAmpsVersion(pluginDescriptor.getAmpsVersion());
+ plugin.setAmpsVersion(getAmpsVersion(pluginDescriptor));
// get the last modified of the "real" plugin jar since that's
the one the user touches
long mtime = deploymentInfo.url.openConnection().getLastModified();
@@ -510,6 +510,21 @@ public class ProductPluginDeployer {
}
}
+ private String getAmpsVersion(PluginDescriptor pluginDescriptor) {
+ if (pluginDescriptor.getAmpsVersion() == null) {
+ return "2.0";
+ }
+
+ ComparableVersion version = new
ComparableVersion(pluginDescriptor.getAmpsVersion());
+ ComparableVersion version2 = new ComparableVersion("2.0");
+
+ if (version.compareTo(version2) <= 0) {
+ return "2.0";
+ }
+
+ return pluginDescriptor.getAmpsVersion();
+ }
+
private void checkVersionCompatibility(String version) throws RuntimeException {
/*if (new OSGiVersionComparator().compare((String) version, (String)
AMPS_VERSION) < 0)
* { throw new RuntimeException("Plugin AMPS requirement " + version +
" not compatible with server's AMPS
diff --git
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
index 7d2265a..bfc7d86 100644
---
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
+++
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
@@ -18,32 +18,8 @@
*/
package org.rhq.enterprise.server.resource.metadata;
-import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.ejb.EJB;
-import javax.ejb.Stateless;
-import javax.persistence.EntityManager;
-import javax.persistence.NoResultException;
-import javax.persistence.NonUniqueResultException;
-import javax.persistence.PersistenceContext;
-import javax.persistence.Query;
-import javax.sql.DataSource;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-
import org.rhq.core.clientapi.agent.metadata.PluginMetadataManager;
import org.rhq.core.clientapi.agent.metadata.SubCategoriesMetadataParser;
import org.rhq.core.clientapi.descriptor.AgentPluginDescriptorUtil;
@@ -72,6 +48,28 @@ import
org.rhq.enterprise.server.measurement.MeasurementDefinitionManagerLocal;
import org.rhq.enterprise.server.measurement.MeasurementScheduleManagerLocal;
import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+import javax.ejb.EJB;
+import javax.ejb.Stateless;
+import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+import javax.persistence.NonUniqueResultException;
+import javax.persistence.PersistenceContext;
+import javax.persistence.Query;
+import javax.sql.DataSource;
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
/**
* This class manages the metadata for resources. Plugins are registered against this
bean so that their metadata can be
* pulled out and stored as necessary.
commit 136646283cce6474558787bb266db9ce3cacecdb
Author: John Sanda <john(a)localhost.localdomain>
Date: Fri Oct 30 13:50:04 2009 -0400
[US 403] Modifying plugin container to load Plugin objects in their entirety.
Adding pluginsOnServer property to PluginContainerConfiguration. This set contains
plugins sent
down from the server. It is only populated when the plugin container is running inside
an agent.
Modyfing PluginUpdate to populate PluginContainerConfiguration.pluginsOnServer with
the plugins
sent down from the server.
Updating PluginManager to store loaded plugin as Plugin objects. Previously, only the
names
were stored. Now we can more easily retrive the ampsVersion of a plugin. Support has
been added
to load plugins both in enterripse (i.e., running inside an agent) and in embedded
mode.
Updating ProductPluginDeployer to set the ampsVersion of the Plugin object that is
creates.
diff --git
a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainerConfiguration.java
b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainerConfiguration.java
index b76354b..563eb47 100644
---
a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainerConfiguration.java
+++
b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainerConfiguration.java
@@ -26,10 +26,13 @@ import java.io.File;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.Map;
+import java.util.Set;
+import java.util.HashSet;
import org.rhq.core.pc.plugin.PluginFinder;
import org.rhq.core.pc.plugin.RootPluginClassLoader;
import org.rhq.core.pluginapi.inventory.PluginContainerDeployment;
+import org.rhq.core.domain.plugin.Plugin;
/**
* Configuration properties for the plugin container and all its internal managers.
@@ -124,6 +127,11 @@ public class PluginContainerConfiguration {
private ServerServices serverServices = null;
/**
+ * The plugins that reside on the server which are sent down to the agent.
+ */
+ private Set<Plugin> pluginsOnServer = new HashSet<Plugin>();
+
+ /**
* This is our hash map that contains the actual properties. We use a map (as opposed
to individual data member
* variables) to support a future enhancement by which our plugins can squirrel away
their own custom global
* properties here.
@@ -704,6 +712,14 @@ public class PluginContainerConfiguration {
this.serverServices = serverServices;
}
+ public Set<Plugin> getPluginsOnServer() {
+ return pluginsOnServer;
+ }
+
+ public void setPluginsOnServer(Set<Plugin> plugins) {
+ pluginsOnServer = plugins;
+ }
+
/**
* Returns whether or not the plugin container is running inside an agent, which
means it is running external to any
* managed product.
diff --git
a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/plugin/PluginManager.java
b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/plugin/PluginManager.java
index 1b9399a..4f71ab2 100644
---
a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/plugin/PluginManager.java
+++
b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/plugin/PluginManager.java
@@ -22,25 +22,16 @@
*/
package org.rhq.core.pc.plugin;
-import java.io.File;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jetbrains.annotations.Nullable;
-
import org.rhq.core.clientapi.agent.PluginContainerException;
import org.rhq.core.clientapi.agent.metadata.PluginDependencyGraph;
import org.rhq.core.clientapi.agent.metadata.PluginMetadataManager;
import org.rhq.core.clientapi.descriptor.AgentPluginDescriptorUtil;
+import org.rhq.core.clientapi.descriptor.PluginTransformer;
import org.rhq.core.clientapi.descriptor.plugin.PluginDescriptor;
+import org.rhq.core.domain.plugin.Plugin;
import org.rhq.core.pc.ContainerService;
import org.rhq.core.pc.PluginContainerConfiguration;
import org.rhq.core.pluginapi.plugin.PluginContext;
@@ -48,6 +39,18 @@ import org.rhq.core.pluginapi.plugin.PluginLifecycleListener;
import org.rhq.core.system.SystemInfo;
import org.rhq.core.system.SystemInfoFactory;
import org.rhq.core.util.exception.ThrowableUtil;
+import org.rhq.core.util.MessageDigestGenerator;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
/**
* This container service will load in all plugins that can be found and will maintain
the complete set of
@@ -60,6 +63,16 @@ import org.rhq.core.util.exception.ThrowableUtil;
* @author John Mazzitelli
*/
public class PluginManager implements ContainerService {
+
+ /**
+ * A callback interface for updating the loadedPlugins list. When running inside of
an agent, loadedPlugins gets
+ * updated with Plugin objects received from the RHQ server. When running in embedded
mode, we have to create the
+ * Plugin objects ourselves.
+ */
+ private static interface UpdateLoadedPlugins {
+ void execute(PluginDescriptor pluginDescriptor, URL pluginURL);
+ }
+
private static final Log log = LogFactory.getLog(PluginManager.class);
/**
@@ -68,9 +81,9 @@ public class PluginManager implements ContainerService {
private Map<String, PluginEnvironment> loadedPluginEnvironments;
/**
- * A list of loaded plugin names in the order in which they were loaded.
+ * A list of loaded plugins in the order in which they were loaded.
*/
- private List<String> loadedPlugins;
+ private List<Plugin> loadedPlugins;
/**
* Cached instances of objects used to initialize and shutdown individual plugins.
@@ -81,6 +94,7 @@ public class PluginManager implements ContainerService {
private PluginMetadataManager metadataManager;
private ClassLoaderManager classLoaderManager;
private PluginContainerConfiguration configuration;
+ private UpdateLoadedPlugins updateLoadedPlugins;
/**
* Finds all plugins using the plugin finder defined in the
@@ -91,10 +105,12 @@ public class PluginManager implements ContainerService {
*/
public void initialize() {
loadedPluginEnvironments = new HashMap<String, PluginEnvironment>();
- loadedPlugins = new ArrayList<String>();
+ loadedPlugins = new ArrayList<Plugin>();
pluginLifecycleListenerCache = new HashMap<String,
PluginLifecycleListener>();
metadataManager = new PluginMetadataManager();
+ initUpdateLoadedPluginsCallback();
+
PluginFinder finder = configuration.getPluginFinder();
File tmpDir = configuration.getTemporaryDirectory();
@@ -161,6 +177,35 @@ public class PluginManager implements ContainerService {
return;
}
+ private void initUpdateLoadedPluginsCallback() {
+ if (configuration.isInsideAgent()) {
+ updateLoadedPlugins = new UpdateLoadedPlugins() {
+ public void execute(PluginDescriptor pluginDescriptor, URL pluginURL) {
+ loadPluginIfFoundInListFromServer(pluginDescriptor);
+ }
+ };
+ }
+ else {
+ updateLoadedPlugins = new UpdateLoadedPlugins() {
+ PluginTransformer transformer = new PluginTransformer();
+
+ public void execute(PluginDescriptor pluginDescriptor, URL pluginURL) {
+ Plugin plugin = transformer.toPlugin(pluginDescriptor, pluginURL);
+ loadedPlugins.add(plugin);
+ }
+ };
+ }
+ }
+
+ private void loadPluginIfFoundInListFromServer(PluginDescriptor pluginDescriptor) {
+ for (Plugin plugin : configuration.getPluginsOnServer()) {
+ if (pluginDescriptor.getName().equals(plugin.getName())) {
+ loadedPlugins.add(plugin);
+ return;
+ }
+ }
+ }
+
/**
* @see ContainerService#shutdown()
*/
@@ -168,20 +213,20 @@ public class PluginManager implements ContainerService {
// Inform the plugins we are shutting them down.
// We want to shut them down in the reverse order that we initialized them.
Collections.reverse(this.loadedPlugins);
- for (String pluginName : this.loadedPlugins) {
- PluginLifecycleListener listener =
this.pluginLifecycleListenerCache.get(pluginName);
+ for (Plugin plugin : loadedPlugins) {
+ PluginLifecycleListener listener =
this.pluginLifecycleListenerCache.get(plugin.getName());
if (listener != null) {
try {
ClassLoader originalCL =
Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(
- this.classLoaderManager.obtainPluginClassLoader(pluginName));
+
this.classLoaderManager.obtainPluginClassLoader(plugin.getName()));
try {
listener.shutdown();
} finally {
Thread.currentThread().setContextClassLoader(originalCL);
}
} catch (Throwable t) {
- log.warn("Failed to get lifecycle listener to shutdown [" +
pluginName + "]. Cause: "
+ log.warn("Failed to get lifecycle listener to shutdown [" +
plugin.getName() + "]. Cause: "
+ ThrowableUtil.getAllMessages(t));
}
}
@@ -298,7 +343,7 @@ public class PluginManager implements ContainerService {
// everything is loaded and initialized
this.loadedPluginEnvironments.put(pluginName, pluginEnvironment);
this.metadataManager.loadPlugin(pluginDescriptor);
- this.loadedPlugins.add(pluginName);
+ updateLoadedPlugins.execute(pluginDescriptor, pluginUrl);
return;
}
diff --git
a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/PluginUpdate.java
b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/PluginUpdate.java
index 605f91a..4e4a07b 100644
--- a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/PluginUpdate.java
+++ b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/PluginUpdate.java
@@ -26,6 +26,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.HashSet;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.ReadWriteLock;
@@ -162,6 +163,8 @@ public class PluginUpdate {
// find out what the latest plugins are available to us
List<Plugin> latest_plugins =
coreServerService.getLatestPlugins();
+ config.setPluginsOnServer(new HashSet(latest_plugins));
+
if (LOG.isDebugEnabled()) {
LOG.debug(AgentI18NResourceKeys.LATEST_PLUGINS_COUNT,
latest_plugins.size());
for (Plugin latest_plugin : latest_plugins) {
diff --git
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ProductPluginDeployer.java
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ProductPluginDeployer.java
index bec6ebb..6a73c7f 100644
---
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ProductPluginDeployer.java
+++
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ProductPluginDeployer.java
@@ -485,6 +485,7 @@ public class ProductPluginDeployer {
plugin.setDisplayName((displayName != null) ? displayName : pluginName);
plugin.setEnabled(true);
plugin.setDescription(pluginDescriptor.getDescription());
+ plugin.setAmpsVersion(pluginDescriptor.getAmpsVersion());
// get the last modified of the "real" plugin jar since that's
the one the user touches
long mtime = deploymentInfo.url.openConnection().getLastModified();
commit a9e92b899c174c4fa7ffef154bb033469a3643e6
Author: John Sanda <john(a)localhost.localdomain>
Date: Fri Oct 30 11:33:42 2009 -0400
[US 403] Initial commit for PluginTransformer, PluginTransformerTest, and
PluginTransformerException
PluginTransformer takes a PluginDescriptor and a URL for the plugin JAR file and
converts them
into a Plugin object. This logic is needed by PluginManager when the plugin container
is used in
embedded mode in order to build the list of loaded plugins. That list was previously a
list of
just plugin names, but now it is a list of the Plugin domain objects. In enterprise
mode, we get
those plugins from the server, but in embedded mode, we have to create the Plugin
objects
ourselves since there is no server to talk to.
diff --git
a/modules/core/client-api/src/main/java/org/rhq/core/clientapi/descriptor/PluginTransformException.java
b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/descriptor/PluginTransformException.java
new file mode 100644
index 0000000..6b31c63
--- /dev/null
+++
b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/descriptor/PluginTransformException.java
@@ -0,0 +1,48 @@
+/*
+ * 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.core.clientapi.descriptor;
+
+/**
+ * An exception that is throw when a plugin transformation fails for some reason.
+ *
+ * @see org.rhq.core.clientapi.descriptor.PluginTransformer
+ */
+public class PluginTransformException extends RuntimeException {
+
+ public PluginTransformException() {
+ super();
+ }
+
+ public PluginTransformException(String message) {
+ super(message);
+ }
+
+ public PluginTransformException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public PluginTransformException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git
a/modules/core/client-api/src/main/java/org/rhq/core/clientapi/descriptor/PluginTransformer.java
b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/descriptor/PluginTransformer.java
new file mode 100644
index 0000000..d1cb6ca
--- /dev/null
+++
b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/descriptor/PluginTransformer.java
@@ -0,0 +1,124 @@
+/*
+ * 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.core.clientapi.descriptor;
+
+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.io.File;
+import java.util.jar.JarFile;
+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 {
+
+ /**
+ * 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(pluginDescriptor.getAmpsVersion());
+ 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 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 {
+ File jarFile = toFile(pluginURL);
+ return MessageDigestGenerator.getDigestString(jarFile);
+ }
+
+ String getVersion(PluginDescriptor pluginDescriptor, URL pluginURL) throws
IOException {
+ if (pluginDescriptor.getVersion() != null) {
+ return pluginDescriptor.getVersion();
+ }
+
+ File pluginJarFile = toFile(pluginURL);
+
+ String version = getVersionFromPluginJarManifest(pluginJarFile);
+
+ if (version == null) {
+ throw new PluginTransformException("No version is defined for plugin jar
[" + pluginJarFile
+ + "]. 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(File pluginJarFile) throws IOException
{
+ JarFile jarFile = new JarFile(pluginJarFile);
+ Manifest manifest = jarFile.getManifest();
+ Attributes attributes = manifest.getMainAttributes();
+
+ return attributes.getValue(Attributes.Name.IMPLEMENTATION_VERSION);
+ }
+
+ private File toFile(URL url) {
+ return new File(url.getPath());
+ }
+
+}
diff --git
a/modules/core/client-api/src/test/java/org/rhq/core/clientapi/descriptor/PluginTransformerTest.java
b/modules/core/client-api/src/test/java/org/rhq/core/clientapi/descriptor/PluginTransformerTest.java
new file mode 100644
index 0000000..f964178
--- /dev/null
+++
b/modules/core/client-api/src/test/java/org/rhq/core/clientapi/descriptor/PluginTransformerTest.java
@@ -0,0 +1,303 @@
+/*
+ * 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.core.clientapi.descriptor;
+
+import static org.testng.Assert.*;
+
+import org.testng.annotations.Test;
+import org.rhq.core.clientapi.descriptor.plugin.PluginDescriptor;
+import org.rhq.core.clientapi.descriptor.plugin.Help;
+import org.rhq.core.domain.plugin.Plugin;
+import org.rhq.core.util.MessageDigestGenerator;
+
+import java.net.URL;
+import java.util.jar.Manifest;
+import java.util.jar.Attributes;
+import java.util.jar.JarOutputStream;
+import java.util.jar.JarFile;
+import java.io.FileOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.ByteArrayInputStream;
+
+public class PluginTransformerTest {
+
+ @Test
+ public void pluginNameShouldBeSetToDescriptorName() throws Exception {
+ PluginDescriptor pluginDescriptor = new PluginDescriptor();
+ pluginDescriptor.setName("testPlugin");
+
+ PluginTransformer transformer = new PluginTransformer();
+
+ Plugin plugin = transformer.toPlugin(pluginDescriptor, getTestPluginURL());
+
+ assertEquals(
+ plugin.getName(),
+ pluginDescriptor.getName(),
+ "The plugin.name property should be set to the plugin descriptor
name."
+ );
+ }
+
+ @Test
+ public void pluginDisplayNameShouldBeSetToDescriptorDisplayName() throws Exception {
+ PluginDescriptor pluginDescriptor = new PluginDescriptor();
+ pluginDescriptor.setName("testPlugin");
+ pluginDescriptor.setDisplayName("Test Plugin");
+
+ PluginTransformer transformer = new PluginTransformer();
+
+ Plugin plugin = transformer.toPlugin(pluginDescriptor, getTestPluginURL());
+
+ assertEquals(
+ plugin.getDisplayName(),
+ pluginDescriptor.getDisplayName(),
+ "The plugin.displayName property should be set to the plugin descriptor
display name."
+ );
+ }
+
+ @Test
+ public void pluginDisplayNameShouldBeSetToDescriptorNameWhenItsDisplayNameIsNull()
throws Exception {
+ PluginDescriptor pluginDescriptor = new PluginDescriptor();
+ pluginDescriptor.setName("testPlugin");
+
+ PluginTransformer transformer = new PluginTransformer();
+
+ Plugin plugin = transformer.toPlugin(pluginDescriptor, getTestPluginURL());
+
+ assertEquals(
+ plugin.getDisplayName(),
+ pluginDescriptor.getName(),
+ "The plugin.displayName property should be set to the plugin descriptor
name when the descriptor display name is null."
+ );
+ }
+
+ @Test
+ public void pluginAmpsVersionShouldBeSetToDescriptorAmpsVersion() throws Exception {
+ PluginDescriptor pluginDescriptor = new PluginDescriptor();
+ pluginDescriptor.setAmpsVersion("2.1");
+
+ PluginTransformer transformer = new PluginTransformer();
+
+ Plugin plugin = transformer.toPlugin(pluginDescriptor, getTestPluginURL());
+
+ assertEquals(
+ plugin.getAmpsVersion(),
+ pluginDescriptor.getAmpsVersion(),
+ "The plugin.ampsVersion property should be set to the plugin descriptor
ampsVersion."
+ );
+ }
+
+ @Test
+ public void pluginDescriptionShouldBeSetToDescriptorDescription() throws Exception {
+ PluginDescriptor pluginDescriptor = new PluginDescriptor();
+ pluginDescriptor.setDescription("description");
+
+ PluginTransformer transformer = new PluginTransformer();
+
+ Plugin plugin = transformer.toPlugin(pluginDescriptor, getTestPluginURL());
+
+ assertEquals(
+ plugin.getDescription(),
+ pluginDescriptor.getDescription(),
+ "The plugin.description property should be set to the plugin descriptor
description."
+ );
+ }
+
+ @Test
+ public void pluginEnabledFlagShouldBeSetToTrue() throws Exception {
+ PluginDescriptor pluginDescriptor = new PluginDescriptor();
+
+ PluginTransformer transformer = new PluginTransformer();
+
+ Plugin plugin = transformer.toPlugin(pluginDescriptor, getTestPluginURL());
+
+ assertTrue(plugin.isEnabled(), "The plugin.enabled property should be set to
true.");
+ }
+
+ @Test
+ public void pluginPathShouldBeSetToPathOfPluginURL() throws Exception {
+ File jarFile = createPluginJARFile();
+
+ PluginDescriptor pluginDescriptor = new PluginDescriptor();
+ URL pluginURL = toURL(jarFile);
+
+ PluginTransformer transformer = new PluginTransformer();
+
+ Plugin plugin = transformer.toPlugin(pluginDescriptor, pluginURL);
+
+ assertEquals(
+ plugin.getPath(),
+ pluginURL.getPath(),
+ "The plugin.path property should be set to the plugin url path."
+ );
+ }
+
+ @Test
+ public void pluginMtimeShouldBeSetToLastModificationTimeOfPluginJarFile() throws
Exception {
+ File jarFile = createPluginJARFile();
+
+ PluginDescriptor pluginDescriptor = new PluginDescriptor();
+ URL pluginURL = toURL(jarFile);
+
+ PluginTransformer transformer = new PluginTransformer();
+
+ Plugin plugin = transformer.toPlugin(pluginDescriptor, pluginURL);
+
+ assertEquals(
+ plugin.getMtime(),
+ jarFile.lastModified(),
+ "The plugin.mtime property should be set to the last modification time
of the plugin JAR file."
+ );
+ }
+
+ @Test
+ public void pluginHelpShouldBeSetToDescriptorHelp() throws Exception {
+ Help help = new Help();
+ help.getContent().add("help");
+
+ PluginDescriptor pluginDescriptor = new PluginDescriptor();
+ pluginDescriptor.setHelp(help);
+
+ PluginTransformer transformer = new PluginTransformer();
+
+ Plugin plugin = transformer.toPlugin(pluginDescriptor, getTestPluginURL());
+
+ assertEquals(
+ plugin.getHelp(),
+ pluginDescriptor.getHelp().getContent().get(0),
+ "The plugin.help property should be set to the plugin descriptor
help."
+ );
+ }
+
+ @Test
+ public void pluginMd5ShouldBeSetToMd5OfPluginJarFile() throws Exception {
+ File jarFile = createPluginJARFile();
+
+ PluginDescriptor pluginDescriptor = new PluginDescriptor();
+ URL pluginURL = toURL(jarFile);
+
+ PluginTransformer transformer = new PluginTransformer();
+
+ Plugin plugin = transformer.toPlugin(pluginDescriptor, pluginURL);
+
+ assertEquals(
+ plugin.getMd5(),
+ MessageDigestGenerator.getDigestString(jarFile),
+ "The plugin.md5 property should be set to the MD5 sum of the plugin JAR
file."
+ );
+ }
+
+ @Test
+ public void pluginVersionShouldBeSetToPluginDescriptorVersion() throws Exception {
+ PluginDescriptor pluginDescriptor = new PluginDescriptor();
+ pluginDescriptor.setVersion("2.1");
+
+ PluginTransformer transformer = new PluginTransformer();
+
+ Plugin plugin = transformer.toPlugin(pluginDescriptor, getTestPluginURL());
+
+ assertEquals(
+ plugin.getVersion(),
+ pluginDescriptor.getVersion(),
+ "The plugin.version property should be set to the plugin descriptor
version."
+ );
+ }
+
+ @Test
+ public void
pluginVersionShouldBeSetToVersionInPluginJarManifestWhenDescriptorVersionIsNull() throws
Exception {
+ File jarFile = createPluginJARFile();
+ URL pluginURL = toURL(jarFile);
+
+ PluginTransformer transformer = new PluginTransformer();
+
+ Plugin plugin = transformer.toPlugin(new PluginDescriptor(), pluginURL);
+
+ assertEquals(
+ plugin.getVersion(),
+ getVersionFromPluginJarManifest(jarFile),
+ "The pliugin.version property should be set to the " +
Attributes.Name.IMPLEMENTATION_VERSION +
+ " attribute in the plugin JAR manifest when the plugin descriptor
version is null."
+ );
+ }
+
+ @Test(expectedExceptions = {PluginTransformException.class})
+ public void
exceptionShouldBeThrownWhenVersionNotFoundInDescriptorOrPluginJarManifest() throws
Exception {
+ File jarFile = createPluginJARFileWithoutVersionInManifest();
+ URL pluginURL = toURL(jarFile);
+
+ PluginTransformer transformer = new PluginTransformer();
+
+ Plugin plugin = transformer.toPlugin(new PluginDescriptor(), pluginURL);
+ }
+
+ URL getTestPluginURL() throws Exception {
+ File jarFile = createPluginJARFile();
+ return toURL(jarFile);
+ }
+
+ File createPluginJARFile() throws Exception {
+ URL url = getClass().getResource(".");
+
+ Manifest manifest = new Manifest();
+ Attributes attrs = manifest.getMainAttributes();
+ attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0");
+ attrs.putValue(Attributes.Name.IMPLEMENTATION_VERSION.toString(),
"2.1");
+
+ File jarFile = new File(url.getPath(), "test-plugin.jar");
+ JarOutputStream stream = new JarOutputStream(new FileOutputStream(jarFile),
manifest);
+
+ stream.flush();
+ stream.close();
+
+ return jarFile;
+ }
+
+ File createPluginJARFileWithoutVersionInManifest() throws Exception {
+ URL url = getClass().getResource(".");
+
+ Manifest manifest = new Manifest();
+
+ File jarFile = new File(url.getPath(), "test-plugin.jar");
+ JarOutputStream stream = new JarOutputStream(new FileOutputStream(jarFile),
manifest);
+
+ stream.flush();
+ stream.close();
+
+ return jarFile;
+ }
+
+ URL toURL(File file) throws Exception {
+ return file.toURI().toURL();
+ }
+
+ String getVersionFromPluginJarManifest(File pluginJarFile) throws Exception {
+ JarFile jarFile = new JarFile(pluginJarFile);
+ Manifest manifest = jarFile.getManifest();
+ Attributes attributes = manifest.getMainAttributes();
+
+ return attributes.getValue(Attributes.Name.IMPLEMENTATION_VERSION);
+ }
+
+}