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

io.cloudslang.lang.enforcer.SpringCleansingRule Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 * (c) Copyright 2016 Hewlett-Packard Development Company, L.P.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Apache License v2.0 which accompany this distribution.
 *
 * The Apache License is available at
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 *******************************************************************************/
package io.cloudslang.lang.enforcer;

import org.apache.maven.enforcer.rule.api.EnforcerRule;
import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;

import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static java.lang.String.format;
import static java.lang.String.valueOf;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.nio.file.Files.isRegularFile;
import static java.nio.file.LinkOption.NOFOLLOW_LINKS;
import static org.apache.commons.io.FileUtils.iterateFiles;
import static org.apache.commons.io.FileUtils.readFileToString;
import static org.apache.commons.lang3.StringUtils.countMatches;


public class SpringCleansingRule implements EnforcerRule {

    private static final String JAVA = "java";
    private static final String OPTIONAL_SPACER = "(\\s)*";
    private static final String REGEX_DOT = "\\.";
    private static final String OPTIONAL_STATIC = "(static )?";

    private static final String ORG = "org";
    private static final String SPRINGFRAMEWORK = "springframework";

    private static final String SPACER_DOT_SPACER = OPTIONAL_SPACER + REGEX_DOT + OPTIONAL_SPACER;
    private static final String regexImport = "import " + OPTIONAL_STATIC + OPTIONAL_SPACER + ORG +
            SPACER_DOT_SPACER + SPRINGFRAMEWORK + "[^;]+" + ";" ;

    private static final Pattern patternImport = Pattern.compile(regexImport);
    private static final String regexCodeLine = OPTIONAL_SPACER + ORG + OPTIONAL_SPACER + REGEX_DOT +
            OPTIONAL_SPACER + SPRINGFRAMEWORK + "(.|\\s)+;" ;

    private static final Pattern patternCodeLine = Pattern.compile(regexCodeLine);
    private static final String STARTED_SCANNING_ORG_SPRINGFRAMEWORK = "Scanning file for org.springframework " +
            "in file '%s'";
    private static final String FINISHED_SCANNING_ORG_SPRINGFRAMEWORK = "Finished scanning for org.springframework " +
            "in file '%s'";
    private static final String FOUND_USAGE_OF_ORG_SPRINGFRAMEWORK_IN_IMPORT_AT_LINE = "Found usage of " +
            "org.springframework in import at line ";
    private static final String FOUND_USAGE_OF_ORG_SPRINGFRAMEWORK_IN_CODE_FRAGMENT_AT_LINE = "Found usage of " +
            "org.springframework in code fragment at line ";

    private static final String CONTEXT = "context";
    private static final String ANNOTATION = "annotation";
    private static final String CONFIGURATION = "Configuration";


    private static final String SPRING_CONFIGURATION_CLASS = OPTIONAL_SPACER + ORG + SPACER_DOT_SPACER +
            SPRINGFRAMEWORK + SPACER_DOT_SPACER + CONTEXT + SPACER_DOT_SPACER + ANNOTATION + SPACER_DOT_SPACER +
            CONFIGURATION;

    private static final Pattern patternConfigurationClass = Pattern.compile(SPRING_CONFIGURATION_CLASS);

    private static final String FOUND_UNWANTED_OCCURRENCE_OF_ORG_SPRINGFRAMEWORK = "Found unwanted occurrence of " +
            "org.springframework at line %d in source '%s'";
    private static final String IN_SOURCE = " in source '";
    private static final String NEW_LINE = "\n";

    /**
     * Simple param. This rule will fail if the value is true.
     */
    private boolean shouldFail = false;

    public void execute(EnforcerRuleHelper helper) throws EnforcerRuleException {
        Log log = helper.getLog();

        try {
            // get the various expressions out of the helper.
            MavenProject project = (MavenProject) helper.evaluate("${project}");
            // MavenSession session = (MavenSession) helper.evaluate("${session}");
            // String target = (String) helper.evaluate("${project.build.directory}");
            // String artifactId = (String) helper.evaluate("${project.artifactId}");

            // ArtifactResolver resolver = (ArtifactResolver) helper.getComponent(ArtifactResolver.class);
            // RuntimeInfo rti = (RuntimeInfo) helper.getComponent(RuntimeInfo.class);
            List compileSourceRoots = project.getCompileSourceRoots();

            for (Object compileSourceRoot : compileSourceRoots) {
                String path = (String) compileSourceRoot;
                applyForJavaSourcesInRoot(path, log);
            }
        } catch (ExpressionEvaluationException e) {
            throw new EnforcerRuleException("Unable to lookup an expression " + e.getLocalizedMessage(), e);
        }
    }

    /**
     * If your rule is cacheable, you must return a unique id when parameters or conditions
     * change that would cause the result to be different. Multiple cached results are stored
     * based on their id.
     * 

* The easiest way to do this is to return a hash computed from the values of your parameters. *

* If your rule is not cacheable, then the result here is not important, you may return anything. */ public String getCacheId() { //no hash on boolean...only parameter so no hash is needed. return "" + this.shouldFail; } /** * This tells the system if the results are cacheable at all. Keep in mind that during * forked builds and other things, a given rule may be executed more than once for the same * project. This means that even things that change from project to project may still * be cacheable in certain instances. */ public boolean isCacheable() { return false; } /** * If the rule is cacheable and the same id is found in the cache, the stored results * are passed to this method to allow double checking of the results. Most of the time * this can be done by generating unique ids, but sometimes the results of objects returned * by the helper need to be queried. You may for example, store certain objects in your rule * and then query them later. */ public boolean isResultValid(EnforcerRule arg0) { return false; } private boolean isSpringConfigurationAnnotatedClass(final String contents) { Matcher matcher = patternConfigurationClass.matcher(contents); return matcher.find(); } private void applyForJavaSourcesInRoot(final String path, final Log log) throws EnforcerRuleException { Iterator fileIterator = iterateFiles(new File(path), new String[]{JAVA}, true); while (fileIterator.hasNext()) { File source = fileIterator.next(); if (isRegularFile(source.toPath(), NOFOLLOW_LINKS)) { if (log.isDebugEnabled()) { log.debug(format(STARTED_SCANNING_ORG_SPRINGFRAMEWORK, source.getAbsolutePath())); } try { String contents = readFileToString(source, UTF_8.displayName()); if (isSpringConfigurationAnnotatedClass(contents)) { log.info(format("Skipping verification for Spring configuration class in file '%s'", source.getAbsolutePath())); continue; } // At this point it is clear this is a regular Java class that is not a Spring Configuration class // and just validate we don't have org.springframework in it findMatchesUsingPattern(source, log, contents, patternImport, FOUND_USAGE_OF_ORG_SPRINGFRAMEWORK_IN_IMPORT_AT_LINE); findMatchesUsingPattern(source, log, contents, patternCodeLine, FOUND_USAGE_OF_ORG_SPRINGFRAMEWORK_IN_CODE_FRAGMENT_AT_LINE); } catch (IOException ignore) { log.error(format("Could not process file '%s'", source)); } if (log.isDebugEnabled()) { log.debug(format(FINISHED_SCANNING_ORG_SPRINGFRAMEWORK, source.getAbsolutePath())); } } } } private void findMatchesUsingPattern(final File javaFile, final Log log, final String contents, final Pattern pattern, String message) throws EnforcerRuleException { Matcher matcherImportForFile = pattern.matcher(contents); if (matcherImportForFile.find()) { int lineNumber = findLineNumber(contents.substring(0, matcherImportForFile.start())); log.info(format(FOUND_UNWANTED_OCCURRENCE_OF_ORG_SPRINGFRAMEWORK, lineNumber, javaFile.getAbsolutePath())); if (shouldFail) { throw new EnforcerRuleException(message + valueOf(lineNumber) + IN_SOURCE + javaFile.getAbsolutePath() + "'"); } } } private int findLineNumber(String contents) { return countMatches(contents, NEW_LINE) + 1; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy