openjpa-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From p..@apache.org
Subject svn commit: r406215 [5/10] - in /incubator/openjpa/trunk/openjpa-lib: ./ java/ java/org/ java/org/apache/ java/org/apache/openjpa/ java/org/apache/openjpa/lib/ java/org/apache/openjpa/lib/conf/ java/org/apache/openjpa/lib/jdbc/ java/org/apache/openjpa/...
Date Sun, 14 May 2006 03:26:02 GMT
Propchange: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/log/LogFactory.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/log/LogFactoryAdapter.java
URL: http://svn.apache.org/viewcvs/incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/log/LogFactoryAdapter.java?rev=406215&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/log/LogFactoryAdapter.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/log/LogFactoryAdapter.java Sat May 13 20:25:56 2006
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openjpa.lib.log;
+
+
+import java.util.*;
+
+
+/**
+ *	<p>Base type that aids in adapting an external log framework to the 
+ *	{@link LogFactory}.</p> 
+ *
+ *	@author	Abe White
+ */	
+public abstract class LogFactoryAdapter
+	implements LogFactory
+{
+	// cache category to log adapters
+	private Map _logs = new HashMap ();
+
+
+	public synchronized Log getLog (String channel)
+	{
+		Log log = (Log) _logs.get (channel);
+		if (log == null)
+		{
+			log = newLogAdapter (channel);
+			_logs.put (channel, log);
+		}
+		return log;
+	}
+
+
+	/**
+	 *	Return a log adapter for the given channel.
+	 */
+	protected abstract Log newLogAdapter (String channel);
+}

Propchange: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/log/LogFactoryAdapter.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/log/LogFactoryImpl.java
URL: http://svn.apache.org/viewcvs/incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/log/LogFactoryImpl.java?rev=406215&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/log/LogFactoryImpl.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/log/LogFactoryImpl.java Sat May 13 20:25:56 2006
@@ -0,0 +1,382 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openjpa.lib.log;
+
+
+import java.io.*;
+import java.util.*;
+
+import org.apache.openjpa.lib.conf.*;
+import org.apache.openjpa.lib.util.*;
+
+
+/**
+ *	Default {@link LogFactory} implementation.  For ease of automatic
+ *	configuration, this implementation keys on only the last dot-separated 
+ *	token of the log channel name.
+ *
+ *	@author	Patrick Linskey
+ */
+public class LogFactoryImpl
+	implements LogFactory, GenericConfigurable
+{
+	private static Localizer _loc = Localizer.forPackage (LogFactoryImpl.class);
+
+	public static final String TRACE_STR = _loc.get ("log-trace");
+	public static final String DEBUG_STR = _loc.get ("log-debug");
+	public static final String INFO_STR = _loc.get ("log-info");
+	public static final String WARN_STR = _loc.get ("log-warn");
+	public static final String ERROR_STR = _loc.get ("log-error");
+	public static final String FATAL_STR = _loc.get ("log-fatal");
+
+	public static final String STDOUT = "stdout";
+	public static final String STDERR = "stderr";
+
+	private static final String NEWLINE = System.getProperty ("line.separator");
+
+
+	/**
+	 *	The time at which this factory was initialized.
+	 */
+	protected final long initializationMillis;
+
+
+	/**
+	 *	The {@link Log}s that this factory manages, keyed by log
+	 *	channel name.
+	 */
+	private Map _logs = new HashMap (); // HashMap<String,Log>
+
+
+	/**
+	 *	The default logging level.
+	 */
+	private short _defaultLogLevel = Log.INFO;
+
+
+	private String _diagContext = null;
+
+
+	/**
+	 *	Storage for logging level configuration specified at
+	 *	configuration time.
+	 */
+	private Map _configuredLevels = new HashMap (); // HashMap<String,Integer>
+
+
+	/**
+	 *	The stream to write to.  Defaults to System.err.
+	 */
+	private PrintStream _out = System.err;
+
+
+	public LogFactoryImpl ()
+	{
+		initializationMillis = System.currentTimeMillis ();
+	}
+
+
+	public synchronized Log getLog (String channel)
+	{
+		LogImpl l = (LogImpl) _logs.get (channel);
+		if (l == null)
+		{
+			l = newLogImpl ();
+			l.setChannel (channel);
+			Short lvl = (Short) _configuredLevels.get (shorten (channel));
+			l.setLevel (lvl == null ? _defaultLogLevel : lvl.shortValue ());
+			_logs.put (channel, l);
+		}
+		return l;
+	}
+
+
+	/**
+	 *	Create a new log.  The log will be cached.
+	 */
+	protected LogImpl newLogImpl ()
+	{
+		return new LogImpl ();
+	}
+
+
+	/**
+	 *	The string name of the default level for unconfigured log channels;
+	 *	used for automatic configuration.
+	 */
+	public void setDefaultLevel (String level)
+	{
+		_defaultLogLevel = getLevel (level);
+	}
+
+
+	/**
+	 *	The default level for unconfigured log channels.
+	 */
+	public short getDefaultLevel ()
+	{
+		return _defaultLogLevel;
+	}
+
+
+	/**
+	 *	The default level for unconfigured log channels.
+	 */
+	public void setDefaultLevel (short level)
+	{
+		_defaultLogLevel = level;
+	}
+
+
+	/**
+	 *	A string to prefix all log messages with. Set to
+	 *	<code>null</code> for no prefix.
+	 */
+	public void setDiagnosticContext (String val)
+	{
+		_diagContext = val;
+	}
+
+
+	/**
+	 *	A string to prefix all log messages with. Set to
+	 *	<code>null</code> for no prefix.
+	 */
+	public String getDiagnosticContext ()
+	{
+		return _diagContext;
+	}
+
+
+	/**
+	 *	The stream to write to.  Recognized values are: <code>stdout</code>
+	 *	and <code>stderr</code>.   Any other value will be considered a 
+	 *	file name.
+	 */
+	public void setFile (String file)
+	{
+		if (STDOUT.equals (file))
+			_out = System.out;
+		else if (STDERR.equals (file))
+			_out = System.err;
+		else
+		{
+			File f = Files.getFile (file, null);
+			try
+			{
+				_out = new PrintStream (new FileOutputStream 
+					(f.getCanonicalPath (), true));
+			}
+			catch (IOException ioe)
+			{
+				throw new IllegalArgumentException (_loc.get ("log-bad-file",
+					file) + " " + ioe.toString ());
+			}
+		} 
+	} 
+
+
+	/**
+	 *	The stream to write to.
+	 */
+	public PrintStream getStream ()
+	{
+		return _out;
+	}
+
+
+	/**
+	 *	The stream to write to.
+	 */
+	public void setStream (PrintStream stream)
+	{
+		if (stream == null)
+			throw new NullPointerException ("stream == null");
+		_out = stream;
+	}
+
+
+	/** 
+	 *  Returns a string representation of the specified log level constant.
+	 */
+	public static String getLevelName (short level)
+	{
+		switch (level)
+		{
+		case Log.TRACE:
+			return TRACE_STR;
+		case Log.DEBUG:
+			return DEBUG_STR;
+		case Log.INFO:
+			return INFO_STR;
+		case Log.WARN:
+			return WARN_STR;
+		case Log.ERROR:
+			return ERROR_STR;
+		case Log.FATAL:
+			return FATAL_STR;
+		default:
+			return _loc.get ("log-unknown");
+		}
+	}
+
+
+	/** 
+	 *  Returns a symbolic constant for the specified string level.
+	 */
+	public static short getLevel (String str)
+	{
+		str = str.toUpperCase ().trim ();
+		short val = 
+			TRACE_STR.equals (str) 	? Log.TRACE	:
+			DEBUG_STR.equals (str) 	? Log.DEBUG	:
+			INFO_STR.equals (str) 	? Log.INFO 	:
+			WARN_STR.equals (str) 	? Log.WARN	:
+			ERROR_STR.equals (str) 	? Log.ERROR	:
+			FATAL_STR.equals (str) 	? Log.FATAL	: -1;
+
+		if (val == -1)
+			throw new IllegalArgumentException 
+				(_loc.get ("log-bad-constant", str));
+
+		return val;
+	}
+
+
+	// ---------- GenericConfigurable implementation ----------
+
+	public void setInto (Map m)
+	{
+		if (!m.isEmpty ())
+		{
+			Map.Entry e;
+			for (Iterator iter = m.entrySet ().iterator (); iter.hasNext (); )
+			{
+				e = (Map.Entry) iter.next ();
+				_configuredLevels.put (shorten ((String) e.getKey ()),
+					new Short (getLevel ((String) e.getValue ())));
+			}
+			m.clear ();
+		}
+	}
+
+
+	private static String shorten (String channel)
+	{
+		return channel.substring (channel.lastIndexOf ('.') + 1);
+	}
+
+
+	/** 
+	 *  A simple implementation of the {@link Log} interface. Writes
+	 *  output to stderr.
+	 */
+	public class LogImpl
+		extends AbstractLog
+	{
+		private short 	_level = INFO;
+		private String 	_channel;
+
+
+		protected boolean isEnabled (short level)
+		{
+			return level >= _level;
+		}
+
+
+		protected void log (short level, String message, Throwable t)
+		{
+			String msg = formatMessage (level, message, t);
+			synchronized (_out)
+			{
+				_out.print (msg);
+			}
+		}
+
+
+		/**
+		 *	Convert <code>message</code> into a string ready to be written to
+		 *	the log.  The string should include the terminating newline.
+	 	 *
+		 *	@param	t	may be null
+		 */
+		protected String formatMessage (short level, String message, 
+			Throwable t)
+		{
+			// we write to a StringBuffer and then flush it all at
+			// once as a single line, since some environments (e.g., JBoss)
+			// override the System output stream to flush any calls
+			// to write without regard to line breaks, making the
+			// output incomprehensibe.
+			StringBuffer buf = new StringBuffer ();
+
+			buf.append (getOffset ());
+			buf.append ("  ");
+			if (_diagContext != null)
+				buf.append (_diagContext).append ("  ");
+			buf.append (getLevelName (level));
+			if (level == INFO || level == WARN)
+				buf.append (" ");
+			buf.append ("  [");
+			buf.append (Thread.currentThread ().getName ());
+			buf.append ("] ");
+			buf.append (_channel);
+			buf.append (" - ");
+			buf.append (message);
+			buf.append (NEWLINE);
+
+			if (t != null)
+			{
+				StringWriter swriter = new StringWriter ();
+				PrintWriter pwriter = new PrintWriter (swriter);
+				t.printStackTrace (pwriter);
+				pwriter.flush ();
+				buf.append (swriter.toString ());
+			}
+			return buf.toString ();
+		}
+
+
+		private long getOffset ()
+		{
+			return System.currentTimeMillis () - initializationMillis;
+		}
+
+
+		public void setChannel (String val)
+		{
+			_channel = val;
+		}
+
+
+		public String getChannel ()
+		{
+			return _channel;
+		}
+
+
+		public void setLevel (short val)
+		{
+			_level = val;
+		}
+
+
+		public short getLevel ()
+		{
+			return _level;
+		}
+	}
+}

Propchange: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/log/LogFactoryImpl.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/log/LogOutputStream.java
URL: http://svn.apache.org/viewcvs/incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/log/LogOutputStream.java?rev=406215&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/log/LogOutputStream.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/log/LogOutputStream.java Sat May 13 20:25:56 2006
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openjpa.lib.log;
+
+
+import java.io.*;
+import java.util.*;
+
+import org.apache.openjpa.lib.log.*;
+
+
+/**
+ *	<p>Many standard components log to {@link OutputStream}s.
+ *	This wrapper class extends the {@link ByteArrayOutputStream}
+ *	class and writes all given data to an underlying {@link Log} instance
+ *	whenever it is flushed and the internally held byte array contains a 
+ *	newline.</p>
+ *
+ *	@author		Abe White, Marc Prud'hommeaux
+ */
+public class LogOutputStream
+	extends ByteArrayOutputStream
+{
+	private static final String _sep = System.getProperty ("line.separator");
+
+	private final int _level;
+	private final Log _log;
+
+	
+	/**
+	 *	Constructor.
+	 *	
+	 *	@param	log		the log to log to
+	 *	@param	level	the level to log at
+	 */
+	public LogOutputStream (Log log, int level)
+	{
+		_log = log;
+		_level = level;
+	}
+	
+	
+	public void flush ()
+		throws IOException
+	{
+		super.flush ();
+
+		String msg = new String (toByteArray ());
+		if (msg != null && msg.length () > 0 && msg.indexOf (_sep) != -1)
+		{
+			// break up the message based on the line separator; this
+			// may be because the flushed buffer contains mutliple lines
+			for (StringTokenizer tok = new StringTokenizer (msg, _sep);
+				tok.hasMoreTokens (); )
+			{
+				String next = tok.nextToken ();
+				log (next);
+			}
+
+			// clear the internally held byte array
+			reset ();
+		}
+	}
+
+
+	private void log (String msg)
+	{
+		switch (_level)
+		{
+		case Log.TRACE:
+			_log.trace (msg);
+			break;
+		case Log.DEBUG:
+			_log.debug (msg);
+			break;
+		case Log.INFO:
+			_log.info (msg);
+			break;
+		case Log.WARN:
+			_log.warn (msg);
+			break;
+		case Log.ERROR:
+			_log.error (msg);
+			break;
+		case Log.FATAL:
+			_log.fatal (msg);
+			break;
+		}
+	}
+}
+

Propchange: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/log/LogOutputStream.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/log/MultiLogFactory.java
URL: http://svn.apache.org/viewcvs/incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/log/MultiLogFactory.java?rev=406215&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/log/MultiLogFactory.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/log/MultiLogFactory.java Sat May 13 20:25:56 2006
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openjpa.lib.log;
+
+import java.util.*;
+
+
+/**
+ * 	A LogFactory implementation to pass events through multiple
+ * 	LogFactory implementations (such as log4j and LogPanelFactory).
+ * 
+ * 	@author Steve Kim
+ */
+public class MultiLogFactory 
+	implements LogFactory
+{
+	private List _delegates;
+	
+	
+	/**
+	 * create an instance with two delegates
+	 */ 
+	public MultiLogFactory (LogFactory d1, LogFactory d2)
+	{
+		this (new LogFactory [] { d1, d2 });
+	}
+
+
+	public MultiLogFactory (LogFactory d1, LogFactory d2, LogFactory d3)
+	{
+		this (new LogFactory [] { d1, d2, d3 });
+	}
+
+	
+	/**
+	 * create an instance with the given delegates
+	 */
+	public MultiLogFactory (LogFactory [] delegates)
+	{
+		_delegates = new LinkedList (Arrays.asList (delegates));;
+	}
+
+
+	public synchronized void addLogFactory (LogFactory factory)
+	{
+		_delegates.add (factory);
+	}
+
+
+	public synchronized void removeLogFactory (LogFactory factory)
+	{
+		_delegates.remove (factory);
+	}
+
+	
+	/**
+	 *	Returns the delegates that this MultiLogFactory delegates
+	 *	messages to.
+	 */
+	public synchronized LogFactory[] getDelegates ()
+	{
+		return (LogFactory[])_delegates.toArray (new LogFactory[0]);
+	}
+
+
+	/**
+	 * returns a Log impl that combines all logs.
+	 */
+	public synchronized Log getLog (String channel)
+	{
+		List logs = new ArrayList (_delegates.size ());
+		for (Iterator i = _delegates.iterator (); i.hasNext (); )
+		{
+			LogFactory f = (LogFactory)i.next ();
+			if (f != null)
+			{
+				Log l = f.getLog (channel);
+				if (l != null)
+					logs.add (l);
+			}
+		}
+
+		return new MultiLog ((Log[])logs.toArray (new Log[logs.size ()]));
+	}
+
+
+	/**
+	 * Combinatory Log impl.
+	 */
+	private static class MultiLog implements Log
+	{
+		private Log[] _logs;
+
+		public MultiLog (Log[] logs)
+		{
+			_logs = logs;
+		}
+
+
+		/**
+		 *	Return the logs that this log delegates to.
+		 */
+		public Log[] getDelegates ()
+		{
+			return _logs;
+		}
+
+
+		public void trace (Object msg)
+		{
+			for (int i = 0; i < _logs.length; i++)
+				_logs[i].trace (msg);
+		}
+
+		
+		public void trace (Object msg, Throwable t)
+		{
+			for (int i = 0; i < _logs.length; i++)
+				_logs[i].trace (msg, t);
+		}
+
+		
+		public void info (Object msg)
+		{
+			for (int i = 0; i < _logs.length; i++)
+				_logs[i].info (msg);
+		}
+
+		
+		public void info (Object msg, Throwable t)
+		{
+			for (int i = 0; i < _logs.length; i++)
+				_logs[i].info (msg, t);
+		}
+
+		
+		public void debug (Object msg)
+		{
+			for (int i = 0; i < _logs.length; i++)
+				_logs[i].debug (msg);
+		}
+
+		
+		public void debug (Object msg, Throwable t)
+		{
+			for (int i = 0; i < _logs.length; i++)
+				_logs[i].debug (msg, t);
+		}
+
+		
+		public void warn (Object msg)
+		{
+			for (int i = 0; i < _logs.length; i++)
+				_logs[i].warn (msg);
+		}
+
+		
+		public void warn (Object msg, Throwable t)
+		{
+			for (int i = 0; i < _logs.length; i++)
+				_logs[i].warn (msg, t);
+		}
+
+		
+		public void error (Object msg)
+		{
+			for (int i = 0; i < _logs.length; i++)
+				_logs[i].error (msg);
+		}
+
+		
+		public void error (Object msg, Throwable t)
+		{
+			for (int i = 0; i < _logs.length; i++)
+				_logs[i].error (msg, t);
+		}
+		
+
+		public void fatal (Object msg)
+		{
+			for (int i = 0; i < _logs.length; i++)
+				_logs[i].fatal (msg);
+		}
+
+		
+		public void fatal (Object msg, Throwable t)
+		{
+			for (int i = 0; i < _logs.length; i++)
+				_logs[i].fatal (msg, t);
+		}
+
+		
+		public boolean isTraceEnabled ()
+		{
+			for (int i = 0; i < _logs.length; i++)
+				if (_logs[i].isTraceEnabled ())
+					return true;
+
+			return false;
+		}
+
+
+		public boolean isInfoEnabled ()
+		{
+			for (int i = 0; i < _logs.length; i++)
+				if (_logs[i].isInfoEnabled ())
+					return true;
+
+			return false;
+		}
+
+
+		public boolean isWarnEnabled ()
+		{
+			for (int i = 0; i < _logs.length; i++)
+				if (_logs[i].isWarnEnabled ())
+					return true;
+
+			return false;
+		}
+
+
+		public boolean isDebugEnabled ()
+		{
+			for (int i = 0; i < _logs.length; i++)
+				if (_logs[i].isDebugEnabled ())
+					return true;
+
+			return false;
+		}
+
+
+
+		public boolean isErrorEnabled ()
+		{
+			for (int i = 0; i < _logs.length; i++)
+				if (_logs[i].isErrorEnabled ())
+					return true;
+
+			return false;
+		}
+
+
+		public boolean isFatalEnabled ()
+		{
+			for (int i = 0; i < _logs.length; i++)
+				if (_logs[i].isFatalEnabled ())
+					return true;
+
+			return false;
+		}
+	}
+}

Propchange: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/log/MultiLogFactory.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/log/NoneLogFactory.java
URL: http://svn.apache.org/viewcvs/incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/log/NoneLogFactory.java?rev=406215&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/log/NoneLogFactory.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/log/NoneLogFactory.java Sat May 13 20:25:56 2006
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openjpa.lib.log;
+
+
+/**
+ *	A log factory implementation that does not do any logging, as
+ *	quickly as possible.
+ *
+ *	@author	Patrick Linskey
+ */
+public class NoneLogFactory
+	implements LogFactory
+{
+	public final Log getLog (String channel)
+	{
+		return NoneLog.getInstance ();
+	}
+
+
+	/**
+	 *	No-op log.
+	 */
+	public static class NoneLog
+		implements Log
+	{
+		private static final NoneLog s_log = new NoneLog ();
+
+
+		public static NoneLog getInstance ()
+		{
+			return s_log;
+		}
+
+
+		public final boolean isDebugEnabled ()
+		{
+			return false;
+		}
+
+
+		public final boolean isErrorEnabled ()
+		{
+			return false;
+		}
+
+
+		public final boolean isFatalEnabled ()
+		{
+			return false;
+		}
+
+
+		public final boolean isInfoEnabled ()
+		{
+			return false;
+		}
+
+
+		public final boolean isTraceEnabled ()
+		{
+			return false;
+		}
+
+
+		public final boolean isWarnEnabled ()
+		{
+			return false;
+		}
+
+
+		public final void trace (Object o)
+		{
+		}
+
+
+		public final void trace (Object o, Throwable t)
+		{
+		}
+
+
+		public final void debug (Object o)
+		{
+		}
+
+
+		public final void debug (Object o, Throwable t)
+		{
+		}
+
+
+		public final void info (Object o)
+		{
+		}
+
+
+		public final void info (Object o, Throwable t)
+		{
+		}
+
+
+		public final void warn (Object o)
+		{
+		}
+
+
+		public final void warn (Object o, Throwable t)
+		{
+		}
+
+
+		public final void error (Object o)
+		{
+		}
+
+
+		public final void error (Object o, Throwable t)
+		{
+		}
+
+
+		public final void fatal (Object o)
+		{
+		}
+
+
+		public final void fatal (Object o, Throwable t)
+		{
+		}
+	}
+}
+

Propchange: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/log/NoneLogFactory.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/log/package.html
URL: http://svn.apache.org/viewcvs/incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/log/package.html?rev=406215&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/log/package.html (added)
+++ incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/log/package.html Sat May 13 20:25:56 2006
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+<html>
+<body>
+	<p><strong>Logging</strong></p>
+	<p>
+		This package provides a lightweight logging interface, a simple
+		implementation that writes logging output to the console and
+		allows for basic log configuration, and plug-ins for the Apache
+		Commons Logging and the Apache Log4J frameworks.
+	</p>
+</body>
+</html>

Propchange: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/log/package.html
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/CFMetaDataParser.java
URL: http://svn.apache.org/viewcvs/incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/CFMetaDataParser.java?rev=406215&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/CFMetaDataParser.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/CFMetaDataParser.java Sat May 13 20:25:56 2006
@@ -0,0 +1,410 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openjpa.lib.meta;
+
+
+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>
+ *
+ *	@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;
+	}
+}

Propchange: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/CFMetaDataParser.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/CFMetaDataSerializer.java
URL: http://svn.apache.org/viewcvs/incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/CFMetaDataSerializer.java?rev=406215&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/CFMetaDataSerializer.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/CFMetaDataSerializer.java Sat May 13 20:25:56 2006
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openjpa.lib.meta;
+
+
+import java.util.*;
+
+import org.apache.commons.collections.map.*;
+import org.xml.sax.*;
+
+
+/**
+ *	<p>Helps serialize metadata objects to package and class elements.</p>
+ *
+ *	@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;
+	}
+}

Propchange: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/CFMetaDataSerializer.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/ClassAnnotationMetaDataFilter.java
URL: http://svn.apache.org/viewcvs/incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/ClassAnnotationMetaDataFilter.java?rev=406215&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/ClassAnnotationMetaDataFilter.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/ClassAnnotationMetaDataFilter.java Sat May 13 20:25:56 2006
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openjpa.lib.meta;
+
+
+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>
+ *
+ *	@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;
+	}
+}

Propchange: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/ClassAnnotationMetaDataFilter.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/ClassArgParser.java
URL: http://svn.apache.org/viewcvs/incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/ClassArgParser.java?rev=406215&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/ClassArgParser.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/ClassArgParser.java Sat May 13 20:25:56 2006
@@ -0,0 +1,696 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+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 serp.bytecode.lowlevel.*;
+import serp.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>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);
+		}
+	}
+}

Propchange: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/ClassArgParser.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/ClassMetaDataIterator.java
URL: http://svn.apache.org/viewcvs/incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/ClassMetaDataIterator.java?rev=406215&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/ClassMetaDataIterator.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/ClassMetaDataIterator.java Sat May 13 20:25:56 2006
@@ -0,0 +1,200 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openjpa.lib.meta;
+
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+import org.apache.openjpa.lib.util.*;
+
+import serp.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.&lt;suffix&gt;".</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 ()
+	{
+	}
+}

Propchange: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/ClassMetaDataIterator.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/ClasspathMetaDataIterator.java
URL: http://svn.apache.org/viewcvs/incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/ClasspathMetaDataIterator.java?rev=406215&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/ClasspathMetaDataIterator.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/ClasspathMetaDataIterator.java Sat May 13 20:25:56 2006
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openjpa.lib.meta;
+
+
+import java.io.*;
+import java.util.*;
+import java.util.zip.*;
+
+import serp.util.*;
+
+
+/**
+ *	<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;
+	}
+}

Propchange: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/ClasspathMetaDataIterator.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/FileMetaDataIterator.java
URL: http://svn.apache.org/viewcvs/incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/FileMetaDataIterator.java?rev=406215&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/FileMetaDataIterator.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/FileMetaDataIterator.java Sat May 13 20:25:56 2006
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openjpa.lib.meta;
+
+
+import java.io.*;
+import java.util.*;
+
+import org.apache.openjpa.lib.util.*;
+
+
+/**
+ *	<p>Iterator over a file, or over all metadata resources below a given 
+ *	directory.</p>
+ *
+ *	@author		Abe White
+ *	@nojavadoc
+ */
+public class FileMetaDataIterator
+	implements MetaDataIterator
+{
+	private static final long SCAN_LIMIT = 100000;
+
+	private static final Localizer _loc = Localizer.forPackage
+		(FileMetaDataIterator.class);
+
+	private final Iterator	_itr;
+	private File			_file = null;
+
+
+	/**
+	 *	Constructor; supply metadata file.
+	 */
+	public FileMetaDataIterator (File file)
+	{
+		_itr = Collections.singleton (file).iterator ();
+	}
+
+
+	/**
+	 *	Constructor; supply root of directory tree to search and optional 
+	 *	file filter.
+	 */
+	public FileMetaDataIterator (File dir, MetaDataFilter filter)
+		throws IOException
+	{
+		if (dir == null)
+			_itr = null;
+		else
+		{
+			Collection metas = new ArrayList ();
+			FileResource rsrc = (filter == null) ? null : new FileResource ();
+			scan (dir, filter, rsrc, metas, 0);
+			_itr = metas.iterator ();
+		}
+	}
+
+
+	/**
+	 *	Scan all files below the given one for metadata files, adding them
+	 *	to the given collection.
+	 */
+	private int scan (File file, MetaDataFilter filter, FileResource rsrc, 
+		Collection metas, int scanned)
+		throws IOException
+	{
+		if (scanned > SCAN_LIMIT)
+			throw new IllegalStateException (_loc.get ("too-many-files",
+				String.valueOf (SCAN_LIMIT)));
+		scanned++;
+
+		if (filter == null)
+			metas.add (file);
+		else
+		{
+			rsrc.setFile (file);
+			if (filter.matches (rsrc))
+				metas.add (file);
+			else
+			{
+				File[] files = file.listFiles ();
+				if (files != null)
+					for (int i = 0; i < files.length; i++)
+						scanned = scan (files[i], filter, rsrc, metas, scanned);
+			}
+		}
+		return scanned;
+	}
+
+
+	public boolean hasNext ()
+	{
+		return _itr != null && _itr.hasNext ();
+	}
+
+
+	public Object next ()
+		throws IOException
+	{
+		if (_itr == null)
+			throw new NoSuchElementException ();
+
+		_file = (File) _itr.next ();
+		return _file.getAbsoluteFile ().toURL ();
+	}
+
+	
+	public InputStream getInputStream ()
+		throws IOException
+	{
+		if (_file == null)
+			throw new IllegalStateException ();
+		return new FileInputStream (_file);
+	}
+
+
+	public File getFile ()
+	{
+		if (_file == null)
+			throw new IllegalStateException ();
+		return _file;
+	}
+
+
+	public void close ()
+	{
+	}
+
+
+	private static class FileResource
+		implements MetaDataFilter.Resource
+	{
+		private File _file = null;
+
+
+		public void setFile (File file)
+		{
+			_file = file;
+		}
+
+
+		public String getName ()
+		{
+			return _file.getName ();
+		}
+
+
+		public byte[] getContent ()
+			throws IOException
+		{
+			long len = _file.length ();
+			if (len <= 0)
+				return new byte[0];
+
+			byte[] content = new byte[(int) len];
+			FileInputStream fin = new FileInputStream (_file);
+			fin.read (content);
+			fin.close ();
+			return content;
+		}
+	}
+}

Propchange: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/FileMetaDataIterator.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/MetaDataFilter.java
URL: http://svn.apache.org/viewcvs/incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/MetaDataFilter.java?rev=406215&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/MetaDataFilter.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/MetaDataFilter.java Sat May 13 20:25:56 2006
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openjpa.lib.meta;
+
+
+import java.io.*;
+
+
+/**
+ *	<p>Filters metadata resources.  Typically used to constrain the results
+ *	of a {@link MetaDataIterator}.</p>
+ *
+ *	@author		Abe White
+ *	@nojavadoc
+ */
+public interface MetaDataFilter
+{
+	/**
+	 *	Return whether the given resource passes the filter.
+	 */
+	public boolean matches (Resource rsrc)
+		throws IOException;
+
+
+	/**
+	 *	Information about a metadata resource.
+	 */
+	public static interface Resource
+	{
+		/**
+		 *	The name of the resource.
+	 	 */
+		public String getName ();
+
+
+		/**
+	 	 *	Resource content.
+		 */
+		public byte[] getContent ()
+			throws IOException;
+	}
+}

Propchange: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/MetaDataFilter.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/MetaDataIterator.java
URL: http://svn.apache.org/viewcvs/incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/MetaDataIterator.java?rev=406215&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/MetaDataIterator.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/MetaDataIterator.java Sat May 13 20:25:56 2006
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openjpa.lib.meta;
+
+
+import java.io.*;
+
+import org.apache.openjpa.lib.util.Closeable; // also in java.io (in 1.5)
+
+
+/**
+ *	<p>Iterator over metadata resources.</p>
+ *
+ *	@author		Abe White
+ */
+public interface MetaDataIterator
+	extends Closeable
+{
+	/**
+	 *	Return whether there is another resource to iterate over.
+	 */
+	public boolean hasNext ()
+		throws IOException;
+
+
+	/**
+	 *	Return the next metadata resource.
+	 */
+	public Object next ()
+		throws IOException;
+
+	
+	/**
+	 *	Return the last-iterated metadata resource content as a stream.
+ 	 */
+	public InputStream getInputStream ()
+		throws IOException;
+
+
+	/**
+	 *	Return the last-iterated metadata resource content as a file, or null
+	 *	if not an extant file.
+ 	 */
+	public File getFile ()
+		throws IOException;
+
+
+	/**
+	 *	Close the resources used by this iterator.
+	 */
+	public void close ();
+}
+

Propchange: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/MetaDataIterator.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/MetaDataIteratorChain.java
URL: http://svn.apache.org/viewcvs/incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/MetaDataIteratorChain.java?rev=406215&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/MetaDataIteratorChain.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/MetaDataIteratorChain.java Sat May 13 20:25:56 2006
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openjpa.lib.meta;
+
+
+import java.io.*;
+import java.util.*;
+
+
+/**
+ *	<p>Metadata iterator that combines several iterators.</p>
+ *
+ *	@author		Abe White
+ *	@nojavadoc
+ */
+public class MetaDataIteratorChain
+	implements MetaDataIterator
+{
+	private List 				_itrs	= null;
+	private int	 				_cur	= -1;
+	private MetaDataIterator	_itr	= null;
+
+
+	/**
+	 *	Default constructor.
+	 */
+	public MetaDataIteratorChain ()
+	{
+	}
+
+
+	/**
+	 *	Combine two iterators.
+	 */
+	public MetaDataIteratorChain (MetaDataIterator itr1, MetaDataIterator itr2)
+	{
+		_itrs = new ArrayList (2);
+		_itrs.add (itr1);
+		_itrs.add (itr2);
+	}
+
+
+	/**
+	 *	Add an iterator to the chain.
+	 */
+	public void addIterator (MetaDataIterator itr)
+	{
+		if (_cur != -1)
+			throw new IllegalStateException ();
+		if (_itrs == null)
+			_itrs = new ArrayList (4);
+		_itrs.add (itr);
+	}
+
+
+	public boolean hasNext ()
+		throws IOException
+	{
+		if (_itrs == null)
+			return false;
+		if (_cur == -1)
+			_cur = 0;
+
+		MetaDataIterator itr;
+		for (; _cur < _itrs.size (); _cur++)
+		{
+			itr = (MetaDataIterator) _itrs.get (_cur);
+			if (itr.hasNext ())
+			{
+				_itr = itr;
+				return true;
+			}
+		}
+		_itr = null;
+		return false;
+	}
+
+
+	public Object next ()
+		throws IOException
+	{
+		if (!hasNext ())
+			throw new NoSuchElementException ();
+		return _itr.next ();
+	}
+
+
+	public InputStream getInputStream ()
+		throws IOException
+	{
+		if (_itr == null)
+			throw new IllegalStateException ();
+		return _itr.getInputStream ();
+	}
+
+
+	public File getFile ()
+		throws IOException
+	{
+		if (_itr == null)
+			throw new IllegalStateException ();
+		return _itr.getFile ();
+	}
+
+
+	public void close ()
+	{
+		for (Iterator itr = _itrs.iterator (); itr.hasNext ();)
+			((MetaDataIterator) itr.next ()).close ();
+	}
+}

Propchange: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/MetaDataIteratorChain.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/MetaDataParser.java
URL: http://svn.apache.org/viewcvs/incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/MetaDataParser.java?rev=406215&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/MetaDataParser.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/MetaDataParser.java Sat May 13 20:25:56 2006
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openjpa.lib.meta;
+
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+
+/**
+ *	<p>Interface for metadata parsers.</p>
+ *
+ *	@author		Abe White
+ *	@nojavadoc
+ */
+public interface MetaDataParser
+{
+	/**
+	 *	The classloader to use to resolve resources, or null for impl-defined
+	 *	default.
+	 */
+	public void setClassLoader (ClassLoader loader);
+
+
+	/**
+	 *	Return the results from the last parse.
+	 */
+	public List getResults ();
+	
+
+	/**
+	 *	Parse the given resource.
+	 */
+	public void parse (String rsrc)
+		throws IOException;
+
+
+	/**
+	 *	Parse the given resource.
+	 */
+	public void parse (URL url)
+		throws IOException;
+
+
+	/**
+	 *	Parse the given file, which may be a directory, in which case it
+	 *	will be scanned recursively for metadata files.
+	 */
+	public void parse (File file)
+		throws IOException;
+
+
+	/**
+	 *	Parse all possible metadata locations for the given class, going 
+	 *	top-down or bottom-up.  If the class is null, only top-level locations 
+	 *	will be parsed.
+	 */
+	public void parse (Class cls, boolean topDown)
+		throws IOException;
+
+
+	/**
+	 *	Parse the metadata in the given reader.
+ 	 *
+	 *	@param	content		reader containing the metadata to parse
+	 *	@param	sourceName	the name of the source being parsed, for use
+	 *						in error messages
+	 */	
+	public void parse (Reader content, String sourceName)
+		throws IOException;
+
+
+	/**
+	 *	Parse the metadata supplied by the given iterator.
+	 */
+	public void parse (MetaDataIterator itr)
+		throws IOException;
+
+
+	/**
+	 *	Clears the cache of parsed resource names.
+	 */
+	public void clear ();
+}

Propchange: incubator/openjpa/trunk/openjpa-lib/java/org/apache/openjpa/lib/meta/MetaDataParser.java
------------------------------------------------------------------------------
    svn:executable = *



Mime
View raw message