]> source.dussan.org Git - aspectj.git/commitdiff
124460: moving xml parser and structure across to weaver from loadtime
authoraclement <aclement>
Sat, 31 Jan 2009 01:09:28 +0000 (01:09 +0000)
committeraclement <aclement>
Sat, 31 Jan 2009 01:09:28 +0000 (01:09 +0000)
weaver/src/aspectj_1_5_0.dtd [new file with mode: 0644]
weaver/src/org/aspectj/weaver/loadtime/definition/Definition.java [new file with mode: 0644]
weaver/src/org/aspectj/weaver/loadtime/definition/DocumentParser.java [new file with mode: 0644]

diff --git a/weaver/src/aspectj_1_5_0.dtd b/weaver/src/aspectj_1_5_0.dtd
new file mode 100644 (file)
index 0000000..1b77624
--- /dev/null
@@ -0,0 +1,147 @@
+<!--*****************************************************************************************************************************
+/*******************************************************************************
+ * 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
+>
diff --git a/weaver/src/org/aspectj/weaver/loadtime/definition/Definition.java b/weaver/src/org/aspectj/weaver/loadtime/definition/Definition.java
new file mode 100644 (file)
index 0000000..7b6da95
--- /dev/null
@@ -0,0 +1,147 @@
+/*******************************************************************************
+ * 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(' ');
+       }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/loadtime/definition/DocumentParser.java b/weaver/src/org/aspectj/weaver/loadtime/definition/DocumentParser.java
new file mode 100644 (file)
index 0000000..101fcba
--- /dev/null
@@ -0,0 +1,272 @@
+/*******************************************************************************
+ * 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"));
+       }
+
+}