org.jboss.loom.utils.as7.AS7ModuleUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.loom.utils.as7.AS7ModuleUtils.java

Source

/**
 * 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 org.jboss.loom.utils.as7;

import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import java.io.Writer;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.commons.lang.StringUtils;
import org.jboss.loom.actions.ModuleCreationAction.ModuleXmlInfo;
import org.jboss.loom.conf.AS7Config;
import org.jboss.loom.ex.MigrationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

/**
 * Util class for generation of module XML.
 *
 * @author Roman Jakubco
 */
public class AS7ModuleUtils {

    private static final String MODULE_NS = "urn:jboss:module:1.1";

    /**
     * Creates module.xml.
     */
    public static void createModuleXML_FreeMarker(ModuleXmlInfo moduleInfo, File modFile)
            throws MigrationException {
        //Writer out = null;
        try {
            Configuration cfg = new Configuration();
            cfg.setClassForTemplateLoading(AS7ModuleUtils.class, "/org/jboss/loom/utils/as7/");
            cfg.setObjectWrapper(new DefaultObjectWrapper());
            cfg.setSharedVariable("modInfo", moduleInfo);

            Template temp = cfg.getTemplate("module.xml.freemarker");

            try (Writer out = new FileWriter(modFile)) {
                temp.process(null, out);
            }
        } catch (TemplateException | IOException ex) {
            throw new MigrationException("Failed creating " + modFile.getPath() + ": " + ex.getMessage(), ex);
        }
    }

    /**
     * Example of module xml,
     * <module xmlns="urn:jboss:module:1.1" name="com.h2database.h2">
     *     <resources>
     *         <resource-root path="h2-1.3.168.jar"/>
     *     </resources>
     *     <dependencies>
     *         <module name="javax.api"/>
     *         <module name="javax.transaction.api"/>
     *         <module name="javax.servlet.api" optional="true"/>
     *     </dependencies>
     * </module>
     * 
     * @Deprecated  Screws up namespaces. I haven't found a way to fix it in JAXP. Switched to FreeMarker.
     */
    public static Document createModuleXML(String moduleName, String jarFile, String[] deps)
            throws ParserConfigurationException {

        Document doc = createDoc();
        //Document doc = createDoc(MODULE_NS, "module");

        Element root = doc.createElement("module");
        //Element root = doc.createElementNS("module", MODULE_NS);
        doc.appendChild(root);
        //Element root = doc.getDocumentElement();
        root.setAttribute("xmlns", MODULE_NS);
        root.setAttribute("name", moduleName);

        Element resources = doc.createElementNS(MODULE_NS, "resources");
        root.appendChild(resources);

        Element resource = doc.createElementNS(MODULE_NS, "resource-root");
        resource.setAttribute("path", jarFile);
        resources.appendChild(resource);

        // Dependencies
        Element dependencies = doc.createElementNS(MODULE_NS, "dependencies");

        boolean optional = false;
        for (String modName : deps) {
            if (modName == null) {
                optional = true;
                continue;
            }
            Element module = doc.createElementNS(MODULE_NS, "module");
            module.setAttribute("name", modName);
            if (optional)
                module.setAttribute("optional", "true");
            dependencies.appendChild(module);
            optional = false;
        }

        root.appendChild(dependencies);

        return doc;
    }

    /**
     *  Parses syntax "foo ?bar baz" into String[]{"foo", null, "bar", "baz"}.
     *  (? and null means that the following dep is optional.)
     */
    private static String[] parseDeps(String str) {
        List<String> deps = new LinkedList();
        for (String name : StringUtils.split(str)) {
            if (name.charAt(0) == '?') {
                deps.add(null);
                name = name.substring(1);
            }
            deps.add(name);
        }
        return deps.toArray(new String[deps.size()]);
    }

    public static File transformDocToFile(Document doc, File file) throws TransformerException {
        final TransformerFactory tf = TransformerFactory.newInstance();
        final Transformer transformer = tf.newTransformer();
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");

        transformer.transform(new DOMSource(doc), new StreamResult(file));

        return file;
    }

    private static Document createDoc() throws ParserConfigurationException {
        return createDoc(null, null);
    }

    private static Document createDoc(String namespace, String rootElmName) throws ParserConfigurationException {
        DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
        // Need specifically Xerces as it treats namespaces better way.
        /*DocumentBuilderFactory domFactory;
        try {
        domFactory = (DocumentBuilderFactory) Class.forName("com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl").newInstance();
        } catch( ClassNotFoundException | InstantiationException | IllegalAccessException ex ) {
        throw new IllegalStateException("JDK's DocumentBuilderFactoryImpl not found:\n    " + ex.getMessage(), ex );
        }*/
        //DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance("com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl", ClassLoader.getSystemClassLoader());

        domFactory.setIgnoringComments(true);
        domFactory.setNamespaceAware(false);
        domFactory.setValidating(false);
        DocumentBuilder builder = domFactory.newDocumentBuilder();

        Document doc = builder.getDOMImplementation().createDocument(namespace, rootElmName, null);// rootElmName
        return doc;
    }

    /**
     *  Returns the name of the module which uses given .jar.
     *  For example, file at modules/system/layers/base/com/h2database/h2/main/h2-1.3.168.jar
     *  should return "com.h2database.h2".
     * 
     *  The current implementation is naive, assuming that the .jar file is in the module's root dir, where module.xml is.
     * 
     *  This method behavior is likely to change with various versions of EAP.
     */
    public static String identifyModuleContainingJar(AS7Config as7Config, File jar) {

        String modAbsPath = as7Config.getModulesDir().getPath();
        String jarAbsPath = jar.getParentFile().getParentFile().getPath();

        String commonPrefix = StringUtils.getCommonPrefix(new String[] { modAbsPath, jarAbsPath });
        String diff = jarAbsPath.substring(commonPrefix.length());

        String modName = StringUtils.removeStart(diff, "/");
        return modName.replace('/', '.');
    }

}// class