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

nl.openweb.hippo.groovy.ScriptClassFactory Maven / Gradle / Ivy

There is a newer version: 1.17
Show newest version
/*
 * Copyright 2019 Open Web IT B.V. (https://www.openweb.nl/)
 *
 * 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 nl.openweb.hippo.groovy;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.List;

import javax.jcr.NamespaceException;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.jackrabbit.spi.NameFactory;
import org.apache.jackrabbit.spi.commons.conversion.NameParser;
import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl;
import org.apache.jackrabbit.spi.commons.namespace.NamespaceMapping;

import groovy.lang.GroovyClassLoader;
import nl.openweb.hippo.groovy.exception.ScriptParseException;
import nl.openweb.hippo.groovy.model.ScriptClass;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;
import static nl.openweb.hippo.groovy.Generator.NEWLINE;
import static nl.openweb.hippo.groovy.Generator.getAnnotationClasses;
import static nl.openweb.hippo.groovy.Generator.getAnnotations;
import static nl.openweb.hippo.groovy.Generator.stripAnnotations;

public class ScriptClassFactory {
    private static final String LINE_END_WINDOWS = "\r\n";
    private static final String LINE_END_LINUX = "\n";
    private static final String LINE_END_MAC = "\r";
    private static final NamespaceMapping NAMESPACE_MAPPING = new NamespaceMapping();
    private static final NameFactory NAME_FACTORY = NameFactoryImpl.getInstance();
    private static final GroovyClassLoader GROOVY_CLASS_LOADER = new GroovyClassLoader();

    private ScriptClassFactory() {
        //No instantiating of this class
    }

    private static NamespaceMapping getNamespaceMapping() throws NamespaceException {
        if (!NAMESPACE_MAPPING.hasPrefix(StringUtils.EMPTY)) {
            NAMESPACE_MAPPING.setMapping(StringUtils.EMPTY, StringUtils.EMPTY);
        }
        return NAMESPACE_MAPPING;
    }

    private static void validateScriptClass(final ScriptClass scriptClass) {
        if (scriptClass == null || scriptClass.getUpdater() == null) {
            return;
        }
        final String name = scriptClass.getUpdater().name();

        try {
            NameParser.parse(name, getNamespaceMapping(), NAME_FACTORY);
        } catch (Exception e) {
            throw new ScriptParseException("Error parsing the updater name for: " + scriptClass.getFile().getAbsolutePath(), e);
        }
    }

    /**
     * Returns a class that has actually nothing but the Bootstrap and Updater Annotations
     *
     * @param file the file to make a class representation of
     * @return a fake class with the Bootstrap and Updater annotations
     */
    public static ScriptClass getInterpretingClass(final File file) {
        return getInterpretingClass(file, false);
    }

    /**
     * Returns a class that has actually nothing but the Bootstrap and Updater Annotations
     *
     * @param file          the file to make a class representation of
     * @param keepLineCount keep linecount when stripping the annotations in the scriptcontent
     * @return a fake class with the Bootstrap and Updater annotations
     */
    public static ScriptClass getInterpretingClass(final File file, final boolean keepLineCount) {
        GROOVY_CLASS_LOADER.clearCache();
        String script;
        try {
            script = readFileEnsuringLinuxLineEnding(file);

            String imports = getAnnotationClasses().stream()
                .map(clazz -> "import " + clazz.getCanonicalName() + ";" + LINE_END_LINUX)
                .collect(joining());
            String interpretCode = imports + String.join(LINE_END_LINUX, getAnnotations(script)) + LINE_END_LINUX + "class InterpretClass {}";
            script = stripAnnotations(script, keepLineCount);
            final ScriptClass scriptClass = new ScriptClass(file, GROOVY_CLASS_LOADER.parseClass(interpretCode), script);
            validateScriptClass(scriptClass);
            return scriptClass;
        } catch (IOException e) {
            return null;
        }
    }

    public static String readFileEnsuringLinuxLineEnding(final File file) throws IOException {
        String content = FileUtils.readFileToString(file, Charset.defaultCharset());
        if (content.contains(LINE_END_MAC)) {
            content = content.replace(LINE_END_WINDOWS, LINE_END_LINUX)
                .replace(LINE_END_MAC, LINE_END_LINUX);
        }
        return content.replaceAll("[\\t ]+" + NEWLINE, NEWLINE);
    }

    public static List getScriptClasses(File sourceDir) {
        return Generator.getGroovyFiles(sourceDir).stream().map(ScriptClassFactory::getInterpretingClass)
            .filter(script -> script.isValid() && !script.isExcluded()).collect(toList());
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy