/*******************************************************************************
* Copyright (c) 2015-16 Inria
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* - Philippe Merle <philippe.merle@inria.fr>
*******************************************************************************/
package org.occiware.mart;
import java.lang.reflect.Field;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import org.eclipse.emf.ecore.EFactory;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.resource.Resource.Factory.Registry;
import org.occiware.clouddesigner.occi.OCCIRegistry;
import org.occiware.clouddesigner.occi.util.OCCIResourceFactoryImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This class provides OCCIware Models@Run.time (MART).
*
* @author Philippe Merle - Inria
*/
public class MART
{
/**
* Initialize the logger.
*/
private static Logger LOGGER = LoggerFactory.getLogger(MART.class);
/**
* This method must be called before any usage of MART
* because MART is running outside of an Eclipse IDE and
* various EMF and OCCI initializations are required.
*/
public static void initMART()
{
LOGGER.info("OCCIware MART initializing...");
// Get the current classloader.
final ClassLoader classLoader = MART.class.getClassLoader();
// Get the OCCI extension registry.
final OCCIRegistry occiRegistry = OCCIRegistry.getInstance();
// Get the EMF file extension to factory map.
final Map<String,Object> ecoreExtensionToFactoryMap = Registry.INSTANCE.getExtensionToFactoryMap();
// Add OCCI resource factory for any extension.
ecoreExtensionToFactoryMap.put("*", new OCCIResourceFactoryImpl());
// Map to store EMF package factory overriding.
final Map<String, EFactory> ecoreFactoryOverrideMap = new HashMap<String, EFactory>();
try {
// Initialize DOM.
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
final DocumentBuilder builder = factory.newDocumentBuilder();
// Iterate over all plugin.xml files found into the classpath.
LOGGER.info(" Scanning all plugin.xml found in the classpath...");
Enumeration<URL> pluginResources = classLoader.getResources("plugin.xml");
for(URL url : java.util.Collections.list(pluginResources)) {
LOGGER.debug(" * " + url.toExternalForm() + "...");
// Parse each plugin.xml file.
final Document document = builder.parse(url.toURI().toString());
final Element root = document.getDocumentElement();
// Iterate over all child nodes.
final NodeList rootNodes = root.getChildNodes();
for (int i=0; i<rootNodes.getLength(); i++) {
Node node = rootNodes.item(i);
if(node.getNodeType() == Node.ELEMENT_NODE) {
final Element element = (Element)node;
if("extension".equals(element.getNodeName())) {
// Manage <extension> element.
final NodeList childNodes = element.getChildNodes();
String point = element.getAttribute("point");
if("org.eclipse.emf.ecore.generated_package".equals(point)) {
//
// Manage <extension point="org.eclipse.emf.ecore.generated_package"> element.
//
for (int j=0; j<childNodes.getLength(); j++) {
Node childNode = childNodes.item(j);
if(childNode.getNodeType() == Node.ELEMENT_NODE) {
final Element childElement = (Element)childNode;
if("package".equals(childElement.getNodeName())) {
//
// Manage <package uri="..." class="..."> element.
//
String uri = childElement.getAttribute("uri");
String className = childElement.getAttribute("class");
// Do not dealt with Eclipse packages.
if(!className.startsWith("org.eclipse.")) {
// Load the class.
Class<?> ePackageClass = loadClass(className);
if(ePackageClass != null) {
try {
// Force initialization of the Ecore package.
Field eInstanceField = ePackageClass.getField("eINSTANCE");
Object eInstance = eInstanceField.get(null);
eInstance.toString();
LOGGER.info(" - EMF package " + className + " at " + uri + " registered.");
} catch (NoSuchFieldException e) {
LOGGER.error("Class " + className + " has no eINSTANCE field!",e);
} catch (SecurityException e) {
LOGGER.error("Security exception!", e);
} catch (IllegalArgumentException e) {
LOGGER.error("Illegal argument exception!", e);
} catch (IllegalAccessException e) {
LOGGER.error("Illegal access exception!", e);
}
}
}
}
}
}
} else if("org.eclipse.emf.ecore.factory_override".equals(point)) {
//
// Manage <extension point="org.eclipse.emf.ecore.factory_override"> element.
//
for (int j=0; j<childNodes.getLength(); j++) {
Node childNode = childNodes.item(j);
if(childNode.getNodeType() == Node.ELEMENT_NODE) {
final Element childElement = (Element)childNode;
if("factory".equals(childElement.getNodeName())) {
//
// Manage <factory uri="..." class="...">
//
String uri = childElement.getAttribute("uri");
String className = childElement.getAttribute("class");
// Do not dealt with Eclipse packages.
if(!className.startsWith("org.eclipse.")) {
// Instantiate the factory class.
EFactory eFactory = (EFactory)newInstance(className);
if(eFactory != null) {
// Register the factory.
ecoreFactoryOverrideMap.put(uri, eFactory);
}
}
}
}
}
} else if("org.eclipse.emf.ecore.extension_parser".equals(point)) {
//
// Manage <extension point="org.eclipse.emf.ecore.extension_parser"> element.
//
for (int j=0; j<childNodes.getLength(); j++) {
Node childNode = childNodes.item(j);
if(childNode.getNodeType() == Node.ELEMENT_NODE) {
final Element childElement = (Element)childNode;
if("parser".equals(childElement.getNodeName())) {
//
// Manage <parser type="..." class="..."> element.
//
String type = childElement.getAttribute("type");
String className = childElement.getAttribute("class");
// Do not dealt with Eclipse packages.
if(!className.startsWith("org.eclipse.")) {
// Instantiate the class.
Object extensionParser = newInstance(className);
if(extensionParser != null) {
// Register the extension parser.
ecoreExtensionToFactoryMap.put(type, extensionParser);
LOGGER.info(" - Ecore factory " + className + " for file extension ." + type + " registered.");
}
}
}
}
}
} else if("org.occiware.clouddesigner.occi.occie".equals(point)) {
//
// Manage <extension point="org.occiware.clouddesigner.occi.occie"> element.
//
for (int j=0; j<childNodes.getLength(); j++) {
Node childNode = childNodes.item(j);
if(childNode.getNodeType() == Node.ELEMENT_NODE) {
final Element childElement = (Element)childNode;
if("occie".equals(childElement.getNodeName())) {
//
// Manage <occie file="..." scheme="..."> element.
//
String file = childElement.getAttribute("file");
String scheme = childElement.getAttribute("scheme");
String resourceUri = getResourceFromClasspath("/" + file);
if(resourceUri != null) {
// Register the OCCI extension
occiRegistry.registerExtension(scheme, getResourceFromClasspath("/" + file));
LOGGER.info(" - OCCI extension " + scheme + " contained in " + file + " registered.");
} else {
LOGGER.warn(" - OCCI extension file " + file + " not found!");
}
}
}
}
}
}
}
}
}
} catch (ParserConfigurationException e) {
LOGGER.error("Parser configuration exception!", e);
} catch (SAXException e) {
LOGGER.error("SAX exception!", e);
} catch (URISyntaxException e) {
LOGGER.error("URI syntax exception!", e);
} catch (IOException e) {
LOGGER.error("IO exception!", e);
}
// Iterate over all Ecore factory overrides
for(Map.Entry<String, EFactory> entry : ecoreFactoryOverrideMap.entrySet()) {
String uri = entry.getKey();
EFactory eFactory = entry.getValue();
// Search the Ecore package.
EPackage epackage = EPackage.Registry.INSTANCE.getEPackage(uri);
if(epackage == null) {
LOGGER.error("EPackage " + uri + " unknown!");
} else {
epackage.setEFactoryInstance(eFactory);
LOGGER.info(" - Ecore factory " + eFactory.getClass().getName() + " for package " + uri + " registered.");
}
}
LOGGER.info("OCCIware MART initialized.");
}
/**
* Get a resource path from the classpath.
* @param path the path into the classpath.
* @return the resource path.
*/
public static String getResourceFromClasspath(String path)
{
java.net.URL resourceUrl = MART.class.getResource(path);
return (resourceUrl != null) ? resourceUrl.toExternalForm() : null;
}
/**
* Report various JVM information.
*/
public static void reportJavaInformation()
{
// Getting the runtime reference from system.
java.lang.Runtime runtime = java.lang.Runtime.getRuntime();
LOGGER.info("Java Runtime available processor = " + runtime.availableProcessors());
LOGGER.info("Java Runtime max memory = " + runtime.maxMemory());
LOGGER.info("Java Runtime total memory = " + runtime.totalMemory());
LOGGER.info("Java Runtime free memory = " + runtime.freeMemory());
int mb = 1024*1024;
LOGGER.info("##### Heap utilization statistics [MB] #####");
// Print used memory
LOGGER.info("Used Memory:" + (runtime.totalMemory() - runtime.freeMemory()) / mb);
// Print free memory
LOGGER.info("Free Memory:" + runtime.freeMemory() / mb);
// Print total available memory
LOGGER.info("Total Memory:" + runtime.totalMemory() / mb);
// Print Maximum available memory
LOGGER.info("Max Memory:" + runtime.maxMemory() / mb);
}
/**
* Load a class.
*/
private static Class<?> loadClass(final String className)
{
try {
LOGGER.debug("Loading class " + className + "...");
return MART.class.getClassLoader().loadClass(className);
} catch (ClassNotFoundException e) {
LOGGER.error("Class " + className + " not found!",e);
}
return null;
}
/**
* Instantiate a class.
*/
private static Object newInstance(final String className)
{
Class<?> clazz = loadClass(className);
if(clazz != null) {
try {
LOGGER.debug("Instantiating class " + className + "...");
return clazz.newInstance();
} catch (InstantiationException e) {
LOGGER.error("Instantiation exception!", e);
} catch (IllegalAccessException e) {
LOGGER.error("Illegal access exception!", e);
}
}
return null;
}
}