001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.maven.plugins.enforcer.internal; 020 021import javax.inject.Inject; 022import javax.inject.Named; 023import javax.inject.Provider; 024import javax.inject.Singleton; 025 026import java.util.ArrayList; 027import java.util.List; 028import java.util.Objects; 029import java.util.Optional; 030 031import org.apache.maven.enforcer.rule.api.EnforcerLevel; 032import org.apache.maven.enforcer.rule.api.EnforcerLogger; 033import org.apache.maven.enforcer.rule.api.EnforcerRuleBase; 034import org.apache.maven.execution.MavenSession; 035import org.apache.maven.plugin.MojoExecution; 036import org.apache.maven.plugin.PluginParameterExpressionEvaluator; 037import org.apache.maven.plugin.logging.Log; 038import org.codehaus.plexus.PlexusContainer; 039import org.codehaus.plexus.classworlds.realm.ClassRealm; 040import org.codehaus.plexus.component.configurator.ComponentConfigurationException; 041import org.codehaus.plexus.component.configurator.ComponentConfigurator; 042import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator; 043import org.codehaus.plexus.component.repository.exception.ComponentLookupException; 044import org.codehaus.plexus.configuration.PlexusConfiguration; 045 046/** 047 * Manage enforcer rules. 048 * 049 * @author Slawomir Jaranowski 050 * @since 3.2.0 051 */ 052@Named 053@Singleton 054public class EnforcerRuleManager { 055 056 private final Provider<MavenSession> sessionProvider; 057 058 private final Provider<MojoExecution> mojoExecutionProvider; 059 060 private final ComponentConfigurator componentConfigurator; 061 062 private final PlexusContainer plexusContainer; 063 064 @Inject 065 public EnforcerRuleManager( 066 Provider<MavenSession> sessionProvider, 067 Provider<MojoExecution> mojoExecutionProvider, 068 @Named("basic") ComponentConfigurator componentConfigurator, 069 PlexusContainer plexusContainer) { 070 this.sessionProvider = Objects.requireNonNull(sessionProvider, "sessionProvider must be not null"); 071 this.mojoExecutionProvider = 072 Objects.requireNonNull(mojoExecutionProvider, "mojoExecutionProvider must be not null"); 073 this.componentConfigurator = 074 Objects.requireNonNull(componentConfigurator, "componentConfigurator must be not null"); 075 this.plexusContainer = Objects.requireNonNull(plexusContainer, "plexusContainer must be not null"); 076 } 077 078 /** 079 * Create enforcer rules based on xml configuration. 080 * 081 * @param rules a rules configuration 082 * @param log a Mojo logger 083 * @return List of rule instances 084 * @throws EnforcerRuleManagerException report a problem during rules creating 085 */ 086 public List<EnforcerRuleDesc> createRules(PlexusConfiguration rules, Log log) throws EnforcerRuleManagerException { 087 088 List<EnforcerRuleDesc> result = new ArrayList<>(); 089 090 if (rules == null || rules.getChildCount() == 0) { 091 return result; 092 } 093 094 ClassRealm classRealm = mojoExecutionProvider 095 .get() 096 .getMojoDescriptor() 097 .getPluginDescriptor() 098 .getClassRealm(); 099 100 ExpressionEvaluator evaluator = 101 new PluginParameterExpressionEvaluator(sessionProvider.get(), mojoExecutionProvider.get()); 102 103 EnforcerLogger enforcerLoggerError = new EnforcerLoggerError(log); 104 EnforcerLogger enforcerLoggerWarn = new EnforcerLoggerWarn(log); 105 106 for (PlexusConfiguration ruleConfig : rules.getChildren()) { 107 // we need rule level before configuration in order to proper set logger 108 EnforcerLevel ruleLevel = getRuleLevelFromConfig(ruleConfig); 109 110 EnforcerRuleDesc ruleDesc = 111 createRuleDesc(ruleConfig.getName(), ruleConfig.getAttribute("implementation"), log); 112 // setup logger before rule configuration 113 ruleDesc.getRule().setLog(ruleLevel == EnforcerLevel.ERROR ? enforcerLoggerError : enforcerLoggerWarn); 114 if (ruleConfig.getChildCount() > 0) { 115 try { 116 componentConfigurator.configureComponent(ruleDesc.getRule(), ruleConfig, evaluator, classRealm); 117 } catch (ComponentConfigurationException e) { 118 throw new EnforcerRuleManagerException(e); 119 } 120 } 121 result.add(ruleDesc); 122 } 123 return result; 124 } 125 126 private EnforcerLevel getRuleLevelFromConfig(PlexusConfiguration ruleConfig) { 127 PlexusConfiguration levelConfig = ruleConfig.getChild("level", false); 128 String level = Optional.ofNullable(levelConfig) 129 .map(PlexusConfiguration::getValue) 130 .orElse(EnforcerLevel.ERROR.name()); 131 return EnforcerLevel.valueOf(level); 132 } 133 134 private EnforcerRuleDesc createRuleDesc(String name, String implementation, Log log) 135 throws EnforcerRuleManagerException { 136 137 // component name should always start at lowercase character 138 String ruleName = Character.toLowerCase(name.charAt(0)) + name.substring(1); 139 140 if (plexusContainer.hasComponent(EnforcerRuleBase.class, ruleName)) { 141 try { 142 return new EnforcerRuleDesc(ruleName, plexusContainer.lookup(EnforcerRuleBase.class, ruleName)); 143 } catch (ComponentLookupException e) { 144 throw new EnforcerRuleManagerException(e); 145 } 146 } 147 148 String ruleClass; 149 if (implementation != null && !implementation.isEmpty()) { 150 ruleClass = implementation; 151 } else { 152 ruleClass = name; 153 } 154 155 if (!ruleClass.contains(".")) { 156 ruleClass = "org.apache.maven.plugins.enforcer." + Character.toUpperCase(ruleClass.charAt(0)) 157 + ruleClass.substring(1); 158 } 159 160 try { 161 log.warn( 162 "ruleName " + ruleName + " with implementation " + ruleClass 163 + "uses the deprecated Maven Enforcer Plugin API. This will not be supported in a future version of the plugin. Please contact the rule maintainer to upgrade the rule implementation to the current API."); 164 return new EnforcerRuleDesc( 165 ruleName, (EnforcerRuleBase) Class.forName(ruleClass).newInstance()); 166 } catch (Exception e) { 167 throw new EnforcerRuleManagerException( 168 "Failed to create enforcer rules with name: " + ruleName + " or for class: " + ruleClass, e); 169 } 170 } 171}