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.enforcer.rules.version; 020 021import javax.inject.Named; 022 023import java.util.Arrays; 024import java.util.Iterator; 025import java.util.List; 026import java.util.regex.Matcher; 027import java.util.regex.Pattern; 028 029import org.apache.commons.lang3.SystemUtils; 030import org.apache.maven.artifact.versioning.ArtifactVersion; 031import org.apache.maven.artifact.versioning.DefaultArtifactVersion; 032import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; 033import org.apache.maven.artifact.versioning.VersionRange; 034import org.apache.maven.enforcer.rule.api.EnforcerRuleException; 035import org.codehaus.plexus.util.StringUtils; 036 037/** 038 * This rule checks that the Java version is allowed. 039 * 040 * @author <a href="mailto:brianf@apache.org">Brian Fox</a> 041 */ 042@Named("requireJavaVersion") 043public final class RequireJavaVersion extends AbstractVersionEnforcer { 044 045 private static final Pattern JDK8_VERSION_PATTERN = Pattern.compile("([\\d.]+)"); 046 047 /** 048 * Display the normalized JDK version. 049 */ 050 private boolean display = false; 051 052 @Override 053 public void setVersion(String theVersion) { 054 055 if ("8".equals(theVersion)) { 056 super.setVersion("1.8"); 057 return; 058 } 059 060 if (!theVersion.contains("8")) { 061 super.setVersion(theVersion); 062 return; 063 } 064 065 Matcher matcher = JDK8_VERSION_PATTERN.matcher(theVersion); 066 067 StringBuffer result = new StringBuffer(); 068 while (matcher.find()) { 069 if ("8".equals(matcher.group(1))) { 070 matcher.appendReplacement(result, "1.8"); 071 } else { 072 matcher.appendReplacement(result, "$1"); 073 } 074 } 075 matcher.appendTail(result); 076 077 super.setVersion(result.toString()); 078 } 079 080 @Override 081 public void execute() throws EnforcerRuleException { 082 String javaVersion = SystemUtils.JAVA_VERSION; 083 String javaVersionNormalized = normalizeJDKVersion(javaVersion); 084 if (display) { 085 getLog().info("Detected Java Version: '" + javaVersion + "'"); 086 getLog().info("Normalized Java Version: '" + javaVersionNormalized + "'"); 087 } else { 088 getLog().debug("Detected Java Version: '" + javaVersion + "'"); 089 getLog().debug("Normalized Java Version: '" + javaVersionNormalized + "'"); 090 } 091 092 ArtifactVersion detectedJdkVersion = new DefaultArtifactVersion(javaVersionNormalized); 093 094 getLog().debug("Parsed Version: Major: " + detectedJdkVersion.getMajorVersion() + " Minor: " 095 + detectedJdkVersion.getMinorVersion() + " Incremental: " + detectedJdkVersion.getIncrementalVersion() 096 + " Build: " + detectedJdkVersion.getBuildNumber() + " Qualifier: " 097 + detectedJdkVersion.getQualifier()); 098 099 setCustomMessageIfNoneConfigured(detectedJdkVersion, getVersion()); 100 101 enforceVersion("JDK", getVersion(), detectedJdkVersion); 102 } 103 104 /** 105 * Converts a jdk string from 1.5.0-11b12 to a single 3 digit version like 1.5.0-11 106 * 107 * @param theJdkVersion to be converted. 108 * @return the converted string. 109 */ 110 public static String normalizeJDKVersion(String theJdkVersion) { 111 112 theJdkVersion = theJdkVersion.replaceAll("_|-", "."); 113 String tokenArray[] = StringUtils.split(theJdkVersion, "."); 114 List<String> tokens = Arrays.asList(tokenArray); 115 StringBuilder buffer = new StringBuilder(theJdkVersion.length()); 116 117 Iterator<String> iter = tokens.iterator(); 118 for (int i = 0; i < tokens.size() && i < 4; i++) { 119 String section = iter.next(); 120 section = section.replaceAll("[^0-9]", ""); 121 122 if (section != null && !section.isEmpty()) { 123 buffer.append(Integer.parseInt(section)); 124 125 if (i != 2) { 126 buffer.append('.'); 127 } else { 128 buffer.append('-'); 129 } 130 } 131 } 132 133 String version = buffer.toString(); 134 version = StringUtils.stripEnd(version, "-"); 135 return StringUtils.stripEnd(version, "."); 136 } 137 138 private void setCustomMessageIfNoneConfigured(ArtifactVersion detectedJdkVersion, String allowedVersionRange) { 139 if (getMessage() == null) { 140 String version; 141 try { 142 VersionRange vr = VersionRange.createFromVersionSpec(allowedVersionRange); 143 version = AbstractVersionEnforcer.toString(vr); 144 } catch (InvalidVersionSpecificationException e) { 145 getLog().debug("Could not parse allowed version range " + allowedVersionRange + " " + e.getMessage()); 146 version = allowedVersionRange; 147 } 148 String message = String.format( 149 "Detected JDK version %s (JAVA_HOME=%s) is not in the allowed range %s.", 150 detectedJdkVersion, SystemUtils.JAVA_HOME, version); 151 super.setMessage(message); 152 } 153 } 154 155 @Override 156 public String toString() { 157 return String.format( 158 "%s[message=%s, version=%s, display=%b]", 159 getClass().getSimpleName(), getMessage(), getVersion(), display); 160 } 161}