1 23 24 package org.enhydra.xml.xmlc.commands.options; 25 26 import java.io.IOException ; 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 ; 34 35 40 43 46 public class OptionsParser { 47 50 private static final boolean DEBUG = false; 51 52 55 static final private String OPT_FILE_SUFFIX = ".xmlc"; 56 57 60 private String [] fCommandArgs; 61 private int fCommandArgIdx; 62 63 66 private OptionSet fOptions; 67 68 71 private ErrorReporter fErrorReporter; 72 73 76 private InputSource [] fMetaDataOptionsFiles; 77 78 81 private boolean fParsedMetaData = false; 82 private boolean fParsedOptionsFile = false; 83 84 87 private MetaData fMetaData; 88 89 92 private String [] posArgs; 93 94 98 private boolean endOfCmdOptions() { 99 if (fCommandArgIdx >= fCommandArgs.length) { 100 return true; } 102 if (fCommandArgs[fCommandArgIdx].equals("--")) { 103 fCommandArgIdx++; 105 return true; 106 } 107 if (!fCommandArgs[fCommandArgIdx].startsWith("-")) { 108 return true; } 110 return false; 111 } 112 113 116 private void invalidOptionError(String name, 117 InputSource inputSource) throws XMLCException { 118 StringBuffer msg = new StringBuffer (); 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 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 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 [] args = new String [numArgs]; 154 System.arraycopy(fCommandArgs, fCommandArgIdx, args, 0, numArgs); 155 option.parse(args, fErrorReporter, fMetaData); 156 } 157 fCommandArgIdx += numArgs; 158 } 159 160 165 private void parseOptions(boolean parseArguments) throws XMLCException { 166 fCommandArgIdx = 0; 167 while (!endOfCmdOptions()) { 168 parseCmdOption(parseArguments); 169 } 170 } 171 172 175 private void parseOptionsFileEntry(InputSource inputSource, 176 String [] 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 [] args = new String [entry.length-1]; 190 System.arraycopy(entry, 1, args, 0, entry.length-1); 191 option.parse(args, fErrorReporter, fMetaData); 192 } 193 194 197 private void parseOptionsFile(InputSource inputSource) 198 throws XMLCException { 199 200 if (fParsedMetaData) { 201 mixedMetaDataOptionsFileError(); 202 } 203 fParsedOptionsFile = true; 204 205 OptionFileParser parsedOpts = new OptionFileParser(inputSource); 206 String [][] opts = parsedOpts.getOptions(); 207 208 for (int idx = 0; idx < opts.length; idx++) { 209 parseOptionsFileEntry(inputSource, opts[idx]); 210 } 211 } 212 213 216 private void parseMetaDataFile(InputSource 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 235 private void parseMetaDataOptionsFile(InputSource inputSource) 236 throws XMLCException { 237 238 try { 241 if (InputSourceOps.isXMLDocument(inputSource)) { 242 parseMetaDataFile(inputSource); 243 } else { 244 parseOptionsFile(inputSource); 245 } 246 } catch (IOException except) { 247 throw new XMLCException("parse of " + inputSource + " failed", 248 except); 249 } 250 } 251 252 255 private void parseMetaDataOptionsFiles() 256 throws XMLCException { 257 for (int idx = fMetaDataOptionsFiles.length-1; idx >= 0; idx--) { 259 parseMetaDataOptionsFile(fMetaDataOptionsFiles[idx]); 260 } 261 } 262 263 266 private void parsePositionalArgs() throws XMLCException { 267 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 [mdCnt]; 276 idx = 0; 277 while ((fCommandArgIdx < fCommandArgs.length) 278 && fCommandArgs[fCommandArgIdx].endsWith(OPT_FILE_SUFFIX)) { 279 fMetaDataOptionsFiles[idx++] = new InputSource (fCommandArgs[fCommandArgIdx]); 280 fCommandArgIdx++; 281 } 282 283 int len = fCommandArgs.length-fCommandArgIdx; 285 posArgs = new String [len]; 286 System.arraycopy(fCommandArgs, fCommandArgIdx, posArgs, 0, len); 287 } 288 289 296 public OptionsParser(OptionSet options, 297 ErrorReporter errorReporter) { 298 fOptions = options; 299 fErrorReporter = errorReporter; 300 } 301 302 307 public void parse(String [] args) throws XMLCException { 308 fCommandArgs = args; 309 fCommandArgIdx = 0; 310 311 parseOptions(false); 313 parsePositionalArgs(); 314 315 getMetaData(); 318 parseMetaDataOptionsFiles(); 320 321 parseOptions(true); 323 fMetaData.getDocument().completeModifications(); 324 } 325 326 329 public OptionSet getOptions() { 330 return fOptions; 331 } 332 333 336 public MetaData getMetaData() { 337 if (fMetaData == null) { 338 fMetaData = MetaDataDocument.newInstance().getMetaData(); 339 } 340 return fMetaData; 341 } 342 343 347 public String [] getPositionalArgs() { 348 return posArgs; 349 } 350 } 351 | Popular Tags |