All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jbake.parser.Engines Maven / Gradle / Ivy

Go to download

JBake is a Java based open source static site/blog generator for developers.

There is a newer version: 2.7.0-rc.7
Show newest version
package org.jbake.parser;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

/**
 * 

A singleton class giving access to markup engines. Markup engines are loaded based on classpath. * New engines may be registered either at runtime (not recommanded) or by putting a descriptor file * on classpath (recommanded).

* *

The descriptor file must be found in META-INF directory and named * org.jbake.parser.MarkupEngines.properties. The format of the file is easy:

* * org.jbake.parser.RawMarkupEngine=html
* org.jbake.parser.AsciidoctorEngine=ad,adoc,asciidoc
* org.jbake.parser.MarkdownEngine=md
*
*

where the key is the class of the engine (must extend {@link org.jbake.parser.MarkupEngine} and have a no-arg * constructor and the value is a comma-separated list of file extensions that this engine is capable of proceeding.

* *

Markup engines are singletons, so are typically used to initialize the underlying renderning engines. They * must not store specific information of a currently processed file (use {@link ParserContext the parser context} * for that).

* * This class loads the engines only if they are found on classpath. If not, the engine is not registered. This allows * JBake to support multiple rendering engines without the explicit need to have them on classpath. This is a better * fit for embedding. * * @author Cédric Champeau * */ public class Engines { private static final Logger LOGGER = LoggerFactory.getLogger(Engines.class); private static final Engines INSTANCE; private final Map parsers; static { INSTANCE = new Engines(); loadEngines(); } public static ParserEngine get(String fileExtension) { return INSTANCE.getEngine(fileExtension); } public static void register(String fileExtension, ParserEngine engine) { INSTANCE.registerEngine(fileExtension, engine); } public static Set getRecognizedExtensions() { return Collections.unmodifiableSet(INSTANCE.parsers.keySet()); } private Engines() { parsers = new HashMap<>(); } private void registerEngine(String fileExtension, ParserEngine markupEngine) { ParserEngine old = parsers.put(fileExtension, markupEngine); if (old != null) { LOGGER.warn("Registered a markup engine for extension [.{}] but another one was already defined: {}", fileExtension, old); } } private ParserEngine getEngine(String fileExtension) { return parsers.get(fileExtension); } /** * This method is used to search for a specific class, telling if loading the engine would succeed. This is * typically used to avoid loading optional modules. * * @param engineClassName engine class, used both as a hint to find it and to create the engine itself. * @return null if the engine is not available, an instance of the engine otherwise */ private static ParserEngine tryLoadEngine(String engineClassName) { try { @SuppressWarnings("unchecked") Class engineClass = (Class) Class.forName(engineClassName, false, Engines.class.getClassLoader()); return engineClass.getDeclaredConstructor().newInstance(); } catch (ClassNotFoundException | NoClassDefFoundError | IllegalAccessException | InstantiationException e) { return new ErrorEngine(engineClassName); } catch (NoSuchMethodException | InvocationTargetException e) { LOGGER.error("unable to instantiate ParserEngine {}", engineClassName); } return null; } /** * This method is used internally to load markup engines. Markup engines are found using descriptor files on classpath, so * adding an engine is as easy as adding a jar on classpath with the descriptor file included. */ private static void loadEngines() { try { ClassLoader cl = Engines.class.getClassLoader(); Enumeration resources = cl.getResources("META-INF/org.jbake.parser.MarkupEngines.properties"); while (resources.hasMoreElements()) { URL url = resources.nextElement(); Properties props = new Properties(); props.load(url.openStream()); for (Map.Entry entry : props.entrySet()) { String className = (String) entry.getKey(); String[] extensions = ((String)entry.getValue()).split(","); registerEngine(className, extensions); } } } catch (IOException e) { LOGGER.error("Error loading Engines", e); } } private static void registerEngine(String className, String... extensions) { ParserEngine engine = tryLoadEngine(className); if (engine != null) { for (String extension : extensions) { register(extension, engine); } if (engine instanceof ErrorEngine) { LOGGER.warn("Unable to load a suitable rendering engine for extensions {}", (Object) extensions); } } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy