All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.aspectj.weaver.loadtime.definition.LightXMLParser Maven / Gradle / Ivy

Go to download

AspectJ tools most notably contains the AspectJ compiler (AJC). AJC applies aspects to Java classes during compilation, fully replacing Javac for plain Java classes and also compiling native AspectJ or annotation-based @AspectJ syntax. Furthermore, AJC can weave aspects into existing class files in a post-compile binary weaving step. This library is a superset of AspectJ weaver and hence also of AspectJ runtime.

There is a newer version: 1.9.22.1
Show newest version
/*******************************************************************************
 * Copyright (c) 2011 Contributors.
 * All rights reserved.
 * This program and the accompanying materials are made available
 * under the terms of the Eclipse Public License v 2.0
 * which accompanies this distribution and is available at
 * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
 *
 * Contributors:
 *   Abraham Nevado - Lucierna	initial implementation
 *******************************************************************************/
package org.aspectj.weaver.loadtime.definition;

import java.io.Reader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

public class LightXMLParser {

	private final static char NULL_CHAR = '\0';
	private Map attributes;
	private ArrayList children;
	private String name;
	private char pushedBackChar;
	private Reader reader;

	private static Map entities = new HashMap<>();

	static {
		entities.put("amp", new char[] { '&' });
		entities.put("quot", new char[] { '"' });
		entities.put("apos", new char[] { '\'' });
		entities.put("lt", new char[] { '<' });
		entities.put("gt", new char[] { '>' });
	}

	public LightXMLParser() {
		this.name = null;
		this.attributes = new HashMap<>();
		this.children = new ArrayList<>();
	}

	public ArrayList getChildrens() {
		return this.children;
	}

	public String getName() {
		return this.name;
	}

	public void parseFromReader(Reader reader) throws Exception {
		this.pushedBackChar = NULL_CHAR;
		this.attributes = new HashMap<>();
		this.name = null;
		this.children = new ArrayList<>();
		this.reader = reader;

		while (true) {
			// Skips whiteSpaces, blanks, \r\n..
			char c = this.skipBlanks();

			// All xml should start by  'z')) && ((c > 'Z') || (c < 'A')) && ((c > '9') || (c < '0')) && (c != '_') && (c != '-')
					&& (c != '.') && (c != ':')) {
				this.pushBackChar(c);
				return;
			}
			result.append(c);
		}
	}

	private void getString(StringBuffer string) throws Exception {
		char delimiter = this.getNextChar();
		if ((delimiter != '\'') && (delimiter != '"')) {
			throw new Exception("Parsing error. Expected ' or \"  but got: " + delimiter);

		}

		while (true) {
			char c = this.getNextChar();
			if (c == delimiter) {
				return;
			} else if (c == '&') {
				this.mapEntity(string);
			} else {
				string.append(c);
			}
		}
	}

	private void getPCData(StringBuffer data) throws Exception {
		while (true) {
			char c = this.getNextChar();
			if (c == '<') {
				c = this.getNextChar();
				if (c == '!') {
					this.checkCDATA(data);
				} else {
					this.pushBackChar(c);
					return;
				}
			} else {
				data.append(c);
			}
		}
	}

	private boolean checkCDATA(StringBuffer buf) throws Exception {
		char c = this.getNextChar();
		if (c != '[') {
			this.pushBackChar(c);
			this.skipCommentOrXmlTag(0);
			return false;
		} else if (!this.checkLiteral("CDATA[")) {
			this.skipCommentOrXmlTag(1); // one [ has already been read
			return false;
		} else {
			int delimiterCharsSkipped = 0;
			while (delimiterCharsSkipped < 3) {
				c = this.getNextChar();
				switch (c) {
				case ']':
					if (delimiterCharsSkipped < 2) {
						delimiterCharsSkipped++;
					} else {
						buf.append(']');
						buf.append(']');
						delimiterCharsSkipped = 0;
					}
					break;
				case '>':
					if (delimiterCharsSkipped < 2) {
						for (int i = 0; i < delimiterCharsSkipped; i++) {
							buf.append(']');
						}
						delimiterCharsSkipped = 0;
						buf.append('>');
					} else {
						delimiterCharsSkipped = 3;
					}
					break;
				default:
					for (int i = 0; i < delimiterCharsSkipped; i++) {
						buf.append(']');
					}
					buf.append(c);
					delimiterCharsSkipped = 0;
				}
			}
			return true;
		}
	}

	private void skipCommentOrXmlTag(int bracketLevel) throws Exception {
		char delim = NULL_CHAR;
		int level = 1;
		char c;
		if (bracketLevel == 0) {
			c = this.getNextChar();
			if (c == '-') {
				c = this.getNextChar();
				if (c == ']') {
					bracketLevel--;
				} else if (c == '[') {
					bracketLevel++;
				} else if (c == '-') {
					this.skipComment();
					return;
				}
			} else if (c == '[') {
				bracketLevel++;
			}
		}
		while (level > 0) {
			c = this.getNextChar();
			if (delim == NULL_CHAR) {
				if ((c == '"') || (c == '\'')) {
					delim = c;
				} else if (bracketLevel <= 0) {
					if (c == '<') {
						level++;
					} else if (c == '>') {
						level--;
					}
				}
				if (c == '[') {
					bracketLevel++;
				} else if (c == ']') {
					bracketLevel--;
				}
			} else {
				if (c == delim) {
					delim = NULL_CHAR;
				}
			}
		}
	}

	private void parseNode(LightXMLParser elt) throws Exception {
		// Now we are in a new node element. Get its name
		StringBuffer buf = new StringBuffer();
		this.getNodeName(buf);
		String name = buf.toString();
		elt.setName(name);

		char c = this.skipBlanks();
		while ((c != '>') && (c != '/')) {
			// Get attributes
			emptyBuf(buf);
			this.pushBackChar(c);
			this.getNodeName(buf);
			String key = buf.toString();
			c = this.skipBlanks();
			if (c != '=') {
				throw new Exception("Parsing error. Expected = but got: " + c);
			}
			// Go up to " character and push it back
			this.pushBackChar(this.skipBlanks());

			emptyBuf(buf);
			this.getString(buf);

			elt.setAttribute(key, buf);

			// Skip blanks
			c = this.skipBlanks();
		}
		if (c == '/') {
			c = this.getNextChar();
			if (c != '>') {
				throw new Exception("Parsing error. Expected > but got: " + c);
			}
			return;
		}

		// Now see if we got content, or CDATA, if content get it: it is free...
		emptyBuf(buf);
		c = this.getWhitespaces(buf);
		if (c != '<') {
			// It is PCDATA
			this.pushBackChar(c);
			this.getPCData(buf);
		} else {
			// It is content: get it, or CDATA.
			while (true) {
				c = this.getNextChar();
				if (c == '!') {
					if (this.checkCDATA(buf)) {
						this.getPCData(buf);
						break;
					} else {
						c = this.getWhitespaces(buf);
						if (c != '<') {
							this.pushBackChar(c);
							this.getPCData(buf);
							break;
						}
					}
				} else {
					if (c != '/') {
						emptyBuf(buf);
					}
					if (c == '/') {
						this.pushBackChar(c);
					}
					break;
				}
			}
		}
		if (buf.length() == 0) {
			// It is a comment
			while (c != '/') {
				if (c == '!') {
					for (int i = 0; i < 2; i++) {
						c = this.getNextChar();
						if (c != '-') {
							throw new Exception("Parsing error. Expected element or comment");
						}
					}
					this.skipComment();
				} else {
					// it is a new node
					this.pushBackChar(c);
					LightXMLParser child = this.createAnotherElement();
					this.parseNode(child);
					elt.addChild(child);
				}
				c = this.skipBlanks();
				if (c != '<') {
					throw new Exception("Parsing error. Expected <, but got: " + c);
				}
				c = this.getNextChar();
			}
			this.pushBackChar(c);
		} // Here content could be grabbed

		c = this.getNextChar();
		if (c != '/') {
			throw new Exception("Parsing error. Expected /, but got: " + c);
		}
		this.pushBackChar(this.skipBlanks());
		if (!this.checkLiteral(name)) {
			throw new Exception("Parsing error. Expected " + name);
		}
		if (this.skipBlanks() != '>') {
			throw new Exception("Parsing error. Expected >, but got: " + c);
		}
	}

	private void skipComment() throws Exception {
		int dashes = 2;
		while (dashes > 0) {
			char ch = this.getNextChar();
			if (ch == '-') {
				dashes -= 1;
			} else {
				dashes = 2;
			}
		}

		char nextChar = this.getNextChar();
		if (nextChar != '>') {
			throw new Exception("Parsing error. Expected > but got: " + nextChar);
		}
	}

	private boolean checkLiteral(String literal) throws Exception {
		int length = literal.length();
		for (int i = 0; i < length; i++) {
			if (this.getNextChar() != literal.charAt(i)) {
				return false;
			}
		}
		return true;
	}

	private char getNextChar() throws Exception {
		if (this.pushedBackChar != NULL_CHAR) {
			char c = this.pushedBackChar;
			this.pushedBackChar = NULL_CHAR;
			return c;
		} else {
			int i = this.reader.read();
			if (i < 0) {
				throw new Exception("Parsing error. Unexpected end of data");
			} else {
				return (char) i;
			}
		}
	}

	private void mapEntity(StringBuffer buf) throws Exception {
		char c = this.NULL_CHAR;
		StringBuilder keyBuf = new StringBuilder();
		while (true) {
			c = this.getNextChar();
			if (c == ';') {
				break;
			}
			keyBuf.append(c);
		}
		String key = keyBuf.toString();
		if (key.charAt(0) == '#') {
			try {
				if (key.charAt(1) == 'x') {
					c = (char) Integer.parseInt(key.substring(2), 16);
				} else {
					c = (char) Integer.parseInt(key.substring(1), 10);
				}
			} catch (NumberFormatException e) {
				throw new Exception("Unknown entity: " + key);
			}
			buf.append(c);
		} else {
			char[] value = entities.get(key);
			if (value == null) {
				throw new Exception("Unknown entity: " + key);
			}
			buf.append(value);
		}
	}

	private void pushBackChar(char c) {
		this.pushedBackChar = c;
	}

	private void addChild(LightXMLParser child) {
		this.children.add(child);
	}

	private void setAttribute(String name, Object value) {
		this.attributes.put(name, value.toString());
	}

	public Map getAttributes() {
		return this.attributes;
	}

	private LightXMLParser createAnotherElement() {
		return new LightXMLParser();
	}

	private void setName(String name) {
		this.name = name;
	}

	private void emptyBuf(StringBuffer buf) {
		buf.setLength(0);
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy