001: package org.objectweb.celtix.tools.common.toolspec.parser;
002:
003: import java.io.ByteArrayOutputStream;
004: import java.io.InputStream;
005: import java.io.PrintStream;
006: import java.util.ArrayList;
007: import java.util.List;
008: import java.util.StringTokenizer;
009: import java.util.logging.Level;
010: import java.util.logging.Logger;
011:
012: import javax.xml.parsers.DocumentBuilderFactory;
013: import javax.xml.transform.Transformer;
014: import javax.xml.transform.TransformerException;
015: import javax.xml.transform.TransformerFactory;
016: import javax.xml.transform.dom.DOMSource;
017: import javax.xml.transform.stream.StreamResult;
018: import javax.xml.transform.stream.StreamSource;
019:
020: import org.w3c.dom.Document;
021: import org.w3c.dom.Element;
022: import org.w3c.dom.NodeList;
023:
024: import org.objectweb.celtix.common.logging.LogUtils;
025: import org.objectweb.celtix.tools.common.toolspec.Tool;
026: import org.objectweb.celtix.tools.common.toolspec.ToolSpec;
027:
028: public class CommandLineParser {
029:
030: private static final Logger LOG = LogUtils
031: .getL7dLogger(CommandLineParser.class);
032: private ToolSpec toolspec;
033:
034: public CommandLineParser(ToolSpec ts) {
035: this .toolspec = ts;
036: }
037:
038: public void setToolSpec(ToolSpec ts) {
039: this .toolspec = ts;
040: }
041:
042: public static String[] getArgsFromString(String s) {
043: StringTokenizer toker = new StringTokenizer(s);
044: List<Object> res = new ArrayList<Object>();
045:
046: while (toker.hasMoreTokens()) {
047: res.add(toker.nextToken());
048: }
049: return res.toArray(new String[res.size()]);
050: }
051:
052: public CommandDocument parseArguments(String args)
053: throws BadUsageException {
054: return parseArguments(getArgsFromString(args));
055: }
056:
057: public CommandDocument parseArguments(String[] args)
058: throws BadUsageException {
059:
060: if (LOG.isLoggable(Level.INFO)) {
061: StringBuffer debugMsg = new StringBuffer(
062: "Parsing arguments: ");
063:
064: for (int i = 0; i < args.length; i++) {
065: debugMsg.append(args[i]).append(" ");
066: }
067: LOG.info(debugMsg.toString());
068: }
069:
070: if (toolspec == null) {
071: throw new IllegalStateException(
072: "No schema known- call to acceptSc"
073: + "hema() must be made and must succeed");
074: }
075:
076: // Create a result document
077:
078: Document resultDoc = null;
079:
080: try {
081: resultDoc = DocumentBuilderFactory.newInstance()
082: .newDocumentBuilder().newDocument();
083: } catch (Exception ex) {
084: LOG.log(Level.SEVERE, "FAIL_CREATE_DOM_MSG");
085: }
086: Element commandEl = resultDoc.createElementNS(
087: "http://www.xsume.com/Xutil/Command", "command");
088:
089: // resultDoc.createAttributeNS("http://www.w3.org/2001/XMLSchema-instance","schemaLocation");
090: commandEl.setAttributeNS(
091: "http://www.w3.org/2001/XMLSchema-instance",
092: "xsi:schemaLocation",
093: "http://www.xsume.com/Xutil/Command http://www.xsume.com/schema/xutil/c"
094: + "ommand.xsd");
095: commandEl.setAttribute("xmlns",
096: "http://www.xsume.com/Xutil/Command");
097: commandEl.setAttribute("xmlns:xsi",
098: "http://www.w3.org/2001/XMLSchema-instance");
099: resultDoc.appendChild(commandEl);
100:
101: TokenInputStream tokens = new TokenInputStream(args);
102:
103: // for all form elements...
104: Element usage = toolspec.getUsage();
105:
106: NodeList usageForms = toolspec.getUsageForms();
107: if (LOG.isLoggable(Level.INFO)) {
108: LOG
109: .info("Found "
110: + usageForms.getLength()
111: + " alternative forms of usage, will use default form");
112: }
113: if (usageForms.getLength() > 0) {
114: ErrorVisitor errors = new ErrorVisitor();
115:
116: for (int i = 0; i < usageForms.getLength(); i++) {
117: Form form = new Form((Element) usageForms.item(i));
118:
119: int pos = tokens.getPosition();
120:
121: if (form.accept(tokens, commandEl, errors)) {
122: commandEl.setAttribute("form", form.getName());
123: break;
124: } else {
125: // if no more left then return null;
126: tokens.setPosition(pos);
127: if (i == usageForms.getLength() - 1) {
128: if (LOG.isLoggable(Level.INFO)) {
129: LOG
130: .info("No more forms left to try, returning null");
131: }
132: throwUsage(errors);
133: }
134: }
135: }
136: } else {
137: ErrorVisitor errors = new ErrorVisitor();
138: Form form = new Form(usage);
139:
140: if (!form.accept(tokens, commandEl, errors)) {
141: throwUsage(errors);
142: }
143: }
144:
145: // output the result document
146: if (LOG.isLoggable(Level.FINE)) {
147: try {
148: Transformer serializer = TransformerFactory
149: .newInstance()
150: .newTransformer(
151: new StreamSource(
152: Tool.class
153: .getResourceAsStream("indent-no-xml-declaration.xsl")));
154:
155: serializer.transform(new DOMSource(resultDoc),
156: new StreamResult(new PrintStream(System.out)));
157: } catch (Exception ex) {
158: LOG
159: .log(Level.SEVERE,
160: "ERROR_SERIALIZE_COMMAND_MSG", ex);
161: }
162: }
163:
164: return new CommandDocument(toolspec, resultDoc);
165: }
166:
167: public void throwUsage(ErrorVisitor errors)
168: throws BadUsageException {
169: try {
170: throw new BadUsageException(getUsage(), errors);
171: } catch (TransformerException ex) {
172: LOG.log(Level.SEVERE, "CANNOT_GET_USAGE_MSG", ex);
173: throw new BadUsageException(errors);
174: }
175: }
176:
177: public String getUsage() throws TransformerException {
178: // REVISIT: style usage document into a form more readily output as a
179: // usage message
180: ByteArrayOutputStream baos = new ByteArrayOutputStream();
181: InputStream in = getClass().getResourceAsStream("usage.xsl");
182:
183: toolspec.transform(in, baos);
184: return baos.toString();
185: }
186:
187: public String getDetailedUsage() throws TransformerException {
188: // REVISIT: style usage document into a form more readily output as a
189: // usage message
190: ByteArrayOutputStream baos = new ByteArrayOutputStream();
191:
192: toolspec.transform(getClass().getResourceAsStream(
193: "detailedUsage.xsl"), baos);
194: return baos.toString();
195: }
196:
197: public String getDetailedUsage(String id) {
198: String result = null;
199: Element element = toolspec.getElementById(id);
200: NodeList annotations = element.getElementsByTagNameNS(
201: Tool.TOOL_SPEC_PUBLIC_ID, "annotation");
202: if ((annotations != null) && (annotations.getLength() > 0)) {
203: result = annotations.item(0).getFirstChild().getNodeValue();
204: }
205: return result;
206: }
207:
208: public String getToolUsage() {
209: return toolspec.getAnnotation();
210: }
211:
212: }
|