001: /*
002: * CmdOpts.java
003: *
004: * Created on November 13, 2001, 1:26 PM
005: */
006:
007: package com.sun.portal.desktop.deployment;
008:
009: import java.io.BufferedReader;
010: import java.io.InputStreamReader;
011: import java.io.PrintStream;
012:
013: import java.util.Vector;
014: import java.util.HashMap;
015:
016: /**
017: *
018: * @author yabob
019: * @version
020: */
021: public class CmdOpts {
022:
023: public static final int STD_NONE = 0;
024: public static final int STD_DPONLY = 1;
025: public static final int STD_PARONLY = 2;
026: public static final int STD_BOTH = 3;
027: public static final int STD_DPOPT = 4;
028:
029: public static final int REM_NONE = 0;
030: public static final int REM_OPTIONAL = 1;
031: public static final int REM_REQUIRED = 3;
032:
033: public static final String GLOBAL_DN = "global";
034:
035: /* Unit test main.
036:
037: public static void main(String args[]) {
038: CmdOpts opts = parseOpts(args,STD_NONE,REM_NONE,"This is a usage message.","rpmvaods");
039: if (opts != null) {
040: System.out.println("auto: "+opts.autoextract());
041: System.out.println("debug: "+opts.debug());
042: System.out.println("modify: "+opts.modify());
043: System.out.println("overwrite: "+opts.overwrite());
044: System.out.println("staticsub: "+opts.staticsub());
045: System.out.println("verbose: "+opts.verbose());
046: }
047: } */
048:
049: private CmdOpts(String args[], int stdargs, int rem,
050: String allowopts) throws ParFileException {
051:
052: int idx;
053:
054: // Set up short commands;
055:
056: m_Short.put("r", "runasdn");
057: m_Short.put("p", "password");
058: m_Short.put("m", "modify");
059: m_Short.put("v", "verbose");
060: m_Short.put("a", "auto");
061: m_Short.put("o", "overwrite");
062: m_Short.put("d", "debug");
063: m_Short.put("s", "static");
064: m_Short.put("V", "version");
065: m_Short.put("?", "help");
066:
067: // Handle options
068:
069: for (idx = 0; idx < args.length; ++idx) {
070:
071: // stripOpt returns the string following the option character,
072: // or null if not an option.
073:
074: String opts = stripOpt(args[idx], allowopts);
075: boolean boolset = true;
076:
077: if (opts == null) {
078: break;
079: }
080: if (opts.startsWith("!") && opts.length() > 1) {
081: boolset = false;
082: opts = opts.substring(1);
083: }
084:
085: // Error check options with arguments after them.
086:
087: boolean hasarg = false;
088: char o1 = opts.charAt(0);
089: switch (o1) {
090: case 'r':
091: case 'p':
092: case 's':
093: if (opts.length() > 1) {
094: Object tok[] = { args[idx] };
095: throw new ParFileException("errorOptBadArg", tok);
096: }
097: hasarg = true;
098: break;
099: default:
100: break;
101: }
102:
103: if (hasarg) {
104: ++idx;
105: if (idx >= args.length) {
106: Object tok[] = { args[idx] };
107: throw new ParFileException("errorOptNoArg", tok);
108: }
109: }
110:
111: // handle options. Ones with arguments are in the outer switch. Flags can be concatenated
112: // together.
113:
114: switch (o1) {
115: case 'r':
116: m_User = args[idx];
117: break;
118: case 'p':
119: m_Pwd = args[idx];
120: break;
121: case 's':
122: m_StaticSub = args[idx];
123: break;
124: default:
125: if (hasarg) {
126: throw new ParFileException("errorHasarg");
127: }
128: for (int cidx = 0; cidx < opts.length(); ++cidx) {
129: switch (opts.charAt(cidx)) {
130: case 'm':
131: m_Modify = boolset;
132: break;
133: case 'v':
134: m_Verbose = boolset;
135: break;
136: case 'o':
137: m_Overwrite = boolset;
138: break;
139: case 'a':
140: m_AutoExtract = boolset;
141: break;
142: case 'd':
143: m_Debug = boolset;
144: break;
145: case 'V':
146: m_Version = boolset;
147: break;
148: case '?':
149: m_Help = boolset;
150: break;
151: default:
152: Object tok[] = { args[idx] };
153: throw new ParFileException(
154: "errorOptUnrecognized", tok);
155: }
156: }
157: break;
158: }
159: }
160:
161: // Skip over explicit option terminator.
162:
163: if (idx < args.length && args[idx].equals(DOUBLEPFX)) {
164: ++idx;
165: }
166:
167: // Figure out how many more standard arguments are required, and whether we have to
168: // handle login. Login has to be handled for cases where we support DP files.
169:
170: int req = 1;
171: m_Login = true;
172: switch (stdargs) {
173: case STD_NONE:
174: req = 0;
175: m_Login = false;
176: break;
177: case STD_PARONLY:
178: m_Login = false;
179: break;
180: case STD_BOTH:
181: req = 2;
182: break;
183: default:
184: break;
185: }
186:
187: if ((args.length - idx) < req) {
188: throw new ParFileException("errorOptNotEnoughArg");
189: }
190:
191: // Pick up the standard arguments.
192:
193: switch (stdargs) {
194: case STD_BOTH:
195: case STD_PARONLY:
196: case STD_DPOPT:
197: m_ParFile = args[idx];
198: ++idx;
199: break;
200: default:
201: break;
202: }
203:
204: switch (stdargs) {
205: case STD_BOTH:
206: case STD_DPONLY:
207: m_DN = args[idx];
208: ++idx;
209: break;
210: case STD_DPOPT:
211: if (idx < args.length) {
212: m_DN = args[idx];
213: ++idx;
214: }
215: break;
216: default:
217: break;
218: }
219:
220: switch (rem) {
221: case REM_NONE:
222: if (args.length > idx) {
223: throw new ParFileException("errorOptUnrecognizedArg");
224: }
225: break;
226: case REM_REQUIRED:
227: if (args.length <= idx) {
228: throw new ParFileException("errorOptNotEnoughArg");
229: }
230: break;
231: default:
232: break;
233: }
234:
235: if (m_Login) {
236: if (m_User == null) {
237: m_User = promptFor("runasdn");
238: }
239:
240: if (m_Pwd == null) {
241: throw new ParFileException("errorOptNoPassword");
242: }
243: }
244:
245: // transfer the remaining arguments to the vector.
246:
247: for (; idx < args.length; ++idx) {
248: m_Remaining.add(args[idx]);
249: }
250: }
251:
252: // public entry point to create a CmdOpts. Handles errors internally and return a null to
253: // indicate failure.
254:
255: public static CmdOpts parseOpts(String args[], int stdargs,
256: int rem, String usage, String allowopts) {
257:
258: CmdOpts opts = null;
259:
260: allowopts = allowopts + "V?"; // we always allow help and version
261:
262: try {
263:
264: // The constructor throws exceptions for "usage" type errors.
265: // We handle login ourself if there are none of those.
266:
267: opts = new CmdOpts(args, stdargs, rem, allowopts);
268: if (opts.m_Login) {
269: try {
270: if (opts.m_Verbose || opts.m_Debug) {
271: System.out
272: .println(Par
273: .getLocalizedString("msgAuthenticating"));
274: }
275: System.out.println(opts.m_User);
276: System.out.println(opts.m_Pwd);
277: opts.m_DRoot = DPRootSpecifier.makeSpecifier(
278: opts.m_User, opts.m_Pwd);
279: if ((opts.m_Verbose || opts.m_Debug)
280: && opts.m_DN != null) {
281: Object tok[] = { opts.m_DN };
282: System.out.println(Par.getLocalizedString(
283: "msgAuthenticated", tok));
284: }
285: opts.m_DRoot.setDN(opts.m_DN);
286: } catch (Exception ex) {
287: opts.produceErrorMessage(ex);
288: return null;
289: }
290: }
291:
292: // We also handle the "version" and "help" options. Either of these are
293: // supposed to "stop processing" according to CLIP spec. We'll just
294: // handle either or both, then return null.
295:
296: if (opts.m_Version) {
297: CmdVersion.printVersion();
298: }
299: if (opts.m_Help) {
300: printUsage(System.out, usage, allowopts);
301: }
302: if (opts.m_Version || opts.m_Help) {
303: return null;
304: }
305:
306: return opts;
307: } catch (ParFileException pex) {
308: Object tokerr[] = { pex.getMessage() };
309: System.err.println(Par.getLocalizedString("msgCmdError",
310: tokerr));
311: printUsage(System.err, usage, allowopts);
312: return null;
313: }
314: }
315:
316: private static void printUsage(PrintStream strm, String usage,
317: String allowopts) {
318: Object tokusg[] = { usage };
319: strm.println(Par.getLocalizedString("msgCmdUsage", tokusg));
320: strm.println(Par.getLocalizedString("msgCmdOptions"));
321: for (int i = 0; i < allowopts.length(); ++i) {
322: char o = allowopts.charAt(i);
323: switch (o) {
324: case 'r':
325: strm.println("\t" + DOUBLEPFX + "runasdn <dn>");
326: break;
327: case 'p':
328: strm.println("\t" + DOUBLEPFX + "password <password>");
329: break;
330: case 'm':
331: strm.println("\t" + DOUBLEPFX + "modify");
332: break;
333: case 'v':
334: strm.println("\t" + DOUBLEPFX + "verbose");
335: break;
336: case 'o':
337: strm.println("\t" + DOUBLEPFX + "overwrite");
338: break;
339: case 'a':
340: strm.println("\t" + DOUBLEPFX + "auto");
341: break;
342: case 'd':
343: strm.println("\t" + DOUBLEPFX + "debug");
344: break;
345: case 's':
346: strm.println("\t" + DOUBLEPFX
347: + "static <static subdirectory>");
348: break;
349: case '?':
350: strm.println("\t" + DOUBLEPFX + "help");
351: break;
352: case 'V':
353: strm.println("\t" + DOUBLEPFX + "version");
354: break;
355: default:
356: System.err
357: .println("\tLOGIC ERROR - CmdOpts doesn't recognize '"
358: + o + "'");
359: break;
360: }
361: }
362: }
363:
364: public Vector remaining() {
365: return m_Remaining;
366: }
367:
368: public boolean modify() {
369: return m_Modify;
370: }
371:
372: public boolean verbose() {
373: return m_Verbose;
374: }
375:
376: public boolean overwrite() {
377: return m_Overwrite;
378: }
379:
380: public boolean autoextract() {
381: return m_AutoExtract;
382: }
383:
384: public String parfile() {
385: return m_ParFile;
386: }
387:
388: public String staticsub() {
389: return m_StaticSub;
390: }
391:
392: public DPRootSpecifier dproot() {
393: return m_DRoot;
394: }
395:
396: public boolean debug() {
397: return m_Debug;
398: }
399:
400: public void produceErrorMessage(Exception ex) {
401: Object tok[] = { ex.getMessage() };
402: System.err.println(Par.getLocalizedString("msgCmdError", tok));
403: if (m_Debug) {
404: ex.printStackTrace(System.err);
405: }
406: }
407:
408: private String promptFor(String prompt) throws ParFileException {
409:
410: try {
411: if (m_BRd == null) {
412: m_BRd = new BufferedReader(new InputStreamReader(
413: System.in));
414: }
415:
416: for (int i = 0; i < 3; ++i) {
417: System.out.print(prompt + ": ");
418: String resp = m_BRd.readLine();
419: if (resp.length() > 0) {
420: return resp;
421: }
422: }
423: } catch (Exception ex) {
424: throw new ParFileException("errorBufferedReader", ex);
425: }
426:
427: throw new ParFileException("errorPromptFailure");
428: }
429:
430: private String stripOpt(String arg, String allowopts)
431: throws ParFileException {
432:
433: // NOTE - NEGATEPFX.startsWith(DOUBLEPFX)
434:
435: if (arg.startsWith(DOUBLEPFX)) {
436: if (arg.equals(DOUBLEPFX)) {
437: return null;
438: }
439:
440: String retpfx = "";
441: int plen = DOUBLEPFX.length();
442: if (arg.startsWith(NEGATEPFX)) {
443: if (arg.equals(NEGATEPFX)) {
444: throw new ParFileException("errorOptNegate");
445: }
446: retpfx = "!";
447: plen = NEGATEPFX.length();
448: }
449:
450: String ochar = arg.substring(plen, plen + 1);
451: String oword = arg.substring(plen);
452: String olookup = (String) m_Short.get(ochar);
453:
454: if (olookup == null || !olookup.equals(oword)) {
455: Object tok[] = { arg };
456: throw new ParFileException("errorUnknownOpt", tok);
457: }
458:
459: if (allowopts.indexOf(ochar) < 0) {
460: Object tok[] = { arg };
461: throw new ParFileException("errorDisallowedOpt", tok);
462: }
463:
464: return retpfx + ochar;
465: }
466:
467: if (arg.startsWith(SINGLEPFX)) {
468: for (int i = 1; i < arg.length(); ++i) {
469: char o = arg.charAt(i);
470: if (allowopts.indexOf(o) < 0) {
471: Object tok[] = { SINGLEPFX + o };
472: throw new ParFileException("errorDisallowedOpt",
473: tok);
474: }
475: }
476: return arg.substring(1);
477: }
478:
479: return null;
480: }
481:
482: private HashMap m_Short = new HashMap();
483:
484: private Vector m_Remaining = new Vector();
485: private boolean m_Modify = false;
486: private boolean m_Verbose = false;
487: private boolean m_Overwrite = false;
488: private boolean m_AutoExtract = false;
489: private boolean m_Debug = false;
490: private boolean m_Login = false;
491: private boolean m_Help = false;
492: private boolean m_Version = false;
493: private String m_ParFile = null;
494: private BufferedReader m_BRd = null;
495: private DPRootSpecifier m_DRoot = null;
496: private String m_User = null;
497: private String m_Pwd = null;
498: private String m_DN = null;
499: private String m_StaticSub = null;
500:
501: private static final String SINGLEPFX = "-";
502: private static final String DOUBLEPFX = "--";
503: private static final String NEGATEPFX = "--no-";
504: }
|