KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > xml > xmlc > commands > options > OptionsParser


1 /*
2  * Enhydra Java Application Server Project
3  *
4  * The contents of this file are subject to the Enhydra Public License
5  * Version 1.1 (the "License"); you may not use this file except in
6  * compliance with the License. You may obtain a copy of the License on
7  * the Enhydra web site ( http://www.enhydra.org/ ).
8  *
9  * Software distributed under the License is distributed on an "AS IS"
10  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
11  * the License for the specific terms governing rights and limitations
12  * under the License.
13  *
14  * The Initial Developer of the Enhydra Application Server is Lutris
15  * Technologies, Inc. The Enhydra Application Server and portions created
16  * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
17  * All Rights Reserved.
18  *
19  * Contributor(s):
20  *
21  * $Id: OptionsParser.java,v 1.2 2005/01/26 08:29:24 jkjome Exp $
22  */

23
24 package org.enhydra.xml.xmlc.commands.options;
25
26 import java.io.IOException JavaDoc;
27
28 import org.enhydra.xml.io.ErrorReporter;
29 import org.enhydra.xml.io.InputSourceOps;
30 import org.enhydra.xml.xmlc.XMLCException;
31 import org.enhydra.xml.xmlc.metadata.MetaData;
32 import org.enhydra.xml.xmlc.metadata.MetaDataDocument;
33 import org.xml.sax.InputSource JavaDoc;
34
35 // FIXME: The integration of metadata is not as smooth as it should be.
36
// probably need to be able to parse multiple metadata files and
37
// then merge them. Also would be nice to not have this handle
38
// metadata at all, doing that with a derived class.
39

40 // FIXME: this whole approach to parsing options seems to be more complex
41
// necessary
42

43 /**
44  * Parse XMLC options, including options files.
45  */

46 public class OptionsParser {
47     /*
48      * Enabled debug tracing.
49      */

50     private static final boolean DEBUG = false;
51
52      /*
53       * Suffix for metadata and options files.
54       */

55     static final private String JavaDoc OPT_FILE_SUFFIX = ".xmlc";
56
57     /*
58      * Command line arguments and index to next argument.
59      */

60     private String JavaDoc[] fCommandArgs;
61     private int fCommandArgIdx;
62
63     /*
64      * Options definition table.
65      */

66     private OptionSet fOptions;
67
68     /*
69      * Used to report errors parsing metadata file.
70      */

71     private ErrorReporter fErrorReporter;
72
73     /*
74      * Ordered list of metadata or options files from cmd line.
75      */

76     private InputSource JavaDoc[] fMetaDataOptionsFiles;
77
78     /**
79      * Track what kind of files we have parsed.
80      */

81     private boolean fParsedMetaData = false;
82     private boolean fParsedOptionsFile = false;
83
84     /**
85      * Metadata object being constructed.
86      */

87     private MetaData fMetaData;
88
89     /**
90      * Positional arguments.
91      */

92     private String JavaDoc[] posArgs;
93
94     /**
95      * Check to see if we are at the end of the command line options.
96      * Will skip the `--' end of line marker.
97      */

98     private boolean endOfCmdOptions() {
99         if (fCommandArgIdx >= fCommandArgs.length) {
100             return true; // No more args
101
}
102         if (fCommandArgs[fCommandArgIdx].equals("--")) {
103             // End of options marker.
104
fCommandArgIdx++;
105             return true;
106         }
107         if (!fCommandArgs[fCommandArgIdx].startsWith("-")) {
108             return true; // No more -options
109
}
110         return false;
111     }
112
113     /**
114      * Generate error for invalid options.
115      */

116     private void invalidOptionError(String JavaDoc name,
117                                     InputSource JavaDoc inputSource) throws XMLCException {
118         StringBuffer JavaDoc msg = new StringBuffer JavaDoc();
119         msg.append("Invalid option \"" + name + "\"");
120         if (inputSource != null) {
121             msg.append(" in " + InputSourceOps.getName(inputSource));
122         }
123         msg.append(", valid options are:\n");
124         msg.append(fOptions.getOptionsMsg());
125         throw new XMLCException(msg.toString());
126     }
127
128     /**
129      * Generate error about mixing metadata and options files.
130      */

131     private void mixedMetaDataOptionsFileError() throws XMLCException {
132         throw new XMLCException("command line specifies both metadata and options files, which is not supported.");
133     }
134
135     /**
136      * Parse a single command line option.
137      */

138     private void parseCmdOption(boolean parseArguments) throws XMLCException {
139         if (DEBUG) {
140             System.err.println("parseCmdOption: " + fCommandArgs[fCommandArgIdx]);
141         }
142         Option option = fOptions.findOption(fCommandArgs[fCommandArgIdx]);
143         if (option == null) {
144             invalidOptionError(fCommandArgs[fCommandArgIdx], null);
145         }
146         fCommandArgIdx++;
147         int numArgs= option.getNumArgs();
148         if (numArgs > (fCommandArgs.length-fCommandArgIdx)) {
149             throw new XMLCException("Insufficient number of arguments for option \""
150                                     + option.getName() + ": " + option.getHelp());
151         }
152         if (parseArguments) {
153             String JavaDoc[] args = new String JavaDoc[numArgs];
154             System.arraycopy(fCommandArgs, fCommandArgIdx, args, 0, numArgs);
155             option.parse(args, fErrorReporter, fMetaData);
156         }
157         fCommandArgIdx += numArgs;
158     }
159
160     /**
161      * Parse options. A preparse can be done to find the positional
162      * arguments or a full parse to get the option arguments. This is
163      * needed to find the positional arguments.
164      */

165     private void parseOptions(boolean parseArguments) throws XMLCException {
166         fCommandArgIdx = 0;
167         while (!endOfCmdOptions()) {
168             parseCmdOption(parseArguments);
169         }
170     }
171
172     /**
173      * Parse an options file line.
174      */

175     private void parseOptionsFileEntry(InputSource JavaDoc inputSource,
176                                        String JavaDoc[] entry)
177             throws XMLCException {
178         Option option = fOptions.findOption(entry[0]);
179         if (option == null) {
180             invalidOptionError(entry[0], inputSource);
181         }
182         int numArgs= option.getNumArgs();
183         if (entry.length-1 != numArgs) {
184             throw new XMLCException("wrong number of arguments for option \""
185                                     + option.getName()
186                                     + " in " + InputSourceOps.getName(inputSource)
187                                     + ": " + option.getHelp());
188         }
189         String JavaDoc[] args = new String JavaDoc[entry.length-1];
190         System.arraycopy(entry, 1, args, 0, entry.length-1);
191         option.parse(args, fErrorReporter, fMetaData);
192     }
193
194     /**
195      * Parse an options file.
196      */

197     private void parseOptionsFile(InputSource JavaDoc inputSource)
198         throws XMLCException {
199
200         if (fParsedMetaData) {
201             mixedMetaDataOptionsFileError();
202         }
203         fParsedOptionsFile = true;
204
205         OptionFileParser parsedOpts = new OptionFileParser(inputSource);
206         String JavaDoc[][] opts = parsedOpts.getOptions();
207
208         for (int idx = 0; idx < opts.length; idx++) {
209             parseOptionsFileEntry(inputSource, opts[idx]);
210         }
211     }
212
213     /**
214      * Parse a metadata file.
215      */

216     private void parseMetaDataFile(InputSource JavaDoc inputSource)
217         throws XMLCException {
218
219         if (fParsedOptionsFile) {
220             mixedMetaDataOptionsFileError();
221         }
222         if (fParsedMetaData) {
223             throw new XMLCException("Multiple XMLC metadata files specified, which is supported; use document with external entity references instead");
224         }
225         fParsedMetaData = true;
226         MetaDataDocument metaDataDoc
227             = MetaDataDocument.parseMetaData(inputSource, fErrorReporter,
228                                              null);
229         fMetaData = metaDataDoc.getMetaData();
230     }
231
232     /**
233      * Parse a metadata or options file.
234      */

235     private void parseMetaDataOptionsFile(InputSource JavaDoc inputSource)
236         throws XMLCException {
237         
238         // Determine if its a metadata file. If it doesn't look like an
239
// XML file, assume its an options file.
240
try {
241             if (InputSourceOps.isXMLDocument(inputSource)) {
242                 parseMetaDataFile(inputSource);
243             } else {
244                 parseOptionsFile(inputSource);
245             }
246         } catch (IOException JavaDoc except) {
247             throw new XMLCException("parse of " + inputSource + " failed",
248                                     except);
249         }
250     }
251
252     /**
253      * Parse metadata or options files.
254      */

255     private void parseMetaDataOptionsFiles()
256         throws XMLCException {
257         // Parse backwards so first one overrides
258
for (int idx = fMetaDataOptionsFiles.length-1; idx >= 0; idx--) {
259             parseMetaDataOptionsFile(fMetaDataOptionsFiles[idx]);
260         }
261     }
262
263     /**
264      * Parse the positional arguments.
265      */

266     private void parsePositionalArgs() throws XMLCException {
267         // Find *.xmlc metadata or options files.
268
int idx;
269         int mdCnt = 0;
270         for (idx = fCommandArgIdx;
271              (idx < fCommandArgs.length) && fCommandArgs[idx].endsWith(OPT_FILE_SUFFIX);
272              idx++) {
273             mdCnt++;
274         }
275         fMetaDataOptionsFiles = new InputSource JavaDoc[mdCnt];
276         idx = 0;
277         while ((fCommandArgIdx < fCommandArgs.length)
278                && fCommandArgs[fCommandArgIdx].endsWith(OPT_FILE_SUFFIX)) {
279             fMetaDataOptionsFiles[idx++] = new InputSource JavaDoc(fCommandArgs[fCommandArgIdx]);
280             fCommandArgIdx++;
281         }
282
283         // Save the remaining positional arguments.
284
int len = fCommandArgs.length-fCommandArgIdx;
285         posArgs = new String JavaDoc[len];
286         System.arraycopy(fCommandArgs, fCommandArgIdx, posArgs, 0, len);
287     }
288
289     /**
290      * Constructor.
291      *
292      * @param optionsSet The set of options to parse, all value are stored in
293      * this object.
294      * @param errorReporter Use to reporrt metadata parse errors.
295      */

296     public OptionsParser(OptionSet options,
297                          ErrorReporter errorReporter) {
298         fOptions = options;
299         fErrorReporter = errorReporter;
300     }
301
302     /**
303      * Parse options.
304      *
305      * @param args The arguments.
306      */

307     public void parse(String JavaDoc[] args) throws XMLCException {
308         fCommandArgs = args;
309         fCommandArgIdx = 0;
310
311         // Must parse once to find the positional arguments.
312
parseOptions(false);
313         parsePositionalArgs();
314
315         // Create metaData object, if not already created.
316
getMetaData(); // creates as side affect
317

318         // Process the option or metadata files.
319
parseMetaDataOptionsFiles();
320  
321         // Parse the command line for real, which will override options files.
322
parseOptions(true);
323         fMetaData.getDocument().completeModifications();
324     }
325
326     /**
327      * Get the parsed options.
328      */

329     public OptionSet getOptions() {
330         return fOptions;
331     }
332
333     /**
334      * Get the metadata object, create if it doesn't exists.
335      */

336     public MetaData getMetaData() {
337         if (fMetaData == null) {
338             fMetaData = MetaDataDocument.newInstance().getMetaData();
339         }
340         return fMetaData;
341     }
342
343     /**
344      * Get the positional arguments. Options files (.xmlc) will
345      * have been removed.
346      */

347     public String JavaDoc[] getPositionalArgs() {
348         return posArgs;
349     }
350 }
351
Popular Tags