kieker.analysis.model.MetaModelHandler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kieker Show documentation
Show all versions of kieker Show documentation
Kieker: Application Performance Monitoring and Dynamic Software Analysis
/***************************************************************************
* Copyright 2013 Kieker Project (http://kieker-monitoring.net)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
***************************************************************************/
package kieker.analysis.model;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.xmi.XMIResource;
import org.eclipse.emf.ecore.xmi.XMLResource;
import org.eclipse.emf.ecore.xmi.impl.EcoreResourceFactoryImpl;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl;
import kieker.analysis.AnalysisController;
import kieker.analysis.IProjectContext;
import kieker.analysis.analysisComponent.AbstractAnalysisComponent;
import kieker.analysis.exception.AnalysisConfigurationException;
import kieker.analysis.model.analysisMetaModel.MIDependency;
import kieker.analysis.model.analysisMetaModel.MIFilter;
import kieker.analysis.model.analysisMetaModel.MIInputPort;
import kieker.analysis.model.analysisMetaModel.MIOutputPort;
import kieker.analysis.model.analysisMetaModel.MIPlugin;
import kieker.analysis.model.analysisMetaModel.MIProject;
import kieker.analysis.model.analysisMetaModel.MIProperty;
import kieker.analysis.model.analysisMetaModel.MIRepository;
import kieker.analysis.model.analysisMetaModel.MIRepositoryConnector;
import kieker.analysis.model.analysisMetaModel.impl.MAnalysisMetaModelFactory;
import kieker.analysis.model.analysisMetaModel.impl.MAnalysisMetaModelPackage;
import kieker.analysis.plugin.AbstractPlugin;
import kieker.analysis.plugin.IPlugin;
import kieker.analysis.plugin.IPlugin.PluginInputPortReference;
import kieker.analysis.plugin.annotation.Plugin;
import kieker.analysis.plugin.annotation.Property;
import kieker.analysis.plugin.filter.AbstractFilterPlugin;
import kieker.analysis.plugin.reader.AbstractReaderPlugin;
import kieker.analysis.repository.AbstractRepository;
import kieker.common.configuration.Configuration;
/**
* This is a helper class for the {@link kieker.analysis.AnalysisController}, which manages the handling of the meta model instances.
*
* @author Andre van Hoorn, Nils Christian Ehmke, Jan Waller
*
* @since 1.8
*/
public final class MetaModelHandler {
private MetaModelHandler() {
// No code necessary
}
/**
* Saves the given meta model project to the given file.
*
* @param file
* The file in which the project will be stored.
* @param project
* The meta model project.
*
* @throws IOException
* If something went wrong during the saving.
*/
public static final void saveProjectToFile(final File file, final MIProject project) throws IOException {
// Create a resource and put the given project into it
final ResourceSet resourceSet = new ResourceSetImpl();
resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("*", new XMIResourceFactoryImpl());
final Resource resource = resourceSet.createResource(URI.createFileURI(file.getAbsolutePath()));
resource.getContents().add(project);
// Make sure that the controller uses utf8 instead of ascii.
final Map options = new HashMap(); // NOPMD (no concurrent access)
options.put(XMLResource.OPTION_ENCODING, "UTF-8");
// Now try to save the resource
resource.save(options);
}
/**
* Loads a meta model project instance from the given file.
*
* @param file
* The file to load the model from.
* @return The meta model instance.
*
* @throws IOException
* If something went wrong during the loading.
*/
public static final MIProject loadProjectFromFile(final File file) throws IOException {
// Create a resource set to work with.
final ResourceSet resourceSet = new ResourceSetImpl();
// Initialize the package - otherwise this method cannot read the element
MAnalysisMetaModelPackage.init();
// Set OPTION_RECORD_UNKNOWN_FEATURE prior to calling getResource.
Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put("*", new EcoreResourceFactoryImpl() {
@Override
public Resource createResource(final URI uri) {
final XMIResourceImpl resource = (XMIResourceImpl) super.createResource(uri);
resource.getDefaultLoadOptions().put(XMLResource.OPTION_RECORD_UNKNOWN_FEATURE, Boolean.TRUE);
return resource;
}
});
// Try to load the resource
final XMIResource resource = (XMIResource) resourceSet.getResource(URI.createFileURI(file.toString()), true);
final EList content;
resource.load(Collections.EMPTY_MAP);
content = resource.getContents();
if (!content.isEmpty()) {
// The first (and only) element should be the project.
return (MIProject) content.get(0);
} else {
throw new IOException("No object found in file '" + file.getAbsolutePath() + "'.");
}
}
/**
* This method can be used to convert a given list of MIProperty
to a configuration object.
*
* @param mProperties
* The properties to be converted.
* @return A filled configuration object.
*/
public static final Configuration modelPropertiesToConfiguration(final EList mProperties) {
final Configuration configuration = new Configuration();
// Run through the properties and convert every single of them
for (final MIProperty mProperty : mProperties) {
configuration.setProperty(mProperty.getName(), mProperty.getValue());
}
return configuration;
}
/**
* This method checks the ports of the given model plugin against the ports of the actual plugin. If there are ports which are in the model instance, but not in
* the "real" plugin, an exception is thrown.
*
* This method should be called during the creation of an AnalysisController via a configuration file to find invalid (outdated) ports.
*
* @param mPlugin
* The model instance of the plugin.
* @param plugin
* The corresponding "real" plugin.
* @throws AnalysisConfigurationException
* If an invalid port has been detected.
*/
public static void checkPorts(final MIPlugin mPlugin, final AbstractPlugin plugin) throws AnalysisConfigurationException {
// Get all ports.
final EList mOutputPorts = mPlugin.getOutputPorts();
final Set outputPorts = new HashSet();
for (final String outputPort : plugin.getAllOutputPortNames()) {
outputPorts.add(outputPort);
}
final Set inputPorts = new HashSet();
for (final String inputPort : plugin.getAllInputPortNames()) {
inputPorts.add(inputPort);
}
// Check whether the ports of the model plugin exist.
for (final MIOutputPort mOutputPort : mOutputPorts) {
if (!outputPorts.contains(mOutputPort.getName())) {
throw new AnalysisConfigurationException("The output port '" + mOutputPort.getName() + "' of '" + mPlugin.getName() + "' (" + mPlugin.getClassname()
+ ") does not exist.");
}
}
final EList mInputPorts = (mPlugin instanceof MIFilter) ? ((MIFilter) mPlugin).getInputPorts() : new BasicEList(); // NOCS
for (final MIInputPort mInputPort : mInputPorts) {
if (!inputPorts.contains(mInputPort.getName())) {
throw new AnalysisConfigurationException("The input port '" + mInputPort.getName() + "' of '" + mPlugin.getName() + "' (" + mPlugin.getClassname()
+ ") does not exist.");
}
}
}
/**
* Converts the given configuration into a list of {@link MIProperty}s using the given factory.
*
* @param configuration
* The configuration to be converted.
* @param factory
* The factory to be used to create the model instances.
* @return A list of model instances.
*/
public static List convertProperties(final Configuration configuration, final MAnalysisMetaModelFactory factory) {
if (null == configuration) { // should not happen, but better be safe than sorry
return Collections.emptyList();
}
final List properties = new ArrayList(configuration.size());
for (final Enumeration> e = configuration.propertyNames(); e.hasMoreElements();) {
final String key = (String) e.nextElement();
final MIProperty property = factory.createProperty();
property.setName(key);
property.setValue(configuration.getStringProperty(key));
properties.add(property);
}
return properties;
}
/**
* Searches for an input port within the given plugin with the given name.
*
* @param mPlugin
* The plugin which will be searched through.
* @param name
* The name of the searched input port.
* @return The searched port or null, if it is not available.
*/
public static final MIInputPort findInputPort(final MIFilter mPlugin, final String name) {
for (final MIInputPort port : mPlugin.getInputPorts()) {
if (port.getName().equals(name)) {
return port;
}
}
return null;
}
/**
* Searches for an output port within the given plugin with the given name.
*
* @param mPlugin
* The plugin which will be searched through.
* @param name
* The name of the searched output port.
* @return The searched port or null, if it is not available.
*/
public static final MIOutputPort findOutputPort(final MIPlugin mPlugin, final String name) {
for (final MIOutputPort port : mPlugin.getOutputPorts()) {
if (port.getName().equals(name)) {
return port;
}
}
return null;
}
/**
* This method can be used to convert the current analysis configuration (which is represented by Java objects) into a meta model.
*
* @param readers
* The readers within the analysis.
* @param filters
* The filters within the analysis.
* @param repositories
* The repositories within the analysis.
* @param dependencies
* The dependencies of the analysis.
* @param projectName
* The name of the project.
* @param globalConfiguration
* The global project configuration.
*
* @return A meta model instance, representing the given analysis.
*
* @throws AnalysisConfigurationException
* If the given analysis components are somehow invalid connected.
*/
public static final MIProject javaToMetaModel(final Collection readers, final Collection filters,
final Collection repositories, final Collection dependencies, final String projectName,
final Configuration globalConfiguration) throws AnalysisConfigurationException {
try {
// Create a factory to create all other model instances.
final MAnalysisMetaModelFactory factory = new MAnalysisMetaModelFactory();
// We start with the project instance
final MIProject mProject = factory.createProject();
mProject.setName(projectName);
mProject.getDependencies().addAll(dependencies);
final Map pluginMap = new HashMap(); // NOPMD (no concurrent access)
final Map repositoryMap = new HashMap(); // NOPMD (no concurrent access)
// Run through all repositories and create the model counterparts.
for (final AbstractRepository repository : repositories) {
final MIRepository mRepository = factory.createRepository();
mRepository.setId(EcoreUtil.generateUUID());
mRepository.setClassname(repository.getClass().getName());
mRepository.getProperties().addAll(MetaModelHandler.convertProperties(repository.getCurrentConfiguration(), factory));
mProject.getRepositories().add(mRepository);
// Remember the mapping.
repositoryMap.put(repository, mRepository);
}
// Run through all plugins and create the model counterparts.
final List plugins = new ArrayList(readers);
plugins.addAll(filters);
for (final AbstractPlugin plugin : plugins) {
MIPlugin mPlugin;
if (plugin instanceof AbstractReaderPlugin) {
mPlugin = factory.createReader();
} else {
mPlugin = factory.createFilter();
}
mPlugin.setId(EcoreUtil.generateUUID());
mPlugin.setClassname(plugin.getClass().getName());
mPlugin.setName(plugin.getName());
mPlugin.getProperties().addAll(MetaModelHandler.convertProperties(plugin.getCurrentConfiguration(), factory));
// Extract the repositories.
for (final Entry repoEntry : plugin.getCurrentRepositories().entrySet()) {
// Try to find the repository within our map.
final AbstractRepository repository = repoEntry.getValue();
final MIRepository mRepository = repositoryMap.get(repository);
// If it doesn't exist, we have a problem...
if (mRepository == null) {
throw new AnalysisConfigurationException("Repository '" + repository.getName() + "' (" + repository.getRepositoryName()
+ ") not contained in project. Maybe the repository has not been registered.");
}
// Now the connector.
final MIRepositoryConnector mRepositoryConn = factory.createRepositoryConnector();
mRepositoryConn.setId(EcoreUtil.generateUUID());
mRepositoryConn.setName(repoEntry.getKey());
mRepositoryConn.setRepository(mRepository);
mPlugin.getRepositories().add(mRepositoryConn);
}
// Create the ports.
final String[] outs = plugin.getAllOutputPortNames();
for (final String out : outs) {
final MIOutputPort mOutputPort = factory.createOutputPort();
mOutputPort.setId(EcoreUtil.generateUUID());
mOutputPort.setName(out);
mPlugin.getOutputPorts().add(mOutputPort);
}
final String[] ins = plugin.getAllInputPortNames();
for (final String in : ins) {
final MIInputPort mInputPort = factory.createInputPort();
mInputPort.setId(EcoreUtil.generateUUID());
mInputPort.setName(in);
((MIFilter) mPlugin).getInputPorts().add(mInputPort);
}
mProject.getPlugins().add(mPlugin);
// Remember the mapping.
pluginMap.put(plugin, mPlugin);
}
// Now connect the plugins.
for (final IPlugin plugin : plugins) {
final MIPlugin mOutputPlugin = pluginMap.get(plugin);
// Check all output ports of the original plugin.
for (final String outputPortName : plugin.getAllOutputPortNames()) {
// Get the corresponding port of the model counterpart and get also the plugins which are currently connected with the original plugin.
final EList subscribers = MetaModelHandler.findOutputPort(mOutputPlugin, outputPortName).getSubscribers();
// Run through all connected plugins.
for (final PluginInputPortReference subscriber : plugin.getConnectedPlugins(outputPortName)) {
final IPlugin subscriberPlugin = subscriber.getPlugin();
final MIPlugin mSubscriberPlugin = pluginMap.get(subscriberPlugin);
// If it doesn't exist, we have a problem...
if (mSubscriberPlugin == null) {
throw new AnalysisConfigurationException("Plugin '" + subscriberPlugin.getName() + "' (" + subscriberPlugin.getPluginName()
+ ") not contained in project. Maybe the plugin has not been registered.");
}
final MIInputPort mInputPort = MetaModelHandler.findInputPort((MIFilter) mSubscriberPlugin, subscriber.getInputPortName());
subscribers.add(mInputPort);
}
}
}
// Now put our global configuration into the model instance
final Set> properties = globalConfiguration.entrySet();
for (final Entry