001: /* JFox, the OpenSource J2EE Application Server
002: *
003: * Copyright (C) 2002 huihoo.com
004: * Distributable under GNU LGPL license
005: * See the GNU Lesser General Public License for more details.
006: */
007:
008: package org.huihoo.jfox.jmx.loading;
009:
010: import java.util.List;
011: import java.util.ArrayList;
012: import java.util.Iterator;
013: import java.io.InputStream;
014: import java.io.ByteArrayOutputStream;
015: import java.net.URL;
016:
017: import javax.management.ServiceNotFoundException;
018: import javax.management.MBeanException;
019:
020: /**
021: * parse a MLet config url to MLetObject iterator
022: *
023: * @author <a href="mailto:young_yy@hotmail.com">Young Yang</a>
024: */
025:
026: public class MLetParser {
027:
028: private static MLetParser me = new MLetParser();
029:
030: private String content = null;
031:
032: private MLetParser() {
033:
034: }
035:
036: public static MLetParser getInstance() {
037: return me;
038: }
039:
040: // parse the mlet configure file by the url to MLetObject iterator
041: public Iterator parse(URL url) throws ServiceNotFoundException,
042: MBeanException {
043: if (url == null)
044: throw new ServiceNotFoundException(
045: "Cannot load MBeans from null URL");
046: List mlets = new ArrayList();
047: try {
048: this .readContent(url);
049: if (content == null || content.trim().length() == 0)
050: return mlets.iterator();
051: this .stripComments(); // strip comments
052: this .toUpperCase(); // mlet tag to upper case
053: Iterator mletSnippets = this .snipMLets();
054: while (mletSnippets.hasNext()) {
055: String mletSnippet = (String) mletSnippets.next();
056: // System.out.println("call parseMLet");
057: MLetObject mlet = parseMLet(mletSnippet);
058: mlets.add(mlet);
059: }
060: } catch (MLetException e) {
061: throw new MBeanException(e, e.toString());
062: }
063: return mlets.iterator();
064:
065: }
066:
067: // read the content from the given url
068: private void readContent(URL url) throws MLetException {
069: ByteArrayOutputStream baos = new ByteArrayOutputStream();
070: byte[] buff = new byte[1024]; // buffer 1K
071: int bytes = -1;
072: try {
073: InputStream in = url.openStream();
074: while ((bytes = in.read(buff)) > -1) {
075: baos.write(buff, 0, bytes);
076: }
077:
078: content = new String(baos.toByteArray());
079: } catch (Exception e) {
080: throw new MLetException(e.toString());
081: } finally {
082: try {
083: baos.close();
084: } catch (Exception e) {
085: }
086: }
087:
088: }
089:
090: // strip the comment <!-- ... -->
091: private void stripComments() throws MLetException {
092: StringBuffer buffer = new StringBuffer();
093: int tag_start = 0;
094: int pointer = -1; // the current position
095: int tag_end = -1;
096: while ((pointer = nextCommentStart(tag_start)) >= 0) {
097: tag_end = nextCommentEnd(pointer + 1);
098: // not found the right bracket
099: if (tag_end < 0)
100: throw new MLetException(
101: "Parse MLet Error, comment not close");
102:
103: String stripped = content.substring(tag_start, pointer);
104: buffer.append(stripped);
105: tag_start = tag_end + MLetTags.COMMENT_END.length();
106: }
107: buffer.append(content.substring(tag_start));
108: content = buffer.toString();
109: }
110:
111: // convent the MLet Tags to upper case, then reset the content
112: private void toUpperCase() throws MLetException {
113: StringBuffer buffer = new StringBuffer();
114: int start = 0;
115: int current = -1;
116: while ((current = nextQuoteStart(start)) >= 0) {
117: int end = nextQuoteEnd(current + 1);
118:
119: if (end < 0) {
120: throw new MLetException(
121: "Missing closing quote at index: " + current);
122: }
123:
124: String converted = content.substring(start, current)
125: .toUpperCase();
126: buffer.append(converted);
127: String quoted = content.substring(current, end + 1);
128: buffer.append(quoted);
129: start = end + 1;
130: }
131: String converted = content.substring(start, content.length())
132: .toUpperCase();
133: buffer.append(converted);
134: content = buffer.toString();
135: }
136:
137: // devide content to MLet string iterator
138: private Iterator snipMLets() throws MLetException {
139: List list = new ArrayList();
140: int tag_start = 0;
141: int current = 0;
142: int tag_end = -1;
143: while ((current = nextMLetStart(tag_start)) >= 0) {
144: tag_end = nextMLetEnd(current + 1);
145: if (tag_end < 0)
146: throw new MLetException("Missing closing mlet tag");
147: String mlet_snippet = content.substring(current, tag_end);
148: list.add(mlet_snippet);
149: tag_start = tag_end + 1;
150: }
151: return list.iterator();
152: }
153:
154: private MLetObject parseMLet(String mletSnippet)
155: throws MLetException {
156: // System.out.println("call parseMLetAttribute");
157: MLetAttribute[] attrs = parseMLetAttribute(mletSnippet);
158: MLetArgument[] args = parseMLetArgument(mletSnippet);
159: return new MLetObject(attrs, args);
160: }
161:
162: // find the MLet attribute
163: private MLetAttribute[] parseMLetAttribute(String mletSnippet)
164: throws MLetException {
165: int tag_start = 0;
166: int tag_end = nextTag(mletSnippet, MLetTags.CLOSE_BRACKET, 1);
167: String codeSnippet = mletSnippet.substring(tag_start,
168: tag_end + 1);
169: // System.out.println(codeSnippet);
170: MLetAttribute[] attrArray = parseAttributes(codeSnippet);
171:
172: MLetAttribute archiveAttr = null;
173: MLetAttribute codeAttr = null;
174: MLetAttribute objectAttr = null;
175: for (int i = 0; i < attrArray.length; i++) {
176: MLetAttribute attr = attrArray[i];
177: if (attr.getName().equalsIgnoreCase(MLetTags.ARCHIVE_ATTR)) {
178: archiveAttr = attr;
179: } else if (attr.getName().equalsIgnoreCase(
180: MLetTags.CODE_ATTR)) {
181: codeAttr = attr;
182: } else if (attr.getName().equalsIgnoreCase(
183: MLetTags.OBJECT_ATTR)) {
184: objectAttr = attr;
185: }
186: }
187: if (archiveAttr == null)
188: throw new MLetException(
189: "The MLet ARCHIVE attribute must be set");
190: if (codeAttr == null && objectAttr == null)
191: throw new MLetException(
192: "The MLet CODE attribute and OBJECT must be set either");
193: if (codeAttr != null && objectAttr != null)
194: throw new MLetException(
195: "The MLet CODE attribute and OBJECT must onlu be set one");
196: return attrArray;
197: }
198:
199: // parse a MLet snippet <MLet> ... </MLet> , pick up the MLetArguments
200: private MLetArgument[] parseMLetArgument(String mletSnippet)
201: throws MLetException {
202: List args = new ArrayList();
203: int tag_start = 0;
204: int current = -1;
205: int tag_end = -1;
206: while ((current = nextArgStart(mletSnippet, tag_start)) >= 0) {
207: tag_end = nextArgEnd(mletSnippet, current + 1);
208: if (tag_end < 0)
209: throw new MLetException("Missing closing arg tag");
210: String argSnippet = mletSnippet.substring(current,
211: tag_end + 1);
212: MLetArgument arg = constructMLetArgument(argSnippet);
213: args.add(arg);
214: tag_start = current + 1;
215: }
216: return (MLetArgument[]) args.toArray(new MLetArgument[0]);
217: }
218:
219: // pick up the MLetArgument from a <ARG TYPE="***" VALUE="***"> code snippet
220: private MLetArgument constructMLetArgument(String argSnippet)
221: throws MLetException {
222: MLetAttribute[] argAttributes = parseAttributes(argSnippet);
223: // verify the args attribute
224: MLetAttribute typeAttr = null;
225: MLetAttribute valueAttr = null;
226: for (int i = 0; i < argAttributes.length; i++) {
227: MLetAttribute attr = argAttributes[i];
228: if (attr.getName().equalsIgnoreCase(MLetTags.TYPE_ATTR)) {
229: typeAttr = attr;
230: } else if (attr.getName().equalsIgnoreCase(
231: MLetTags.VALUE_ATTR)) {
232: valueAttr = attr;
233: }
234: }
235:
236: if (typeAttr == null || valueAttr == null)
237: throw new MLetException(
238: "MLet ARG must have TYPE and VALUE attribute");
239:
240: return new MLetArgument(typeAttr, valueAttr);
241: }
242:
243: // get attribute from <TAG ATTRIBUTE1="a" ATTRIBUTE2="b">
244: // split by " "
245: private MLetAttribute[] parseAttributes(String codeSnippet)
246: throws MLetException {
247: List attrs = new ArrayList();
248: // trip <TAG
249: int spaceIndex = codeSnippet.indexOf(" ");
250: if (spaceIndex < 0)
251: throw new MLetException("invalid mlet: " + codeSnippet);
252: codeSnippet = codeSnippet.substring(spaceIndex, codeSnippet
253: .length() - 1);
254:
255: int start = 0;
256: int current = -1;
257: String snippet = "";
258: while ((current = nextQuote(codeSnippet, start)) >= 0) { // firset quote index
259: current = nextQuote(codeSnippet, current + 1); // second quote index
260: if (current < 0)
261: throw new MLetException("invalid mlet: " + codeSnippet);
262: snippet = codeSnippet.substring(start, current + 1); // snippet like ATTRIBUTE1="a"
263: start = current + 1;
264: MLetAttribute attr = constructAttribute(snippet);
265: attrs.add(attr);
266: }
267: return (MLetAttribute[]) attrs.toArray(new MLetAttribute[0]);
268: }
269:
270: // construct MLetAttribute from ATTRIBUTE1="a"
271: private MLetAttribute constructAttribute(String codeSnippet)
272: throws MLetException {
273: int equalIndex = codeSnippet.indexOf("=");
274: if (equalIndex < 0)
275: throw new MLetException("invalid attribute");
276: String propName = codeSnippet.substring(0, equalIndex).trim();
277: String propValue = codeSnippet.substring(equalIndex + 1).trim();
278: // trip the "\""
279: if (propValue.startsWith("\"") && propValue.endsWith("\"")) {
280: propValue = propValue.substring(1, propValue.length() - 1);
281: MLetAttribute attr = new MLetAttribute(propName, propValue);
282: return attr;
283: }
284: throw new MLetException("Attribte " + propName
285: + " is invalid format");
286: }
287:
288: private int nextCommentStart(int start) {
289: return content.indexOf(MLetTags.COMMENT_START, start);
290: }
291:
292: private int nextCommentEnd(int start) {
293: return content.indexOf(MLetTags.COMMENT_END, start);
294: }
295:
296: private int nextQuoteStart(int start) {
297: return content.indexOf(MLetTags.QUOTE, start);
298: }
299:
300: private int nextQuoteEnd(int start) {
301: int index = content.indexOf(MLetTags.QUOTE, start);
302: while (index > 1) {
303: if (content.charAt(index - 1) == '\\') { // escape "
304: index = content.indexOf(MLetTags.QUOTE, index);
305: }
306: break;
307: }
308: return index;
309: }
310:
311: private int nextQuote(String snippet, int start) {
312: int index = snippet.indexOf(MLetTags.QUOTE, start);
313: while (index > 1) {
314: if (snippet.charAt(index - 1) == '\\') { // escape "
315: index = snippet.indexOf(MLetTags.QUOTE, index);
316: }
317: break;
318: }
319: return index;
320: }
321:
322: private int nextMLetStart(int start) {
323: return content.indexOf(MLetTags.OPEN_BRACKET
324: + MLetTags.MLET_TAG, start);
325: }
326:
327: private int nextMLetEnd(int start) {
328: return content.indexOf(MLetTags.OPEN_BRACKET + "/"
329: + MLetTags.MLET_TAG + MLetTags.CLOSE_BRACKET, start);
330: }
331:
332: private int nextArgStart(String mletSnippet, int start) {
333: return mletSnippet.indexOf(MLetTags.OPEN_BRACKET
334: + MLetTags.ARG_TAG, start);
335: }
336:
337: private int nextArgEnd(String mletSnippet, int start) {
338: return mletSnippet.indexOf(MLetTags.CLOSE_BRACKET, start);
339: }
340:
341: private int nextTag(String code, String tag, int start) {
342: return code.indexOf(tag, start);
343: }
344:
345: public static void main(String[] args) throws Exception {
346: MLetParser parser = MLetParser.getInstance();
347: Iterator it = parser.parse(new URL("file://d:/jboss.conf"));
348: while (it.hasNext()) {
349: MLetObject mlet = (MLetObject) it.next();
350: System.out.println(mlet.getAttribute("CODE") + ", "
351: + mlet.getAttribute("ARCHIVE"));
352: }
353:
354: System.out.println(System.getProperty("user.dir"));
355: }
356:
357: }
|