├── maven-toolchains-cli.png ├── index.http ├── src ├── main │ ├── java │ │ └── org │ │ │ └── apache │ │ │ └── maven │ │ │ └── plugins │ │ │ └── toolchain │ │ │ ├── ToolchainsRequirement.java │ │ │ ├── ToolchainConverter.java │ │ │ ├── FoojayService.java │ │ │ └── ToolchainMojo.java │ └── resources │ │ └── META-INF │ │ └── plexus │ │ └── components.xml └── test │ └── java │ └── org │ └── apache │ └── maven │ └── plugins │ └── toolchain │ └── FoojayServiceTest.java ├── .gitignore ├── README.md ├── pom.xml └── LICENSE.txt /maven-toolchains-cli.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linux-china/toolchains-maven-plugin/HEAD/maven-toolchains-cli.png -------------------------------------------------------------------------------- /index.http: -------------------------------------------------------------------------------- 1 | ### get all distributions with versions 2 | GET https://api.foojay.io/disco/v3.0/distributions 3 | 4 | ### get download information for a specific distribution and version 5 | GET https://api.foojay.io/disco/v3.0/packages?distro=graalvm_ce17&version=22.3&latest=overall&operating_system=linux&libc_type=&architecture=x64&bitness=64&archive_type=tar.gz&package_type=jdk&discovery_scope_id=directly_downloadable&match=any&javafx_bundled=false&directly_downloadable=true&release_status=ga -------------------------------------------------------------------------------- /src/main/java/org/apache/maven/plugins/toolchain/ToolchainsRequirement.java: -------------------------------------------------------------------------------- 1 | package org.apache.maven.plugins.toolchain; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one 5 | * or more contributor license agreements. See the NOTICE file 6 | * distributed with this work for additional information 7 | * regarding copyright ownership. The ASF licenses this file 8 | * to you under the Apache License, Version 2.0 (the 9 | * "License"); you may not use this file except in compliance 10 | * with the License. You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, 15 | * software distributed under the License is distributed on an 16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 17 | * KIND, either express or implied. See the License for the 18 | * specific language governing permissions and limitations 19 | * under the License. 20 | */ 21 | 22 | import java.util.Collections; 23 | import java.util.Map; 24 | import java.util.Set; 25 | 26 | /** 27 | * Type for plugin's toolchain attribute representing toolchains requirements. 28 | * 29 | * @author mkleint 30 | * @see ToolchainConverter the custom Plexus converter to instantiate this class 31 | */ 32 | public final class ToolchainsRequirement 33 | { 34 | Map> toolchains; 35 | 36 | public Map> getToolchains() 37 | { 38 | return Collections.unmodifiableMap( toolchains ); 39 | } 40 | 41 | public Set getToolchainsTypes() 42 | { 43 | return Collections.unmodifiableSet( toolchains.keySet() ); 44 | } 45 | 46 | public Map getParams( String type ) 47 | { 48 | return Collections.unmodifiableMap( toolchains.get( type ) ); 49 | } 50 | } -------------------------------------------------------------------------------- /src/test/java/org/apache/maven/plugins/toolchain/FoojayServiceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package org.apache.maven.plugins.toolchain; 20 | 21 | 22 | import org.apache.maven.monitor.logging.DefaultLog; 23 | import org.codehaus.plexus.logging.console.ConsoleLogger; 24 | import org.junit.Test; 25 | 26 | public class FoojayServiceTest { 27 | FoojayService foojayService = new FoojayService(new DefaultLog(new ConsoleLogger()), null); 28 | 29 | @Test 30 | public void testParseDownloadUrl() throws Exception { 31 | final String[] jdkLoadUrl = foojayService.parseFileNameAndDownloadUrl("17", "oracle-open-jdk"); 32 | System.out.println("filename: " + jdkLoadUrl[0]); 33 | System.out.println("url: " + jdkLoadUrl[1]); 34 | } 35 | 36 | @Test 37 | public void testParseGraalVMDownloadUrl() throws Exception { 38 | final String[] jdkLoadUrl = foojayService.parseFileNameAndDownloadUrl("22.2", "graalvm_ce17"); 39 | System.out.println("filename: " + jdkLoadUrl[0]); 40 | System.out.println("url: " + jdkLoadUrl[1]); 41 | } 42 | 43 | @Test 44 | public void testDownloadAndExtract() throws Exception { 45 | foojayService.downloadAndExtractJdk("15", "oracle_open_jdk"); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/plexus/components.xml: -------------------------------------------------------------------------------- 1 | 19 | 20 | 21 | 22 | 23 | org.codehaus.plexus.component.configurator.ComponentConfigurator 24 | toolchains-requirement-configurator 25 | org.codehaus.plexus.component.configurator.BasicComponentConfigurator 26 | 27 | 28 | org.codehaus.plexus.component.configurator.converters.lookup.ConverterLookup 29 | toolchains-requirement-configurator 30 | 31 | 32 | 33 | 34 | 35 | org.codehaus.plexus.component.configurator.converters.lookup.ConverterLookup 36 | toolchains-requirement-configurator 37 | org.codehaus.plexus.component.configurator.converters.lookup.DefaultConverterLookup 38 | 39 | 40 | org.codehaus.plexus.component.configurator.converters.ConfigurationConverter 41 | ToolchainsRequirement 42 | customConverters 43 | 44 | 45 | 46 | 47 | 48 | org.codehaus.plexus.component.configurator.converters.ConfigurationConverter 49 | ToolchainsRequirement 50 | org.apache.maven.plugins.toolchain.ToolchainConverter 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.toptal.com/developers/gitignore/api/java,maven,jetbrains+all 2 | # Edit at https://www.toptal.com/developers/gitignore?templates=java,maven,jetbrains+all 3 | 4 | ### Java ### 5 | # Compiled class file 6 | *.class 7 | 8 | # Log file 9 | *.log 10 | 11 | # BlueJ files 12 | *.ctxt 13 | 14 | # Mobile Tools for Java (J2ME) 15 | .mtj.tmp/ 16 | 17 | # Package Files # 18 | *.jar 19 | *.war 20 | *.nar 21 | *.ear 22 | *.zip 23 | *.tar.gz 24 | *.rar 25 | 26 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 27 | hs_err_pid* 28 | 29 | ### JetBrains+all ### 30 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 31 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 32 | 33 | # User-specific stuff 34 | .idea/**/workspace.xml 35 | .idea/**/tasks.xml 36 | .idea/**/usage.statistics.xml 37 | .idea/**/dictionaries 38 | .idea/**/shelf 39 | 40 | # AWS User-specific 41 | .idea/**/aws.xml 42 | 43 | # Generated files 44 | .idea/**/contentModel.xml 45 | 46 | # Sensitive or high-churn files 47 | .idea/**/dataSources/ 48 | .idea/**/dataSources.ids 49 | .idea/**/dataSources.local.xml 50 | .idea/**/sqlDataSources.xml 51 | .idea/**/dynamic.xml 52 | .idea/**/uiDesigner.xml 53 | .idea/**/dbnavigator.xml 54 | 55 | # Gradle 56 | .idea/**/gradle.xml 57 | .idea/**/libraries 58 | 59 | # Gradle and Maven with auto-import 60 | # When using Gradle or Maven with auto-import, you should exclude module files, 61 | # since they will be recreated, and may cause churn. Uncomment if using 62 | # auto-import. 63 | # .idea/artifacts 64 | # .idea/compiler.xml 65 | # .idea/jarRepositories.xml 66 | # .idea/modules.xml 67 | # .idea/*.iml 68 | # .idea/modules 69 | # *.iml 70 | # *.ipr 71 | 72 | # CMake 73 | cmake-build-*/ 74 | 75 | # Mongo Explorer plugin 76 | .idea/**/mongoSettings.xml 77 | 78 | # File-based project format 79 | *.iws 80 | 81 | # IntelliJ 82 | out/ 83 | 84 | # mpeltonen/sbt-idea plugin 85 | .idea_modules/ 86 | 87 | # JIRA plugin 88 | atlassian-ide-plugin.xml 89 | 90 | # Cursive Clojure plugin 91 | .idea/replstate.xml 92 | 93 | # Crashlytics plugin (for Android Studio and IntelliJ) 94 | com_crashlytics_export_strings.xml 95 | crashlytics.properties 96 | crashlytics-build.properties 97 | fabric.properties 98 | 99 | # Editor-based Rest Client 100 | .idea/httpRequests 101 | 102 | # Android studio 3.1+ serialized cache file 103 | .idea/caches/build_file_checksums.ser 104 | 105 | ### JetBrains+all Patch ### 106 | # Ignores the whole .idea folder and all .iml files 107 | # See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360 108 | 109 | .idea/ 110 | 111 | # Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 112 | 113 | *.iml 114 | modules.xml 115 | .idea/misc.xml 116 | *.ipr 117 | 118 | # Sonarlint plugin 119 | .idea/sonarlint 120 | 121 | ### Maven ### 122 | target/ 123 | pom.xml.tag 124 | pom.xml.releaseBackup 125 | pom.xml.versionsBackup 126 | pom.xml.next 127 | release.properties 128 | dependency-reduced-pom.xml 129 | buildNumber.properties 130 | .mvn/timing.properties 131 | # https://github.com/takari/maven-wrapper#usage-without-binary-jar 132 | .mvn/wrapper/maven-wrapper.jar 133 | 134 | ### Maven Patch ### 135 | # Eclipse m2e generated files 136 | # Eclipse Core 137 | .project 138 | # JDT-specific (Eclipse Java Development Tools) 139 | .classpath 140 | 141 | # End of https://www.toptal.com/developers/gitignore/api/java,maven,jetbrains+all 142 | 143 | -------------------------------------------------------------------------------- /src/main/java/org/apache/maven/plugins/toolchain/ToolchainConverter.java: -------------------------------------------------------------------------------- 1 | package org.apache.maven.plugins.toolchain; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one 5 | * or more contributor license agreements. See the NOTICE file 6 | * distributed with this work for additional information 7 | * regarding copyright ownership. The ASF licenses this file 8 | * to you under the Apache License, Version 2.0 (the 9 | * "License"); you may not use this file except in compliance 10 | * with the License. You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, 15 | * software distributed under the License is distributed on an 16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 17 | * KIND, either express or implied. See the License for the 18 | * specific language governing permissions and limitations 19 | * under the License. 20 | */ 21 | 22 | import java.util.HashMap; 23 | import java.util.Map; 24 | 25 | import org.codehaus.plexus.component.configurator.ComponentConfigurationException; 26 | import org.codehaus.plexus.component.configurator.ConfigurationListener; 27 | import org.codehaus.plexus.component.configurator.converters.AbstractConfigurationConverter; 28 | import org.codehaus.plexus.component.configurator.converters.lookup.ConverterLookup; 29 | import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator; 30 | import org.codehaus.plexus.configuration.PlexusConfiguration; 31 | 32 | /** 33 | * Custom Plexus ConfigurationConverter to instantiate ToolchainRequirement from configuration. 34 | * 35 | * @author mkleint 36 | * @see ToolchainsRequirement 37 | */ 38 | public class ToolchainConverter 39 | extends AbstractConfigurationConverter 40 | { 41 | 42 | /** 43 | * @see org.codehaus.plexus.component.configurator.converters.ConfigurationConverter#canConvert(java.lang.Class) 44 | */ 45 | @Override 46 | public boolean canConvert( Class type ) 47 | { 48 | return ToolchainsRequirement.class.isAssignableFrom( type ); 49 | } 50 | 51 | /** 52 | * @see org.codehaus.plexus.component.configurator.converters.ConfigurationConverter#fromConfiguration(org.codehaus.plexus.component.configurator.converters.lookup.ConverterLookup, org.codehaus.plexus.configuration.PlexusConfiguration, java.lang.Class, java.lang.Class, java.lang.ClassLoader, org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator, org.codehaus.plexus.component.configurator.ConfigurationListener) 53 | */ 54 | @Override 55 | public Object fromConfiguration( ConverterLookup converterLookup, 56 | PlexusConfiguration configuration, 57 | Class type, Class baseType, 58 | ClassLoader classLoader, 59 | ExpressionEvaluator expressionEvaluator, 60 | ConfigurationListener listener ) 61 | throws ComponentConfigurationException 62 | { 63 | ToolchainsRequirement retValue = new ToolchainsRequirement(); 64 | 65 | processConfiguration( retValue, configuration, expressionEvaluator ); 66 | 67 | return retValue; 68 | } 69 | 70 | private void processConfiguration( ToolchainsRequirement requirement, 71 | PlexusConfiguration configuration, 72 | ExpressionEvaluator expressionEvaluator ) 73 | throws ComponentConfigurationException 74 | { 75 | Map> map = new HashMap<>(); 76 | 77 | PlexusConfiguration[] tools = configuration.getChildren(); 78 | for ( PlexusConfiguration tool : tools ) 79 | { 80 | String type = tool.getName(); 81 | PlexusConfiguration[] params = tool.getChildren(); 82 | 83 | Map parameters = new HashMap<>(); 84 | for ( PlexusConfiguration param : params ) 85 | { 86 | parameters.put( param.getName(), param.getValue() ); 87 | } 88 | map.put( type, parameters ); 89 | } 90 | 91 | requirement.toolchains = map; 92 | } 93 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 17 | Toolchains Maven Plugin 18 | ========================= 19 | 20 | Extend maven-toolchains-plugin to add JDK auto download and toolchains.xml management. 21 | 22 | # Features 23 | 24 | * JDK auto download by Foojay API support, and install directory is `~/.m2/jdks` 25 | * Add new toolchain into toolchains.xml dynamically 26 | * SDKMAN integration: add JDK to toolchains.xml from [SDKMAN](https://sdkman.io/) if SDKMAN detected 27 | * JBang integration: add/auto-install JDK to toolchains.xml from [JBang](https://www.jbang.dev/) if jbang detected 28 | 29 | # Requirements 30 | 31 | * Maven 3.5+ 32 | * JDK 1.7+ 33 | 34 | # How to use? 35 | 36 | Add following plugin configuration to your pom.xml: 37 | 38 | ```xml 39 | 40 | 41 | 42 | 43 | org.mvnsearch 44 | toolchains-maven-plugin 45 | 4.5.0 46 | 47 | 48 | 49 | toolchain 50 | 51 | 52 | 53 | 54 | 55 | 56 | 17 57 | 58 | 59 | 60 | 61 | 62 | 63 | ``` 64 | 65 | And you can try it quickly: 66 | 67 | ``` 68 | $ git clone https://github.com/linux-china/java17-demo.git 69 | $ cd java17-demo 70 | $ mvn compile 71 | ``` 72 | 73 | # GraalVM support 74 | 75 | * vendor should be `graalvm_ce17` or `graalvm_ce11` 76 | * version is GraalVM version(not Java version), such as `22.3` or `22.3.0` 77 | * GraalVM native-image component will be installed automatically 78 | 79 | ```xml 80 | 81 | 82 | org.mvnsearch 83 | toolchains-maven-plugin 84 | 4.5.0 85 | 86 | 87 | 88 | toolchain 89 | 90 | 91 | 92 | 93 | 94 | 95 | 22.3 96 | graalvm_ce17 97 | 98 | 99 | 100 | 101 | ``` 102 | 103 | # How to get a list of all supported distributions and JDK versions? 104 | 105 | Please visit https://api.foojay.io/disco/v3.0/distributions to get all information. 106 | 107 | * jdk vendor is the value of `api_parameter` 108 | * jdk version value could be any value in `versions` array 109 | 110 | Or you can use [Maven toolchains CLI](https://github.com/linux-china/maven-toolchains-cli) to get all supported JDKs information. 111 | 112 | ![Maven toolchains CLI](maven-toolchains-cli.png) 113 | 114 | # How to skip toolchains maven plugin on CI/CD platform? 115 | 116 | ``` 117 | $ mvn -Dtoolchain.skip -DskipTests package 118 | ``` 119 | 120 | # Different JDK for main/test code 121 | 122 | Maven has support for using different source and target java versions for your project's main code and tests. 123 | You can add `testJdk` toolchain in `toolchains-maven-plugin` to specify the JDK for test code as below: 124 | 125 | ```xml 126 | 127 | 128 | 129 | org.apache.maven.plugins 130 | maven-compiler-plugin 131 | 3.11.0 132 | 133 | 134 | default-testCompile 135 | test-compile 136 | 137 | testCompile 138 | 139 | 140 | 141 | 18 142 | 143 | 144 | 145 | 146 | 147 | 8 148 | 8 149 | true 150 | 18 151 | 18 152 | 18 153 | --enable-preview 154 | 155 | 156 | 157 | 158 | org.mvnsearch 159 | toolchains-maven-plugin 160 | 4.5.0 161 | 162 | 163 | 164 | toolchain 165 | 166 | 167 | 168 | 169 | 170 | 171 | 8 172 | 173 | 174 | 18 175 | 176 | 177 | 178 | 179 | 180 | ``` 181 | 182 | # References 183 | 184 | * Apache Maven Toolchains Plugin: https://maven.apache.org/plugins/maven-toolchains-plugin/ 185 | * Maven toolchains CLI: https://github.com/linux-china/maven-toolchains-cli 186 | * Disco CLI: a command line interface for the foojay.io Disco API - https://github.com/HanSolo/discocli 187 | * foojay DiscoAPI: https://api.foojay.io/swagger-ui/ 188 | * Gradle Toolchains for JVM:https://docs.gradle.org/current/userguide/toolchains.html 189 | 190 | 191 | sdkman support: sdk install java 17.0.7-graalce 192 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 21 | 22 | 24 | 4.0.0 25 | 26 | 27 | maven-plugins 28 | org.apache.maven.plugins 29 | 34 30 | 31 | 32 | 33 | org.mvnsearch 34 | toolchains-maven-plugin 35 | 4.5.1-SNAPSHOT 36 | maven-plugin 37 | 38 | Apache Maven Toolchains Plugin with JDK auto download 39 | 40 | Apache Maven Toolchains Plugin with JDK auto download 41 | 42 | https://github.com/linux-china/toolchains-maven-plugin 43 | 44 | 45 | 3.5.0 46 | 1.7 47 | ${java.version} 48 | ${java.version} 49 | 50 | 51 | 52 | ${mavenVersion} 53 | 54 | 55 | 56 | 57 | linux_china 58 | Libing Chen 59 | https://twitter.com/linux_china 60 | 61 | Developer 62 | 63 | 64 | 65 | 66 | 67 | 68 | The Apache License, Version 2.0 69 | https://www.apache.org/licenses/LICENSE-2.0.txt 70 | 71 | 72 | 73 | 74 | scm:git:git@github.com:linux-china/toolchains-maven-plugin.git 75 | scm:git:git@github.com:linux-china/toolchains-maven-plugin.git 76 | https://github.com/linux-china/toolchains-maven-plugin 77 | 78 | 79 | 80 | 81 | ossrh 82 | https://oss.sonatype.org/content/repositories/snapshots 83 | 84 | 85 | ossrh 86 | https://oss.sonatype.org/service/local/staging/deploy/maven2/ 87 | 88 | 89 | 90 | 91 | 92 | org.apache.maven 93 | maven-plugin-api 94 | ${mavenVersion} 95 | 96 | 97 | org.apache.maven 98 | maven-core 99 | ${mavenVersion} 100 | 101 | 102 | org.apache.maven.plugin-tools 103 | maven-plugin-annotations 104 | 3.5 105 | provided 106 | 107 | 108 | com.google.code.gson 109 | gson 110 | 2.8.8 111 | 112 | 113 | org.apache.httpcomponents 114 | httpclient 115 | 4.5.13 116 | 117 | 118 | org.codehaus.plexus 119 | plexus-archiver 120 | 4.2.5 121 | 122 | 123 | junit 124 | junit 125 | 4.13.2 126 | test 127 | 128 | 129 | 130 | 131 | 132 | 133 | maven-checkstyle-plugin 134 | 135 | true 136 | 137 | 138 | 139 | org.apache.rat 140 | apache-rat-plugin 141 | 142 | true 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | release 151 | 152 | 153 | 154 | org.sonatype.plugins 155 | nexus-staging-maven-plugin 156 | 1.6.13 157 | true 158 | 159 | ossrh 160 | https://s01.oss.sonatype.org/ 161 | true 162 | 163 | 164 | 165 | org.apache.maven.plugins 166 | maven-source-plugin 167 | 3.2.1 168 | 169 | 170 | attach-sources 171 | 172 | jar-no-fork 173 | 174 | 175 | 176 | 177 | 178 | org.apache.maven.plugins 179 | maven-javadoc-plugin 180 | 3.1.1 181 | 182 | 183 | attach-javadocs 184 | 185 | jar 186 | 187 | 188 | 189 | 190 | 191 | org.apache.maven.plugins 192 | maven-gpg-plugin 193 | 1.6 194 | 195 | 196 | sign-artifacts 197 | verify 198 | 199 | sign 200 | 201 | 202 | 203 | --pinentry-mode 204 | loopback 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | -------------------------------------------------------------------------------- /src/main/java/org/apache/maven/plugins/toolchain/FoojayService.java: -------------------------------------------------------------------------------- 1 | package org.apache.maven.plugins.toolchain; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.JsonElement; 5 | import com.google.gson.JsonObject; 6 | import org.apache.commons.compress.archivers.ArchiveInputStream; 7 | import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; 8 | import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; 9 | import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; 10 | import org.apache.commons.io.FileUtils; 11 | import org.apache.http.HttpHost; 12 | import org.apache.http.HttpResponse; 13 | import org.apache.http.auth.AuthScope; 14 | import org.apache.http.auth.Credentials; 15 | import org.apache.http.auth.UsernamePasswordCredentials; 16 | import org.apache.http.client.CredentialsProvider; 17 | import org.apache.http.client.HttpClient; 18 | import org.apache.http.client.methods.HttpGet; 19 | import org.apache.http.impl.client.BasicCredentialsProvider; 20 | import org.apache.http.impl.client.HttpClientBuilder; 21 | import org.apache.http.impl.client.HttpClients; 22 | import org.apache.http.util.EntityUtils; 23 | import org.apache.maven.plugin.logging.Log; 24 | import org.apache.maven.settings.Proxy; 25 | import org.codehaus.plexus.archiver.AbstractUnArchiver; 26 | import org.codehaus.plexus.archiver.tar.TarGZipUnArchiver; 27 | import org.codehaus.plexus.archiver.zip.ZipUnArchiver; 28 | import org.codehaus.plexus.logging.Logger; 29 | import org.codehaus.plexus.logging.console.ConsoleLogger; 30 | 31 | import java.io.File; 32 | import java.net.URL; 33 | import java.nio.file.Files; 34 | import java.nio.file.Path; 35 | import java.nio.file.Paths; 36 | 37 | /* 38 | * Licensed to the Apache Software Foundation (ASF) under one 39 | * or more contributor license agreements. See the NOTICE file 40 | * distributed with this work for additional information 41 | * regarding copyright ownership. The ASF licenses this file 42 | * to you under the Apache License, Version 2.0 (the 43 | * "License"); you may not use this file except in compliance 44 | * with the License. You may obtain a copy of the License at 45 | * 46 | * http://www.apache.org/licenses/LICENSE-2.0 47 | * 48 | * Unless required by applicable law or agreed to in writing, 49 | * software distributed under the License is distributed on an 50 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 51 | * KIND, either express or implied. See the License for the 52 | * specific language governing permissions and limitations 53 | * under the License. 54 | */ 55 | 56 | public class FoojayService { 57 | private final HttpClient httpClient; 58 | 59 | private final Log log; 60 | 61 | public FoojayService(Log log, Proxy proxy) { 62 | this.log = log; 63 | // https://maven.apache.org/guides/mini/guide-proxies.html 64 | if (proxy != null) { 65 | final HttpClientBuilder builder = HttpClients.custom(); 66 | builder.setProxy(new HttpHost(proxy.getHost(), proxy.getPort(), proxy.getProtocol())); 67 | if (proxy.getUsername() != null) { 68 | Credentials credentials = new UsernamePasswordCredentials(proxy.getUsername(), proxy.getPassword()); 69 | AuthScope authScope = new AuthScope(proxy.getHost(), proxy.getPort()); 70 | CredentialsProvider credsProvider = new BasicCredentialsProvider(); 71 | credsProvider.setCredentials(authScope, credentials); 72 | builder.setDefaultCredentialsProvider(credsProvider); 73 | } 74 | httpClient = builder.build(); 75 | } else { 76 | httpClient = HttpClients.createDefault(); 77 | } 78 | } 79 | 80 | public Path downloadAndExtractJdk(String version, String vendor) throws Exception { 81 | log.info("Begin to install JDK " + version); 82 | final String[] fileNameAndDownloadUrl = parseFileNameAndDownloadUrl(version, vendor); 83 | if (fileNameAndDownloadUrl == null) { 84 | return null; 85 | } 86 | String jdkFileName = fileNameAndDownloadUrl[0]; 87 | String downloadUrl = fileNameAndDownloadUrl[1]; 88 | final Path userHome = Paths.get(System.getProperty("user.home")); 89 | Path jdksDir = userHome.resolve(".m2").resolve("jdks"); 90 | if (!jdksDir.toFile().exists()) { 91 | //noinspection ResultOfMethodCallIgnored 92 | jdksDir.toFile().mkdir(); 93 | } 94 | Path jdkHome = downloadAndExtract(downloadUrl, jdkFileName, jdksDir); 95 | if (jdkHome.resolve("Contents").resolve("Home").toFile().exists()) { // mac tgz 96 | jdkHome = jdkHome.resolve("Contents").resolve("Home"); 97 | } 98 | log.info("JDK installed: " + jdkHome.toAbsolutePath()); 99 | if (vendor.contains("graalvm")) { 100 | Path guBin = jdkHome.resolve("bin").resolve("gu"); 101 | ProcessBuilder pb = new ProcessBuilder(guBin.toAbsolutePath().toString(), "install", "native-image", "--ignore"); 102 | pb.environment().put("GRAALVM_HOME", jdkHome.toAbsolutePath().toString()); 103 | pb.start(); 104 | } 105 | return jdkHome; 106 | } 107 | 108 | public String[] parseFileNameAndDownloadUrl(String version, String vendor) { 109 | String os = getOsName(); 110 | String archiveType = "tar.gz"; 111 | if (os.equals("windows")) { 112 | archiveType = "zip"; 113 | } 114 | String archName = getArchName(); 115 | String bitness = archName.equals("x32") ? "32" : "64"; 116 | String libcType; 117 | switch (os) { 118 | case "linux": 119 | libcType = "glibc"; 120 | break; 121 | case "windows": 122 | libcType = "c_std_lib"; 123 | break; 124 | case "macos": 125 | libcType = "libc"; 126 | break; 127 | default: 128 | libcType = ""; 129 | break; 130 | } 131 | String queryUrl = "https://api.foojay.io/disco/v3.0/packages?" 132 | + "distribution=" + vendor 133 | + "&version=" + version 134 | + "&operating_system=" + os 135 | + "&architecture=" + archName 136 | + "&bitness=" + bitness 137 | + "&archive_type=" + archiveType 138 | + "&libc_type=" + libcType 139 | + "&latest=overall&package_type=jdk&discovery_scope_id=directly_downloadable&match=any&javafx_bundled=false&directly_downloadable=true&release_status=ga"; 140 | HttpGet request = new HttpGet(queryUrl); 141 | try { 142 | final HttpResponse response = httpClient.execute(request); 143 | if (response.getStatusLine().getStatusCode() == 200) { 144 | Gson gson = new Gson(); 145 | final JsonObject jsonObject = gson.fromJson(EntityUtils.toString(response.getEntity()), JsonElement.class).getAsJsonObject(); 146 | final JsonObject pkgJson = jsonObject.getAsJsonArray("result").get(0).getAsJsonObject(); 147 | String pkgInfoUri = pkgJson.getAsJsonObject("links").get("pkg_info_uri").getAsString(); 148 | HttpGet pkgInfoGet = new HttpGet(pkgInfoUri); 149 | final HttpResponse pkgInfoResponse = httpClient.execute(pkgInfoGet); 150 | if (pkgInfoResponse.getStatusLine().getStatusCode() == 200) { 151 | final JsonObject pkgInfoJson = gson.fromJson(EntityUtils.toString(pkgInfoResponse.getEntity()), JsonElement.class).getAsJsonObject(); 152 | String downloadUrl = pkgInfoJson.getAsJsonArray("result").get(0).getAsJsonObject().get("direct_download_uri").getAsString(); 153 | return new String[]{pkgJson.get("filename").getAsString(), downloadUrl}; 154 | } 155 | } 156 | } catch (Exception e) { 157 | log.error("Error to parse response from " + queryUrl, e); 158 | } 159 | return null; 160 | } 161 | 162 | private Path downloadAndExtract(String link, String fileName, Path destDir) throws Exception { 163 | File destFile = destDir.resolve(fileName).toFile(); 164 | if (!destFile.exists()) { 165 | log.info("Download " + fileName + " from " + link); 166 | FileUtils.copyURLToFile(new URL(link), destFile); 167 | } 168 | log.info("Extract " + fileName); 169 | String extractDir = getRootNameInArchive(destFile); 170 | extractArchiveFile(destFile, destDir.toFile()); 171 | //noinspection ResultOfMethodCallIgnored 172 | destFile.delete(); 173 | return destDir.resolve(extractDir); 174 | } 175 | 176 | private String getRootNameInArchive(File archiveFile) throws Exception { 177 | ArchiveInputStream archiveInputStream; 178 | if (archiveFile.getName().endsWith("tar.gz") || archiveFile.getName().endsWith("tgz")) { 179 | archiveInputStream = new TarArchiveInputStream(new GzipCompressorInputStream(Files.newInputStream(archiveFile.toPath()))); 180 | } else { 181 | archiveInputStream = new ZipArchiveInputStream((Files.newInputStream(archiveFile.toPath()))); 182 | } 183 | String name = archiveInputStream.getNextEntry().getName(); 184 | while (name.startsWith(".") && name.length() < 4) { // fix '.._' bug 185 | name = archiveInputStream.getNextEntry().getName(); 186 | } 187 | archiveInputStream.close(); 188 | if (name.startsWith("./")) { 189 | name = name.substring(2); 190 | } 191 | if (name.contains("/")) { 192 | name = name.substring(0, name.indexOf("/")); 193 | } 194 | return name; 195 | } 196 | 197 | 198 | private void extractArchiveFile(File sourceFile, File destDir) { 199 | String fileName = sourceFile.getName(); 200 | final AbstractUnArchiver unArchiver; 201 | if (fileName.endsWith(".tgz") || fileName.endsWith(".tar.gz")) { 202 | unArchiver = new TarGZipUnArchiver(); 203 | } else { 204 | unArchiver = new ZipUnArchiver(); 205 | } 206 | unArchiver.enableLogging(new ConsoleLogger(Logger.LEVEL_ERROR, "console")); 207 | unArchiver.setSourceFile(sourceFile); 208 | unArchiver.setDestDirectory(destDir); 209 | unArchiver.setOverwrite(true); 210 | unArchiver.extract(); 211 | } 212 | 213 | private String getOsName() { 214 | String os = System.getProperty("os.name").toLowerCase(); 215 | if (os.contains("mac")) { 216 | return "macos"; 217 | } else if (os.contains("windows")) { 218 | return "windows"; 219 | } else { 220 | return "linux"; 221 | } 222 | } 223 | 224 | private String getArchName() { 225 | String arch = System.getProperty("os.arch").toLowerCase(); 226 | if (arch.contains("x86_32") || arch.contains("amd32")) { 227 | arch = "x32"; 228 | } else if (arch.contains("aarch64") || arch.contains("arm64")) { 229 | arch = "aarch64"; 230 | } else { 231 | arch = "x64"; 232 | } 233 | return arch; 234 | } 235 | } 236 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [2021] [linux_china] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /src/main/java/org/apache/maven/plugins/toolchain/ToolchainMojo.java: -------------------------------------------------------------------------------- 1 | package org.apache.maven.plugins.toolchain; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one 5 | * or more contributor license agreements. See the NOTICE file 6 | * distributed with this work for additional information 7 | * regarding copyright ownership. The ASF licenses this file 8 | * to you under the Apache License, Version 2.0 (the 9 | * "License"); you may not use this file except in compliance 10 | * with the License. You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, 15 | * software distributed under the License is distributed on an 16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 17 | * KIND, either express or implied. See the License for the 18 | * specific language governing permissions and limitations 19 | * under the License. 20 | */ 21 | 22 | import org.apache.maven.execution.MavenSession; 23 | import org.apache.maven.plugin.AbstractMojo; 24 | import org.apache.maven.plugin.MojoExecutionException; 25 | import org.apache.maven.plugin.MojoFailureException; 26 | import org.apache.maven.plugins.annotations.Component; 27 | import org.apache.maven.plugins.annotations.LifecyclePhase; 28 | import org.apache.maven.plugins.annotations.Mojo; 29 | import org.apache.maven.plugins.annotations.Parameter; 30 | import org.apache.maven.toolchain.MisconfiguredToolchainException; 31 | import org.apache.maven.toolchain.ToolchainManagerPrivate; 32 | import org.apache.maven.toolchain.ToolchainPrivate; 33 | import org.apache.maven.toolchain.java.DefaultJavaToolChain; 34 | import org.apache.maven.toolchain.model.ToolchainModel; 35 | import org.codehaus.plexus.logging.console.ConsoleLogger; 36 | import org.codehaus.plexus.util.xml.Xpp3Dom; 37 | import org.codehaus.plexus.util.xml.Xpp3DomBuilder; 38 | import org.codehaus.plexus.util.xml.Xpp3DomWriter; 39 | 40 | import java.io.File; 41 | import java.io.FileReader; 42 | import java.io.FileWriter; 43 | import java.nio.file.Path; 44 | import java.nio.file.Paths; 45 | import java.util.ArrayList; 46 | import java.util.List; 47 | import java.util.Map; 48 | import java.util.Properties; 49 | 50 | /** 51 | * Check that toolchains requirements are met by currently configured toolchains and 52 | * store the selected toolchains in build context for later retrieval by other plugins. 53 | * 54 | * @author mkleint 55 | */ 56 | @Mojo(name = "toolchain", defaultPhase = LifecyclePhase.VALIDATE, 57 | configurator = "toolchains-requirement-configurator", 58 | threadSafe = true) 59 | public class ToolchainMojo extends AbstractMojo { 60 | private static final Object LOCK = new Object(); 61 | /** 62 | * 63 | */ 64 | @Component 65 | private ToolchainManagerPrivate toolchainManagerPrivate; 66 | 67 | /** 68 | * The current build session instance. This is used for toolchain manager API calls. 69 | */ 70 | @Parameter(defaultValue = "${session}", readonly = true, required = true) 71 | private MavenSession session; 72 | 73 | /** 74 | * Toolchains requirements, specified by one 75 | *
  <toolchain-type>
 76 |    *    <param>expected value</param>
 77 |    *    ...
 78 |    *  </toolchain-type>
79 | * element for each required toolchain. 80 | */ 81 | @Parameter(required = true) 82 | private ToolchainsRequirement toolchains; 83 | /** 84 | * skip toolchains or not, or use -Dtoolchain.skip 85 | */ 86 | @Parameter(property = "skip", defaultValue = "false") 87 | private boolean skip; 88 | 89 | @Override 90 | public void execute() 91 | throws MojoExecutionException, MojoFailureException { 92 | final String toolchainsSkip = System.getProperty("toolchain.skip"); 93 | if (toolchainsSkip != null) { 94 | skip = Boolean.parseBoolean(toolchainsSkip); 95 | } 96 | if (skip) { 97 | getLog().info("toolchain plugin skipped."); 98 | return; 99 | } 100 | if (toolchains == null) { 101 | // should not happen since parameter is required... 102 | getLog().warn("No toolchains requirements configured."); 103 | return; 104 | } 105 | 106 | List nonMatchedTypes = new ArrayList<>(); 107 | 108 | for (Map.Entry> entry : toolchains.getToolchains().entrySet()) { 109 | String type = entry.getKey(); 110 | 111 | if (!selectToolchain(type, entry.getValue())) { 112 | nonMatchedTypes.add(type); 113 | } 114 | } 115 | 116 | if (!nonMatchedTypes.isEmpty()) { 117 | // TODO add the default toolchain instance if defined?? 118 | StringBuilder buff = new StringBuilder(); 119 | buff.append("Cannot find matching toolchain definitions for the following toolchain types:"); 120 | 121 | for (String type : nonMatchedTypes) { 122 | buff.append(System.lineSeparator()); 123 | buff.append(getToolchainRequirementAsString(type, toolchains.getParams(type))); 124 | } 125 | 126 | getLog().error(buff.toString()); 127 | 128 | throw new MojoFailureException(buff.toString() + System.lineSeparator() 129 | + "Please make sure you define the required toolchains in your ~/.m2/toolchains.xml file."); 130 | } 131 | } 132 | 133 | protected String getToolchainRequirementAsString(String type, Map params) { 134 | StringBuilder buff = new StringBuilder(); 135 | 136 | buff.append(type).append(" ["); 137 | 138 | if (params.size() == 0) { 139 | buff.append(" any"); 140 | } else { 141 | for (Map.Entry param : params.entrySet()) { 142 | buff.append(" ").append(param.getKey()).append("='").append(param.getValue()); 143 | buff.append("'"); 144 | } 145 | } 146 | 147 | buff.append(" ]"); 148 | 149 | return buff.toString(); 150 | } 151 | 152 | protected boolean selectToolchain(String type, Map params) 153 | throws MojoExecutionException { 154 | String toolchainType = type; 155 | if (toolchainType.equals("testJdk")) { 156 | toolchainType = "jdk"; 157 | } 158 | getLog().info("Required toolchain: " + getToolchainRequirementAsString(toolchainType, params)); 159 | int typeFound = 0; 160 | ToolchainPrivate toolchain = null; 161 | try { 162 | ToolchainPrivate[] tcs = getToolchains(toolchainType); 163 | for (ToolchainPrivate tc : tcs) { 164 | if (!toolchainType.equals(tc.getType())) { 165 | // useful because of MNG-5716 166 | continue; 167 | } 168 | typeFound++; 169 | if (tc.matchesRequirements(params)) { 170 | getLog().info("Found matching toolchain for toolchainType " + toolchainType + ": " + tc); 171 | toolchain = tc; 172 | break; 173 | } 174 | } 175 | } catch (MisconfiguredToolchainException ex) { 176 | throw new MojoExecutionException("Misconfigured toolchains.", ex); 177 | } 178 | //no toolchain found 179 | if (toolchain == null && toolchainType.equalsIgnoreCase("jdk")) { 180 | String version = params.get("version"); 181 | String vendor = params.get("vendor"); 182 | if (vendor == null || vendor.isEmpty()) { 183 | vendor = "oracle_open_jdk"; 184 | } 185 | //sdkman check first 186 | if (vendor.equalsIgnoreCase("oracle_open_jdk")) { 187 | final Path userHome = Paths.get(System.getProperty("user.home")); 188 | Path sdkmanJavaDirs = userHome.resolve(".sdkman").resolve("candidates").resolve("java"); 189 | if (sdkmanJavaDirs.toFile().exists()) { 190 | toolchain = findJdkFromSdkman(sdkmanJavaDirs, version); 191 | } 192 | } 193 | //jbang check 194 | if (toolchain==null && vendor.equalsIgnoreCase("oracle_open_jdk")) { 195 | final Path userHome = Paths.get(System.getProperty("user.home")); 196 | Path jbangHome = userHome.resolve(".jbang"); 197 | if (jbangHome.toFile().exists()) { 198 | toolchain = findJdkFromJbang(jbangHome, version, vendor); 199 | } 200 | } 201 | 202 | //install JDK automatically 203 | if (toolchain == null) { 204 | toolchain = autoInstallJdk(version, vendor); 205 | } 206 | //attach new toolchain to session 207 | if (toolchain != null) { 208 | final Map> requestToolchains = session.getRequest().getToolchains(); 209 | if (!requestToolchains.containsKey("jdk")) { 210 | requestToolchains.put("jdk", new ArrayList()); 211 | } 212 | requestToolchains.get("jdk").add(toolchain.getModel()); 213 | } 214 | } 215 | if (toolchain != null) { 216 | if (type.equals("jdk")) { 217 | toolchainManagerPrivate.storeToolchainToBuildContext(toolchain, session); 218 | } 219 | return true; 220 | } else { 221 | getLog().error("No toolchain " + ((typeFound == 0) ? "found" : ("matched from " + typeFound + " found")) 222 | + " for toolchainType " + toolchainType); 223 | return false; 224 | } 225 | } 226 | 227 | private ToolchainPrivate[] getToolchains(String type) 228 | throws MojoExecutionException, MisconfiguredToolchainException { 229 | return toolchainManagerPrivate.getToolchainsForType(type, session); 230 | } 231 | 232 | /** 233 | * install JDK and modify toolchains.xml automatically 234 | * 235 | * @param version version 236 | * @param vendor vendor 237 | * @return toolchain 238 | */ 239 | private ToolchainPrivate autoInstallJdk(String version, String vendor) { 240 | FoojayService foojayService = new FoojayService(getLog(), session.getSettings().getActiveProxy()); 241 | try { 242 | Path jdkHome = foojayService.downloadAndExtractJdk(version, vendor); 243 | if (jdkHome != null) { 244 | return addJDKToToolchains(jdkHome, version, vendor); 245 | } 246 | } catch (Exception e) { 247 | getLog().error("Failed to download and install JDK", e); 248 | } 249 | return null; 250 | } 251 | 252 | private ToolchainPrivate findJdkFromJbang(Path jbangHome, String version, String vendor) { 253 | try { 254 | String majorVersion = version; 255 | if (majorVersion.contains(".")) { 256 | if (version.startsWith("1.")) { 257 | majorVersion = "8"; 258 | } else { 259 | majorVersion = version.substring(0, version.indexOf(".")); 260 | } 261 | } 262 | Path jdkHome = jbangHome.resolve("cache").resolve("jdks").resolve(majorVersion); 263 | if (!jdkHome.toFile().exists()) { 264 | Path jbangPath = jbangHome.resolve("bin").resolve("jbang"); 265 | if (System.getProperty("os.name").toLowerCase().contains("windows")) { 266 | jbangPath = jbangHome.resolve("bin").resolve("jbang.cmd"); 267 | } 268 | if (!jbangPath.toFile().exists()) { 269 | return null; 270 | } 271 | System.out.println("jbang install " + majorVersion); 272 | String jbangCmd = jbangPath.toAbsolutePath().toString(); 273 | final Process process = new ProcessBuilder(jbangCmd, "jdk", "install", majorVersion).start(); 274 | process.waitFor(); 275 | } 276 | return addJDKToToolchains(jdkHome, version, vendor); 277 | } catch (Exception e) { 278 | getLog().error("Failed to find JDK from jbang", e); 279 | } 280 | return null; 281 | } 282 | 283 | private ToolchainPrivate findJdkFromSdkman(Path sdkmanJavaDirs, String version) { 284 | try { 285 | Path jdkHome = sdkmanJavaDirs.resolve(version); 286 | if (jdkHome.toFile().exists()) { 287 | return addJDKToToolchains(jdkHome, version, ""); 288 | } 289 | } catch (Exception e) { 290 | getLog().error("Failed to find JDK from sdkman, please use `sdk install " + version + "` to install JDK", e); 291 | } 292 | return null; 293 | } 294 | 295 | private ToolchainPrivate addJDKToToolchains(Path jdkHome, String version, String vendor) throws Exception { 296 | final ToolchainPrivate javaToolChain = buildJdkToolchain(version, vendor, jdkHome.toAbsolutePath().toString()); 297 | File toolchainsXml = new File(new File(System.getProperty("user.home")), ".m2/toolchains.xml"); 298 | Xpp3Dom toolchainsDom; 299 | if (toolchainsXml.exists()) { 300 | toolchainsDom = Xpp3DomBuilder.build(new FileReader(toolchainsXml)); 301 | } else { 302 | toolchainsDom = new Xpp3Dom("toolchains"); 303 | } 304 | toolchainsDom.addChild(jdkToolchainDom(version, vendor, jdkHome.toAbsolutePath().toString())); 305 | final FileWriter writer = new FileWriter(toolchainsXml); 306 | Xpp3DomWriter.write(writer, toolchainsDom); 307 | writer.close(); 308 | return javaToolChain; 309 | } 310 | 311 | private ToolchainPrivate buildJdkToolchain(String version, String vendor, String jdkHome) { 312 | ToolchainModel toolchainModel = new ToolchainModel(); 313 | toolchainModel.setType("jdk"); 314 | Properties provides = new Properties(); 315 | provides.setProperty("version", version); 316 | provides.setProperty("vendor", vendor); 317 | toolchainModel.setProvides(provides); 318 | Xpp3Dom configuration = new Xpp3Dom("configuration"); 319 | configuration.addChild(createElement("jdkHome", jdkHome)); 320 | toolchainModel.setConfiguration(configuration); 321 | DefaultJavaToolChain javaToolChain = new DefaultJavaToolChain(toolchainModel, new ConsoleLogger()); 322 | javaToolChain.setJavaHome(jdkHome); 323 | return javaToolChain; 324 | } 325 | 326 | private Xpp3Dom jdkToolchainDom(String version, String vendor, String jdkHome) { 327 | Xpp3Dom toolchainDom = new Xpp3Dom("toolchain"); 328 | toolchainDom.addChild(createElement("type", "jdk")); 329 | Xpp3Dom providesDom = new Xpp3Dom("provides"); 330 | providesDom.addChild(createElement("version", version)); 331 | providesDom.addChild(createElement("vendor", vendor)); 332 | Xpp3Dom configurationDom = new Xpp3Dom("configuration"); 333 | configurationDom.addChild(createElement("jdkHome", jdkHome)); 334 | toolchainDom.addChild(providesDom); 335 | toolchainDom.addChild(configurationDom); 336 | return toolchainDom; 337 | } 338 | 339 | private Xpp3Dom createElement(String name, String value) { 340 | Xpp3Dom dom = new Xpp3Dom(name); 341 | dom.setValue(value); 342 | return dom; 343 | } 344 | 345 | } 346 | --------------------------------------------------------------------------------