1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License.
17  */
18 
19 /**
20  * @author Vitaly A. Provodin
21  */
22 
23 /**
24  * Created on 26.01.2005
25  */
26 package org.apache.harmony.jpda.tests.framework;
27 
28 import java.util.HashMap;
29 
30 /**
31  * This class provides access to options for running JPDA tests.
32  * <p>
33  * The settings are presented as a set of getters and setters for test options,
34  * which can be implemented in different ways. In this implementation test
35  * options are implemented via VM system properties, which can be specified
36  * using option '-D' in VM command line.
37  * <p>
38  * The following options are currently recognized:
39  * <ul>
40  * <li><code>jpda.settings.debuggeeJavaHome</code>
41  *   - path to Java bundle to run debuggee on
42  * <li><code>jpda.settings.debuggeeJavaExec</code>
43  *   - name of Java executable to run debuggee on
44  * <li><code>jpda.settings.debuggeeJavaPath</code>
45  *   - full path to Java executable to run debuggee on
46  * <li><code>jpda.settings.debuggeeAgentName</code>
47  *   - name of agent native library
48  * <li><code>jpda.settings.debuggeeAgentExtraOptions</code>
49  *   - extra options for agent
50  * <li><code>jpda.settings.debuggeeClassName</code>
51  *   - full name of class to run debuggee with
52  * <li><code>jpda.settings.debuggeeVMExtraOptions</code>
53  *   - extra options to run debuggee with
54  * <li><code>jpda.settings.debuggeeSuspend</code>
55  *   - debuggee suspend mode ("y"|"n")
56  * <li><code>jpda.settings.transportWrapperClass</code>
57  *   - class name of TransportWrapper implementation
58  * <li><code>jpda.settings.transportAddress</code>
59  *   - address for JDWP connection
60  * <li><code>jpda.settings.connectorKind</code>
61  *   - type of JDWP connection (attach or listen)
62  * <li><code>jpda.settings.syncPort</code>
63  *   - port number for sync connection (chosen by the OS if not set or set to 0)
64  * <li><code>jpda.settings.timeout</code>
65  *   - timeout used in JPDA tests
66  * <li><code>jpda.settings.waitingTime</code>
67  *   - timeout for waiting events
68  * </ul>
69  * <li><code>jpda.settings.verbose</code>
70  *   - flag that disables (default) or enables writing messages to the log
71  * </ul>
72  * All options have default values, if they are not specified.
73  *
74  */
75 public class TestOptions {
76 
77     /** Default timeout value for various operations. */
78     public static final int DEFAULT_TIMEOUT = 1 * 60 * 1000; // 1 minute
79 
80     /** Default time interval for waiting for various events. */
81     public static final int DEFAULT_WAITING_TIME = DEFAULT_TIMEOUT;
82 
83     /** Default static address for transport connection. */
84     public static final String DEFAULT_ATTACHING_ADDRESS = "127.0.0.1:9898";
85 
86     /** Default port number for sync connection. */
87     public static final String DEFAULT_STATIC_SYNC_PORT = "9797";
88 
89     /** Default port number for sync connection. */
90     public static final int DEFAULT_SYNC_PORT = 0;
91 
92     /** Default class name for transport wrapper. */
93     public static final String DEFAULT_TRANSPORT_WRAPPER
94         = "org.apache.harmony.jpda.tests.framework.jdwp.SocketTransportWrapper";
95 
96     /** Default aclass name for debuggee application. */
97     public static final String DEFAULT_DEBUGGEE_CLASS_NAME
98         = "org.apache.harmony.jpda.tests.jdwp.share.debuggee.HelloWorld";
99 
100     // current waiting time value (negative means using default value)
101     private long waitingTime = -1;
102 
103     // current timeout value (negative means using default value)
104     private long timeout = -1;
105 
106     // internally set property values
107     private HashMap<String, String> internalProperties = new HashMap<>();
108 
109     /**
110      * Constructs an instance of this class.
111      */
TestOptions()112     public TestOptions() {
113         super();
114     }
115 
116     /**
117      * Returns path to Java bundle to run debuggee on.
118      *
119      * @return option "jpda.settings.debuggeeJavaHome" or system property
120      *         "java.home" by default.
121      */
getDebuggeeJavaHome()122     public String getDebuggeeJavaHome() {
123         return getProperty("jpda.settings.debuggeeJavaHome", getProperty("java.home", null));
124     }
125 
126     /**
127      * Returns name of Java executable to run debuggee on.
128      *
129      * @return option "jpda.settings.debuggeeJavaExec" or "java" by default.
130      */
getDebuggeeJavaExec()131     public String getDebuggeeJavaExec() {
132         return getProperty("jpda.settings.debuggeeJavaExec", "java");
133     }
134 
135     /**
136      * Returns full path to Java executable to run debuggee on.
137      *
138      * @return option "jpda.settings.debuggeeJavaPath" or construct path from
139      *         getDebuggeeJavaHome() and getDebuggeeJavaExec() by default.
140      */
getDebuggeeJavaPath()141     public String getDebuggeeJavaPath() {
142         return getProperty("jpda.settings.debuggeeJavaPath",
143                 getDebuggeeJavaHome() + "/bin/" + getDebuggeeJavaExec());
144     }
145 
146     /**
147      * Returns class name of TransportWrapper implementation.
148      *
149      * @return option "jpda.settings.transportWrapperClass" or
150      *         DEFAULT_TRANSPORT_WRAPPER by default.
151      */
getTransportWrapperClassName()152     public String getTransportWrapperClassName() {
153         return getProperty("jpda.settings.transportWrapperClass",
154                 DEFAULT_TRANSPORT_WRAPPER);
155     }
156 
157     /**
158      * Returns address for JDWP connection or null for dynamic address.
159      *
160      * @return option "jpda.settings.transportAddress" or null by default.
161      */
getTransportAddress()162     public String getTransportAddress() {
163         return getProperty("jpda.settings.transportAddress", null);
164     }
165 
166     /**
167      * Sets address to attach to debuggee.
168      *
169      * @param address to attach
170      */
setTransportAddress(String address)171     public void setTransportAddress(String address) {
172         setProperty("jpda.settings.transportAddress", address);
173     }
174 
175     /**
176      * Returns name of JDWP agent library.
177      *
178      * @return option "jpda.settings.debuggeeAgentName" or "jdwp" by default
179      */
getDebuggeeAgentName()180     public String getDebuggeeAgentName() {
181         return getProperty("jpda.settings.debuggeeAgentName", "jdwp");
182     }
183 
184     /**
185      * Returns string with extra options for agent.
186      *
187      * @return option "jpda.settings.debuggeeAgentExtraOptions" or "" by default
188      */
getDebuggeeAgentExtraOptions()189     public String getDebuggeeAgentExtraOptions() {
190         return getProperty("jpda.settings.debuggeeAgentExtraOptions", "");
191     }
192 
193     /**
194      * Returns string with all options for agent including specified connection
195      * address.
196      *
197      * @param address - address to attach
198      * @param isDebuggerListen - true if debugger is listening for connection
199      *
200      * @return string with all agent options
201      */
getDebuggeeAgentOptions(String address, boolean isDebuggerListen)202     public String getDebuggeeAgentOptions(String address, boolean isDebuggerListen) {
203         String serv;
204         if (isDebuggerListen) {
205             serv = "n";
206         } else {
207             serv = "y";
208         }
209 
210         // add ',' to agent extra options if required
211         String agentExtraOptions = getDebuggeeAgentExtraOptions();
212         if (agentExtraOptions.length() > 0 && agentExtraOptions.charAt(0) != ',') {
213             agentExtraOptions = "," + agentExtraOptions;
214         }
215 
216         return getProperty("jpda.settings.debuggeeAgentOptions",
217                 "transport=dt_socket,address=" + address + ",server=" + serv
218                 + ",suspend=" + getDebuggeeSuspend() + agentExtraOptions);
219     }
220 
221     /**
222      * Returns string with all options for agent including specified connection
223      * address (only for debugger in listening mode). It just calls
224      * <ul>
225      * <li><code>getDebuggeeAgentOptions(address, true)</code></li>
226      * </ul>
227      *
228      * @deprecated This method is used as workaround for old tests and will be removed soon.
229      *
230      * @param address - address to attach
231      *
232      * @return string with all agent options
233      */
getDebuggeeAgentOptions(String address)234     public String getDebuggeeAgentOptions(String address) {
235         return getDebuggeeAgentOptions(address, true);
236     }
237 
238     /**
239      * Returns VM classpath value to run debuggee with.
240      *
241      * @return system property "java.class.path" by default.
242      */
getDebuggeeClassPath()243     public String getDebuggeeClassPath() {
244         return getProperty("java.class.path", null);
245     }
246 
247     /**
248      * Returns full name of the class to start debuggee with.
249      *
250      * @return option "jpda.settings.debuggeeClassName" or
251      *         "org.apache.harmony.jpda.tests.jdwp.share.debuggee.HelloWorld" by default
252      */
getDebuggeeClassName()253     public String getDebuggeeClassName() {
254         return getProperty("jpda.settings.debuggeeClassName", DEFAULT_DEBUGGEE_CLASS_NAME);
255     }
256 
257     /**
258      * Sets full name of the class to start debuggee with.
259      *
260      * @param className
261      *            full class name
262      */
setDebuggeeClassName(String className)263     public void setDebuggeeClassName(String className) {
264         setProperty("jpda.settings.debuggeeClassName", className);
265     }
266 
267     /**
268      * Returns string with extra options to start debuggee with.
269      *
270      * @return option "jpda.settings.debuggeeVMExtraOptions" or "" by default
271      */
getDebuggeeVMExtraOptions()272     public String getDebuggeeVMExtraOptions() {
273         String extOpts = getProperty("jpda.settings.debuggeeVMExtraOptions", "");
274         extOpts = extOpts + " -Djpda.settings.verbose=" + isVerbose();
275         return extOpts;
276     }
277 
278     /**
279      * Returns debuggee suspend mode ("y"|"n").
280      *
281      * @return option "jpda.settings.debuggeeSuspend" or "y" by default
282      */
getDebuggeeSuspend()283     public String getDebuggeeSuspend() {
284         return getProperty("jpda.settings.debuggeeSuspend", "y");
285     }
286 
287     /**
288      * Returns debuggee suspend mode ("y"|"n").
289      *
290      * @param mode
291      *            suspend mode
292      */
setDebuggeeSuspend(String mode)293     public void setDebuggeeSuspend(String mode) {
294         setProperty("jpda.settings.debuggeeSuspend", mode);
295     }
296 
297     /**
298      * Checks if debuggee is launched in suspend mode.
299      *
300      * @return true if debuggee is launched in suspend mode
301      */
isDebuggeeSuspend()302     public boolean isDebuggeeSuspend() {
303         return getDebuggeeSuspend().equals("y");
304     }
305 
306     /**
307      * Returns string representation of TCP/IP port for synchronization channel.
308      *
309      * @return string with port number or null
310      */
getSyncPortString()311     public String getSyncPortString() {
312         return getProperty("jpda.settings.syncPort", null);
313     }
314 
315     /**
316      * Returns type of connection with debuggee.
317      *
318      * @return system property "jpda.settings.connectorKind" or "listen" by default.
319      */
getConnectorKind()320     public String getConnectorKind() {
321         return getProperty("jpda.settings.connectorKind", "listen");
322     }
323 
324     /**
325      * Checks if attach connection with debuggee.
326      *
327      * @return true, if attach connection, false otherwise.
328      */
isAttachConnectorKind()329     public boolean isAttachConnectorKind() {
330         return ((getConnectorKind()).equals("attach"));
331 
332     }
333 
334     /**
335      * Checks if listen connection with debuggee.
336      *
337      * @return true, if listen connection, false otherwise.
338      */
isListenConnectorKind()339     public boolean isListenConnectorKind() {
340         return (getConnectorKind().equals("listen"));
341     }
342 
343     /**
344      * Sets connectorKind to attach to debuggee.
345      */
setAttachConnectorKind()346     public void setAttachConnectorKind() {
347         setConnectorKind("attach");
348     }
349 
350     /**
351      * Sets connectorKind to listen connection from debuggee.
352      */
setListenConnectorKind()353     public void setListenConnectorKind() {
354         setConnectorKind("listen");
355     }
356 
357     /**
358      * Sets kind of connector (attach or listen).
359      */
setConnectorKind(String kind)360     public void setConnectorKind(String kind) {
361         setProperty("jpda.settings.connectorKind", kind);
362     }
363 
364     /**
365      * Returns kind of launching debuggee VM, which can be "auto" or "manual".
366      *
367      * @return option "jpda.settings.debuggeeLaunchKind" or "auto" by default.
368      */
getDebuggeeLaunchKind()369     public String getDebuggeeLaunchKind() {
370         return getProperty("jpda.settings.debuggeeLaunchKind", "auto");
371     }
372 
373     /**
374      * Returns TCP/IP port for synchronization channel.
375      *
376      * @return port number if it is set, or DEFAULT_SYNC_PORT otherwise.
377      */
getSyncPortNumber()378     public int getSyncPortNumber() {
379         String buf = getSyncPortString();
380         if (buf == null) {
381             return DEFAULT_SYNC_PORT;
382         }
383 
384         try {
385             return Integer.parseInt(buf);
386         } catch (NumberFormatException e) {
387             throw new TestErrorException(e);
388         }
389     }
390 
391     /**
392      * Returns timeout for JPDA tests in milliseconds.
393      *
394      * @return option "jpda.settings.timeout" or DEFAULT_TIMEOUT by default.
395      */
getTimeout()396     public long getTimeout() {
397         if (timeout < 0) {
398             timeout = DEFAULT_TIMEOUT;
399             String buf = getProperty("jpda.settings.timeout", null);
400             if (buf != null) {
401                 try {
402                     timeout = Long.parseLong(buf);
403                 } catch (NumberFormatException e) {
404                     throw new TestErrorException(e);
405                 }
406             }
407         }
408         return timeout;
409     }
410 
411     /**
412      * Sets timeout for JPDA tests in milliseconds.
413      *
414      * @param timeout
415      *            timeout to be set
416      */
setTimeout(long timeout)417     public void setTimeout(long timeout) {
418         if (timeout < 0) {
419             throw new TestErrorException("Cannot set negative timeout value: "
420                     + timeout);
421         }
422         this.timeout = timeout;
423     }
424 
425     /**
426      * Returns waiting time for events in milliseconds.
427      *
428      * @return waiting time
429      */
getWaitingTime()430     public long getWaitingTime() {
431         if (waitingTime < 0) {
432             waitingTime = DEFAULT_WAITING_TIME;
433             String buf = getProperty("jpda.settings.waitingTime", null);
434             if (buf != null) {
435                 try {
436                     waitingTime = Long.parseLong(buf);
437                 } catch (NumberFormatException e) {
438                     throw new TestErrorException(e);
439                 }
440             }
441         }
442         return waitingTime;
443     }
444 
445     /**
446      * Sets waiting time for events in milliseconds.
447      *
448      * @param waitingTime
449      *            waiting time to be set
450      */
setWaitingTime(long waitingTime)451     public void setWaitingTime(long waitingTime) {
452         this.waitingTime = waitingTime;
453     }
454 
455     /**
456      * Returns whether print to log is enabled.
457      *
458      * @return false (default) if log is disabled or true otherwise.
459      */
isVerbose()460     public boolean isVerbose() {
461         return isTrue(getProperty("jpda.settings.verbose", "true"));
462     }
463 
464     /**
465      * Converts text to boolean.
466      *
467      * @param str string representing boolean value
468      * @return boolean
469      */
isTrue(String str)470     static public boolean isTrue(String str) {
471         return str != null && (
472             str.equalsIgnoreCase("true") ||
473             str.equalsIgnoreCase("yes") ||
474             str.equalsIgnoreCase("on") ||
475             str.equals("1"));
476     }
477 
478     /**
479      * Returns value of given property if it was set internally or specified in system properties.
480      *
481      * @param name
482      *           property name
483      * @param defaultValue
484      *           default value for given property
485      * @return string value of given property or default value if no such property found
486      */
getProperty(String name, String defaultValue)487     protected String getProperty(String name, String defaultValue) {
488         String value = (String)internalProperties.get(name);
489         if (value != null) {
490             return value;
491         }
492         return System.getProperty(name, defaultValue);
493     }
494 
495     /**
496      * Sets internal value of given property to override corresponding system property.
497      *
498      * @param name
499      *           proparty name
500      * @param value
501      *           value for given property
502      */
setProperty(String name, String value)503     protected void setProperty(String name, String value) {
504         internalProperties.put(name, value);
505     }
506 
507 }
508