001: /*
002: * <copyright>
003: *
004: * Copyright 1997-2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026:
027: package org.cougaar.tools.server;
028:
029: import java.util.Collections;
030: import java.util.Enumeration;
031: import java.util.HashMap;
032: import java.util.List;
033: import java.util.Map;
034: import java.util.Properties;
035:
036: /**
037: * Immutable description for a remote process.
038: */
039: public final class ProcessDescription implements java.io.Serializable {
040:
041: // Make the props and args mutable. This simplifies
042: // some client code, but is generally a bad idea.
043: private static final boolean MAKE_IMMUTABLE = false;
044:
045: private final String name;
046: private final String group;
047: private final Map javaProps;
048: private final List commandLineArgs;
049:
050: public ProcessDescription(String name, String group, Map javaProps,
051: List commandLineArgs) {
052: this .name = prepareName(name);
053: this .group = prepareGroup(group);
054: this .javaProps = prepareProps(javaProps);
055: this .commandLineArgs = prepareArgs(commandLineArgs);
056: }
057:
058: /**
059: * Get the "name" identifier for this process.
060: * <p>
061: * All processes must have globally-unique names.
062: */
063: public String getName() {
064: return name;
065: }
066:
067: /**
068: * Get the optional "group" identifier for this process.
069: * <p>
070: * This can be used to tag multiple processes into logical
071: * groups.
072: */
073: public String getGroup() {
074: return group;
075: }
076:
077: /**
078: * Get the java properties, which is an unmodifiable map
079: * of (String, String) pairs.
080: * <p>
081: * All properties fall into three groups: <ul>
082: * <li>"<b>env.*</b>" process environment properties
083: * (e.g. "env.DISPLAY=..")</li>
084: * <li>"<b>java.*</b>" java options
085: * (e.g. "java.class.path=..")</li>
086: * <li>"<b>*</b>" for all other "-D" system properties
087: * (e.g. "foo=bar")</li>
088: * </ul><br>
089: * If the value is <tt>null</tt> then this property is
090: * to be <i>removed</i> from the default list of properties
091: * (if one is specified on the server).
092: * <p>
093: * Double-prefixes ("env.env.*" and "java.java.*") are
094: * stripped and converted to "-D" properties. For example,
095: * "java.java.duck=quack" is converted to "-Djava.duck=quack".
096: * <p>
097: * Some properties of note:<ul>
098: * <li>"java.jar=" specify an java executable jar, this
099: * property defaults to empty (no executable jar)</li>
100: * <li>"java.class.name=" to set the classname, which
101: * is required if the "java.jar=.." is not specified.
102: * If both the classname and jar are specified then
103: * the classname is ignored.</li>
104: * <li>"java.class.path=" specify the java classpath -- note
105: * that this *doesn't* adopt the server's classpath!
106: * If the "java.jar=.." is specified then this property
107: * is ignored. If both this property and "java.jar=.."
108: * are not specified then this property defaults to the
109: * system-default classpath</li>
110: * <li>"java.jvm.program=" to set the java executable
111: * (defaults to "${java.home}/bin/java")</li>
112: * <li>"java.jvm.mode=" to set the JVM mode
113: * ("classic", "hotspot", "client", or "server");
114: * defaults to "hotspot"</li>
115: * <li>"java.jvm.green=" to add "-green" for green threads,
116: * defaults to false.
117: * <li>"java.Xbootclasspath[/p|/a]=" to set the bootclasspath.
118: * "java.Xbootclasspath/p=" is used to prefix the default
119: * bootclasspath, or "java.Xbootclasspath/a=" to append</li>
120: * <li>"java.heap.min=" to specify the minimum heap size,
121: * such as "100m" for 100 megabytes; defaults to a
122: * system-specify value</li>
123: * <li>"java.heap.max=" to specify the maximum heap size,
124: * such as "300m" for 300 megabytes; defaults to a
125: * system-specify value</li>
126: * <li>"java.stack.size=" to specify the Java thread stack size,
127: * such as "10m" for 10 megabytes; defaults to a
128: * system-specify value</li>
129: * <li>"java.enable.assertions[=(|true|false|package|classname)]
130: * to turn on JDK 1.4 assertion checking (-ea)</li>
131: * <li>"java.disable.assertions[=(|true|false|package|classname)]
132: * to turn off JDK 1.4 assertion checking (-da)</li>
133: * <li>"java.enable.system.assertions[=(|true|false])]
134: * to turn on JDK 1.4 system assertion checking (-esa)</li>
135: * <li>"java.disable.system.assertions[=(|true|false])]
136: * to turn off JDK 1.4 system assertion checking (-dsa)</li>
137: * <li>"java.*" for all other "-*" properties, such as
138: * "java.Xnoclassgc=" for "-Xnoclassgc"</li>
139: * </ul>
140: */
141: public Map getJavaProperties() {
142: return javaProps;
143: }
144:
145: /**
146: * Get the command-line arguments, which is an unmodifiable
147: * list of non-null Strings.
148: * <p>
149: * These arguments are in addition to the optional
150: * java-properties.
151: */
152: public List getCommandLineArguments() {
153: return commandLineArgs;
154: }
155:
156: public String toString() {
157: return "Process \"" + name + "\" of group \"" + group + "\"";
158: }
159:
160: public int hashCode() {
161: // could cache
162: return name.hashCode();
163: }
164:
165: public boolean equals(Object o) {
166: if (o == this ) {
167: return true;
168: }
169: if (!(o instanceof ProcessDescription)) {
170: return false;
171: }
172: ProcessDescription pd = (ProcessDescription) o;
173: if (!(name.equals(pd.name))) {
174: return false;
175: }
176: if (!(group.equals(pd.group))) {
177: return false;
178: }
179: if (!(javaProps.equals(pd.javaProps))) {
180: return false;
181: }
182: if (!(commandLineArgs.equals(pd.commandLineArgs))) {
183: return false;
184: }
185: return true;
186: }
187:
188: private static String prepareName(String s) {
189: if (s == null) {
190: throw new IllegalArgumentException("Name must be non-null");
191: }
192: return s;
193: }
194:
195: private static String prepareGroup(String s) {
196: if (s == null) {
197: return "<none>";
198: }
199: return s;
200: }
201:
202: /**
203: * Does three things:
204: * <ol>
205: * <li>Use a zero-size map if passed null</li>
206: * <li>Flatten "java.util.Properies" to a "java.util.HashMap",
207: * since Properties has bad "get(..)" and "size()"
208: * implementations</li>
209: * <li>Wrap the map into an unmodifiable map</li>
210: * </ol>.
211: */
212: private static Map prepareProps(Map m) {
213: if (!MAKE_IMMUTABLE) {
214: // FIXME check for Properties with non-null defaults,
215: // since sometimes "getProperty(..)" != "get(..)"
216: return m;
217: }
218: if (m == null) {
219: return Collections.EMPTY_MAP;
220: }
221: // flatten properties
222: Map nm = m;
223: if (m instanceof Properties) {
224: Properties props = (Properties) m;
225: nm = new HashMap();
226: for (Enumeration en = props.propertyNames(); en
227: .hasMoreElements();) {
228: String name = (String) en.nextElement();
229: String value = props.getProperty(name);
230: nm.put(name, value);
231: }
232: } else {
233: // verify (String, String) pairs
234: }
235: // force immutable
236: Map ret = Collections.unmodifiableMap(nm);
237: return ret;
238: }
239:
240: /**
241: * Does three things:
242: * <ol>
243: * <li>Use a zero-size list if passed null</li>
244: * <li>Make sure the list only contains non-null Strings</li>
245: * <li>Wrap the list into an unmodifiable list</li>
246: * </ol>.
247: */
248: private static List prepareArgs(List l) {
249: if (!MAKE_IMMUTABLE) {
250: return l;
251: }
252: if (l == null) {
253: return Collections.EMPTY_LIST;
254: }
255: // check for strings
256: int n = l.size();
257: for (int i = 0; i < n; i++) {
258: Object oi = l.get(i);
259: if (!(oi instanceof String)) {
260: throw new IllegalArgumentException(
261: "Command line argument [" + i
262: + "] is not a String: " + oi);
263: }
264: }
265: // force immutable
266: List ret = Collections.unmodifiableList(l);
267: return ret;
268: }
269:
270: private static final long serialVersionUID = 2938472839235681283L;
271: }
|