001/* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2008-2010 Sun Microsystems, Inc. 025 * Portions Copyright 2012-2015 ForgeRock AS. 026 */ 027 028package org.opends.quicksetup; 029 030import org.forgerock.i18n.LocalizableMessage; 031import org.forgerock.i18n.LocalizableMessageBuilder; 032 033import static org.opends.messages.AdminToolMessages.*; 034import static com.forgerock.opendj.cli.Utils.wrapText; 035 036import org.opends.quicksetup.util.Utils; 037import com.forgerock.opendj.cli.ClientException; 038import com.forgerock.opendj.cli.ConsoleApplication; 039import com.forgerock.opendj.cli.Menu; 040import com.forgerock.opendj.cli.MenuBuilder; 041import com.forgerock.opendj.cli.MenuResult; 042 043import java.util.List; 044 045import org.forgerock.i18n.slf4j.LocalizedLogger; 046 047/** 048 * Supports user interactions for a command line driven application. 049 */ 050public class CliUserInteraction extends ConsoleApplication 051 implements UserInteraction { 052 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 053 054 private final boolean isInteractive; 055 private final boolean isForceOnError; 056 057 /** 058 * Creates an instance that will use standard streams for interaction and with 059 * the provided CLI arguments. 060 * @param ud The CLI arguments. 061 */ 062 public CliUserInteraction(UserData ud) { 063 isInteractive = ud == null || ud.isInteractive(); 064 isForceOnError = ud != null && ud.isForceOnError(); 065 } 066 067 /** {@inheritDoc} */ 068 public Object confirm(LocalizableMessage summary, LocalizableMessage details, 069 LocalizableMessage title, MessageType type, LocalizableMessage[] options, 070 LocalizableMessage def) { 071 return confirm(summary, details, null, title, type, options, def, null); 072 } 073 074 /** {@inheritDoc} */ 075 public Object confirm(LocalizableMessage summary, LocalizableMessage details, LocalizableMessage fineDetails, 076 LocalizableMessage title, MessageType type, LocalizableMessage[] options, 077 LocalizableMessage def, LocalizableMessage viewDetailsOption) { 078 MenuBuilder<Integer> builder = new MenuBuilder<>(this); 079 080 LocalizableMessageBuilder b = new LocalizableMessageBuilder(); 081 b.append(summary); 082 b.append(Constants.LINE_SEPARATOR); 083 b.append(details); 084 builder.setPrompt(b.toMessage()); 085 086 int defInt = -1; 087 for (int i=0; i<options.length; i++) 088 { 089 builder.addNumberedOption(options[i], MenuResult.success(i+1)); 090 if (options[i].equals(def)) 091 { 092 defInt = i+1; 093 } 094 } 095 096 if (fineDetails != null) { 097 LocalizableMessage detailsPrompt = viewDetailsOption; 098 if (detailsPrompt == null) 099 { 100 detailsPrompt = INFO_CLI_VIEW_DETAILS.get(); 101 } 102 builder.addNumberedOption(detailsPrompt, 103 MenuResult.success(options.length + 1)); 104 } 105 106 builder.setDefault(LocalizableMessage.raw(String.valueOf(defInt)), 107 MenuResult.success(defInt)); 108 109 Menu<Integer> menu = builder.toMenu(); 110 111 Object returnValue = null; 112 boolean menuDisplayed = false; 113 while (returnValue == null) { 114 int respInt; 115 try 116 { 117 if (menuDisplayed) 118 { 119 println(); 120 builder.setPrompt(null); 121 menu = builder.toMenu(); 122 } 123 MenuResult<Integer> m = menu.run(); 124 menuDisplayed = true; 125 126 if (m.isSuccess()) 127 { 128 respInt = m.getValue(); 129 } 130 else 131 { 132 // Should never happen. 133 throw new RuntimeException(); 134 } 135 } 136 catch (ClientException ce) 137 { 138 respInt = defInt; 139 logger.warn(LocalizableMessage.raw("Error reading input: "+ce, ce)); 140 } 141 if (fineDetails != null && respInt == options.length + 1) { 142 println(); 143 println(String.valueOf(fineDetails)); 144 } else { 145 returnValue = options[respInt - 1]; 146 } 147 } 148 return returnValue; 149 } 150 151 /** {@inheritDoc} */ 152 public String createUnorderedList(List<?> list) { 153 StringBuilder sb = new StringBuilder(); 154 if (list != null) { 155 for (Object o : list) { 156 sb.append(/*bullet=*/"* "); 157 sb.append(o); 158 sb.append(Constants.LINE_SEPARATOR); 159 } 160 } 161 return sb.toString(); 162 } 163 164 private void println(String text) { 165 text = Utils.convertHtmlBreakToLineSeparator(text); 166 text = Utils.stripHtml(text); 167 text = wrapText(text, Utils.getCommandLineMaxLineWidth()); 168 getErrorStream().println(text); 169 } 170 171 /** {@inheritDoc} */ 172 public boolean isAdvancedMode() { 173 return false; 174 } 175 176 /** {@inheritDoc} */ 177 public boolean isInteractive() { 178 return isInteractive; 179 } 180 181 /** {@inheritDoc} */ 182 @Override 183 public boolean isMenuDrivenMode() { 184 return true; 185 } 186 187 /** {@inheritDoc} */ 188 public boolean isQuiet() { 189 return false; 190 } 191 192 /** {@inheritDoc} */ 193 public boolean isScriptFriendly() { 194 return false; 195 } 196 197 /** {@inheritDoc} */ 198 public boolean isVerbose() { 199 return true; 200 } 201 202 /** {@inheritDoc} */ 203 public boolean isCLI() 204 { 205 return true; 206 } 207 208 /** {@inheritDoc} */ 209 public boolean isForceOnError() { 210 return isForceOnError; 211 } 212}