1. /*
  2. * @(#)MLetParser.java 1.26 04/04/16
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.management.loading;
  8. // java import
  9. import java.net.URL;
  10. import java.net.URLConnection;
  11. import java.net.MalformedURLException;
  12. import java.io.Reader;
  13. import java.io.IOException;
  14. import java.io.BufferedReader;
  15. import java.io.InputStreamReader;
  16. import java.io.File;
  17. import java.util.Hashtable;
  18. import java.util.Vector;
  19. import com.sun.jmx.trace.Trace;
  20. /**
  21. * This class is used for parsing URLs.
  22. *
  23. * @since 1.5
  24. */
  25. class MLetParser {
  26. /*
  27. * ------------------------------------------
  28. * PRIVATE VARIABLES
  29. * ------------------------------------------
  30. */
  31. /**
  32. * The current character
  33. */
  34. private int c;
  35. /**
  36. * Tag to parse.
  37. */
  38. private static String tag = "mlet";
  39. /**
  40. * The name of this class to be used for trace messages
  41. */
  42. private String dbgTag = "MLetParser";
  43. /*
  44. * ------------------------------------------
  45. * CONSTRUCTORS
  46. * ------------------------------------------
  47. */
  48. /**
  49. * Create an MLet parser object
  50. */
  51. public MLetParser() {
  52. }
  53. /*
  54. * ------------------------------------------
  55. * PUBLIC METHODS
  56. * ------------------------------------------
  57. */
  58. /**
  59. * Scan spaces.
  60. */
  61. public void skipSpace(Reader in) throws IOException {
  62. while ((c >= 0) && ((c == ' ') || (c == '\t') || (c == '\n') || (c == '\r'))) {
  63. c = in.read();
  64. }
  65. }
  66. /**
  67. * Scan identifier
  68. */
  69. public String scanIdentifier(Reader in) throws IOException {
  70. StringBuffer buf = new StringBuffer();
  71. while (true) {
  72. if (((c >= 'a') && (c <= 'z')) ||
  73. ((c >= 'A') && (c <= 'Z')) ||
  74. ((c >= '0') && (c <= '9')) || (c == '_')) {
  75. buf.append((char)c);
  76. c = in.read();
  77. } else {
  78. return buf.toString();
  79. }
  80. }
  81. }
  82. /**
  83. * Scan tag
  84. */
  85. public Hashtable scanTag(Reader in) throws IOException {
  86. Hashtable atts = new Hashtable();
  87. skipSpace(in);
  88. while (c >= 0 && c != '>') {
  89. String att = scanIdentifier(in);
  90. String val = "";
  91. skipSpace(in);
  92. if (c == '=') {
  93. int quote = -1;
  94. c = in.read();
  95. skipSpace(in);
  96. if ((c == '\'') || (c == '\"')) {
  97. quote = c;
  98. c = in.read();
  99. }
  100. StringBuffer buf = new StringBuffer();
  101. while ((c > 0) &&
  102. (((quote < 0) && (c != ' ') && (c != '\t') &&
  103. (c != '\n') && (c != '\r') && (c != '>'))
  104. || ((quote >= 0) && (c != quote)))) {
  105. buf.append((char)c);
  106. c = in.read();
  107. }
  108. if (c == quote) {
  109. c = in.read();
  110. }
  111. skipSpace(in);
  112. val = buf.toString();
  113. }
  114. atts.put(att.toLowerCase(), val);
  115. skipSpace(in);
  116. }
  117. return atts;
  118. }
  119. /**
  120. * Scan an html file for <mlet> tags
  121. */
  122. public Vector parse(URL url) throws IOException {
  123. String mth = "parse";
  124. // Warning Messages
  125. String requiresNameWarning = "<param name=... value=...> tag requires name parameter.";
  126. String paramOutsideWarning = "<param> tag outside <mlet> ... </mlet>.";
  127. String requiresCodeWarning = "<mlet> tag requires either code or object parameter.";
  128. String requiresJarsWarning = "<mlet> tag requires archive parameter.";
  129. URLConnection conn;
  130. conn = url.openConnection();
  131. Reader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
  132. // The original URL may have been redirected - this
  133. // sets it to whatever URL/codebase we ended up getting
  134. //
  135. url = conn.getURL();
  136. Vector mlets = new Vector();
  137. Hashtable atts = null;
  138. Vector types = new Vector();
  139. Vector values = new Vector();
  140. // debug("parse","*** Parsing " + url );
  141. while(true) {
  142. c = in.read();
  143. if (c == -1)
  144. break;
  145. if (c == '<') {
  146. c = in.read();
  147. if (c == '/') {
  148. c = in.read();
  149. String nm = scanIdentifier(in);
  150. if (nm.equalsIgnoreCase(tag)) {
  151. if (atts != null) {
  152. // Constructor parameters
  153. if ((types.size() == values.size()) && ((!types.isEmpty()) && (!values.isEmpty()))) {
  154. atts.put("types", types.clone());
  155. atts.put("values", values.clone());
  156. }
  157. mlets.addElement(new MLetContent(url, atts));
  158. }
  159. atts = null;
  160. types.removeAllElements();
  161. values.removeAllElements();
  162. }
  163. } else {
  164. String nm = scanIdentifier(in);
  165. if (nm.equalsIgnoreCase("arg")) {
  166. Hashtable t = scanTag(in);
  167. String att = (String) t.get("type");
  168. if (att == null) {
  169. if (isTraceOn()) {
  170. trace(mth, requiresNameWarning);
  171. }
  172. throw new IOException(requiresNameWarning);
  173. } else {
  174. if (atts != null) {
  175. types.addElement(att);
  176. } else {
  177. if (isTraceOn()) {
  178. trace(mth, paramOutsideWarning);
  179. }
  180. throw new IOException(paramOutsideWarning);
  181. }
  182. }
  183. String val = (String) t.get("value");
  184. if (val == null) {
  185. if (isTraceOn()) {
  186. trace(mth, requiresNameWarning);
  187. }
  188. throw new IOException(requiresNameWarning);
  189. } else {
  190. if (atts != null) {
  191. values.addElement(val);
  192. } else {
  193. if (isTraceOn()) {
  194. trace(mth, paramOutsideWarning);
  195. }
  196. throw new IOException(paramOutsideWarning);
  197. }
  198. }
  199. }
  200. else {
  201. if (nm.equalsIgnoreCase(tag)) {
  202. atts = scanTag(in);
  203. if (atts.get("code") == null && atts.get("object") == null) {
  204. if (isTraceOn()) {
  205. trace(mth, requiresCodeWarning);
  206. }
  207. atts = null;
  208. throw new IOException(requiresCodeWarning);
  209. }
  210. if (atts.get("archive") == null) {
  211. if (isTraceOn()) {
  212. trace(mth, requiresJarsWarning);
  213. }
  214. atts = null;
  215. throw new IOException(requiresJarsWarning);
  216. }
  217. }
  218. }
  219. }
  220. }
  221. }
  222. in.close();
  223. return mlets;
  224. }
  225. /**
  226. * Parse the document pointed by the URL urlname
  227. */
  228. public Vector parseURL(String urlname) throws IOException {
  229. // Parse the document
  230. //
  231. URL url = null;
  232. if (urlname.indexOf(':') <= 1) {
  233. String userDir = System.getProperty("user.dir");
  234. String prot;
  235. if (userDir.charAt(0) == '/' ||
  236. userDir.charAt(0) == File.separatorChar) {
  237. prot = "file:";
  238. } else {
  239. prot = "file:/";
  240. }
  241. url =
  242. new URL(prot + userDir.replace(File.separatorChar, '/') + "/");
  243. url = new URL(url, urlname);
  244. } else {
  245. url = new URL(urlname);
  246. }
  247. // Return list of parsed MLets
  248. //
  249. return parse(url);
  250. }
  251. /*
  252. * ------------------------------------------
  253. * PRIVATE METHODS
  254. * ------------------------------------------
  255. */
  256. // TRACES & DEBUG
  257. //---------------
  258. private boolean isTraceOn() {
  259. return Trace.isSelected(Trace.LEVEL_TRACE, Trace.INFO_MLET);
  260. }
  261. private void trace(String clz, String func, String info) {
  262. Trace.send(Trace.LEVEL_TRACE, Trace.INFO_MLET, clz, func, info);
  263. }
  264. private void trace(String func, String info) {
  265. trace(dbgTag, func, info);
  266. }
  267. private boolean isDebugOn() {
  268. return Trace.isSelected(Trace.LEVEL_DEBUG, Trace.INFO_MLET);
  269. }
  270. private void debug(String clz, String func, String info) {
  271. Trace.send(Trace.LEVEL_DEBUG, Trace.INFO_MLET, clz, func, info);
  272. }
  273. private void debug(String func, String info) {
  274. debug(dbgTag, func, info);
  275. }
  276. }