001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.mx.loading;
023:
024: import java.util.Set;
025: import java.util.HashSet;
026: import java.util.StringTokenizer;
027: import java.util.NoSuchElementException;
028:
029: import java.net.URL;
030: import java.net.MalformedURLException;
031:
032: import java.text.ParseException;
033:
034: import java.io.IOException;
035: import java.io.BufferedReader;
036: import java.io.InputStreamReader;
037:
038: import org.jboss.logging.Logger;
039:
040: /**
041: * Parses an MLet text file confirming to spec format.
042: *
043: * @see javax.management.MLet
044: * @see javax.management.MBeanFileParser
045: *
046: * @author <a href="mailto:juha@jboss.org">Juha Lindfors</a>.
047: * @version $Revision: 57200 $
048: */
049: public class MLetParser implements MBeanFileParser {
050: private static final Logger log = Logger
051: .getLogger(MLetParser.class);
052:
053: // MBeanFileParser implementation --------------------------------
054:
055: /**
056: * Reads an MLet text file from a given URL.
057: *
058: * @param url URL to MLet text file
059: * @return set containing <tt>MBeanElement</tt> objects representing
060: * the parsed MBean entries
061: * @throws ParseException if there was error in reading the MLet text file
062: * @throws MalformedURLException if the <tt>url</tt> argument cannot be used to
063: * construct a valid URL.
064: */
065: public Set parseMBeanFile(String url) throws ParseException,
066: MalformedURLException {
067: return parseMBeanFile(new URL(url));
068: }
069:
070: /**
071: * Reads an MLet text file from a given URL.
072: *
073: * @param url URL to MLet text file
074: * @return set containing <tt>MBeanElement</tt> objects representing the parsed
075: * MBean entries
076: * @throws ParseException if there was an error in reading the MLet text file
077: */
078: public Set parseMBeanFile(URL url) throws ParseException {
079: Set mlets = new HashSet();
080: MBeanElement element = null;
081:
082: try {
083: BufferedReader reader = new BufferedReader(
084: new InputStreamReader(url.openStream()));
085: int c = -1;
086:
087: // read the file
088: while ((c = reader.read()) != -1) {
089: // read and parse one tag at a time
090: if (c == '<') {
091: StringBuffer buf = new StringBuffer(1000);
092: boolean readMore = true;
093:
094: // read the element contents
095: while (readMore) {
096: c = reader.read();
097:
098: if (c == -1)
099: throw new ParseException(
100: "Unexpected end of file. Tag was not closed: "
101: + buf.toString().replace(
102: '\t', ' ').replace(
103: '\n', ' ').replace(
104: '\r', ' ').trim(),
105: 0);
106:
107: if (c == '>') {
108: readMore = false;
109: break;
110: }
111:
112: buf.append((char) c);
113: }
114:
115: // tokenize the element contents
116: StringTokenizer tokenizer = new StringTokenizer(buf
117: .toString(), "= \n\t\r");
118: String tagName = null, attributeName = null, attributeValue = null;
119:
120: // first token is the tag name
121: if (tokenizer.hasMoreTokens())
122: tagName = tokenizer.nextToken().trim();
123:
124: // parse MLET tag
125: if (tagName.equals("MLET")) {
126: element = new MBeanElement();
127:
128: while (tokenizer.hasMoreTokens()) {
129: try {
130: // following tokens are attribute name=value pairs
131: attributeName = tokenizer.nextToken(
132: "= \n\t\r").trim();
133: attributeValue = tokenizer.nextToken(
134: " \n\t\r").trim();
135:
136: if (attributeValue.equals("="))
137: attributeValue = tokenizer
138: .nextToken();
139:
140: // CODE attribute
141: if (attributeName.equals("CODE")) {
142: element.setCode(attributeValue);
143: }
144:
145: // OBJET attribute
146: else if (attributeName.equals("OBJECT"))
147: element.setObject(attributeValue);
148:
149: // ARCHIVE attribute
150: else if (attributeName
151: .equals("ARCHIVE"))
152: // FIXME: according to spec "archivelist" must be in quotes, we don't enforce that
153: element.setArchive(attributeValue);
154:
155: // CODEBASE attribute
156: else if (attributeName
157: .equals("CODEBASE"))
158: element.setCodebase(attributeValue);
159:
160: // NAME attribute
161: else if (attributeName.equals("NAME"))
162: element.setName(attributeValue);
163:
164: // VERSION attribute
165: else if (attributeName
166: .equals("VERSION"))
167: element.setVersion(attributeValue);
168: } catch (NoSuchElementException e) {
169: // couldn't find a valid attribute, value pair
170: // ignore and move to next one
171:
172: log
173: .warn("No value found for attribute '"
174: + attributeName);
175: }
176: }
177:
178: if (element.getCode() == null
179: && element.getObject() == null)
180: throw new ParseException(
181: "<"
182: + buf.toString().replace(
183: '\n', ' ').replace(
184: '\r', ' ').replace(
185: '\t', ' ').trim()
186: + "> is missing mandatory CODE | OBJECT attribute",
187: 0);
188: if (element.getArchives().size() == 0)
189: throw new ParseException(
190: "<"
191: + buf.toString().replace(
192: '\n', ' ').replace(
193: '\r', ' ').replace(
194: '\t', ' ').trim()
195: + "> is missing mandatory ARCHIVE attribute",
196: 0);
197: }
198:
199: // parse </MLET> tag
200: else if (tagName.equals("/MLET")) {
201: mlets.add(element);
202: element = null;
203: }
204:
205: // parse <ARG> tag
206: else if (tagName.equals("ARG")) {
207: try {
208: // if second token is not TYPE then skip the attribute
209: if (!tokenizer.nextToken().equals("TYPE"))
210: continue;
211:
212: String type = tokenizer.nextToken();
213:
214: // if fourth token is not VALUE then skip the attribute
215: if (!tokenizer.nextToken().equals("VALUE"))
216: continue;
217:
218: String value = tokenizer
219: .nextToken(" \n\t\r");
220:
221: // element is non-null if we're within <MLET> </MLET> tags
222: if (element != null)
223: element.addArg(type, value);
224: } catch (NoSuchElementException e) {
225: // malformed ARG tag means the MBean can't be instantiated
226: element = null;
227:
228: log.warn("Malformed element: <"
229: + buf.toString() + ">");
230: }
231: }
232: } // end of if (c == '<')
233: } // while((c = reader.read()) != -1)
234:
235: // get rid of any null elements
236: mlets.remove(null);
237: return mlets;
238: } catch (IOException e) {
239: throw new ParseException(e.toString(), 0);
240: }
241: }
242:
243: }
|