/*
* 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.enterprise.server.plugin.pc.content.metadata;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.rhq.core.clientapi.agent.metadata.ConfigurationMetadataParser;
import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
import org.rhq.core.domain.content.ContentSourceType;
import org.rhq.core.domain.content.DownloadMode;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.content.ContentPluginDescriptorType;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.content.ContentSourceTypeDefinition;
/**
* This is meant to provide an interface to the underlying metadata of a server plugin for content. It will load,
* translate and cache the metadata for the rest of the services in the form of the domain object classes and the jaxb
* version of the descriptors.
*
* @author John Mazzitelli
*/
public class ContentSourcePluginMetadataManager {
private Log log = LogFactory.getLog(ContentSourcePluginMetadataManager.class);
// outer map is keyed by plugin name; inner map keyed by content source type name
private Map<String, Map<String, ContentSourceType>> loadedPlugins;
public ContentSourcePluginMetadataManager() {
loadedPlugins = new HashMap<String, Map<String, ContentSourceType>>();
}
/**
* This will remove all knowledge of the given plugin - that is, all content source types deployed by the plugin
* will be removed from this manager.
*
* @param pluginName the plugin whose types are to be removed
*/
public synchronized void unloadPlugin(String pluginName) {
loadedPlugins.remove(pluginName);
}
/**
* Transforms the pluginDescriptor into domain object form and stores those objects.
*
* @param pluginDescriptor the descriptor to transform
*
* @return the new content source types represented by this descriptor (not a copy)
*/
public synchronized Collection<ContentSourceType> loadPlugin(ContentPluginDescriptorType pluginDescriptor) {
try {
Map<String, ContentSourceType> pluginTypes = loadedPlugins.get(pluginDescriptor.getName());
if (pluginTypes != null) {
pluginTypes.clear(); // this is a redeploy, delete the original types
} else {
pluginTypes = new HashMap<String, ContentSourceType>();
loadedPlugins.put(pluginDescriptor.getName(), pluginTypes);
}
for (ContentSourceTypeDefinition newType : pluginDescriptor.getContentSourceType()) {
// TODO: right now, content source types cannot have the same name as any other one
// even if defined in another plugin (i.e plugin's content types are not scoped)
// Do we care? This just means one plugin dev cannot name a content source type
// something that another plugin dev used already in another plugin.
if (getContentSourceType(newType.getName()) == null) {
// create the new domain object represented by the XML
ContentSourceType contentSourceType = new ContentSourceType();
contentSourceType.setName(newType.getName());
contentSourceType.setDisplayName(newType.getDisplayName());
contentSourceType.setDescription(newType.getDescription());
contentSourceType.setPluginName(pluginDescriptor.getName());
contentSourceType.setDefaultLazyLoad(newType.isLazyLoad());
contentSourceType.setDefaultDownloadMode(DownloadMode.valueOf(newType.getDownloadMode()
.toUpperCase()));
contentSourceType.setDefaultSyncSchedule(newType.getSyncSchedule());
contentSourceType.setContentSourceApiClass(newType.getApiClass());
ConfigurationDefinition configDef = ConfigurationMetadataParser.parse(newType.getName(), newType
.getConfiguration());
contentSourceType.setContentSourceConfigurationDefinition(configDef);
// add the new domain object to the list of domain objects for this plugin
pluginTypes.put(contentSourceType.getName(), contentSourceType);
} else {
throw new Exception("Cannot redefine an existing content source type:" + newType.getName());
}
}
return pluginTypes.values();
} catch (Exception e) {
log.error("Error transforming plugin descriptor [" + pluginDescriptor.getName() + "]", e);
}
return null;
}
/**
* Returns the {@link ContentSourceType} that has the given name. If no plugin defined a type with that name, <code>
* null</code> is returned.
*
* @param typeName the name of the content source type to return
*
* @return the content source type with the given name or <code>null</code> if none exists
*/
public synchronized ContentSourceType getContentSourceType(String typeName) {
for (Map<String, ContentSourceType> pluginTypes : loadedPlugins.values()) {
ContentSourceType type = pluginTypes.get(typeName);
if (type != null) {
return type;
}
}
return null;
}
/**
* Returns all the {@link ContentSourceType}s that have been defined in all plugins.
*
* @return all content source types defined; will be empty if there are none
*/
public synchronized Set<ContentSourceType> getAllContentSourceTypes() {
Set<ContentSourceType> allTypes = new HashSet<ContentSourceType>();
for (Map<String, ContentSourceType> pluginTypes : loadedPlugins.values()) {
allTypes.addAll(pluginTypes.values());
}
return allTypes;
}
/**
* Returns the names of all plugins that defined content source types.
*
* @return all plugin names
*/
public synchronized Set<String> getPluginNames() {
return this.loadedPlugins.keySet();
}
/**
* Returns the {@link ContentSourceType}s defined by the given plugin. If there is no plugin with that name, <code>
* null</code> is returned.
*
* @param pluginName the name of the plugin whose types are to be returned
*
* @return the content source types defined by the given plugin or <code>null</code> if no plugin exists with that
* name - the returned collection is not a copy, its backed by this manager
*/
public synchronized Collection<ContentSourceType> getContentSourceTypesByPlugin(String pluginName) {
Map<String, ContentSourceType> pluginTypes = loadedPlugins.get(pluginName);
if (pluginTypes == null) {
return null;
}
return pluginTypes.values();
}
/**
* Returns the name of the plugin that deployed the given content source type. <code>null</code> will be returned if
* unknown.
*
* @param type the name of the plugin that deployed this type is to be returned
*
* @return name of the plugin
*/
public synchronized String getPluginNameFromContentSourceType(ContentSourceType type) {
Set<String> pluginNames = loadedPlugins.keySet();
for (String pluginName : pluginNames) {
if (loadedPlugins.get(pluginName).containsValue(type)) {
return pluginName;
}
}
return null;
}
}