KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > mx4j > loading > MLetParser


1 /*
2  * Copyright (C) MX4J.
3  * All rights reserved.
4  *
5  * This software is distributed under the terms of the MX4J License version 1.0.
6  * See the terms of the MX4J License in the documentation provided with this software.
7  */

8
9 package mx4j.loading;
10
11 import java.lang.reflect.Constructor JavaDoc;
12 import java.util.ArrayList JavaDoc;
13 import java.util.List JavaDoc;
14
15 import javax.management.MalformedObjectNameException JavaDoc;
16 import javax.management.ObjectName JavaDoc;
17 import javax.management.loading.MLet JavaDoc;
18
19 /**
20  * The parser for MLet files, as specified in the JMX documentation.
21  * This parser is case insensitive regards to the MLet tags: MLET is equal to mlet and to MLet.
22  * This parser also supports XML-style comments in the file.
23  *
24  * @author <a HREF="mailto:biorn_steedom@users.sourceforge.net">Simone Bordet</a>
25  * @version $Revision: 1.3 $
26  */

27 public class MLetParser
28 {
29    public static final String JavaDoc OPEN_COMMENT = "<!--";
30    public static final String JavaDoc CLOSE_COMMENT = "-->";
31
32    public static final String JavaDoc OPEN_BRACKET = "<";
33    public static final String JavaDoc CLOSE_BRACKET = ">";
34
35    public static final String JavaDoc MLET_TAG = "MLET";
36    public static final String JavaDoc CODE_ATTR = "CODE";
37    public static final String JavaDoc OBJECT_ATTR = "OBJECT";
38    public static final String JavaDoc ARCHIVE_ATTR = "ARCHIVE";
39    public static final String JavaDoc CODEBASE_ATTR = "CODEBASE";
40    public static final String JavaDoc NAME_ATTR = "NAME";
41    public static final String JavaDoc VERSION_ATTR = "VERSION";
42
43    public static final String JavaDoc ARG_TAG = "ARG";
44    public static final String JavaDoc TYPE_ATTR = "TYPE";
45    public static final String JavaDoc VALUE_ATTR = "VALUE";
46
47    private MLet JavaDoc mlet;
48
49    /**
50     * Creates a new MLetParser
51     */

52    public MLetParser()
53    {
54    }
55
56    /**
57     * Creates a new MLetParser
58     * @param mlet The MLet used to resolve classes specified in the ARG tags.
59     */

60    public MLetParser(MLet JavaDoc mlet)
61    {
62       this.mlet = mlet;
63    }
64
65    /**
66     * Parses the given content, that must contains a valid MLet file.
67     *
68     * @param content The content to parse
69     * @return A list of {@link MLetTag}s
70     * @throws MLetParseException If the content is not a valid MLet file
71     */

72    public List JavaDoc parse(String JavaDoc content) throws MLetParseException
73    {
74       if (content == null) throw new MLetParseException("MLet file content cannot be null");
75
76       // Strip comments
77
content = stripComments(content.trim());
78       content = convertToUpperCase(content);
79
80       ArrayList JavaDoc mlets = parseMLets(content);
81       if (mlets.size() < 1) throw new MLetParseException("MLet file is empty");
82
83       ArrayList JavaDoc mletTags = new ArrayList JavaDoc();
84       for (int i = 0; i < mlets.size(); ++i)
85       {
86          String JavaDoc mletTag = (String JavaDoc)mlets.get(i);
87
88          MLetTag tag = parseMLet(mletTag);
89          mletTags.add(tag);
90       }
91
92       return mletTags;
93    }
94
95    private MLetTag parseMLet(String JavaDoc content) throws MLetParseException
96    {
97       MLetTag tag = new MLetTag();
98       parseMLetAttributes(tag, content);
99       parseMLetArguments(tag, content);
100       return tag;
101    }
102
103    private ArrayList JavaDoc parseMLets(String JavaDoc content) throws MLetParseException
104    {
105       ArrayList JavaDoc list = new ArrayList JavaDoc();
106       int start = 0;
107       int current = -1;
108       while ((current = findOpenTag(content, start, MLET_TAG)) >= 0)
109       {
110          int end = findCloseTag(content, current + 1, MLET_TAG, true);
111          if (end < 0) throw new MLetParseException("MLET tag not closed at index: " + current);
112
113          String JavaDoc mlet = content.substring(current, end);
114          list.add(mlet);
115
116          start = end + 1;
117       }
118       return list;
119    }
120
121    private void parseMLetArguments(MLetTag tag, String JavaDoc content) throws MLetParseException
122    {
123       int start = 0;
124       int current = -1;
125       while ((current = findOpenTag(content, start, ARG_TAG)) >= 0)
126       {
127          int end = findCloseTag(content, current + 1, ARG_TAG, false);
128          if (end < 0) throw new MLetParseException("ARG tag not closed");
129
130          String JavaDoc arg = content.substring(current, end);
131
132          int type = arg.indexOf(TYPE_ATTR);
133          if (type < 0) throw new MLetParseException("Missing TYPE attribute");
134
135          int value = arg.indexOf(VALUE_ATTR);
136          if (value < 0) throw new MLetParseException("Missing VALUE attribute");
137
138          String JavaDoc className = findAttributeValue(arg, type, TYPE_ATTR);
139          tag.addArg(className, convertToObject(className, findAttributeValue(arg, value, VALUE_ATTR)));
140
141          start = end + 1;
142       }
143    }
144
145    private void parseMLetAttributes(MLetTag tag, String JavaDoc content) throws MLetParseException
146    {
147       int end = content.indexOf(CLOSE_BRACKET);
148       String JavaDoc attributes = content.substring(0, end);
149
150       // Find mandatory attributes
151
int archive = -1;
152       int object = -1;
153       int code = -1;
154
155       archive = attributes.indexOf(ARCHIVE_ATTR);
156       if (archive < 0) throw new MLetParseException("Missing ARCHIVE attribute");
157
158       code = attributes.indexOf(CODE_ATTR);
159       object = attributes.indexOf(OBJECT_ATTR);
160       if (code < 0 && object < 0) throw new MLetParseException("Missing CODE or OBJECT attribute");
161       if (code > 0 && object > 0) throw new MLetParseException("CODE and OBJECT attributes cannot be both present");
162
163       if (code >= 0)
164          tag.setCode(findAttributeValue(attributes, code, CODE_ATTR));
165       else
166          tag.setObject(findAttributeValue(attributes, object, OBJECT_ATTR));
167
168       tag.setArchive(findAttributeValue(attributes, archive, ARCHIVE_ATTR));
169
170       // Look for optional attributes
171
int codebase = attributes.indexOf(CODEBASE_ATTR);
172       if (codebase >= 0) tag.setCodeBase(findAttributeValue(attributes, codebase, CODEBASE_ATTR));
173
174       int name = attributes.indexOf(NAME_ATTR);
175       if (name >= 0)
176       {
177          String JavaDoc objectName = findAttributeValue(attributes, name, NAME_ATTR);
178          try
179          {
180             tag.setName(new ObjectName JavaDoc(objectName));
181          }
182          catch (MalformedObjectNameException JavaDoc x)
183          {
184             throw new MLetParseException("Invalid ObjectName: " + objectName);
185          }
186       }
187
188       int version = attributes.indexOf(VERSION_ATTR);
189       if (version >= 0) tag.setVersion(findAttributeValue(attributes, version, VERSION_ATTR));
190    }
191
192    private String JavaDoc findAttributeValue(String JavaDoc content, int start, String JavaDoc attribute) throws MLetParseException
193    {
194       int equal = content.indexOf('=', start);
195       if (equal < 0) throw new MLetParseException("Missing '=' for attribute");
196
197       // Ensure no garbage
198
if (!attribute.equals(content.substring(start, equal).trim())) throw new MLetParseException("Invalid attribute");
199
200       int begin = content.indexOf('"', equal + 1);
201       if (begin < 0) throw new MLetParseException("Missing quotes for attribute value");
202
203       // Ensure no garbage
204
if (content.substring(equal + 1, begin).trim().length() != 0) throw new MLetParseException("Invalid attribute value");
205
206       int end = content.indexOf('"', begin + 1);
207       if (end < 0) throw new MLetParseException("Missing quote for attribute value");
208
209       return content.substring(begin + 1, end).trim();
210    }
211
212    private int findOpenTag(String JavaDoc content, int start, String JavaDoc tag)
213    {
214       String JavaDoc opening = new StringBuffer JavaDoc(OPEN_BRACKET).append(tag).toString();
215       return content.indexOf(opening, start);
216    }
217
218    private int findCloseTag(String JavaDoc content, int start, String JavaDoc tag, boolean strictSyntax)
219    {
220       int count = 1;
221
222       do
223       {
224          int close = content.indexOf(CLOSE_BRACKET, start);
225          if (close < 0)
226          {
227             return -1;
228          }
229          int open = content.indexOf(OPEN_BRACKET, start);
230          if (open >= 0 && close > open)
231          {
232             ++count;
233          }
234          else
235          {
236             --count;
237             if (count == 0)
238             {
239                // Either I found the closing bracket of the open tag,
240
// or the closing tag
241
if (!strictSyntax || (strictSyntax && content.charAt(close - 1) == '/'))
242                {
243                   // Found the closing tag
244
return close + 1;
245                }
246                else
247                {
248                   // Found the closing bracket of the open tag, go for the full closing tag
249
String JavaDoc closing = new StringBuffer JavaDoc(OPEN_BRACKET).append("/").append(tag).append(CLOSE_BRACKET).toString();
250                   close = content.indexOf(closing, start);
251                   if (close < 0)
252                      return -1;
253                   else
254                      return close + closing.length();
255                }
256             }
257          }
258
259          start = close + 1;
260       }
261       while (true);
262    }
263
264    private String JavaDoc stripComments(String JavaDoc content) throws MLetParseException
265    {
266       StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
267       int start = 0;
268       int current = -1;
269       while ((current = content.indexOf(OPEN_COMMENT, start)) >= 0)
270       {
271          int end = content.indexOf(CLOSE_COMMENT, current + 1);
272
273          if (end < 0) throw new MLetParseException("Missing close comment tag at index: " + current);
274
275          String JavaDoc stripped = content.substring(start, current);
276          buffer.append(stripped);
277          start = end + CLOSE_COMMENT.length();
278       }
279       String JavaDoc stripped = content.substring(start, content.length());
280       buffer.append(stripped);
281       return buffer.toString();
282    }
283
284    private String JavaDoc convertToUpperCase(String JavaDoc content) throws MLetParseException
285    {
286       StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
287       int start = 0;
288       int current = -1;
289       while ((current = content.indexOf("\"", start)) >= 0)
290       {
291          int end = content.indexOf("\"", current + 1);
292
293          if (end < 0) throw new MLetParseException("Missing closing quote at index: " + current);
294
295          String JavaDoc converted = content.substring(start, current).toUpperCase();
296          buffer.append(converted);
297          String JavaDoc quoted = content.substring(current, end + 1);
298          buffer.append(quoted);
299          start = end + 1;
300       }
301       String JavaDoc converted = content.substring(start, content.length()).toUpperCase();
302       buffer.append(converted);
303       return buffer.toString();
304    }
305
306    private Object JavaDoc convertToObject(String JavaDoc clsName, String JavaDoc value) throws MLetParseException
307    {
308       try
309       {
310          if (clsName.equals("boolean") || clsName.equals("java.lang.Boolean"))
311             return Boolean.valueOf(value);
312          else if (clsName.equals("byte") || clsName.equals("java.lang.Byte"))
313             return Byte.valueOf(value);
314          else if (clsName.equals("char") || clsName.equals("java.lang.Character"))
315          {
316             char ch = 0;
317             if (value.length() > 0) ch = value.charAt(0);
318             return new Character JavaDoc(ch);
319          }
320          else if (clsName.equals("short") || clsName.equals("java.lang.Short"))
321             return Short.valueOf(value);
322          else if (clsName.equals("int") || clsName.equals("java.lang.Integer"))
323             return Integer.valueOf(value);
324          else if (clsName.equals("long") || clsName.equals("java.lang.Long"))
325             return Long.valueOf(value);
326          else if (clsName.equals("float") || clsName.equals("java.lang.Float"))
327             return Float.valueOf(value);
328          else if (clsName.equals("double") || clsName.equals("java.lang.Double"))
329             return Double.valueOf(value);
330          else if (clsName.equals("java.lang.String"))
331             return value;
332          else if (mlet != null)
333          {
334             try
335             {
336                Class JavaDoc cls = mlet.loadClass(clsName);
337                Constructor JavaDoc ctor = cls.getConstructor(new Class JavaDoc[]{String JavaDoc.class});
338                return ctor.newInstance(new Object JavaDoc[]{value});
339             }
340             catch (Exception JavaDoc ignored)
341             {
342             }
343          }
344       }
345       catch (NumberFormatException JavaDoc x)
346       {
347          throw new MLetParseException("Invalid value: " + value);
348       }
349       return null;
350    }
351 }
352
Popular Tags