1 /* 2 * Copyright (c) 2015, 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.tools.jimage; 26 27 import java.io.PrintWriter; 28 import java.text.MessageFormat; 29 import java.util.ArrayList; 30 import java.util.List; 31 import java.util.Locale; 32 import java.util.MissingResourceException; 33 import java.util.ResourceBundle; 34 35 /** 36 * 37 * JImage tools shared helper. 38 */ 39 public final class TaskHelper { 40 41 public class BadArgs extends Exception { 42 43 static final long serialVersionUID = 8765093759964640721L; 44 45 private BadArgs(String key, Object... args) { 46 super(bundleHelper.getMessage(key, args)); 47 this.key = key; 48 this.args = args; 49 } 50 51 public BadArgs showUsage(boolean b) { 52 showUsage = b; 53 return this; 54 } 55 public final String key; 56 public final Object[] args; 57 public boolean showUsage; 58 } 59 60 public static abstract class Option<T> { 61 62 final boolean hasArg; 63 final String[] aliases; 64 65 public Option(boolean hasArg, String... aliases) { 66 this.hasArg = hasArg; 67 this.aliases = aliases; 68 } 69 70 public boolean isHidden() { 71 return false; 72 } 73 74 public boolean matches(String opt) { 75 for (String a : aliases) { 76 if (a.equals(opt)) { 77 return true; 78 } else if (opt.startsWith("--") && hasArg && opt.startsWith(a + "=")) { 79 return true; 80 } 81 } 82 return false; 83 } 84 85 public boolean ignoreRest() { 86 return false; 87 } 88 89 protected abstract void process(T task, String opt, String arg) throws BadArgs; 90 } 91 92 public static abstract class HiddenOption<T> extends Option<T> { 93 94 public HiddenOption(boolean hasArg, String... aliases) { 95 super(hasArg, aliases); 96 } 97 98 @Override 99 public boolean isHidden() { 100 return true; 101 } 102 } 103 104 private class ResourceBundleHelper { 105 106 private final ResourceBundle bundle; 107 108 ResourceBundleHelper(String path) { 109 Locale locale = Locale.getDefault(); 110 try { 111 bundle = ResourceBundle.getBundle(path, locale); 112 } catch (MissingResourceException e) { 113 throw new InternalError("Cannot find resource bundle for locale " + locale); 114 } 115 } 116 117 String getMessage(String key, Object... args) { 118 String val = bundle.getString(key); 119 return MessageFormat.format(val, args); 120 } 121 122 } 123 124 public class OptionsHelper<T> { 125 126 private final List<Option<T>> options; 127 128 OptionsHelper(List<Option<T>> options) { 129 this.options = options; 130 } 131 132 public List<String> handleOptions(T task, String[] args) throws BadArgs { 133 List<String> rest = new ArrayList<>(); 134 // process options 135 for (int i = 0; i < args.length; i++) { 136 if (args[i].charAt(0) == '-') { 137 String name = args[i]; 138 Option<T> option = getOption(name); 139 if (option == null) { 140 throw new BadArgs("err.unknown.option", name).showUsage(true); 141 } 142 String param = null; 143 if (option.hasArg) { 144 if (name.startsWith("--") && name.indexOf('=') > 0) { 145 param = name.substring(name.indexOf('=') + 1, name.length()); 146 } else if (i + 1 < args.length) { 147 param = args[++i]; 148 } 149 if (param == null || param.isEmpty() || param.charAt(0) == '-') { 150 throw new BadArgs("err.missing.arg", name).showUsage(true); 151 } 152 } 153 option.process(task, name, param); 154 if (option.ignoreRest()) { 155 i = args.length; 156 } 157 } else { 158 rest.add(args[i]); 159 } 160 } 161 return rest; 162 } 163 164 private Option<T> getOption(String name) throws BadArgs { 165 for (Option<T> o : options) { 166 if (o.matches(name)) { 167 return o; 168 } 169 } 170 return null; 171 } 172 173 public void showHelp(String progName, String pluginsHeader) { 174 log.println(bundleHelper.getMessage("main.usage", progName)); 175 for (Option<?> o : options) { 176 String name = o.aliases[0].substring(1); // there must always be at least one name 177 name = name.charAt(0) == '-' ? name.substring(1) : name; 178 if (o.isHidden() || name.equals("h")) { 179 continue; 180 } 181 log.println(bundleHelper.getMessage("main.opt." + name)); 182 } 183 } 184 } 185 186 private PrintWriter log; 187 private final ResourceBundleHelper bundleHelper; 188 189 public TaskHelper(String path) { 190 this.bundleHelper = new ResourceBundleHelper(path); 191 } 192 193 public <T> OptionsHelper<T> newOptionsHelper(Class<T> clazz, Option<?>[] options) { 194 List<Option<T>> optionsList = new ArrayList<>(); 195 for (Option<?> o : options) { 196 @SuppressWarnings("unchecked") 197 Option<T> opt = (Option<T>) o; 198 optionsList.add(opt); 199 } 200 return new OptionsHelper<>(optionsList); 201 } 202 203 public BadArgs newBadArgs(String key, Object... args) { 204 return new BadArgs(key, args); 205 } 206 207 public String getMessage(String key, Object... args) { 208 return bundleHelper.getMessage(key, args); 209 } 210 211 public void setLog(PrintWriter log) { 212 this.log = log; 213 } 214 215 public void reportError(String key, Object... args) { 216 log.println(bundleHelper.getMessage("error.prefix") + " " + bundleHelper.getMessage(key, args)); 217 } 218 219 public void warning(String key, Object... args) { 220 log.println(bundleHelper.getMessage("warn.prefix") + " " + bundleHelper.getMessage(key, args)); 221 } 222 223 public void showVersion(boolean full) { 224 log.println(version(full ? "full" : "release")); 225 } 226 227 public String version(String key) { 228 return System.getProperty("java.version"); 229 } 230 231 }