LCOV - code coverage report
Current view: top level - pgm/init/api - ConsoleUI.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 15 103 14.6 %
Date: 2022-11-19 15:00:39 Functions: 11 25 44.0 %

          Line data    Source code
       1             : // Copyright (C) 2009 The Android Open Source Project
       2             : //
       3             : // Licensed under the Apache License, Version 2.0 (the "License");
       4             : // you may not use this file except in compliance with the License.
       5             : // You may obtain a copy of the License at
       6             : //
       7             : // http://www.apache.org/licenses/LICENSE-2.0
       8             : //
       9             : // Unless required by applicable law or agreed to in writing, software
      10             : // distributed under the License is distributed on an "AS IS" BASIS,
      11             : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             : // See the License for the specific language governing permissions and
      13             : // limitations under the License.
      14             : 
      15             : package com.google.gerrit.pgm.init.api;
      16             : 
      17             : import com.google.errorprone.annotations.FormatMethod;
      18             : import com.google.errorprone.annotations.FormatString;
      19             : import com.google.gerrit.common.Die;
      20             : import com.google.gerrit.common.Nullable;
      21             : import java.io.Console;
      22             : import java.util.EnumSet;
      23             : import java.util.Set;
      24             : 
      25             : /** Console based interaction with the invoking user. */
      26          15 : public abstract class ConsoleUI {
      27             :   /** Get a UI instance, assuming interactive mode. */
      28             :   public static ConsoleUI getInstance() {
      29           0 :     return getInstance(false);
      30             :   }
      31             : 
      32             :   /** Get a UI instance, possibly forcing batch mode. */
      33             :   public static ConsoleUI getInstance(boolean batchMode) {
      34          15 :     Console console = batchMode ? null : System.console();
      35          15 :     return console != null ? new Interactive(console) : new Batch();
      36             :   }
      37             : 
      38             :   /** Constructs an exception indicating the user aborted the operation. */
      39             :   protected static Die abort() {
      40           0 :     return new Die("aborted by user");
      41             :   }
      42             : 
      43             :   /** Returns true if this is a batch UI that has no user interaction. */
      44             :   public abstract boolean isBatch();
      45             : 
      46             :   /** Display a header message before a series of prompts. */
      47             :   public abstract void header(String fmt, Object... args);
      48             : 
      49             :   /** Display a message. */
      50             :   public abstract void message(String fmt, Object... args);
      51             : 
      52             :   /** Request the user to answer a yes/no question. */
      53             :   public abstract boolean yesno(Boolean def, String fmt, Object... args);
      54             : 
      55             :   /** Prints a message asking the user to let us know when its safe to continue. */
      56             :   public abstract void waitForUser();
      57             : 
      58             :   /** Prompt the user for a string, suggesting a default, and returning choice. */
      59             :   public abstract String readString(String def, String fmt, Object... args);
      60             : 
      61             :   /** Prompt the user to make a choice from an allowed list of values. */
      62             :   public abstract String readString(
      63             :       String def, Set<String> allowedValues, String fmt, Object... args);
      64             : 
      65             :   /** Prompt the user for an integer value, suggesting a default. */
      66             :   public int readInt(int def, String fmt, Object... args) {
      67             :     for (; ; ) {
      68          15 :       String p = readString(String.valueOf(def), fmt, args);
      69             :       try {
      70          15 :         return Integer.parseInt(p.trim(), 10);
      71           0 :       } catch (NumberFormatException e) {
      72           0 :         System.err.println("error: Invalid integer format: " + p.trim());
      73             :       }
      74           0 :     }
      75             :   }
      76             : 
      77             :   /** Prompt the user for a password, returning the string; null if blank. */
      78             :   public abstract String password(String fmt, Object... args);
      79             : 
      80             :   /** Display an error message on the system stderr. */
      81             :   @FormatMethod
      82             :   public void error(String format, Object... args) {
      83          15 :     System.err.println(String.format(format, args));
      84          15 :     System.err.flush();
      85          15 :   }
      86             : 
      87             :   /** Prompt the user to make a choice from an enumeration's values. */
      88             :   public abstract <T extends Enum<?>, A extends EnumSet<? extends T>> T readEnum(
      89             :       T def, A options, String fmt, Object... args);
      90             : 
      91             :   private static class Interactive extends ConsoleUI {
      92             :     private final Console console;
      93             : 
      94           0 :     Interactive(Console console) {
      95           0 :       this.console = console;
      96           0 :     }
      97             : 
      98             :     @Override
      99             :     public boolean isBatch() {
     100           0 :       return false;
     101             :     }
     102             : 
     103             :     @Override
     104             :     @FormatMethod
     105             :     public boolean yesno(Boolean def, String fmt, Object... args) {
     106           0 :       final String prompt = String.format(fmt, args);
     107             :       for (; ; ) {
     108           0 :         String y = "y";
     109           0 :         String n = "n";
     110           0 :         if (def != null) {
     111           0 :           if (def) {
     112           0 :             y = "Y";
     113             :           } else {
     114           0 :             n = "N";
     115             :           }
     116             :         }
     117             : 
     118           0 :         String yn = console.readLine("%-30s [%s/%s]? ", prompt, y, n);
     119           0 :         if (yn == null) {
     120           0 :           throw abort();
     121             :         }
     122           0 :         yn = yn.trim();
     123           0 :         if (def != null && yn.isEmpty()) {
     124           0 :           return def;
     125             :         }
     126           0 :         if (yn.equalsIgnoreCase("y") || yn.equalsIgnoreCase("yes")) {
     127           0 :           return true;
     128             :         }
     129           0 :         if (yn.equalsIgnoreCase("n") || yn.equalsIgnoreCase("no")) {
     130           0 :           return false;
     131             :         }
     132           0 :       }
     133             :     }
     134             : 
     135             :     @Override
     136             :     public void waitForUser() {
     137           0 :       if (console.readLine("Press enter to continue ") == null) {
     138           0 :         throw abort();
     139             :       }
     140           0 :     }
     141             : 
     142             :     @Override
     143             :     @FormatMethod
     144             :     public String readString(String def, @FormatString String fmt, Object... args) {
     145           0 :       final String prompt = String.format(fmt, args);
     146             :       String r;
     147           0 :       if (def != null) {
     148           0 :         r = console.readLine("%-30s [%s]: ", prompt, def);
     149             :       } else {
     150           0 :         r = console.readLine("%-30s : ", prompt);
     151             :       }
     152           0 :       if (r == null) {
     153           0 :         throw abort();
     154             :       }
     155           0 :       r = r.trim();
     156           0 :       if (r.isEmpty()) {
     157           0 :         return def;
     158             :       }
     159           0 :       return r;
     160             :     }
     161             : 
     162             :     @Override
     163             :     @FormatMethod
     164             :     public String readString(
     165             :         String def, Set<String> allowedValues, @FormatString String fmt, Object... args) {
     166             :       for (; ; ) {
     167           0 :         String r = readString(def, fmt, args);
     168           0 :         if (allowedValues.contains(r.toLowerCase())) {
     169           0 :           return r.toLowerCase();
     170             :         }
     171           0 :         if (!"?".equals(r)) {
     172           0 :           console.printf("error: '%s' is not a valid choice\n", r);
     173             :         }
     174           0 :         console.printf("       Supported options are:\n");
     175           0 :         for (String v : allowedValues) {
     176           0 :           console.printf("         %s\n", v.toLowerCase());
     177           0 :         }
     178           0 :       }
     179             :     }
     180             : 
     181             :     @Override
     182             :     @FormatMethod
     183             :     @Nullable
     184             :     public String password(String fmt, Object... args) {
     185           0 :       final String prompt = String.format(fmt, args);
     186             :       for (; ; ) {
     187           0 :         final char[] a1 = console.readPassword("%-30s : ", prompt);
     188           0 :         if (a1 == null) {
     189           0 :           throw abort();
     190             :         }
     191             : 
     192           0 :         final char[] a2 = console.readPassword("%30s : ", "confirm password");
     193           0 :         if (a2 == null) {
     194           0 :           throw abort();
     195             :         }
     196             : 
     197           0 :         final String s1 = new String(a1);
     198           0 :         final String s2 = new String(a2);
     199           0 :         if (!s1.equals(s2)) {
     200           0 :           console.printf("error: Passwords did not match; try again\n");
     201           0 :           continue;
     202             :         }
     203           0 :         return !s1.isEmpty() ? s1 : null;
     204             :       }
     205             :     }
     206             : 
     207             :     @Override
     208             :     @FormatMethod
     209             :     public <T extends Enum<?>, A extends EnumSet<? extends T>> T readEnum(
     210             :         T def, A options, String fmt, Object... args) {
     211           0 :       final String prompt = String.format(fmt, args);
     212             :       for (; ; ) {
     213           0 :         String r = console.readLine("%-30s [%s/?]: ", prompt, def.toString().toLowerCase());
     214           0 :         if (r == null) {
     215           0 :           throw abort();
     216             :         }
     217           0 :         r = r.trim();
     218           0 :         if (r.isEmpty()) {
     219           0 :           return def;
     220             :         }
     221           0 :         for (T e : options) {
     222           0 :           if (e.toString().equalsIgnoreCase(r)) {
     223           0 :             return e;
     224             :           }
     225           0 :         }
     226           0 :         if (!"?".equals(r)) {
     227           0 :           console.printf("error: '%s' is not a valid choice\n", r);
     228             :         }
     229           0 :         console.printf("       Supported options are:\n");
     230           0 :         for (T e : options) {
     231           0 :           console.printf("         %s\n", e.toString().toLowerCase());
     232           0 :         }
     233           0 :       }
     234             :     }
     235             : 
     236             :     @Override
     237             :     public void header(String fmt, Object... args) {
     238           0 :       fmt = fmt.replace("\n", "\n*** ");
     239           0 :       console.printf("\n*** " + fmt + "\n*** \n\n", args);
     240           0 :     }
     241             : 
     242             :     @Override
     243             :     public void message(String fmt, Object... args) {
     244           0 :       console.printf(fmt, args);
     245           0 :     }
     246             :   }
     247             : 
     248             :   private static class Batch extends ConsoleUI {
     249             :     @Override
     250             :     public boolean isBatch() {
     251          15 :       return true;
     252             :     }
     253             : 
     254             :     @Override
     255             :     public boolean yesno(Boolean def, String fmt, Object... args) {
     256          15 :       return def != null ? def : true;
     257             :     }
     258             : 
     259             :     @Override
     260             :     public String readString(String def, String fmt, Object... args) {
     261          15 :       return def;
     262             :     }
     263             : 
     264             :     @Override
     265             :     public String readString(String def, Set<String> allowedValues, String fmt, Object... args) {
     266          15 :       return def;
     267             :     }
     268             : 
     269             :     @Override
     270           0 :     public void waitForUser() {}
     271             : 
     272             :     @Override
     273             :     public String password(String fmt, Object... args) {
     274           0 :       return null;
     275             :     }
     276             : 
     277             :     @Override
     278             :     public <T extends Enum<?>, A extends EnumSet<? extends T>> T readEnum(
     279             :         T def, A options, String fmt, Object... args) {
     280          15 :       return def;
     281             :     }
     282             : 
     283             :     @Override
     284          15 :     public void header(String fmt, Object... args) {}
     285             : 
     286             :     @Override
     287          15 :     public void message(String fmt, Object... args) {}
     288             :   }
     289             : }

Generated by: LCOV version 1.16+git.20220603.dfeb750