1 /* 2 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package jdk.incubator.jpackage.internal; 26 27 import java.io.IOException; 28 import java.nio.file.Path; 29 import java.text.MessageFormat; 30 import java.util.ArrayList; 31 import java.util.List; 32 import java.util.concurrent.atomic.AtomicBoolean; 33 import java.util.function.BiFunction; 34 import java.util.function.Function; 35 import java.util.stream.Stream; 36 37 38 public final class ToolValidator { 39 40 ToolValidator(String tool) { 41 this(Path.of(tool)); 42 } 43 44 ToolValidator(Path toolPath) { 45 this.toolPath = toolPath; 46 args = new ArrayList<>(); 47 48 if (Platform.getPlatform() == Platform.LINUX) { 49 setCommandLine("--version"); 50 } 51 52 setToolNotFoundErrorHandler(null); 53 setToolOldVersionErrorHandler(null); 54 } 55 56 ToolValidator setCommandLine(String... args) { 57 this.args = List.of(args); 58 return this; 59 } 60 61 ToolValidator setMinimalVersion(Comparable<String> v) { 62 minimalVersion = v; 63 return this; 64 } 65 66 ToolValidator setVersionParser(Function<Stream<String>, String> v) { 67 versionParser = v; 68 return this; 69 } 70 71 ToolValidator setToolNotFoundErrorHandler( 72 BiFunction<String, IOException, ConfigException> v) { 73 toolNotFoundErrorHandler = v; 74 return this; 75 } 76 77 ToolValidator setToolOldVersionErrorHandler(BiFunction<String, String, ConfigException> v) { 78 toolOldVersionErrorHandler = v; 79 return this; 80 } 81 82 ConfigException validate() { 83 List<String> cmdline = new ArrayList<>(); 84 cmdline.add(toolPath.toString()); 85 cmdline.addAll(args); 86 87 String name = toolPath.getFileName().toString(); 88 try { 89 ProcessBuilder pb = new ProcessBuilder(cmdline); 90 AtomicBoolean canUseTool = new AtomicBoolean(); 91 if (minimalVersion == null) { 92 // No version check. 93 canUseTool.setPlain(true); 94 } 95 96 String[] version = new String[1]; 97 Executor.of(pb).setOutputConsumer(lines -> { 98 if (versionParser != null && minimalVersion != null) { 99 version[0] = versionParser.apply(lines); 100 if (minimalVersion.compareTo(version[0]) < 0) { 101 canUseTool.setPlain(true); 102 } 103 } 104 }).execute(); 105 106 if (!canUseTool.getPlain()) { 107 if (toolOldVersionErrorHandler != null) { 108 return toolOldVersionErrorHandler.apply(name, version[0]); 109 } 110 return new ConfigException(MessageFormat.format(I18N.getString( 111 "error.tool-old-version"), name, minimalVersion), 112 MessageFormat.format(I18N.getString( 113 "error.tool-old-version.advice"), name, 114 minimalVersion)); 115 } 116 } catch (IOException e) { 117 if (toolNotFoundErrorHandler != null) { 118 return toolNotFoundErrorHandler.apply(name, e); 119 } 120 return new ConfigException(MessageFormat.format(I18N.getString( 121 "error.tool-not-found"), name, e.getMessage()), 122 MessageFormat.format(I18N.getString( 123 "error.tool-not-found.advice"), name), e); 124 } 125 126 // All good. Tool can be used. 127 return null; 128 } 129 130 private final Path toolPath; 131 private List<String> args; 132 private Comparable<String> minimalVersion; 133 private Function<Stream<String>, String> versionParser; 134 private BiFunction<String, IOException, ConfigException> toolNotFoundErrorHandler; 135 private BiFunction<String, String, ConfigException> toolOldVersionErrorHandler; 136 }