You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pc...@apache.org on 2006/06/28 21:34:40 UTC
svn commit: r417856 [10/22] - in /incubator/openjpa/trunk/openjpa-lib: java/
main/ main/java/ main/java/org/apache/openjpa/lib/ant/
main/java/org/apache/openjpa/lib/conf/ main/java/org/apache/openjpa/lib/jdbc/
main/java/org/apache/openjpa/lib/log/ main...
Modified: incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/meta/CFMetaDataParser.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/meta/CFMetaDataParser.java?rev=417856&r1=415364&r2=417856&view=diff
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/meta/CFMetaDataParser.java (original)
+++ incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/meta/CFMetaDataParser.java Wed Jun 28 12:34:33 2006
@@ -15,396 +15,346 @@
*/
package org.apache.openjpa.lib.meta;
+import org.apache.openjpa.lib.util.*;
import org.xml.sax.*;
-import org.apache.openjpa.lib.util.*;
-
import serp.util.*;
/**
- * <p>Custom SAX parser used by the system to quickly parse metadata files
- * for classes.</p>
+ * <p>Custom SAX parser used by the system to quickly parse metadata files
+ * for classes.</p>
*
- * @author Abe White
- * @nojavadoc
- */
-public class CFMetaDataParser
- extends XMLMetaDataParser
-{
- static final String[] PACKAGES = new String[] {
- "java.lang.", "java.util.", "java.math."
- };
- private static final Localizer _loc = Localizer.forPackage
- (CFMetaDataParser.class);
-
- // the current package and class being parsed
- private String _package = null;
- private String _class = null;
-
-
- public CFMetaDataParser ()
- {
- setParseText (false);
- }
-
-
- /**
- * The name of the package element. Defaults to "package".
- */
- protected boolean isPackageElementName (String name)
- {
- return "package".equals (name);
- }
-
-
- /**
- * The attribute of the package element that holds the name, or null to
- * use the element text. Defaults to "name".
- */
- protected String getPackageAttributeName ()
- {
- return "name";
- }
-
-
- /**
- * The depth of the package element. Defaults to 1.
- */
- protected int getPackageElementDepth ()
- {
- return 1;
- }
-
-
- /**
- * The name of the class element. Defaults to "class".
- */
- protected boolean isClassElementName (String name)
- {
- return "class".equals (name);
- }
-
-
- /**
- * The attribute of the class element that holds the name, or null to
- * use the element text. Defaults to "name".
- */
- protected String getClassAttributeName ()
- {
- return "name";
- }
-
-
- /**
- * The depth of the class element. Defaults to 2.
- */
- protected int getClassElementDepth ()
- {
- return 2;
- }
-
-
- protected boolean startElement (String name, Attributes attrs)
- throws SAXException
- {
- // skip root element
- int depth = currentDepth ();
- if (depth == 0)
- return true;
-
- try
- {
- if (depth == getPackageElementDepth ()
- && isPackageElementName (name))
- return startPackage (name, attrs);
- if (depth == getClassElementDepth () && isClassElementName (name))
- return startClass (name, attrs);
- if (depth > getClassElementDepth () && _class != null
- && getClassAttributeName () != null)
- return startClassElement (name, attrs);
- if (depth > getPackageElementDepth () && _package != null
- && getPackageAttributeName () != null)
- return startPackageElement (name, attrs);
- return startSystemElement (name, attrs);
- }
- catch (SAXException se)
- {
- throw se;
- }
- catch (NullPointerException npe)
- {
- throw getException (_loc.get ("parse-error", name), npe);
- }
- }
-
-
- protected void endElement (String name)
- throws SAXException
- {
- // skip root element
- int depth = currentDepth ();
- if (depth == 0)
- return;
-
- try
- {
- if (depth == getPackageElementDepth ()
- && isPackageElementName (name))
- endPackage (name);
- else if (depth == getClassElementDepth ()
- && isClassElementName (name))
- endClass (name);
- else if (depth > getClassElementDepth () && _class != null
- && getClassAttributeName () != null)
- endClassElement (name);
- else if (depth > getPackageElementDepth () && _package != null
- && getPackageAttributeName () != null)
- endPackageElement (name);
- else
- endSystemElement (name);
- }
- catch (SAXException se)
- {
- throw se;
- }
- catch (NullPointerException npe)
- {
- throw getException (_loc.get ("parse-error", name), npe);
- }
- }
-
-
- /**
- * Start a package. Parses out package attribute by default.
- * Return false to skip package element and its contents.
- */
- protected boolean startPackage (String elem, Attributes attrs)
- throws SAXException
- {
- if (getPackageAttributeName () != null)
- {
- _package = attrs.getValue (getPackageAttributeName ());
- if (_package == null)
- _package = "";
- }
- return true;
- }
-
-
- /**
- * End a package. Parses contained text by default.
- */
- protected void endPackage (String elem)
- {
- if (getPackageAttributeName () != null)
- _package = null;
- else
- _package = currentText ();
- }
-
-
- /**
- * Start a class. Parses out class name by default. Return
- * false to skip class element and its contents.
- */
- protected boolean startClass (String elem, Attributes attrs)
- throws SAXException
- {
- if (getClassAttributeName () != null)
- {
- _class = attrs.getValue (getClassAttributeName ());
- if (_package != null && _package.length () > 0
- && _class.indexOf ('.') == -1)
- _class = _package + "." + _class;
- }
- return true;
- }
-
-
- /**
- * End a class. Parses contained text by default.
- */
- protected void endClass (String elem)
- throws SAXException
- {
- if (getClassAttributeName () != null)
- _class = null;
- else
- {
- _class = currentText ();
- if (_package != null && _package.length () > 0
- && _class.indexOf ('.') == -1)
- _class = _package + "." + _class;
- }
- }
-
-
- /**
- * Override this method marking the start of an element outside of any
- * package or class.
- */
- protected boolean startSystemElement (String name, Attributes attrs)
- throws SAXException
- {
- return false;
- }
-
-
- /**
- * Override this method marking the end of an element outside of any
- * package or class.
- */
- protected void endSystemElement (String name)
- throws SAXException
- {
- }
-
-
- /**
- * Override this method marking the start of an element within a declared
- * package.
- */
- protected boolean startPackageElement (String name, Attributes attrs)
- throws SAXException
- {
- return false;
- }
-
-
- /**
- * Override this method marking the end of an element within a declared
- * package.
- */
- protected void endPackageElement (String name)
- throws SAXException
- {
- }
-
-
- /**
- * Override this method marking the start of an element within a declared
- * class.
- */
- protected boolean startClassElement (String name, Attributes attrs)
- throws SAXException
- {
- return false;
- }
-
-
- /**
- * Override this method marking the end of an element within a declared
- * class.
- */
- protected void endClassElement (String name)
- throws SAXException
- {
- }
-
-
- /**
- * Override this method to clear any state and ready the parser for
- * a new document. Subclasses should call
- * <code>super.reset ()</code> to clear superclass state.
- */
- protected void reset ()
- {
- super.reset ();
- _package = null;
- _class = null;
- }
-
-
- /**
- * Return the current class being parsed; the returned name will
- * be fully qualified.
- */
- protected String currentClassName ()
- {
- return _class;
- }
-
-
- /**
- * Return the current package being parsed.
- */
- protected String currentPackage ()
- {
- return _package;
- }
-
-
- /**
- * Helper method to create the {@link Class} for the given name,
- * taking into account the package currently being parsed for relative
- * class names.
- */
- protected Class classForName (String name, boolean resolve)
- throws SAXException
- {
- if (name == null)
- return null;
- Class cls = classForName (name, _package, resolve,
- currentClassLoader ());
- if (cls == null)
- throw getException (_loc.get ("invalid-class", name));
- return cls;
- }
-
-
- /**
- * Load the given class name against the given package and the set
- * of accepted standard packages. Return null if the class cannot be
- * loaded.
- */
- public static Class classForName (String name, String pkg,
- boolean resolve, ClassLoader loader)
- {
- if (name == null || name.length () == 0)
- return null;
-
- if (loader == null)
- loader = Thread.currentThread ().getContextClassLoader ();
- boolean fullName = name.indexOf ('.') != -1;
- boolean noPackage = pkg == null || pkg.length () == 0;
- try
- {
- if (fullName || noPackage)
- return Strings.toClass (name, resolve, loader);
- return Strings.toClass (pkg + "." + name, resolve, loader);
- }
- catch (RuntimeException re)
- {
- }
-
- // if not a full name, now try the name without a package
- if (!fullName && !noPackage)
- {
- try
- {
- return Strings.toClass (name, resolve, loader);
- }
- catch (RuntimeException re)
- {
- }
- }
-
- // try with standard packages
- if (!fullName)
- {
- for (int i = 0; i < PACKAGES.length; i++)
- {
- try
- {
- return Strings.toClass(PACKAGES[i] + name, resolve, loader);
- }
- catch (RuntimeException re)
- {
- }
- }
- }
- return null;
- }
+ * @author Abe White
+ * @nojavadoc */
+public class CFMetaDataParser extends XMLMetaDataParser {
+ static final String[] PACKAGES = new String[] {
+ "java.lang.", "java.util.", "java.math."
+ };
+ private static final Localizer _loc = Localizer.forPackage(CFMetaDataParser.class);
+
+ // the current package and class being parsed
+ private String _package = null;
+ private String _class = null;
+
+ public CFMetaDataParser() {
+ setParseText(false);
+ }
+
+ /**
+ * The name of the package element. Defaults to "package".
+ */
+ protected boolean isPackageElementName(String name) {
+ return "package".equals(name);
+ }
+
+ /**
+ * The attribute of the package element that holds the name, or null to
+ * use the element text. Defaults to "name".
+ */
+ protected String getPackageAttributeName() {
+ return "name";
+ }
+
+ /**
+ * The depth of the package element. Defaults to 1.
+ */
+ protected int getPackageElementDepth() {
+ return 1;
+ }
+
+ /**
+ * The name of the class element. Defaults to "class".
+ */
+ protected boolean isClassElementName(String name) {
+ return "class".equals(name);
+ }
+
+ /**
+ * The attribute of the class element that holds the name, or null to
+ * use the element text. Defaults to "name".
+ */
+ protected String getClassAttributeName() {
+ return "name";
+ }
+
+ /**
+ * The depth of the class element. Defaults to 2.
+ */
+ protected int getClassElementDepth() {
+ return 2;
+ }
+
+ protected boolean startElement(String name, Attributes attrs)
+ throws SAXException {
+ // skip root element
+ int depth = currentDepth();
+
+ if (depth == 0) {
+ return true;
+ }
+
+ try {
+ if ((depth == getPackageElementDepth()) &&
+ isPackageElementName(name)) {
+ return startPackage(name, attrs);
+ }
+
+ if ((depth == getClassElementDepth()) && isClassElementName(name)) {
+ return startClass(name, attrs);
+ }
+
+ if ((depth > getClassElementDepth()) && (_class != null) &&
+ (getClassAttributeName() != null)) {
+ return startClassElement(name, attrs);
+ }
+
+ if ((depth > getPackageElementDepth()) && (_package != null) &&
+ (getPackageAttributeName() != null)) {
+ return startPackageElement(name, attrs);
+ }
+
+ return startSystemElement(name, attrs);
+ } catch (SAXException se) {
+ throw se;
+ } catch (NullPointerException npe) {
+ throw getException(_loc.get("parse-error", name), npe);
+ }
+ }
+
+ protected void endElement(String name) throws SAXException {
+ // skip root element
+ int depth = currentDepth();
+
+ if (depth == 0) {
+ return;
+ }
+
+ try {
+ if ((depth == getPackageElementDepth()) &&
+ isPackageElementName(name)) {
+ endPackage(name);
+ } else if ((depth == getClassElementDepth()) &&
+ isClassElementName(name)) {
+ endClass(name);
+ } else if ((depth > getClassElementDepth()) && (_class != null) &&
+ (getClassAttributeName() != null)) {
+ endClassElement(name);
+ } else if ((depth > getPackageElementDepth()) &&
+ (_package != null) && (getPackageAttributeName() != null)) {
+ endPackageElement(name);
+ } else {
+ endSystemElement(name);
+ }
+ } catch (SAXException se) {
+ throw se;
+ } catch (NullPointerException npe) {
+ throw getException(_loc.get("parse-error", name), npe);
+ }
+ }
+
+ /**
+ * Start a package. Parses out package attribute by default.
+ * Return false to skip package element and its contents.
+ */
+ protected boolean startPackage(String elem, Attributes attrs)
+ throws SAXException {
+ if (getPackageAttributeName() != null) {
+ _package = attrs.getValue(getPackageAttributeName());
+
+ if (_package == null) {
+ _package = "";
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * End a package. Parses contained text by default.
+ */
+ protected void endPackage(String elem) {
+ if (getPackageAttributeName() != null) {
+ _package = null;
+ } else {
+ _package = currentText();
+ }
+ }
+
+ /**
+ * Start a class. Parses out class name by default. Return
+ * false to skip class element and its contents.
+ */
+ protected boolean startClass(String elem, Attributes attrs)
+ throws SAXException {
+ if (getClassAttributeName() != null) {
+ _class = attrs.getValue(getClassAttributeName());
+
+ if ((_package != null) && (_package.length() > 0) &&
+ (_class.indexOf('.') == -1)) {
+ _class = _package + "." + _class;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * End a class. Parses contained text by default.
+ */
+ protected void endClass(String elem) throws SAXException {
+ if (getClassAttributeName() != null) {
+ _class = null;
+ } else {
+ _class = currentText();
+
+ if ((_package != null) && (_package.length() > 0) &&
+ (_class.indexOf('.') == -1)) {
+ _class = _package + "." + _class;
+ }
+ }
+ }
+
+ /**
+ * Override this method marking the start of an element outside of any
+ * package or class.
+ */
+ protected boolean startSystemElement(String name, Attributes attrs)
+ throws SAXException {
+ return false;
+ }
+
+ /**
+ * Override this method marking the end of an element outside of any
+ * package or class.
+ */
+ protected void endSystemElement(String name) throws SAXException {
+ }
+
+ /**
+ * Override this method marking the start of an element within a declared
+ * package.
+ */
+ protected boolean startPackageElement(String name, Attributes attrs)
+ throws SAXException {
+ return false;
+ }
+
+ /**
+ * Override this method marking the end of an element within a declared
+ * package.
+ */
+ protected void endPackageElement(String name) throws SAXException {
+ }
+
+ /**
+ * Override this method marking the start of an element within a declared
+ * class.
+ */
+ protected boolean startClassElement(String name, Attributes attrs)
+ throws SAXException {
+ return false;
+ }
+
+ /**
+ * Override this method marking the end of an element within a declared
+ * class.
+ */
+ protected void endClassElement(String name) throws SAXException {
+ }
+
+ /**
+ * Override this method to clear any state and ready the parser for
+ * a new document. Subclasses should call
+ * <code>super.reset ()</code> to clear superclass state.
+ */
+ protected void reset() {
+ super.reset();
+ _package = null;
+ _class = null;
+ }
+
+ /**
+ * Return the current class being parsed; the returned name will
+ * be fully qualified.
+ */
+ protected String currentClassName() {
+ return _class;
+ }
+
+ /**
+ * Return the current package being parsed.
+ */
+ protected String currentPackage() {
+ return _package;
+ }
+
+ /**
+ * Helper method to create the {@link Class} for the given name,
+ * taking into account the package currently being parsed for relative
+ * class names.
+ */
+ protected Class classForName(String name, boolean resolve)
+ throws SAXException {
+ if (name == null) {
+ return null;
+ }
+
+ Class cls = classForName(name, _package, resolve, currentClassLoader());
+
+ if (cls == null) {
+ throw getException(_loc.get("invalid-class", name));
+ }
+
+ return cls;
+ }
+
+ /**
+ * Load the given class name against the given package and the set
+ * of accepted standard packages. Return null if the class cannot be
+ * loaded.
+ */
+ public static Class classForName(String name, String pkg, boolean resolve,
+ ClassLoader loader) {
+ if ((name == null) || (name.length() == 0)) {
+ return null;
+ }
+
+ if (loader == null) {
+ loader = Thread.currentThread().getContextClassLoader();
+ }
+
+ boolean fullName = name.indexOf('.') != -1;
+ boolean noPackage = (pkg == null) || (pkg.length() == 0);
+
+ try {
+ if (fullName || noPackage) {
+ return Strings.toClass(name, resolve, loader);
+ }
+
+ return Strings.toClass(pkg + "." + name, resolve, loader);
+ } catch (RuntimeException re) {
+ }
+
+ // if not a full name, now try the name without a package
+ if (!fullName && !noPackage) {
+ try {
+ return Strings.toClass(name, resolve, loader);
+ } catch (RuntimeException re) {
+ }
+ }
+
+ // try with standard packages
+ if (!fullName) {
+ for (int i = 0; i < PACKAGES.length; i++) {
+ try {
+ return Strings.toClass(PACKAGES[i] + name, resolve, loader);
+ } catch (RuntimeException re) {
+ }
+ }
+ }
+
+ return null;
+ }
}
Modified: incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/meta/CFMetaDataSerializer.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/meta/CFMetaDataSerializer.java?rev=417856&r1=415364&r2=417856&view=diff
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/meta/CFMetaDataSerializer.java (original)
+++ incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/meta/CFMetaDataSerializer.java Wed Jun 28 12:34:33 2006
@@ -15,102 +15,96 @@
*/
package org.apache.openjpa.lib.meta;
+import org.apache.commons.collections.map.*;
-import java.util.*;
+import org.apache.openjpa.lib.util.*;
-import org.apache.commons.collections.map.*;
import org.xml.sax.*;
+import java.util.*;
+
/**
- * <p>Helps serialize metadata objects to package and class elements.</p>
+ * <p>Helps serialize metadata objects to package and class elements.</p>
*
- * @see CFMetaDataParser
+ * @see CFMetaDataParser
*
- * @author Abe White
- * @nojavadoc
- */
-public abstract class CFMetaDataSerializer
- extends XMLMetaDataSerializer
-{
- private String _package = null;
-
-
- /**
- * The default package for objects being serialized.
- */
- protected String getPackage ()
- {
- return _package;
- }
-
-
- /**
- * The default package for objects being serialized.
- */
- protected void setPackage (String pkg)
- {
- _package = pkg;
- }
-
-
- /**
- * Helper method to group objects by package.
- *
- * @return mapping of package name to a collection of objects in
- * that package
- */
- protected Map groupByPackage (Collection objs)
- throws SAXException
- {
- Map packages = new LinkedMap ();
- String packageName;
- Collection packageObjs;
- Object obj;
- for (Iterator itr = objs.iterator (); itr.hasNext ();)
- {
- obj = itr.next ();
- packageName = getPackage (obj);
- packageObjs = (Collection) packages.get (packageName);
- if (packageObjs == null)
- {
- packageObjs = new LinkedList ();
- packages.put (packageName, packageObjs);
- }
- packageObjs.add (obj);
- }
- return packages;
- }
-
-
- /**
- * Return the package name of the given object, or null if not in a
- * package. Used by {@link #groupByPackage}. Returns null by default.
- */
- protected String getPackage (Object obj)
- {
- return null;
- }
-
-
- /**
- * Returns the given class name, stripping the package if it is not
- * needed.
- */
- protected String getClassName (String name)
- {
- // check if in current package; make sure not in a sub-package
- if (_package != null
- && name.lastIndexOf ('.') == _package.length ()
- && name.startsWith (_package))
- return name.substring (_package.length () + 1);
-
- // check other known packages
- String[] packages = CFMetaDataParser.PACKAGES;
- for (int i = 0; i < packages.length; i++)
- if (name.startsWith (packages[i])
- && name.lastIndexOf ('.') == packages[i].length () - 1)
- return name.substring (packages[i].length ());
- return name;
- }
+ * @author Abe White
+ * @nojavadoc */
+public abstract class CFMetaDataSerializer extends XMLMetaDataSerializer {
+ private static final Localizer _loc = Localizer.forPackage(CFMetaDataSerializer.class);
+ private String _package = null;
+
+ /**
+ * The default package for objects being serialized.
+ */
+ protected String getPackage() {
+ return _package;
+ }
+
+ /**
+ * The default package for objects being serialized.
+ */
+ protected void setPackage(String pkg) {
+ _package = pkg;
+ }
+
+ /**
+ * Helper method to group objects by package.
+ *
+ * @return mapping of package name to a collection of objects in
+ * that package
+ */
+ protected Map groupByPackage(Collection objs) throws SAXException {
+ Map packages = new LinkedMap();
+ String packageName;
+ Collection packageObjs;
+ Object obj;
+
+ for (Iterator itr = objs.iterator(); itr.hasNext();) {
+ obj = itr.next();
+ packageName = getPackage(obj);
+ packageObjs = (Collection) packages.get(packageName);
+
+ if (packageObjs == null) {
+ packageObjs = new LinkedList();
+ packages.put(packageName, packageObjs);
+ }
+
+ packageObjs.add(obj);
+ }
+
+ return packages;
+ }
+
+ /**
+ * Return the package name of the given object, or null if not in a
+ * package. Used by {@link #groupByPackage}. Returns null by default.
+ */
+ protected String getPackage(Object obj) {
+ return null;
+ }
+
+ /**
+ * Returns the given class name, stripping the package if it is not
+ * needed.
+ */
+ protected String getClassName(String name) {
+ // check if in current package; make sure not in a sub-package
+ if ((_package != null) && (name.lastIndexOf('.') == _package.length()) &&
+ name.startsWith(_package)) {
+ return name.substring(_package.length() + 1);
+ }
+
+ // check other known packages
+ String[] packages = CFMetaDataParser.PACKAGES;
+
+ for (int i = 0; i < packages.length; i++)
+ if (name.startsWith(packages[i]) &&
+ (name.lastIndexOf('.') == (packages[i].length() - 1))) {
+ return name.substring(packages[i].length());
+ }
+
+ return name;
+ }
}
Modified: incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/meta/ClassAnnotationMetaDataFilter.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/meta/ClassAnnotationMetaDataFilter.java?rev=417856&r1=415364&r2=417856&view=diff
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/meta/ClassAnnotationMetaDataFilter.java (original)
+++ incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/meta/ClassAnnotationMetaDataFilter.java Wed Jun 28 12:34:33 2006
@@ -15,189 +15,197 @@
*/
package org.apache.openjpa.lib.meta;
+import serp.bytecode.lowlevel.*;
import java.io.*;
-import serp.bytecode.lowlevel.*;
-
/**
- * <p>Filter that looks for classes with one of a set of annotations.
- * See JDK 1.5 JVM spec for details on annotation bytecode:<br />
- * java.sun.com/docs/books/vmspec/2nd-edition/ClassFileFormat-final-draft.pdf
- * </p>
+ * <p>Filter that looks for classes with one of a set of annotations.
+ * See JDK 1.5 JVM spec for details on annotation bytecode:<br />
+ * java.sun.com/docs/books/vmspec/2nd-edition/ClassFileFormat-final-draft.pdf
+ * </p>
*
- * @author Abe White
- * @nojavadoc
- */
-public class ClassAnnotationMetaDataFilter
- implements MetaDataFilter
-{
- private final String[] _annos;
-
-
- /**
- * Constructor; supply annotation to match against.
- */
- public ClassAnnotationMetaDataFilter (Class anno)
- {
- this (new Class[] { anno });
- }
-
-
- /**
- * Constructor; supply annotations to match against.
- */
- public ClassAnnotationMetaDataFilter (Class[] annos)
- {
- _annos = new String[annos.length];
- for (int i = 0; i < annos.length; i++)
- _annos[i] = "L" + annos[i].getName ().replace ('.', '/') + ";";
- }
-
-
- public boolean matches (Resource rsrc)
- throws IOException
- {
- if (_annos.length == 0 || !rsrc.getName ().endsWith (".class"))
- return false;
-
- ConstantPoolTable table = new ConstantPoolTable (rsrc.getContent ());
- int idx = table.getEndIndex ();
- idx += 6; // skip access, cls, super
-
- // skip interfaces
- int interfaces = table.readUnsignedShort (idx);
- idx += 2 + interfaces * 2;
-
- // skip fields and methods
- int fields = table.readUnsignedShort (idx);
- idx += 2;
- for (int i = 0; i < fields; i++)
- idx += skipFieldOrMethod (table, idx);
- int methods = table.readUnsignedShort (idx);
- idx += 2;
- for (int i = 0; i < methods; i++)
- idx += skipFieldOrMethod (table, idx);
-
- // look for annotation attrs
- int attrs = table.readUnsignedShort (idx);
- idx += 2;
- int name;
- for (int i = 0; i < attrs; i++)
- {
- name = table.readUnsignedShort (idx);
- idx += 2;
- if ("RuntimeVisibleAnnotations".equals (table.readString
- (table.get (name))))
- return matchAnnotations (table, idx + 4);
- idx += 4 + table.readInt (idx);
- }
- return false;
- }
-
-
- /**
- * Return whether the given annotations match our candidates.
- */
- private boolean matchAnnotations (ConstantPoolTable table, int idx)
- {
- int annos = table.readUnsignedShort (idx);
- idx += 2;
-
- int type;
- int props;
- for (int i = 0; i < annos; i++)
- {
- type = table.readUnsignedShort (idx);
- idx += 2;
- if (matchAnnotation (table.readString (table.get (type))))
- return true;
-
- props = table.readUnsignedShort (idx);
- idx += 2;
- for (int j = 0; j < props; j++)
- {
- idx += 2; // name
- idx += skipAnnotationPropertyValue (table, idx);
- }
- }
- return false;
- }
-
-
- /**
- * Return whether the given annotation matches our candidates.
- */
- private boolean matchAnnotation (String name)
- {
- for (int i = 0; i < _annos.length; i++)
- if (name.equals (_annos[i]))
- return true;
- return false;
- }
-
-
- /**
- * Skip an annotation property value, returning the number of bytes
- * skipped.
- */
- private static int skipAnnotationPropertyValue (ConstantPoolTable table,
- int idx)
- {
- int skipped = 0;
- switch (table.readByte (idx + skipped++)) // value type
- {
- case 'Z': // bool
- case 'B': // byte
- case 'C': // char
- case 'D': // double
- case 'F': // float
- case 'I': // int
- case 'J': // long
- case 'S': // short
- case 's': // string
- case 'c': // class
- skipped += 2;
- break;
- case 'e': // enum ptr
- skipped += 4;
- break;
- case '[': // array
- int size = table.readUnsignedShort (idx + skipped);
- skipped += 2;
- for (int i = 0; i < size; i++)
- skipped += skipAnnotationPropertyValue (table, idx + skipped);
- break;
- case '@': // anno
- skipped += 2; // type
- int props = table.readUnsignedShort (idx + skipped);
- skipped += 2;
- for (int j = 0; j < props; j++)
- {
- skipped += 2; // name
- skipped += skipAnnotationPropertyValue (table,
- idx + skipped);
- }
- break;
- }
- return skipped;
- }
-
-
- /**
- * Skip the current field or method, returning the number of bytes skipped.
- */
- private static int skipFieldOrMethod (ConstantPoolTable table, int idx)
- {
- int attrs = table.readUnsignedShort (idx + 6);
- int skipped = 8;
- int len;
- for (int i = 0; i < attrs; i++)
- {
- len = table.readInt (idx + skipped + 2);
- skipped += 6 + len;
- }
- return skipped;
- }
+ * @author Abe White
+ * @nojavadoc */
+public class ClassAnnotationMetaDataFilter implements MetaDataFilter {
+ private final String[] _annos;
+
+ /**
+ * Constructor; supply annotation to match against.
+ */
+ public ClassAnnotationMetaDataFilter(Class anno) {
+ this(new Class[] { anno });
+ }
+
+ /**
+ * Constructor; supply annotations to match against.
+ */
+ public ClassAnnotationMetaDataFilter(Class[] annos) {
+ _annos = new String[annos.length];
+
+ for (int i = 0; i < annos.length; i++)
+ _annos[i] = "L" + annos[i].getName().replace('.', '/') + ";";
+ }
+
+ public boolean matches(Resource rsrc) throws IOException {
+ if ((_annos.length == 0) || !rsrc.getName().endsWith(".class")) {
+ return false;
+ }
+
+ ConstantPoolTable table = new ConstantPoolTable(rsrc.getContent());
+ int idx = table.getEndIndex();
+ idx += 6; // skip access, cls, super
+
+ // skip interfaces
+ int interfaces = table.readUnsignedShort(idx);
+ idx += (2 + (interfaces * 2));
+
+ // skip fields and methods
+ int fields = table.readUnsignedShort(idx);
+ idx += 2;
+
+ for (int i = 0; i < fields; i++)
+ idx += skipFieldOrMethod(table, idx);
+
+ int methods = table.readUnsignedShort(idx);
+ idx += 2;
+
+ for (int i = 0; i < methods; i++)
+ idx += skipFieldOrMethod(table, idx);
+
+ // look for annotation attrs
+ int attrs = table.readUnsignedShort(idx);
+ idx += 2;
+
+ int name;
+
+ for (int i = 0; i < attrs; i++) {
+ name = table.readUnsignedShort(idx);
+ idx += 2;
+
+ if ("RuntimeVisibleAnnotations".equals(table.readString(table.get(
+ name)))) {
+ return matchAnnotations(table, idx + 4);
+ }
+
+ idx += (4 + table.readInt(idx));
+ }
+
+ return false;
+ }
+
+ /**
+ * Return whether the given annotations match our candidates.
+ */
+ private boolean matchAnnotations(ConstantPoolTable table, int idx) {
+ int annos = table.readUnsignedShort(idx);
+ idx += 2;
+
+ int type;
+ int props;
+
+ for (int i = 0; i < annos; i++) {
+ type = table.readUnsignedShort(idx);
+ idx += 2;
+
+ if (matchAnnotation(table.readString(table.get(type)))) {
+ return true;
+ }
+
+ props = table.readUnsignedShort(idx);
+ idx += 2;
+
+ for (int j = 0; j < props; j++) {
+ idx += 2; // name
+ idx += skipAnnotationPropertyValue(table, idx);
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Return whether the given annotation matches our candidates.
+ */
+ private boolean matchAnnotation(String name) {
+ for (int i = 0; i < _annos.length; i++)
+ if (name.equals(_annos[i])) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Skip an annotation property value, returning the number of bytes
+ * skipped.
+ */
+ private static int skipAnnotationPropertyValue(ConstantPoolTable table,
+ int idx) {
+ int skipped = 0;
+
+ switch (table.readByte(idx + skipped++)) // value type
+ {
+ case 'Z': // bool
+ case 'B': // byte
+ case 'C': // char
+ case 'D': // double
+ case 'F': // float
+ case 'I': // int
+ case 'J': // long
+ case 'S': // short
+ case 's': // string
+ case 'c': // class
+ skipped += 2;
+
+ break;
+
+ case 'e': // enum ptr
+ skipped += 4;
+
+ break;
+
+ case '[': // array
+
+ int size = table.readUnsignedShort(idx + skipped);
+ skipped += 2;
+
+ for (int i = 0; i < size; i++)
+ skipped += skipAnnotationPropertyValue(table, idx + skipped);
+
+ break;
+
+ case '@': // anno
+ skipped += 2; // type
+
+ int props = table.readUnsignedShort(idx + skipped);
+ skipped += 2;
+
+ for (int j = 0; j < props; j++) {
+ skipped += 2; // name
+ skipped += skipAnnotationPropertyValue(table, idx + skipped);
+ }
+
+ break;
+ }
+
+ return skipped;
+ }
+
+ /**
+ * Skip the current field or method, returning the number of bytes skipped.
+ */
+ private static int skipFieldOrMethod(ConstantPoolTable table, int idx) {
+ int attrs = table.readUnsignedShort(idx + 6);
+ int skipped = 8;
+ int len;
+
+ for (int i = 0; i < attrs; i++) {
+ len = table.readInt(idx + skipped + 2);
+ skipped += (6 + len);
+ }
+
+ return skipped;
+ }
}
Modified: incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/meta/ClassArgParser.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/meta/ClassArgParser.java?rev=417856&r1=415364&r2=417856&view=diff
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/meta/ClassArgParser.java (original)
+++ incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/meta/ClassArgParser.java Wed Jun 28 12:34:33 2006
@@ -15,682 +15,740 @@
*/
package org.apache.openjpa.lib.meta;
-
-import java.io.*;
-import java.util.*;
-
import org.apache.commons.lang.exception.*;
import org.apache.openjpa.lib.util.*;
+import org.xml.sax.*;
+import org.xml.sax.Attributes;
+
import serp.bytecode.lowlevel.*;
+
import serp.util.*;
+import java.io.*;
+
+import java.net.*;
+
+import java.util.*;
+
/**
- * <p>Parser used to resolve arguments into java classes.
- * Interprets command-line args as either class names, .class files or
- * resources, .java files or resources, or metadata files or resources
- * conforming to the common format defined by {@link CFMetaDataParser}.
- * Transforms the information in these args into {@link Class} instances.</p>
+ * <p>Parser used to resolve arguments into java classes.
+ * Interprets command-line args as either class names, .class files or
+ * resources, .java files or resources, or metadata files or resources
+ * conforming to the common format defined by {@link CFMetaDataParser}.
+ * Transforms the information in these args into {@link Class} instances.</p>
*
- * <p>Note that when parsing .java files, only the main class in the file
- * is detected. Other classes defined in the file, such as inner classes,
- * are not added to the returned classes list.</p>
+ * <p>Note that when parsing .java files, only the main class in the file
+ * is detected. Other classes defined in the file, such as inner classes,
+ * are not added to the returned classes list.</p>
*
- * @author Abe White
- * @nojavadoc
- */
-public class ClassArgParser
-{
- private static final int TOKEN_EOF = -1;
- private static final int TOKEN_NONE = 0;
- private static final int TOKEN_PACKAGE = 1;
- private static final int TOKEN_CLASS = 2;
- private static final int TOKEN_PACKAGE_NOATTR = 3;
- private static final int TOKEN_CLASS_NOATTR = 4;
-
- private static final Localizer _loc = Localizer.forPackage
- (ClassArgParser.class);
-
- private ClassLoader _loader = null;
- private char[] _packageAttr = "name".toCharArray ();
- private char[] _classAttr = "name".toCharArray ();
- private char[][] _beginElements = { { 'p' }, { 'c' } };
- private char[][] _endElements = { "ackage".toCharArray (),
- "lass".toCharArray () };
-
- /**
- * The class loader with which to load parsed classes.
- */
- public ClassLoader getClassLoader ()
- {
- return _loader;
- }
-
-
- /**
- * The class loader with which to load parsed classes.
- */
- public void setClassLoader (ClassLoader loader)
- {
- _loader = loader;
- }
-
-
- /**
- * Set the the relevant metadata file structure so that metadata files
- * containing class names can be parsed. Null attribute names indicate
- * that the text content of the element contains the data.
- */
- public void setMetaDataStructure (String packageElementName,
- String packageAttributeName, String[] classElementNames,
- String classAttributeName)
- {
- // calculate how many chars deep we have to go to identify each element
- // name as unique. this is extremely inefficient for large N, but
- // should never be called for more than a few elements
- char[] buf = new char[classElementNames.length + 1];
- int charIdx = 0;
- for (; true; charIdx++)
- {
- for (int i = 0; i < buf.length; i++)
- {
- if (i == 0)
- {
- if (charIdx == packageElementName.length ())
- throw new UnsupportedOperationException (_loc.get
- ("cant-diff-elems"));
- buf[i] = packageElementName.charAt (charIdx);
- }
- else
- {
- if (charIdx == classElementNames[i - 1].length ())
- throw new UnsupportedOperationException (_loc.get
- ("cant-diff-elems"));
- buf[i] = classElementNames[i - 1].charAt (charIdx);
- }
- }
- if (charsUnique (buf))
- break;
- }
-
- _packageAttr = (packageAttributeName == null) ? null
- : packageAttributeName.toCharArray ();
- _classAttr = (classAttributeName == null) ? null
- : classAttributeName.toCharArray ();
- _beginElements = new char[classElementNames.length + 1][];
- _endElements = new char[classElementNames.length + 1][];
- _beginElements[0] = packageElementName.substring (0, charIdx + 1).
- toCharArray ();
- _endElements[0] = packageElementName.substring (charIdx + 1).
- toCharArray ();
- for (int i = 0; i < classElementNames.length; i++)
- {
- _beginElements[i + 1] = classElementNames[i].
- substring (0, charIdx + 1).toCharArray ();
- _endElements[i + 1] = classElementNames[i].
- substring (charIdx + 1).toCharArray ();
- }
- }
-
-
- /**
- * Return true if all characters in given buffer are unique.
- */
- private static boolean charsUnique (char[] buf)
- {
- for (int i = buf.length - 1; i >= 0; i--)
- for (int j = 0; j < i; j++)
- if (buf[j] == buf[i])
- return false;
- return true;
- }
-
-
- /**
- * Return the {@link Class} representation of the class(es) named in the
- * given arg.
- *
- * @param arg a class name, .java file, .class file, or metadata
- * file naming the type(s) to act on
- */
- public Class[] parseTypes (String arg)
- {
- String[] names = parseTypeNames (arg);
- Class[] objs = new Class[names.length];
- for (int i = 0; i < names.length; i++)
- objs[i] = Strings.toClass (names[i], _loader);
- return objs;
- }
-
-
- /**
- * Return the {@link Class} representation of the class(es) named in the
- * given metadatas.
- */
- public Class[] parseTypes (MetaDataIterator itr)
- {
- String[] names = parseTypeNames (itr);
- Class[] objs = new Class[names.length];
- for (int i = 0; i < names.length; i++)
- objs[i] = Strings.toClass (names[i], _loader);
- return objs;
- }
-
-
- /**
- * Return a mapping of each metadata resource to an array of its
- * contained classes.
- */
- public Map mapTypes (MetaDataIterator itr)
- {
- Map map = mapTypeNames (itr);
- Map.Entry entry;
- String[] names;
- Class[] objs;
- for (Iterator i = map.entrySet ().iterator (); i.hasNext ();)
- {
- entry = (Map.Entry) i.next ();
- names = (String[]) entry.getValue ();
- objs = new Class[names.length];
- for (int j = 0; j < names.length; j++)
- objs[j] = Strings.toClass (names[j], _loader);
- entry.setValue (objs);
- }
- return map;
- }
-
-
- /**
- * Return the names of the class(es) from the given arg.
- *
- * @param arg a class name, .java file, .class file, or metadata
- * file naming the type(s) to act on
- * @throws IllegalArgumentException with appropriate message on error
- */
- public String[] parseTypeNames (String arg)
- {
- if (arg == null)
- return new String[0];
-
- try
- {
- File file = Files.getFile (arg, _loader);
- if (arg.endsWith (".class"))
- return new String[] { getFromClassFile (file) };
- if (arg.endsWith (".java"))
- return new String[] { getFromJavaFile (file) };
- if (file.exists ())
- {
- Collection col = getFromMetaDataFile (file);
- return (String[]) col.toArray (new String[col.size ()]);
- }
- }
- catch (Exception e)
- {
- throw new NestableRuntimeException (_loc.get ("class-arg", arg), e);
- }
-
- // must be a class name
- return new String[] { arg };
- }
-
-
- /**
- * Return the names of the class(es) from the given metadatas.
- */
- public String[] parseTypeNames (MetaDataIterator itr)
- {
- if (itr == null)
- return new String[0];
-
- List names = new ArrayList ();
- Object source = null;
- try
- {
- while (itr.hasNext ())
- {
- source = itr.next ();
- appendTypeNames (source, itr.getInputStream (), names);
- }
- }
- catch (Exception e)
- {
- throw new NestableRuntimeException (_loc.get ("class-arg", source),
- e);
- }
- return (String[]) names.toArray (new String[names.size ()]);
- }
-
-
- /**
- * Parse the names in the given metadata iterator stream, closing the
- * stream on completion.
- */
- private void appendTypeNames (Object source, InputStream in, List names)
- throws IOException
- {
- try
- {
- if (source.toString ().endsWith (".class"))
- names.add (getFromClass (in));
- names.addAll (getFromMetaData (new InputStreamReader (in)));
- }
- finally
- {
- try { in.close (); } catch (IOException ioe) {}
- }
- }
-
-
- /**
- * Return a mapping of each metadata resource to an array of its contained
- * class names.
- */
- public Map mapTypeNames (MetaDataIterator itr)
- {
- if (itr == null)
- return Collections.EMPTY_MAP;
-
- Map map = new HashMap ();
- Object source = null;
- List names = new ArrayList ();
- try
- {
- while (itr.hasNext ())
- {
- source = itr.next ();
- appendTypeNames (source, itr.getInputStream (), names);
- if (!names.isEmpty ())
- map.put (source, (String[]) names.toArray
- (new String[names.size ()]));
- names.clear ();
- }
- }
- catch (Exception e)
- {
- throw new NestableRuntimeException (_loc.get ("class-arg", source),
- e);
- }
- return map;
- }
-
-
- /**
- * Returns the class named in the given .class file.
- */
- private String getFromClassFile (File file)
- throws IOException
- {
- FileInputStream fin = null;
- try
- {
- fin = new FileInputStream (file);
- return getFromClass (fin);
- }
- finally
- {
- if (fin != null)
- try { fin.close (); } catch (IOException ioe) {}
- }
- }
-
-
- /**
- * Returns the class name in the given .class bytecode.
- */
- private String getFromClass (InputStream in)
- throws IOException
- {
- ConstantPoolTable table = new ConstantPoolTable (in);
- int idx = table.getEndIndex ();
- idx += 2; // access flags
- int clsEntry = table.readUnsignedShort (idx);
- int utfEntry = table.readUnsignedShort (table.get (clsEntry));
- return table.readString (table.get (utfEntry)).replace ('/', '.');
- }
-
-
- /**
- * Returns the class named in the given .java file.
- */
- private String getFromJavaFile (File file)
- throws IOException
- {
- BufferedReader in = null;
- try
- {
- // find the line with the package declaration
- in = new BufferedReader (new FileReader (file));
- String line;
- StringBuffer pack = null;
- while ((line = in.readLine ()) != null)
- {
- line = line.trim ();
- if (line.startsWith ("package "))
- {
- line = line.substring (8).trim ();
-
- // strip off anything beyond the package declaration
- pack = new StringBuffer ();
- for (int i = 0; i < line.length (); i++)
- {
- if (Character.isJavaIdentifierPart (line.charAt (i))
- || line.charAt (i) == '.')
- pack.append (line.charAt (i));
- else
- break;
- }
- break;
- }
- }
-
- // strip '.java'
- String clsName = file.getName ();
- clsName = clsName.substring (0, clsName.length () - 5);
-
- // prefix with package
- if (pack != null && pack.length () > 0)
- clsName = pack + "." + clsName;
-
- return clsName;
- }
- finally
- {
- if (in != null)
- try { in.close (); } catch (IOException ioe) {}
- }
- }
-
-
- /**
- * Returns the classes named in the given common format metadata file.
- */
- private Collection getFromMetaDataFile (File file)
- throws IOException
- {
- FileReader in = null;
- try
- {
- in = new FileReader (file);
- return getFromMetaData (in);
- }
- finally
- {
- if (in != null)
- try { in.close (); } catch (IOException ioe) {}
- }
- }
-
-
- /**
- * Returns the classes named in the given common format metadata stream.
- */
- private Collection getFromMetaData (Reader xml)
- throws IOException
- {
- Collection names = new ArrayList ();
- BufferedReader in = new BufferedReader (xml);
-
- boolean comment = false;
- int token = TOKEN_NONE;
- String pkg = "";
- String name;
- read: for (int ch = 0, last = 0, last2 = 0;
- ch == '<' || (ch = in.read ()) != -1; last2 = last, last = ch)
- {
- // handle comments
- if (comment && last2 == '-' && last == '-' && ch == '>')
- {
- comment = false;
- continue;
- }
- if (comment)
- {
- if (ch == '<')
- {
- ch = in.read ();
- if (ch == -1)
- break read;
- }
- continue;
- }
- if (last2 == '<' && last == '!' && ch == '-')
- {
- comment = true;
- continue;
- }
-
- // if not an element start, skip it
- if (ch != '<')
- continue;
- token = TOKEN_NONE; // reset token
- last = ch; // update needed for comment detection
- ch = readThroughWhitespace (in);
- if (ch == '/' || ch == '!' || ch == '?')
- continue;
-
- // read element name; look for packages and classes
- token = readElementToken (ch, in);
- switch (token)
- {
- case TOKEN_EOF:
- break read;
- case TOKEN_PACKAGE:
- pkg = readAttribute (in, _packageAttr);
- if (pkg == null)
- break read;
- break;
- case TOKEN_PACKAGE_NOATTR:
- pkg = readElementText (in);
- if (pkg == null)
- break read;
- ch = '<'; // reading element text reads to next '<'
- break;
- case TOKEN_CLASS:
- name = readAttribute (in, _classAttr);
- if (name == null)
- break read;
- if (pkg.length () > 0 && name.indexOf ('.') == -1)
- names.add (pkg + "." + name);
- else
- names.add (name);
- break;
- case TOKEN_CLASS_NOATTR:
- name = readElementText (in);
- if (name == null)
- break read;
- ch = '<'; // reading element text reads to next '<'
- if (pkg.length () > 0 && name.indexOf ('.') == -1)
- names.add (pkg + "." + name);
- else
- names.add (name);
- break;
- }
- }
- return names;
- }
-
-
- /**
- * Read the name of the current XML element and return the matching token.
- */
- private int readElementToken (int ch, Reader in)
- throws IOException
- {
- // look through the beginning element names to find what element this
- // might be (if any)
- int matchIdx = -1;
- int matched = 0;
- int dq = 0;
- for (int beginIdx = 0; beginIdx < _beginElements[0].length; beginIdx++)
- {
- if (beginIdx != 0)
- ch = in.read ();
- if (ch == -1)
- return TOKEN_EOF;
-
- matched = 0;
- for (int i = 0; i < _beginElements.length; i++)
- {
- if ((dq & (2 << i)) != 0)
- continue;
-
- if (ch == _beginElements[i][beginIdx])
- {
- matchIdx = i;
- matched++;
- }
- else
- dq |= 2 << i;
- }
-
- if (matched == 0)
- break;
- }
- if (matched != 1)
- return TOKEN_NONE;
-
- // make sure the rest of the element name matches
- char[] match = _endElements[matchIdx];
- for (int i = 0; i < match.length; i++)
- {
- ch = in.read ();
- if (ch == -1)
- return TOKEN_EOF;
- if (ch != match[i])
- return TOKEN_NONE;
- }
-
- // read the next char to make sure we finished the element name
- ch = in.read ();
- if (ch == -1)
- return TOKEN_EOF;
- if (ch == '>')
- {
- if (matchIdx == 0 && _packageAttr == null)
- return TOKEN_PACKAGE_NOATTR;
- if (matchIdx != 0 && _classAttr == null)
- return TOKEN_CLASS_NOATTR;
- }
- else if (Character.isWhitespace ((char) ch))
- {
- if (matchIdx == 0 && _packageAttr != null)
- return TOKEN_PACKAGE;
- if (matchIdx != 0 && _classAttr != null)
- return TOKEN_CLASS;
- }
- return TOKEN_NONE;
- }
-
-
- /**
- * Read the attribute with the given name in chars of the current XML
- * element.
- */
- private String readAttribute (Reader in, char[] name)
- throws IOException
- {
- int expected = 0;
- for (int ch, last = 0; true; last = ch)
- {
- ch = in.read ();
- if (ch == -1)
- return null;
- if (ch == '>')
- return "";
-
- // if not expected char or still looking for 'n' and previous
- // char is not whitespace, keep looking
- if (ch != name[expected] || (expected == 0 && last != 0
- && !Character.isWhitespace ((char) last)))
- {
- expected = 0;
- continue;
- }
-
- // found expected char; have we found the whole "name"?
- expected++;
- if (expected == name.length)
- {
- // make sure the next char is '='
- ch = readThroughWhitespace (in);
- if (ch == -1)
- return null;
- if (ch != '=')
- {
- expected = 0;
- continue;
- }
-
- // toss out any subsequent whitespace and the next char, which
- // is the opening quote for the attr value, then read until the
- // closing quote
- readThroughWhitespace (in);
- return readAttributeValue (in);
- }
- }
- }
-
-
- /**
- * Read the current text value until the next element.
- */
- private String readElementText (Reader in)
- throws IOException
- {
- StringBuffer buf = null;
- int ch;
- while (true)
- {
- ch = in.read ();
- if (ch == -1)
- return null;
- if (ch == '<')
- break;
- if (Character.isWhitespace ((char) ch))
- continue;
- if (buf == null)
- buf = new StringBuffer ();
- buf.append ((char) ch);
- }
- return (buf == null) ? "" : buf.toString ();
- }
-
-
- /**
- * Read until the next non-whitespace character.
- */
- private int readThroughWhitespace (Reader in)
- throws IOException
- {
- int ch;
- while (true)
- {
- ch = in.read ();
- if (ch == -1 || !Character.isWhitespace ((char) ch))
- return ch;
- }
- }
-
-
- /**
- * Return the current attribute value.
- */
- private String readAttributeValue (Reader in)
- throws IOException
- {
- StringBuffer buf = new StringBuffer ();
- int ch;
- while (true)
- {
- ch = in.read ();
- if (ch == -1)
- return null;
- if (ch == '\'' || ch == '"')
- return buf.toString ();
- buf.append ((char) ch);
- }
- }
+ * @author Abe White
+ * @nojavadoc */
+public class ClassArgParser {
+ private static final int TOKEN_EOF = -1;
+ private static final int TOKEN_NONE = 0;
+ private static final int TOKEN_PACKAGE = 1;
+ private static final int TOKEN_CLASS = 2;
+ private static final int TOKEN_PACKAGE_NOATTR = 3;
+ private static final int TOKEN_CLASS_NOATTR = 4;
+ private static final Localizer _loc = Localizer.forPackage(ClassArgParser.class);
+ private ClassLoader _loader = null;
+ private char[] _packageAttr = "name".toCharArray();
+ private char[] _classAttr = "name".toCharArray();
+ private char[][] _beginElements = {
+ { 'p' },
+ { 'c' }
+ };
+ private char[][] _endElements = {
+ "ackage".toCharArray(), "lass".toCharArray()
+ };
+
+ /**
+ * The class loader with which to load parsed classes.
+ */
+ public ClassLoader getClassLoader() {
+ return _loader;
+ }
+
+ /**
+ * The class loader with which to load parsed classes.
+ */
+ public void setClassLoader(ClassLoader loader) {
+ _loader = loader;
+ }
+
+ /**
+ * Set the the relevant metadata file structure so that metadata files
+ * containing class names can be parsed. Null attribute names indicate
+ * that the text content of the element contains the data.
+ */
+ public void setMetaDataStructure(String packageElementName,
+ String packageAttributeName, String[] classElementNames,
+ String classAttributeName) {
+ // calculate how many chars deep we have to go to identify each element
+ // name as unique. this is extremely inefficient for large N, but
+ // should never be called for more than a few elements
+ char[] buf = new char[classElementNames.length + 1];
+ int charIdx = 0;
+
+ for (; true; charIdx++) {
+ for (int i = 0; i < buf.length; i++) {
+ if (i == 0) {
+ if (charIdx == packageElementName.length()) {
+ throw new UnsupportedOperationException(_loc.get(
+ "cant-diff-elems"));
+ }
+
+ buf[i] = packageElementName.charAt(charIdx);
+ } else {
+ if (charIdx == classElementNames[i - 1].length()) {
+ throw new UnsupportedOperationException(_loc.get(
+ "cant-diff-elems"));
+ }
+
+ buf[i] = classElementNames[i - 1].charAt(charIdx);
+ }
+ }
+
+ if (charsUnique(buf)) {
+ break;
+ }
+ }
+
+ _packageAttr = (packageAttributeName == null) ? null
+ : packageAttributeName.toCharArray();
+ _classAttr = (classAttributeName == null) ? null
+ : classAttributeName.toCharArray();
+ _beginElements = new char[classElementNames.length + 1][];
+ _endElements = new char[classElementNames.length + 1][];
+ _beginElements[0] = packageElementName.substring(0, charIdx + 1)
+ .toCharArray();
+ _endElements[0] = packageElementName.substring(charIdx + 1).toCharArray();
+
+ for (int i = 0; i < classElementNames.length; i++) {
+ _beginElements[i + 1] = classElementNames[i].substring(0,
+ charIdx + 1).toCharArray();
+ _endElements[i + 1] = classElementNames[i].substring(charIdx + 1)
+ .toCharArray();
+ }
+ }
+
+ /**
+ * Return true if all characters in given buffer are unique.
+ */
+ private static boolean charsUnique(char[] buf) {
+ for (int i = buf.length - 1; i >= 0; i--)
+ for (int j = 0; j < i; j++)
+ if (buf[j] == buf[i]) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Return the {@link Class} representation of the class(es) named in the
+ * given arg.
+ *
+ * @param arg a class name, .java file, .class file, or metadata
+ * file naming the type(s) to act on
+ */
+ public Class[] parseTypes(String arg) {
+ String[] names = parseTypeNames(arg);
+ Class[] objs = new Class[names.length];
+
+ for (int i = 0; i < names.length; i++)
+ objs[i] = Strings.toClass(names[i], _loader);
+
+ return objs;
+ }
+
+ /**
+ * Return the {@link Class} representation of the class(es) named in the
+ * given metadatas.
+ */
+ public Class[] parseTypes(MetaDataIterator itr) {
+ String[] names = parseTypeNames(itr);
+ Class[] objs = new Class[names.length];
+
+ for (int i = 0; i < names.length; i++)
+ objs[i] = Strings.toClass(names[i], _loader);
+
+ return objs;
+ }
+
+ /**
+ * Return a mapping of each metadata resource to an array of its
+ * contained classes.
+ */
+ public Map mapTypes(MetaDataIterator itr) {
+ Map map = mapTypeNames(itr);
+ Map.Entry entry;
+ String[] names;
+ Class[] objs;
+
+ for (Iterator i = map.entrySet().iterator(); i.hasNext();) {
+ entry = (Map.Entry) i.next();
+ names = (String[]) entry.getValue();
+ objs = new Class[names.length];
+
+ for (int j = 0; j < names.length; j++)
+ objs[j] = Strings.toClass(names[j], _loader);
+
+ entry.setValue(objs);
+ }
+
+ return map;
+ }
+
+ /**
+ * Return the names of the class(es) from the given arg.
+ *
+ * @param arg a class name, .java file, .class file, or metadata
+ * file naming the type(s) to act on
+ * @throws IllegalArgumentException with appropriate message on error
+ */
+ public String[] parseTypeNames(String arg) {
+ if (arg == null) {
+ return new String[0];
+ }
+
+ try {
+ File file = Files.getFile(arg, _loader);
+
+ if (arg.endsWith(".class")) {
+ return new String[] { getFromClassFile(file) };
+ }
+
+ if (arg.endsWith(".java")) {
+ return new String[] { getFromJavaFile(file) };
+ }
+
+ if (file.exists()) {
+ Collection col = getFromMetaDataFile(file);
+
+ return (String[]) col.toArray(new String[col.size()]);
+ }
+ } catch (Exception e) {
+ throw new NestableRuntimeException(_loc.get("class-arg", arg), e);
+ }
+
+ // must be a class name
+ return new String[] { arg };
+ }
+
+ /**
+ * Return the names of the class(es) from the given metadatas.
+ */
+ public String[] parseTypeNames(MetaDataIterator itr) {
+ if (itr == null) {
+ return new String[0];
+ }
+
+ List names = new ArrayList();
+ Object source = null;
+
+ try {
+ while (itr.hasNext()) {
+ source = itr.next();
+ appendTypeNames(source, itr.getInputStream(), names);
+ }
+ } catch (Exception e) {
+ throw new NestableRuntimeException(_loc.get("class-arg", source), e);
+ }
+
+ return (String[]) names.toArray(new String[names.size()]);
+ }
+
+ /**
+ * Parse the names in the given metadata iterator stream, closing the
+ * stream on completion.
+ */
+ private void appendTypeNames(Object source, InputStream in, List names)
+ throws IOException {
+ try {
+ if (source.toString().endsWith(".class")) {
+ names.add(getFromClass(in));
+ }
+
+ names.addAll(getFromMetaData(new InputStreamReader(in)));
+ } finally {
+ try {
+ in.close();
+ } catch (IOException ioe) {
+ }
+ }
+ }
+
+ /**
+ * Return a mapping of each metadata resource to an array of its contained
+ * class names.
+ */
+ public Map mapTypeNames(MetaDataIterator itr) {
+ if (itr == null) {
+ return Collections.EMPTY_MAP;
+ }
+
+ Map map = new HashMap();
+ Object source = null;
+ List names = new ArrayList();
+
+ try {
+ while (itr.hasNext()) {
+ source = itr.next();
+ appendTypeNames(source, itr.getInputStream(), names);
+
+ if (!names.isEmpty()) {
+ map.put(source,
+ (String[]) names.toArray(new String[names.size()]));
+ }
+
+ names.clear();
+ }
+ } catch (Exception e) {
+ throw new NestableRuntimeException(_loc.get("class-arg", source), e);
+ }
+
+ return map;
+ }
+
+ /**
+ * Returns the class named in the given .class file.
+ */
+ private String getFromClassFile(File file) throws IOException {
+ FileInputStream fin = null;
+
+ try {
+ fin = new FileInputStream(file);
+
+ return getFromClass(fin);
+ } finally {
+ if (fin != null) {
+ try {
+ fin.close();
+ } catch (IOException ioe) {
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the class name in the given .class bytecode.
+ */
+ private String getFromClass(InputStream in) throws IOException {
+ ConstantPoolTable table = new ConstantPoolTable(in);
+ int idx = table.getEndIndex();
+ idx += 2; // access flags
+
+ int clsEntry = table.readUnsignedShort(idx);
+ int utfEntry = table.readUnsignedShort(table.get(clsEntry));
+
+ return table.readString(table.get(utfEntry)).replace('/', '.');
+ }
+
+ /**
+ * Returns the class named in the given .java file.
+ */
+ private String getFromJavaFile(File file) throws IOException {
+ BufferedReader in = null;
+
+ try {
+ // find the line with the package declaration
+ in = new BufferedReader(new FileReader(file));
+
+ String line;
+ StringBuffer pack = null;
+
+ while ((line = in.readLine()) != null) {
+ line = line.trim();
+
+ if (line.startsWith("package ")) {
+ line = line.substring(8).trim();
+
+ // strip off anything beyond the package declaration
+ pack = new StringBuffer();
+
+ for (int i = 0; i < line.length(); i++) {
+ if (Character.isJavaIdentifierPart(line.charAt(i)) ||
+ (line.charAt(i) == '.')) {
+ pack.append(line.charAt(i));
+ } else {
+ break;
+ }
+ }
+
+ break;
+ }
+ }
+
+ // strip '.java'
+ String clsName = file.getName();
+ clsName = clsName.substring(0, clsName.length() - 5);
+
+ // prefix with package
+ if ((pack != null) && (pack.length() > 0)) {
+ clsName = pack + "." + clsName;
+ }
+
+ return clsName;
+ } finally {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException ioe) {
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the classes named in the given common format metadata file.
+ */
+ private Collection getFromMetaDataFile(File file) throws IOException {
+ FileReader in = null;
+
+ try {
+ in = new FileReader(file);
+
+ return getFromMetaData(in);
+ } finally {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException ioe) {
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the classes named in the given common format metadata stream.
+ */
+ private Collection getFromMetaData(Reader xml) throws IOException {
+ Collection names = new ArrayList();
+ BufferedReader in = new BufferedReader(xml);
+
+ boolean comment = false;
+ int token = TOKEN_NONE;
+ String pkg = "";
+ String name;
+read:
+ for (int ch = 0, last = 0, last2 = 0;
+ (ch == '<') || ((ch = in.read()) != -1);
+ last2 = last, last = ch) {
+ // handle comments
+ if (comment && (last2 == '-') && (last == '-') && (ch == '>')) {
+ comment = false;
+
+ continue;
+ }
+
+ if (comment) {
+ if (ch == '<') {
+ ch = in.read();
+
+ if (ch == -1) {
+ break read;
+ }
+ }
+
+ continue;
+ }
+
+ if ((last2 == '<') && (last == '!') && (ch == '-')) {
+ comment = true;
+
+ continue;
+ }
+
+ // if not an element start, skip it
+ if (ch != '<') {
+ continue;
+ }
+
+ token = TOKEN_NONE; // reset token
+ last = ch; // update needed for comment detection
+ ch = readThroughWhitespace(in);
+
+ if ((ch == '/') || (ch == '!') || (ch == '?')) {
+ continue;
+ }
+
+ // read element name; look for packages and classes
+ token = readElementToken(ch, in);
+
+ switch (token) {
+ case TOKEN_EOF:
+ break read;
+
+ case TOKEN_PACKAGE:
+ pkg = readAttribute(in, _packageAttr);
+
+ if (pkg == null) {
+ break read;
+ }
+
+ break;
+
+ case TOKEN_PACKAGE_NOATTR:
+ pkg = readElementText(in);
+
+ if (pkg == null) {
+ break read;
+ }
+
+ ch = '<'; // reading element text reads to next '<'
+
+ break;
+
+ case TOKEN_CLASS:
+ name = readAttribute(in, _classAttr);
+
+ if (name == null) {
+ break read;
+ }
+
+ if ((pkg.length() > 0) && (name.indexOf('.') == -1)) {
+ names.add(pkg + "." + name);
+ } else {
+ names.add(name);
+ }
+
+ break;
+
+ case TOKEN_CLASS_NOATTR:
+ name = readElementText(in);
+
+ if (name == null) {
+ break read;
+ }
+
+ ch = '<'; // reading element text reads to next '<'
+
+ if ((pkg.length() > 0) && (name.indexOf('.') == -1)) {
+ names.add(pkg + "." + name);
+ } else {
+ names.add(name);
+ }
+
+ break;
+ }
+ }
+
+ return names;
+ }
+
+ /**
+ * Read the name of the current XML element and return the matching token.
+ */
+ private int readElementToken(int ch, Reader in) throws IOException {
+ // look through the beginning element names to find what element this
+ // might be (if any)
+ int matchIdx = -1;
+ int matched = 0;
+ int dq = 0;
+
+ for (int beginIdx = 0; beginIdx < _beginElements[0].length;
+ beginIdx++) {
+ if (beginIdx != 0) {
+ ch = in.read();
+ }
+
+ if (ch == -1) {
+ return TOKEN_EOF;
+ }
+
+ matched = 0;
+
+ for (int i = 0; i < _beginElements.length; i++) {
+ if ((dq & (2 << i)) != 0) {
+ continue;
+ }
+
+ if (ch == _beginElements[i][beginIdx]) {
+ matchIdx = i;
+ matched++;
+ } else {
+ dq |= (2 << i);
+ }
+ }
+
+ if (matched == 0) {
+ break;
+ }
+ }
+
+ if (matched != 1) {
+ return TOKEN_NONE;
+ }
+
+ // make sure the rest of the element name matches
+ char[] match = _endElements[matchIdx];
+
+ for (int i = 0; i < match.length; i++) {
+ ch = in.read();
+
+ if (ch == -1) {
+ return TOKEN_EOF;
+ }
+
+ if (ch != match[i]) {
+ return TOKEN_NONE;
+ }
+ }
+
+ // read the next char to make sure we finished the element name
+ ch = in.read();
+
+ if (ch == -1) {
+ return TOKEN_EOF;
+ }
+
+ if (ch == '>') {
+ if ((matchIdx == 0) && (_packageAttr == null)) {
+ return TOKEN_PACKAGE_NOATTR;
+ }
+
+ if ((matchIdx != 0) && (_classAttr == null)) {
+ return TOKEN_CLASS_NOATTR;
+ }
+ } else if (Character.isWhitespace((char) ch)) {
+ if ((matchIdx == 0) && (_packageAttr != null)) {
+ return TOKEN_PACKAGE;
+ }
+
+ if ((matchIdx != 0) && (_classAttr != null)) {
+ return TOKEN_CLASS;
+ }
+ }
+
+ return TOKEN_NONE;
+ }
+
+ /**
+ * Read the attribute with the given name in chars of the current XML
+ * element.
+ */
+ private String readAttribute(Reader in, char[] name)
+ throws IOException {
+ int expected = 0;
+
+ for (int ch, last = 0; true; last = ch) {
+ ch = in.read();
+
+ if (ch == -1) {
+ return null;
+ }
+
+ if (ch == '>') {
+ return "";
+ }
+
+ // if not expected char or still looking for 'n' and previous
+ // char is not whitespace, keep looking
+ if ((ch != name[expected]) ||
+ ((expected == 0) && (last != 0) &&
+ !Character.isWhitespace((char) last))) {
+ expected = 0;
+
+ continue;
+ }
+
+ // found expected char; have we found the whole "name"?
+ expected++;
+
+ if (expected == name.length) {
+ // make sure the next char is '='
+ ch = readThroughWhitespace(in);
+
+ if (ch == -1) {
+ return null;
+ }
+
+ if (ch != '=') {
+ expected = 0;
+
+ continue;
+ }
+
+ // toss out any subsequent whitespace and the next char, which
+ // is the opening quote for the attr value, then read until the
+ // closing quote
+ readThroughWhitespace(in);
+
+ return readAttributeValue(in);
+ }
+ }
+ }
+
+ /**
+ * Read the current text value until the next element.
+ */
+ private String readElementText(Reader in) throws IOException {
+ StringBuffer buf = null;
+ int ch;
+
+ while (true) {
+ ch = in.read();
+
+ if (ch == -1) {
+ return null;
+ }
+
+ if (ch == '<') {
+ break;
+ }
+
+ if (Character.isWhitespace((char) ch)) {
+ continue;
+ }
+
+ if (buf == null) {
+ buf = new StringBuffer();
+ }
+
+ buf.append((char) ch);
+ }
+
+ return (buf == null) ? "" : buf.toString();
+ }
+
+ /**
+ * Read until the next non-whitespace character.
+ */
+ private int readThroughWhitespace(Reader in) throws IOException {
+ int ch;
+
+ while (true) {
+ ch = in.read();
+
+ if ((ch == -1) || !Character.isWhitespace((char) ch)) {
+ return ch;
+ }
+ }
+ }
+
+ /**
+ * Return the current attribute value.
+ */
+ private String readAttributeValue(Reader in) throws IOException {
+ StringBuffer buf = new StringBuffer();
+ int ch;
+
+ while (true) {
+ ch = in.read();
+
+ if (ch == -1) {
+ return null;
+ }
+
+ if ((ch == '\'') || (ch == '"')) {
+ return buf.toString();
+ }
+
+ buf.append((char) ch);
+ }
+ }
}
Modified: incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/meta/ClassMetaDataIterator.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/meta/ClassMetaDataIterator.java?rev=417856&r1=415364&r2=417856&view=diff
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/meta/ClassMetaDataIterator.java (original)
+++ incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/meta/ClassMetaDataIterator.java Wed Jun 28 12:34:33 2006
@@ -15,186 +15,184 @@
*/
package org.apache.openjpa.lib.meta;
-
-import java.io.*;
-import java.net.*;
-import java.util.*;
+import org.apache.commons.collections.set.*;
import org.apache.openjpa.lib.util.*;
import serp.util.*;
+import java.io.*;
+
+import java.net.*;
+
+import java.util.*;
+
/**
- * <p>Iterator over all metadata resources that might contain the
- * metadata for a given class, starting with the most general. Assumes that
- * package-level resources are named "package.<suffix>".</p>
+ * <p>Iterator over all metadata resources that might contain the
+ * metadata for a given class, starting with the most general. Assumes that
+ * package-level resources are named "package.<suffix>".</p>
*
- * @author Abe White
- * @nojavadoc
- */
-public class ClassMetaDataIterator
- implements MetaDataIterator
-{
- private final ClassLoader _loader;
- private final List _locs;
- private int _loc = -1;
- private final List _urls = new ArrayList (3);
- private int _url = -1;
-
-
- /**
- * Constructor; supply the class whose metadata to find, the suffix
- * of metadata files, and whether to parse top-down or bottom-up.
- */
- public ClassMetaDataIterator (Class cls, String suffix, boolean topDown)
- {
- this (cls, suffix, null, topDown);
- }
-
-
- /**
- * Constructor; supply the class whose metadata to find, the suffix
- * of metadata files, and whether to parse top-down or bottom-up.
- */
- public ClassMetaDataIterator (Class cls, String suffix, ClassLoader loader,
- boolean topDown)
- {
- // skip classes that can't have metadata
- if (cls != null && (cls.isPrimitive ()
- || cls.getName ().startsWith ("java.")
- || cls.getName ().startsWith ("javax.")))
- {
- _loader = null;
- _locs = Collections.EMPTY_LIST;
- return;
- }
-
- if (loader == null)
- {
- MultiClassLoader multi = new MultiClassLoader ();
- multi.addClassLoader (multi.SYSTEM_LOADER);
- multi.addClassLoader (multi.THREAD_LOADER);
- multi.addClassLoader (getClass ().getClassLoader ());
- if (cls != null && cls.getClassLoader () != null)
- multi.addClassLoader (cls.getClassLoader ());
- loader = multi;
- }
- _loader = loader;
-
- // collect the set of all possible metadata locations; start with
- // system locations
- _locs = new ArrayList ();
- _locs.add ("META-INF/package" + suffix);
- _locs.add ("WEB-INF/package" + suffix);
- _locs.add ("package" + suffix);
-
- // put this legacy location at the end regardless of whether we're
- // going top down or bottom up so we don't have to parse it as often
- // during testing
- if (!topDown)
- _locs.add ("system" + suffix);
-
- if (cls != null)
- {
- // also check:
- // 1. for each package from the top down to cls' package:
- // <path>/package<suffix>
- // <path>/<package-name><suffix> (legacy support)
- // <path>/../<package-name><suffix> (legacy support)
- // 2. <path>/<class-name><suffix>
- String pkg = Strings.getPackageName (cls).replace ('.', '/');
- if (pkg.length () > 0)
- {
- int idx, start = 0;
- String pkgName, path, upPath = "";
- do
- {
- idx = pkg.indexOf ('/', start);
- if (idx == -1)
- {
- pkgName = (start == 0) ? pkg : pkg.substring (start);
- path = pkg + "/";
- }
- else
- {
- pkgName = pkg.substring (start, idx);
- path = pkg.substring (0, idx + 1);
- }
-
- _locs.add (path + "package" + suffix);
- _locs.add (path + pkgName + suffix); // legacy
- _locs.add (upPath + pkgName + suffix); // legacy
- if (idx == -1)
- _locs.add (path + Strings.getClassName (cls) + suffix);
-
- start = idx + 1;
- upPath = path;
- }
- while (idx != -1);
- }
- else
- {
- // <class-name><suffix> for top-level classes
- _locs.add (cls.getName () + suffix);
- }
- }
- if (topDown)
- _locs.add ("system" + suffix); // legacy
- else
- Collections.reverse (_locs);
- }
-
-
- public boolean hasNext ()
- throws IOException
- {
- Enumeration e;
- while (_url + 1 >= _urls.size ())
- {
- if (++_loc >= _locs.size ())
- return false;
-
- _url = -1;
- _urls.clear ();
- e = _loader.getResources ((String) _locs.get (_loc));
- while (e.hasMoreElements ())
- _urls.add (e.nextElement ());
- }
- return true;
- }
-
-
- public Object next ()
- throws IOException
- {
- if (!hasNext ())
- throw new NoSuchElementException ();
- return _urls.get (++_url);
- }
-
-
- public InputStream getInputStream ()
- throws IOException
- {
- if (_url == -1 || _url >= _urls.size ())
- throw new IllegalStateException ();
- return ((URL) _urls.get (_url)).openStream ();
- }
-
-
- public File getFile ()
- throws IOException
- {
- if (_url == -1 || _url >= _urls.size ())
- throw new IllegalStateException ();
- File file = new File (URLDecoder.decode (((URL) _urls.get (_url)).
- getFile ()));
- return (file.exists ()) ? file : null;
- }
-
-
- public void close ()
- {
- }
+ * @author Abe White
+ * @nojavadoc */
+public class ClassMetaDataIterator implements MetaDataIterator {
+ private final ClassLoader _loader;
+ private final List _locs;
+ private int _loc = -1;
+ private final List _urls = new ArrayList(3);
+ private int _url = -1;
+ private URL _last = null;
+
+ /**
+ * Constructor; supply the class whose metadata to find, the suffix
+ * of metadata files, and whether to parse top-down or bottom-up.
+ */
+ public ClassMetaDataIterator(Class cls, String suffix, boolean topDown) {
+ this(cls, suffix, null, topDown);
+ }
+
+ /**
+ * Constructor; supply the class whose metadata to find, the suffix
+ * of metadata files, and whether to parse top-down or bottom-up.
+ */
+ public ClassMetaDataIterator(Class cls, String suffix, ClassLoader loader,
+ boolean topDown) {
+ // skip classes that can't have metadata
+ if ((cls != null) &&
+ (cls.isPrimitive() || cls.getName().startsWith("java.") ||
+ cls.getName().startsWith("javax."))) {
+ _loader = null;
+ _locs = Collections.EMPTY_LIST;
+
+ return;
+ }
+
+ if (loader == null) {
+ MultiClassLoader multi = new MultiClassLoader();
+ multi.addClassLoader(multi.SYSTEM_LOADER);
+ multi.addClassLoader(multi.THREAD_LOADER);
+ multi.addClassLoader(getClass().getClassLoader());
+
+ if ((cls != null) && (cls.getClassLoader() != null)) {
+ multi.addClassLoader(cls.getClassLoader());
+ }
+
+ loader = multi;
+ }
+
+ _loader = loader;
+
+ // collect the set of all possible metadata locations; start with
+ // system locations
+ _locs = new ArrayList();
+ _locs.add("META-INF/package" + suffix);
+ _locs.add("WEB-INF/package" + suffix);
+ _locs.add("package" + suffix);
+
+ // put this legacy location at the end regardless of whether we're
+ // going top down or bottom up so we don't have to parse it as often
+ // during testing
+ if (!topDown) {
+ _locs.add("system" + suffix);
+ }
+
+ if (cls != null) {
+ // also check:
+ // 1. for each package from the top down to cls' package:
+ // <path>/package<suffix>
+ // <path>/<package-name><suffix> (legacy support)
+ // <path>/../<package-name><suffix> (legacy support)
+ // 2. <path>/<class-name><suffix>
+ String pkg = Strings.getPackageName(cls).replace('.', '/');
+
+ if (pkg.length() > 0) {
+ int idx;
+ int start = 0;
+ String pkgName;
+ String path;
+ String upPath = "";
+
+ do {
+ idx = pkg.indexOf('/', start);
+
+ if (idx == -1) {
+ pkgName = (start == 0) ? pkg : pkg.substring(start);
+ path = pkg + "/";
+ } else {
+ pkgName = pkg.substring(start, idx);
+ path = pkg.substring(0, idx + 1);
+ }
+
+ _locs.add(path + "package" + suffix);
+ _locs.add(path + pkgName + suffix); // legacy
+ _locs.add(upPath + pkgName + suffix); // legacy
+
+ if (idx == -1) {
+ _locs.add(path + Strings.getClassName(cls) + suffix);
+ }
+
+ start = idx + 1;
+ upPath = path;
+ } while (idx != -1);
+ } else {
+ // <class-name><suffix> for top-level classes
+ _locs.add(cls.getName() + suffix);
+ }
+ }
+
+ if (topDown) {
+ _locs.add("system" + suffix); // legacy
+ } else {
+ Collections.reverse(_locs);
+ }
+ }
+
+ public boolean hasNext() throws IOException {
+ Enumeration e;
+
+ while ((_url + 1) >= _urls.size()) {
+ if (++_loc >= _locs.size()) {
+ return false;
+ }
+
+ _url = -1;
+ _urls.clear();
+ e = _loader.getResources((String) _locs.get(_loc));
+
+ while (e.hasMoreElements())
+ _urls.add(e.nextElement());
+ }
+
+ return true;
+ }
+
+ public Object next() throws IOException {
+ if (!hasNext()) {
+ throw new NoSuchElementException();
+ }
+
+ return _urls.get(++_url);
+ }
+
+ public InputStream getInputStream() throws IOException {
+ if ((_url == -1) || (_url >= _urls.size())) {
+ throw new IllegalStateException();
+ }
+
+ return ((URL) _urls.get(_url)).openStream();
+ }
+
+ public File getFile() throws IOException {
+ if ((_url == -1) || (_url >= _urls.size())) {
+ throw new IllegalStateException();
+ }
+
+ File file = new File(URLDecoder.decode(
+ ((URL) _urls.get(_url)).getFile()));
+
+ return (file.exists()) ? file : null;
+ }
+
+ public void close() {
+ }
}
Modified: incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/meta/ClasspathMetaDataIterator.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/meta/ClasspathMetaDataIterator.java?rev=417856&r1=415364&r2=417856&view=diff
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/meta/ClasspathMetaDataIterator.java (original)
+++ incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/meta/ClasspathMetaDataIterator.java Wed Jun 28 12:34:33 2006
@@ -15,71 +15,69 @@
*/
package org.apache.openjpa.lib.meta;
+import serp.util.*;
import java.io.*;
+
import java.util.*;
import java.util.zip.*;
-import serp.util.*;
-
/**
- * <p>Iterator over directories in the classpath.</p>
+ * <p>Iterator over directories in the classpath.</p>
*
- * @author Abe White
- * @nojavadoc
- */
-public class ClasspathMetaDataIterator
- extends MetaDataIteratorChain
-{
- /**
- * Default constructor; iterates over all classpath elements.
- */
- public ClasspathMetaDataIterator ()
- throws IOException
- {
- this (null, null);
- }
-
-
- /**
- * Constructor; supply the classpath directories to scan and an optional
- * resource filter. The given directories may be null to scan all
- * classpath directories.
- */
- public ClasspathMetaDataIterator (String[] dirs, MetaDataFilter filter)
- throws IOException
- {
- Properties props = System.getProperties ();
- String path = props.getProperty ("java.class.path");
- String[] tokens = Strings.split (path,
- props.getProperty ("path.separator"), 0);
-
- for (int i = 0; i < tokens.length; i++)
- {
- if (dirs != null && dirs.length != 0 && !endsWith (tokens[i], dirs))
- continue;
-
- File file = new File (tokens[i]);
- if (!file.exists ())
- continue;
- if (file.isDirectory ())
- addIterator (new FileMetaDataIterator (file, filter));
- else if (tokens[i].endsWith (".jar"))
- addIterator (new ZipFileMetaDataIterator (new ZipFile (file),
- filter));
- }
- }
-
-
- /**
- * Return true if the given token ends with any of the given strings.
- */
- private static boolean endsWith (String token, String[] suffs)
- {
- for (int i = 0; i < suffs.length; i++)
- if (token.endsWith (suffs[i]))
- return true;
- return false;
- }
+ * @author Abe White
+ * @nojavadoc */
+public class ClasspathMetaDataIterator extends MetaDataIteratorChain {
+ /**
+ * Default constructor; iterates over all classpath elements.
+ */
+ public ClasspathMetaDataIterator() throws IOException {
+ this(null, null);
+ }
+
+ /**
+ * Constructor; supply the classpath directories to scan and an optional
+ * resource filter. The given directories may be null to scan all
+ * classpath directories.
+ */
+ public ClasspathMetaDataIterator(String[] dirs, MetaDataFilter filter)
+ throws IOException {
+ Properties props = System.getProperties();
+ String path = props.getProperty("java.class.path");
+ String[] tokens = Strings.split(path,
+ props.getProperty("path.separator"), 0);
+
+ for (int i = 0; i < tokens.length; i++) {
+ if ((dirs != null) && (dirs.length != 0) &&
+ !endsWith(tokens[i], dirs)) {
+ continue;
+ }
+
+ File file = new File(tokens[i]);
+
+ if (!file.exists()) {
+ continue;
+ }
+
+ if (file.isDirectory()) {
+ addIterator(new FileMetaDataIterator(file, filter));
+ } else if (tokens[i].endsWith(".jar")) {
+ addIterator(new ZipFileMetaDataIterator(new ZipFile(file),
+ filter));
+ }
+ }
+ }
+
+ /**
+ * Return true if the given token ends with any of the given strings.
+ */
+ private static boolean endsWith(String token, String[] suffs) {
+ for (int i = 0; i < suffs.length; i++)
+ if (token.endsWith(suffs[i])) {
+ return true;
+ }
+
+ return false;
+ }
}