1 /*
2  * Written and copyright 2001-2003 Tobias Minich. Distributed under the GNU
3  * General Public License; see the README file. This code comes with NO
4  * WARRANTY.
5  *
6  * Set.java
7  *
8  * Created on 23.03.2004
9  *
10  */
11 package org.gudy.azureus2.ui.console.commands;
12 
13 import java.io.PrintStream;
14 import java.util.HashMap;
15 import java.util.Iterator;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.TreeSet;
19 
20 import org.gudy.azureus2.core3.config.COConfigurationManager;
21 import org.gudy.azureus2.core3.util.SHA1Hasher;
22 import org.gudy.azureus2.ui.common.ExternalUIConst;
23 import org.gudy.azureus2.ui.console.ConsoleInput;
24 import org.pf.text.StringPattern;
25 
26 /**
27  * command that allows manipulation of Azureus' runtime properties.
28  * - when called without any parameters, it lists all of the available runtime properties.
29  * - when called with 1 parameter, it shows the current value of that parameter
30  * - when called with 2 or 3 parameters, it assigns a specified value to the
31  *   specified parameter name. (the third parameter forces the property to be set
32  *   to a particular type, otherwise we try and guess the type by the current value)
33  * @author Tobias Minich, Paul Duran
34  */
35 public class Set extends IConsoleCommand {
36 
37 	private static final String NULL_STRING = "__NULL__";
38 
Set()39 	public Set()
40 	{
41 		super("set", "+");
42 	}
43 
getCommandDescriptions()44 	public String getCommandDescriptions() {
45 		return("set [options] [parameter] [value]\t\t+\tSet a configuration parameter. Use \"param name\" when the name includes a space. If value is omitted, the current setting is shown. Parameter may be a wildcard to narrow results");
46 	}
printHelpExtra(PrintStream out, List args)47 	public void printHelpExtra(PrintStream out, List args) {
48 		out.println("> -----");
49 		out.println("'set' common parameter abbreviations: ");
50 		out.println("\tmax_up: Maximum upload speed in KB/sec" );		// see ExternalUIConst for the mappings for these
51 		out.println("\tmax_down: Maximum download speed in KB/sec" );
52 		out.println("'set' options: ");
53 		out.println("\t-export\t\tPrints all the options with non-defaut values.");
54 	}
55 
execute(String commandName,ConsoleInput ci, List args)56 	public void execute(String commandName,ConsoleInput ci, List args) {
57 
58 		boolean		non_defaults = false;
59 
60 		Iterator	it = args.iterator();
61 
62 		while( it.hasNext()){
63 			String	arg = (String)it.next();
64 			if ( arg.equals( "-export" )){
65 				non_defaults = true;
66 				it.remove();
67 			}
68 		}
69 		if( args.isEmpty() )
70 		{
71 			displayOptions(ci.out, new StringPattern("*"), non_defaults );
72 			return;
73 		}
74 		String external_name = (String) args.get(0);
75 		String internal_name = (String) ExternalUIConst.parameterlegacy.get(external_name);
76 		if( internal_name == null || internal_name.length() == 0 )
77 		{
78 			internal_name = external_name;
79 		}
80 //		else
81 //			ci.out.println("> converting " + origParamName + " to " + parameter);
82 
83 		Parameter param;
84 		switch( args.size() )
85 		{
86 			case 1:
87 				// allow wildcards : eg: Core* or *DHT* to shorten result list
88 				StringPattern sp = new StringPattern(internal_name);
89 				if( sp.hasWildcard() )
90 				{
91 					displayOptions(ci.out, sp, non_defaults);
92 				}
93 				else
94 				{
95 					// try to display the value of the specified parameter
96 					if( ! COConfigurationManager.doesParameterDefaultExist( internal_name ) )
97 					{
98 						ci.out.println("> Command 'set': Parameter '" + external_name + "' unknown.");
99 						return;
100 					}
101 					param = Parameter.get(internal_name,external_name);
102 
103 					ci.out.println( param.getString( false ) );
104 				}
105 				break;
106 			case 2:
107 			case 3:
108 				String setto = (String) args.get(1);
109 				String type;
110 				if( args.size() == 2 )
111 				{
112 					// guess the parameter type by getting the current value and determining its type
113 					param = Parameter.get( internal_name, external_name );
114 					type = param.getType();
115 				}
116 				else
117 					type = (String) args.get(2);
118 
119 				boolean success = false;
120 				if( type.equalsIgnoreCase("int") || type.equalsIgnoreCase("integer") ) {
121 					COConfigurationManager.setParameter( internal_name, Integer.parseInt( setto ) );
122 					success = true;
123 				}
124 				else if( type.equalsIgnoreCase("bool") || type.equalsIgnoreCase("boolean") ) {
125 
126 					boolean	value;
127 
128 					if ( setto.equalsIgnoreCase("true") || setto.equalsIgnoreCase("y") || setto.equals("1" )){
129 						value = true;
130 					}else{
131 						value = false;
132 					}
133 
134 					COConfigurationManager.setParameter( internal_name, value );
135 					success = true;
136 				}
137 				else if( type.equalsIgnoreCase("float") ) {
138 					COConfigurationManager.setParameter( internal_name, Float.parseFloat( setto ) );
139 					success = true;
140 				}
141 				else if( type.equalsIgnoreCase("string") ) {
142 					COConfigurationManager.setParameter( internal_name, setto );
143 					success = true;
144 				}
145 				else if( type.equalsIgnoreCase("password") ) {
146 					SHA1Hasher hasher = new SHA1Hasher();
147 
148 					byte[] password = setto.getBytes();
149 
150 					byte[] encoded;
151 
152 					if(password.length > 0){
153 
154 						encoded = hasher.calculateHash(password);
155 
156 					}else{
157 
158 						encoded = password;
159 					}
160 
161 					COConfigurationManager.setParameter( internal_name, encoded );
162 
163 					success = true;
164 				}
165 
166 				if( success ) {
167 					COConfigurationManager.save();
168 					ci.out.println("> Parameter '" + external_name + "' set to '" + setto + "'. [" + type + "]");
169 				}
170 				else ci.out.println("ERROR: invalid type given");
171 
172 				break;
173 			default:
174 				ci.out.println("Usage: 'set \"parameter\" value type', where type = int, bool, float, string, password");
175 				break;
176 		}
177 	}
178 
displayOptions(PrintStream out, StringPattern sp, boolean non_defaults)179 	private void displayOptions(PrintStream out, StringPattern sp, boolean non_defaults)
180 	{
181 		sp.setIgnoreCase(true);
182 		Iterator I = non_defaults?COConfigurationManager.getDefinedParameters().iterator():COConfigurationManager.getAllowedParameters().iterator();
183 		Map backmap = new HashMap();
184 		for (Iterator iter = ExternalUIConst.parameterlegacy.entrySet().iterator(); iter.hasNext();) {
185 			Map.Entry entry = (Map.Entry) iter.next();
186 			backmap.put( entry.getValue(), entry.getKey() );
187 		}
188 		TreeSet srt = new TreeSet();
189 		while (I.hasNext()) {
190 			String internal_name = (String) I.next();
191 
192 			String	external_name = (String) backmap.get(internal_name);
193 
194 			if ( external_name == null ){
195 
196 				external_name = internal_name;
197 			}
198 			if( sp.matches(external_name) )
199 			{
200 				Parameter param = Parameter.get( internal_name, external_name );
201 
202 				if ( non_defaults ){
203 
204 					if ( !param.isDefault()){
205 
206 						srt.add( param.getString( true ));
207 					}
208 				}else{
209 
210 					srt.add( param.getString( false ));
211 				}
212 			}
213 		}
214 		I = srt.iterator();
215 		while (I.hasNext()) {
216 			out.println((String) I.next());
217 		}
218 	}
219 
220 	/**
221 	 * class that represents a parameter. we can use one of these objects to
222 	 * verify a parameter's type and value as well as whether or not a value has been set.
223 	 * @author pauld
224 	 */
225 	private static class Parameter
226 	{
227 		private static final int PARAM_INT 		= 1;
228 		private static final int PARAM_BOOLEAN 	= 2;
229 		private static final int PARAM_STRING 	= 4;
230 		private static final int PARAM_OTHER 	= 8;
231 
232 		/**
233 		 * returns a new Parameter object reprenting the specified parameter name
234 		 * @param parameter
235 		 * @return
236 		 */
237 		public static Parameter
get( String internal_name, String external_name )238 		get(
239 			String	internal_name,
240 			String	external_name )
241 		{
242 			int underscoreIndex = external_name.indexOf('_');
243 			int nextchar = external_name.charAt(underscoreIndex + 1);
244 
245 			if ( 	internal_name != external_name &&
246 					"ibs".indexOf(nextchar) >= 0 ){
247 
248 				try {
249 					if( nextchar == 'i' )
250 					{
251 						int value = COConfigurationManager.getIntParameter(internal_name, Integer.MIN_VALUE);
252 						return new Parameter(internal_name, external_name, value == Integer.MIN_VALUE ? (Integer)null : new Integer(value) );
253 					}
254 					else if( nextchar == 'b' )
255 					{
256 						// firstly get it as an integer to make sure it is actually set to something
257 						if( COConfigurationManager.getIntParameter(internal_name, Integer.MIN_VALUE) != Integer.MIN_VALUE )
258 						{
259 							boolean b = COConfigurationManager.getBooleanParameter(internal_name);
260 							return new Parameter(internal_name, external_name, Boolean.valueOf(b));
261 						}
262 						else
263 						{
264 							return new Parameter(internal_name, external_name, (Boolean)null);
265 						}
266 					}
267 					else
268 					{
269 						String value = COConfigurationManager.getStringParameter(internal_name, NULL_STRING);
270 						return new Parameter( internal_name, external_name, NULL_STRING.equals(value) ? null : value);
271 					}
272 				} catch (Throwable e){
273 
274 				}
275 			}
276 
277 			Object v = COConfigurationManager.getParameter( internal_name );
278 
279 			try {
280 				if ( v instanceof Long || v instanceof Integer ){
281 
282 					int value = COConfigurationManager.getIntParameter(internal_name, Integer.MIN_VALUE);
283 
284 					return new Parameter(internal_name, external_name, value == Integer.MIN_VALUE ? (Integer)null : new Integer(value) );
285 
286 				}else if ( v instanceof Boolean ){
287 
288 					boolean value = COConfigurationManager.getBooleanParameter( internal_name );
289 
290 					return new Parameter( internal_name, external_name, Boolean.valueOf( value ));
291 
292 				}else if ( v instanceof String || v instanceof byte[] ){
293 
294 					String value = COConfigurationManager.getStringParameter(internal_name);
295 
296 					return new Parameter( internal_name, external_name, NULL_STRING.equals(value) ? null : value);
297 				}else{
298 
299 					return new Parameter( internal_name, external_name, v, PARAM_OTHER );
300 				}
301 			}catch( Throwable e2 ){
302 
303 				return new Parameter( internal_name, external_name, v, PARAM_OTHER );
304 			}
305 		}
306 
Parameter( String iname, String ename, Boolean val )307 		public Parameter( String iname, String ename, Boolean val )
308 		{
309 			this(iname,ename, val, PARAM_BOOLEAN);
310 		}
Parameter( String iname, String ename, Integer val )311 		public Parameter( String iname, String ename, Integer val )
312 		{
313 			this(iname,ename, val, PARAM_INT);
314 		}
Parameter( String iname, String ename, String val )315 		public Parameter( String iname, String ename, String val )
316 		{
317 			this(iname,ename, val, PARAM_STRING);
318 		}
Parameter( String _iname, String _ename, Object _val, int _type )319 		private Parameter( String _iname, String _ename, Object _val, int _type )
320 		{
321 			type = _type;
322 			iname = _iname;
323 			ename = _ename;
324 			value = _val;
325 			isSet = (value != null);
326 
327 			if ( !isSet ){
328 
329 				def = COConfigurationManager.getDefault(iname);
330 
331 				if  ( def != null ){
332 
333 					if ( def instanceof Long ){
334 
335 						type = PARAM_INT;
336 					}
337 				}
338 			}
339 		}
340 		private int type;
341 		private String iname;
342 		private String ename;
343 		private Object value;
344 		private boolean isSet;
345 		private Object	def;
346 
getType()347 		public String getType()
348 		{
349 			switch( type )
350 			{
351 				case PARAM_BOOLEAN:
352 					return "bool";
353 				case PARAM_INT:
354 					return "int";
355 				case PARAM_STRING:
356 					return "string";
357 				default:
358 					return "unknown";
359 			}
360 		}
361 
362 		public boolean
isDefault()363 		isDefault()
364 		{
365 			return( !isSet );
366 		}
367 
368 		public String
getString( boolean set_format )369 		getString(
370 			boolean	set_format )
371 		{
372 			if( isSet ){
373 				if ( set_format ){
374 
375 					return( "set " + quoteIfNeeded( ename ) + " " + quoteIfNeeded(value.toString()) + " " + getType());
376 
377 				}else{
378 
379 					return "> " + ename + ": " + value + " [" + getType() + "]";
380 				}
381 			}else{
382 				if ( def == null ){
383 
384 					return "> " + ename + " is not set. [" + getType() + "]";
385 
386 				}else{
387 					return "> " + ename + " is not set. [" + getType() + ", default: " + def + "]";
388 				}
389 			}
390 		}
391 
392 		protected String
quoteIfNeeded( String str )393 		quoteIfNeeded(
394 			String	str )
395 		{
396 			if ( str.indexOf(' ') == -1 ){
397 
398 				return( str );
399 			}
400 
401 			return( "\"" + str + "\"" );
402 		}
403 	}
404 }
405