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 = createRuleDesc(ruleConfig.getName(), ruleConfig.getAttribute("implementation")); 111 // setup logger before rule configuration 112 ruleDesc.getRule().setLog(ruleLevel == EnforcerLevel.ERROR ? enforcerLoggerError : enforcerLoggerWarn); 113 if (ruleConfig.getChildCount() > 0) { 114 try { 115 componentConfigurator.configureComponent(ruleDesc.getRule(), ruleConfig, evaluator, classRealm); 116 } catch (ComponentConfigurationException e) { 117 throw new EnforcerRuleManagerException(e); 118 } 119 } 120 result.add(ruleDesc); 121 } 122 return result; 123 } 124 125 private EnforcerLevel getRuleLevelFromConfig(PlexusConfiguration ruleConfig) { 126 PlexusConfiguration levelConfig = ruleConfig.getChild("level", false); 127 String level = Optional.ofNullable(levelConfig) 128 .map(PlexusConfiguration::getValue) 129 .orElse(EnforcerLevel.ERROR.name()); 130 return EnforcerLevel.valueOf(level); 131 } 132 133 private EnforcerRuleDesc createRuleDesc(String name, String implementation) throws EnforcerRuleManagerException { 134 135 // component name should always start at lowercase character 136 String ruleName = Character.toLowerCase(name.charAt(0)) + name.substring(1); 137 138 if (plexusContainer.hasComponent(EnforcerRuleBase.class, ruleName)) { 139 try { 140 return new EnforcerRuleDesc(ruleName, plexusContainer.lookup(EnforcerRuleBase.class, ruleName)); 141 } catch (ComponentLookupException e) { 142 throw new EnforcerRuleManagerException(e); 143 } 144 } 145 146 String ruleClass; 147 if (implementation != null && !implementation.isEmpty()) { 148 ruleClass = implementation; 149 } else { 150 ruleClass = name; 151 } 152 153 if (!ruleClass.contains(".")) { 154 ruleClass = "org.apache.maven.plugins.enforcer." + Character.toUpperCase(ruleClass.charAt(0)) 155 + ruleClass.substring(1); 156 } 157 158 try { 159 return new EnforcerRuleDesc( 160 ruleName, (EnforcerRuleBase) Class.forName(ruleClass).newInstance()); 161 } catch (Exception e) { 162 throw new EnforcerRuleManagerException( 163 "Failed to create enforcer rules with name: " + ruleName + " or for class: " + ruleClass, e); 164 } 165 } 166}