/*
* 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 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.sync.validators;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.persistence.EntityManager;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.plugin.Plugin;
import org.rhq.core.domain.plugin.PluginDeploymentType;
import org.rhq.enterprise.server.resource.metadata.PluginManagerLocal;
import org.rhq.enterprise.server.sync.ExportReader;
import org.rhq.enterprise.server.sync.ExportWriter;
import org.rhq.enterprise.server.util.LookupUtil;
/**
* This implementation checks that the two installations
* have the exact same plugins deployed.
*
* Note that this class is currently not used by any synchronizer but
* exists for "demo" purposes.
*
* @author Lukas Krejci
*/
public class DeployedAgentPluginsValidator implements ConsistencyValidator {
public static class ConsistentPlugin extends Plugin {
private static final long serialVersionUID = 1L;
public ConsistentPlugin() {
}
public ConsistentPlugin(Plugin p) {
setName(p.getName());
setVersion(p.getVersion());
setMd5(p.getMd5());
}
@Override
public int hashCode() {
return getName().hashCode() * getVersion().hashCode() * getMd5().hashCode();
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof ConsistentPlugin)) {
return false;
}
ConsistentPlugin p = (ConsistentPlugin) other;
return getName().equals(p.getName()) && getVersion().equals(p.getVersion())
&& getMd5().equals(p.getMd5());
}
}
private PluginManagerLocal pluginManager;
private Set<ConsistentPlugin> pluginsToValidate;
public DeployedAgentPluginsValidator() {
this(LookupUtil.getPluginManager());
}
public DeployedAgentPluginsValidator(PluginManagerLocal pluginManager) {
this.pluginManager = pluginManager;
}
/**
* Provided for testability
* @return the pluginsToValidate
*/
public Set<ConsistentPlugin> getPluginsToValidate() {
return pluginsToValidate;
}
/**
* Provided for testability
* @param pluginsToValidate the pluginsToValidate to set
*/
public void setPluginsToValidate(Set<ConsistentPlugin> pluginsToValidate) {
this.pluginsToValidate = pluginsToValidate;
}
@Override
public void initialize(Subject subject, EntityManager entityManager) {
}
@Override
public void exportState(ExportWriter writer) throws XMLStreamException {
List<Plugin> plugins = pluginManager.getInstalledPlugins();
for (Plugin plugin : plugins) {
if (plugin.getDeployment() == PluginDeploymentType.AGENT) {
writer.writeStartElement("plugin");
writer.writeAttribute("name", plugin.getName());
writer.writeAttribute("hash", plugin.getMd5());
writer.writeAttribute("version", plugin.getVersion());
writer.writeEndElement();
}
}
}
@Override
public void initializeExportedStateValidation(ExportReader reader) throws XMLStreamException {
pluginsToValidate = new HashSet<ConsistentPlugin>();
while (reader.hasNext()) {
switch (reader.next()) {
case XMLStreamReader.START_ELEMENT:
if ("plugin".equals(reader.getName().getLocalPart())) {
ConsistentPlugin p = new ConsistentPlugin();
p.setName(reader.getAttributeValue(null, "name"));
p.setMd5(reader.getAttributeValue(null, "hash"));
p.setVersion(reader.getAttributeValue(null, "version"));
pluginsToValidate.add(p);
} else {
throw new XMLStreamException(
"Illegal tag encountered in the DeployedAgentPluginsValidator section: " + reader.getName()
+ " on location: " + reader.getLocation());
}
}
}
}
@Override
public void validateExportedState() throws InconsistentStateException {
List<Plugin> localPlugins = pluginManager.getInstalledPlugins();
Set<ConsistentPlugin> localAgentPlugins = new HashSet<ConsistentPlugin>();
for(Plugin p : localPlugins) {
if (p.getDeployment() == PluginDeploymentType.AGENT) {
localAgentPlugins.add(new ConsistentPlugin(p));
}
}
if (localAgentPlugins.size() != pluginsToValidate.size()) {
throwIncosistentException(localAgentPlugins, pluginsToValidate);
}
for (ConsistentPlugin localPlugin : localAgentPlugins) {
if (!pluginsToValidate.contains(localPlugin)) {
throwIncosistentException(localAgentPlugins, pluginsToValidate);
}
}
}
@Override
public int hashCode() {
//all the deployed plugins validators are equal
return 0;
}
@Override
public boolean equals(Object obj) {
//The deployed plugins validators are all equal to each other
//because there is no difference in the "output" given by any
//instance.
if (this == obj) {
return true;
}
if (obj instanceof DeployedAgentPluginsValidator) {
return true;
}
return false;
}
private static void throwIncosistentException(Collection<ConsistentPlugin> localPlugins, Collection<ConsistentPlugin> expectedPlugins)
throws InconsistentStateException {
StringBuilder bld = new StringBuilder(
"Installed plugins are not consistent with the plugins required by the export.");
bld.append(" The export expects these plugins to be deployed: ");
appendPlugins(bld, expectedPlugins);
bld.append(". But the following plugins were found in the local installation: ");
appendPlugins(bld, localPlugins);
throw new InconsistentStateException(bld.toString());
}
private static void appendPlugins(StringBuilder bld, Collection<ConsistentPlugin> plugins) {
bld.append("[");
int size = plugins.size();
int i = 0;
for (Plugin p : plugins) {
++i;
appendPlugin(bld, p);
if (i < size) {
bld.append(", ");
}
}
bld.append("]");
}
private static void appendPlugin(StringBuilder bld, Plugin p) {
bld.append("Plugin[name='").append(p.getName()).append("'");
bld.append(", version='").append(p.getVersion()).append("'");
bld.append(", md5='").append(p.getMd5()).append("']");
}
}