--- /dev/null
+<!--*****************************************************************************************************************************
+/*******************************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Alexandre Vasseur initial implementation
+ *******************************************************************************/
+AspectJ 5 DTD
+
+To use this DTD, start your defintion file with
+ <!DOCTYPE aspectj PUBLIC
+ "-//AspectJ//DTD 1.5.0//EN"
+ "http://.../dtd/aspectj_1_5_0.dtd">
+
+You can also use the "aliasing DTD" that matchs always the latest release of AspectJ
+<!DOCTYPE aspectj PUBLIC
+ "-//AspectJ//DTD//EN"
+ "http://.../dtd/aspectj.dtd">
+
+To not use this DTD, start your definition file with
+ <?xml version="1.0"?>
+
+******************************************************************************************************************************-->
+
+
+<!--*****************************************************************************************************************************
+aspectj
+*********************************************************************************************************************************
+[aspectj] defines the root element
+******************************************************************************************************************************-->
+<!ELEMENT aspectj (
+ weaver?,
+ aspects?
+)>
+<!--*****************************************************************************************************************************
+weaver
+*********************************************************************************************************************************
+[weaver] defines the weaver configuration
+@options defines a command like line of option
+ When multiple aspectj DD are found, the options are simply toggled
+ TODO: Note: the scope of the options can be ClassLoader aware but should be assumed JVM wide
+******************************************************************************************************************************-->
+<!ELEMENT weaver (
+ (include | exclude | dump)*
+)>
+<!ATTLIST weaver
+ options CDATA #IMPLIED
+>
+<!--*****************************************************************************************************************************
+include
+*********************************************************************************************************************************
+[include] narrows the scope of the weaver
+A class must be matched by ALL the include elements to be exposed to the weaver
+@within defines a type pattern
+ (it is not a startWith)
+******************************************************************************************************************************-->
+<!ELEMENT include EMPTY>
+<!ATTLIST include
+ within CDATA #REQUIRED
+>
+<!--*****************************************************************************************************************************
+exclude
+*********************************************************************************************************************************
+[exclude] narrows the scope of the weaver
+A class must be matched by NONE of the exclude elements to be exposed to the weaver
+@within defines a type pattern
+ (it is not a startWith)
+ TODO should it be called @from: "<exclude from=..> instead of <exclude within=..>
+ TODO: AND must be written that way and not with the "&&" symbol. Thus NOT and OR exists as well.
+******************************************************************************************************************************-->
+<!ELEMENT exclude EMPTY>
+<!ATTLIST exclude
+ within CDATA #REQUIRED
+>
+<!--*****************************************************************************************************************************
+dump
+*********************************************************************************************************************************
+[dump] control post-weaving dump to the "./_dump" folder (debugging purpose only)
+@within defines a type pattern
+ (it is not a startWith)
+******************************************************************************************************************************-->
+<!ELEMENT dump EMPTY>
+<!ATTLIST dump
+ within CDATA #REQUIRED
+>
+<!--*****************************************************************************************************************************
+aspects
+*********************************************************************************************************************************
+[aspects] defines a set of aspects
+Note: include only include among Union{aspect, concrete-aspect} WITHIN THIS SOLE aop.xml
+******************************************************************************************************************************-->
+<!ELEMENT aspects (
+ (aspect | exclude | include | concrete-aspect)*
+)>
+<!--*****************************************************************************************************************************
+aspect
+*********************************************************************************************************************************
+[aspect] defines an aspect to include
+ @name FQN of the aspect, nested class must use $
+******************************************************************************************************************************-->
+<!ELEMENT aspect EMPTY>
+<!ATTLIST aspect
+ name CDATA #REQUIRED
+>
+<!--*****************************************************************************************************************************
+exclude
+*********************************************************************************************************************************
+[exclude] defines a set of aspect to exclude
+ @within within pattern (even from other systems / parent classloader)
+SAME AS FOR weaver/exclude
+******************************************************************************************************************************-->
+<!--*****************************************************************************************************************************
+concrete-aspect
+*********************************************************************************************************************************
+[concrete-aspect] defines a concrete aspect from an abstract one
+ @name FQN of the concrete aspect (use $ for nested class) [will be jit generated]
+ @extends FQN of the abstract aspect (use $ for nested class)
+******************************************************************************************************************************-->
+<!ELEMENT concrete-aspect (
+ pointcut+
+)>
+<!ATTLIST concrete-aspect
+ name CDATA #REQUIRED
+ extends CDATA #REQUIRED
+ precedence CDATA #IMPLIED
+ perclause CDATA #IMPLIED
+>
+<!--*****************************************************************************************************************************
+pointcut
+*********************************************************************************************************************************
+[pointcut] defines a concrete pointcut within a concrete aspect from an abstract one
+ @name name of the abstract pointcut (method name, unique in aspect class hierarchy)
+ @expression pointcut expression
+ Note: for argument binding, the bounded arguments must be present and bounded:
+ <pointcut name="myAdvice(int i)" expression="... AND args(i)"/>
+ TODO: AND must be written that way and not with the "&&" symbol. Thus NOT and OR exists as well.
+******************************************************************************************************************************-->
+<!ELEMENT pointcut EMPTY>
+<!ATTLIST pointcut
+ name CDATA #REQUIRED
+ expression CDATA #REQUIRED
+>
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Alexandre Vasseur initial implementation
+ *******************************************************************************/
+package org.aspectj.weaver.loadtime.definition;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A POJO that contains raw strings from the XML (sort of XMLBean for our simple LTW DTD)
+ *
+ * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
+ */
+public class Definition {
+
+ private final StringBuffer m_weaverOptions;
+
+ private final List m_dumpPatterns;
+
+ private boolean m_dumpBefore;
+
+ private boolean perClassloaderDumpDir;
+
+ private final List m_includePatterns;
+
+ private final List m_excludePatterns;
+
+ private final List m_aspectClassNames;
+
+ private final List m_aspectExcludePatterns;
+
+ private final List m_aspectIncludePatterns;
+
+ private final List m_concreteAspects;
+
+ public Definition() {
+ m_weaverOptions = new StringBuffer();
+ m_dumpBefore = false;
+ perClassloaderDumpDir = false;
+ m_dumpPatterns = new ArrayList(0);
+ m_includePatterns = new ArrayList(0);
+ m_excludePatterns = new ArrayList(0);
+ m_aspectClassNames = new ArrayList();
+ m_aspectExcludePatterns = new ArrayList(0);
+ m_aspectIncludePatterns = new ArrayList(0);
+ m_concreteAspects = new ArrayList(0);
+ }
+
+ public String getWeaverOptions() {
+ return m_weaverOptions.toString();
+ }
+
+ public List getDumpPatterns() {
+ return m_dumpPatterns;
+ }
+
+ public void setDumpBefore(boolean b) {
+ m_dumpBefore = b;
+ }
+
+ public boolean shouldDumpBefore() {
+ return m_dumpBefore;
+ }
+
+ public void setCreateDumpDirPerClassloader(boolean b) {
+ perClassloaderDumpDir = b;
+ }
+
+ public boolean createDumpDirPerClassloader() {
+ return perClassloaderDumpDir;
+ }
+
+ public List getIncludePatterns() {
+ return m_includePatterns;
+ }
+
+ public List getExcludePatterns() {
+ return m_excludePatterns;
+ }
+
+ public List getAspectClassNames() {
+ return m_aspectClassNames;
+ }
+
+ public List getAspectExcludePatterns() {
+ return m_aspectExcludePatterns;
+ }
+
+ public List getAspectIncludePatterns() {
+ return m_aspectIncludePatterns;
+ }
+
+ public List getConcreteAspects() {
+ return m_concreteAspects;
+ }
+
+ public static class ConcreteAspect {
+ public final String name;
+ public final String extend;
+ public final String precedence;
+ public final List pointcuts;
+ public final String perclause;
+
+ public ConcreteAspect(String name, String extend) {
+ this(name, extend, null, null);
+ }
+
+ public ConcreteAspect(String name, String extend, String precedence, String perclause) {
+ this.name = name;
+ // make sure extend set to null if ""
+ if (extend == null || extend.length() == 0) {
+ this.extend = null;
+ if (precedence == null || precedence.length() == 0) {
+ throw new RuntimeException("Not allowed");
+ }
+ } else {
+ this.extend = extend;
+ }
+ this.precedence = precedence;
+ this.pointcuts = new ArrayList();
+ this.perclause = perclause;
+ }
+ }
+
+ public static class Pointcut {
+ public final String name;
+ public final String expression;
+
+ public Pointcut(String name, String expression) {
+ this.name = name;
+ this.expression = expression;
+ }
+ }
+
+ public void appendWeaverOptions(String option) {
+ m_weaverOptions.append(option.trim()).append(' ');
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Alexandre Vasseur initial implementation
+ *******************************************************************************/
+package org.aspectj.weaver.loadtime.definition;
+
+import java.io.InputStream;
+import java.net.URL;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.aspectj.util.LangUtil;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.DefaultHandler;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+/**
+ * FIXME AV - doc, concrete aspect
+ *
+ * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
+ */
+public class DocumentParser extends DefaultHandler {
+
+ /**
+ * The current DTD public id. The matching dtd will be searched as a resource.
+ */
+ private final static String DTD_PUBLIC_ID = "-//AspectJ//DTD 1.5.0//EN";
+
+ /**
+ * The DTD alias, for better user experience.
+ */
+ private final static String DTD_PUBLIC_ID_ALIAS = "-//AspectJ//DTD//EN";
+
+ /**
+ * A handler to the DTD stream so that we are only using one file descriptor
+ */
+ private final static InputStream DTD_STREAM = DocumentParser.class.getResourceAsStream("/aspectj_1_5_0.dtd");
+
+ private final static String ASPECTJ_ELEMENT = "aspectj";
+ private final static String WEAVER_ELEMENT = "weaver";
+ private final static String DUMP_ELEMENT = "dump";
+ private final static String DUMP_BEFOREANDAFTER_ATTRIBUTE = "beforeandafter";
+ private final static String DUMP_PERCLASSLOADERDIR_ATTRIBUTE = "perclassloaderdumpdir";
+ private final static String INCLUDE_ELEMENT = "include";
+ private final static String EXCLUDE_ELEMENT = "exclude";
+ private final static String OPTIONS_ATTRIBUTE = "options";
+ private final static String ASPECTS_ELEMENT = "aspects";
+ private final static String ASPECT_ELEMENT = "aspect";
+ private final static String CONCRETE_ASPECT_ELEMENT = "concrete-aspect";
+ private final static String NAME_ATTRIBUTE = "name";
+ private final static String EXTEND_ATTRIBUTE = "extends";
+ private final static String PRECEDENCE_ATTRIBUTE = "precedence";
+ private final static String PERCLAUSE_ATTRIBUTE = "perclause";
+ private final static String POINTCUT_ELEMENT = "pointcut";
+ private final static String WITHIN_ATTRIBUTE = "within";
+ private final static String EXPRESSION_ATTRIBUTE = "expression";
+
+ private final Definition m_definition;
+
+ private boolean m_inAspectJ;
+ private boolean m_inWeaver;
+ private boolean m_inAspects;
+
+ private Definition.ConcreteAspect m_lastConcreteAspect;
+
+ private DocumentParser() {
+ m_definition = new Definition();
+ }
+
+ public static Definition parse(final URL url) throws Exception {
+ InputStream in = null;
+ try {
+ DocumentParser parser = new DocumentParser();
+
+ XMLReader xmlReader = getXMLReader();
+ xmlReader.setContentHandler(parser);
+ xmlReader.setErrorHandler(parser);
+
+ try {
+ xmlReader.setFeature("http://xml.org/sax/features/validation", false);
+ } catch (SAXException e) {
+ // fine, the parser don't do validation
+ }
+ try {
+ xmlReader.setFeature("http://xml.org/sax/features/external-general-entities", false);
+ } catch (SAXException e) {
+ // fine, the parser don't do validation
+ }
+ try {
+ xmlReader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
+ } catch (SAXException e) {
+ // fine, the parser don't do validation
+ }
+
+ xmlReader.setEntityResolver(parser);
+ in = url.openStream();
+ xmlReader.parse(new InputSource(in));
+ return parser.m_definition;
+ } finally {
+ try {
+ in.close();
+ } catch (Throwable t) {
+
+ }
+ }
+ }
+
+ private static XMLReader getXMLReader() throws SAXException, ParserConfigurationException {
+ XMLReader xmlReader = null;
+
+ /* Try this first for Java 5 */
+ try {
+ xmlReader = XMLReaderFactory.createXMLReader();
+ }
+
+ /* .. and ignore "System property ... not set" and then try this instead */
+ catch (SAXException ex) {
+ xmlReader = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
+ }
+ return xmlReader;
+ }
+
+ public InputSource resolveEntity(String publicId, String systemId) throws SAXException {
+ if (publicId.equals(DTD_PUBLIC_ID) || publicId.equals(DTD_PUBLIC_ID_ALIAS)) {
+ InputStream in = DTD_STREAM;
+ if (in == null) {
+ System.err.println("AspectJ - WARN - could not read DTD " + publicId);
+ return null;
+ } else {
+ return new InputSource(in);
+ }
+ } else {
+ System.err.println("AspectJ - WARN - unknown DTD " + publicId + " - consider using " + DTD_PUBLIC_ID);
+ return null;
+ }
+ }
+
+ public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+ if (ASPECT_ELEMENT.equals(qName)) {
+ String name = attributes.getValue(NAME_ATTRIBUTE);
+ if (!isNull(name)) {
+ m_definition.getAspectClassNames().add(name);
+ }
+ } else if (WEAVER_ELEMENT.equals(qName)) {
+ String options = attributes.getValue(OPTIONS_ATTRIBUTE);
+ if (!isNull(options)) {
+ m_definition.appendWeaverOptions(options);
+ }
+ m_inWeaver = true;
+ } else if (CONCRETE_ASPECT_ELEMENT.equals(qName)) {
+ String name = attributes.getValue(NAME_ATTRIBUTE);
+ String extend = attributes.getValue(EXTEND_ATTRIBUTE);
+ String precedence = attributes.getValue(PRECEDENCE_ATTRIBUTE);
+ String perclause = attributes.getValue(PERCLAUSE_ATTRIBUTE);
+ if (!isNull(name)) {
+ m_lastConcreteAspect = new Definition.ConcreteAspect(name, extend, precedence, perclause);
+ // if (isNull(precedence) && !isNull(extend)) {// if no precedence, then extends must be there
+ // m_lastConcreteAspect = new Definition.ConcreteAspect(name, extend);
+ // } else if (!isNull(precedence)) {
+ // // wether a pure precedence def, or an extendsANDprecedence def.
+ // m_lastConcreteAspect = new Definition.ConcreteAspect(name, extend, precedence, perclause);
+ // }
+ m_definition.getConcreteAspects().add(m_lastConcreteAspect);
+ }
+ } else if (POINTCUT_ELEMENT.equals(qName) && m_lastConcreteAspect != null) {
+ String name = attributes.getValue(NAME_ATTRIBUTE);
+ String expression = attributes.getValue(EXPRESSION_ATTRIBUTE);
+ if (!isNull(name) && !isNull(expression)) {
+ m_lastConcreteAspect.pointcuts.add(new Definition.Pointcut(name, replaceXmlAnd(expression)));
+ }
+ } else if (ASPECTJ_ELEMENT.equals(qName)) {
+ if (m_inAspectJ) {
+ throw new SAXException("Found nested <aspectj> element");
+ }
+ m_inAspectJ = true;
+ } else if (ASPECTS_ELEMENT.equals(qName)) {
+ m_inAspects = true;
+ } else if (INCLUDE_ELEMENT.equals(qName) && m_inWeaver) {
+ String typePattern = getWithinAttribute(attributes);
+ if (!isNull(typePattern)) {
+ m_definition.getIncludePatterns().add(typePattern);
+ }
+ } else if (EXCLUDE_ELEMENT.equals(qName) && m_inWeaver) {
+ String typePattern = getWithinAttribute(attributes);
+ if (!isNull(typePattern)) {
+ m_definition.getExcludePatterns().add(typePattern);
+ }
+ } else if (DUMP_ELEMENT.equals(qName) && m_inWeaver) {
+ String typePattern = getWithinAttribute(attributes);
+ if (!isNull(typePattern)) {
+ m_definition.getDumpPatterns().add(typePattern);
+ }
+ String beforeAndAfter = attributes.getValue(DUMP_BEFOREANDAFTER_ATTRIBUTE);
+ if (isTrue(beforeAndAfter)) {
+ m_definition.setDumpBefore(true);
+ }
+ String perWeaverDumpDir = attributes.getValue(DUMP_PERCLASSLOADERDIR_ATTRIBUTE);
+ if (isTrue(perWeaverDumpDir)) {
+ m_definition.setCreateDumpDirPerClassloader(true);
+ }
+ } else if (EXCLUDE_ELEMENT.equals(qName) && m_inAspects) {
+ String typePattern = getWithinAttribute(attributes);
+ if (!isNull(typePattern)) {
+ m_definition.getAspectExcludePatterns().add(typePattern);
+ }
+ } else if (INCLUDE_ELEMENT.equals(qName) && m_inAspects) {
+ String typePattern = getWithinAttribute(attributes);
+ if (!isNull(typePattern)) {
+ m_definition.getAspectIncludePatterns().add(typePattern);
+ }
+ } else {
+ throw new SAXException("Unknown element while parsing <aspectj> element: " + qName);
+ }
+ super.startElement(uri, localName, qName, attributes);
+ }
+
+ private String getWithinAttribute(Attributes attributes) {
+ return replaceXmlAnd(attributes.getValue(WITHIN_ATTRIBUTE));
+ }
+
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+ if (CONCRETE_ASPECT_ELEMENT.equals(qName)) {
+ m_lastConcreteAspect = null;
+ } else if (ASPECTJ_ELEMENT.equals(qName)) {
+ m_inAspectJ = false;
+ } else if (WEAVER_ELEMENT.equals(qName)) {
+ m_inWeaver = false;
+ } else if (ASPECTS_ELEMENT.equals(qName)) {
+ m_inAspects = false;
+ }
+ super.endElement(uri, localName, qName);
+ }
+
+ // TODO AV - define what we want for XML parser error - for now stderr
+ public void warning(SAXParseException e) throws SAXException {
+ super.warning(e);
+ }
+
+ public void error(SAXParseException e) throws SAXException {
+ super.error(e);
+ }
+
+ public void fatalError(SAXParseException e) throws SAXException {
+ super.fatalError(e);
+ }
+
+ private static String replaceXmlAnd(String expression) {
+ // TODO AV do we need to handle "..)AND" or "AND(.." ?
+ return LangUtil.replace(expression, " AND ", " && ");
+ }
+
+ private boolean isNull(String s) {
+ return (s == null || s.length() <= 0);
+ }
+
+ private boolean isTrue(String s) {
+ return (s != null && s.equals("true"));
+ }
+
+}