openjpa-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From p..@apache.org
Subject svn commit: r570948 - in /openjpa/trunk: openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ openjpa-kernel/src/main/java/org/apache/openjpa/conf/ openjpa-kernel/src/main/java/org/apache/openjpa/enhance/ openjpa-kernel/src/main/java/org/apa...
Date Wed, 29 Aug 2007 22:07:45 GMT
Author: pcl
Date: Wed Aug 29 15:07:44 2007
New Revision: 570948

URL: http://svn.apache.org/viewvc?rev=570948&view=rev
Log:
OPENJPA-344. Enable serialization of metadata and query compilation caches. This implementation requires that the user run a tool to build the cache, and set a configuration property to tell OpenJPA where the serialized data is stored.

Added:
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/CacheMarshaller.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/CacheMarshallerImpl.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/CacheMarshallersValue.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/MetaDataCacheMaintenance.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/MetaDataRepositoryValue.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/NoOpCacheMarshaller.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAVersionAndConfigurationTypeValidationPolicy.java
    openjpa/trunk/openjpa-kernel/src/test/java/org/apache/openjpa/conf/
    openjpa/trunk/openjpa-kernel/src/test/java/org/apache/openjpa/meta/
    openjpa/trunk/openjpa-kernel/src/test/java/org/apache/openjpa/meta/TestMemberProvider.java
    openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/conf/
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/conf/TestCacheMarshaller.java
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/conf/TestCacheMarshallerEndToEnd.java
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/NamedQueryEntity.java
Modified:
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/JDBCExpressionFactory.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SelectConstructor.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/QueryCompilationCacheValue.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/ReflectingPersistenceCapable.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ExpressionStoreQuery.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Expression.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/QueryExpressions.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Value.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/FieldMetaData.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataRepository.java
    openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/conf/localizer.properties

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/JDBCExpressionFactory.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/JDBCExpressionFactory.java?rev=570948&r1=570947&r2=570948&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/JDBCExpressionFactory.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/JDBCExpressionFactory.java Wed Aug 29 15:07:44 2007
@@ -18,6 +18,8 @@
  */
 package org.apache.openjpa.jdbc.kernel.exps;
 
+import java.io.Serializable;
+
 import org.apache.openjpa.jdbc.meta.ClassMapping;
 import org.apache.openjpa.jdbc.meta.JavaSQLTypes;
 import org.apache.openjpa.jdbc.sql.DBDictionary;
@@ -43,7 +45,7 @@
  * @nojavadoc
  */
 public class JDBCExpressionFactory
-    implements ExpressionFactory {
+    implements ExpressionFactory, Serializable {
 
     private static final Val NULL = new Null();
     private static final Val CURRENT_DATE = new CurrentDate(JavaSQLTypes.DATE);

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java?rev=570948&r1=570947&r2=570948&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java Wed Aug 29 15:07:44 2007
@@ -18,6 +18,7 @@
  */
 package org.apache.openjpa.jdbc.kernel.exps;
 
+import java.io.Serializable;
 import java.sql.SQLException;
 import java.util.Iterator;
 import java.util.LinkedList;
@@ -319,7 +320,7 @@
         action.data = meta;
         _actions.add(action);
         _cast = null;
-        _key = false;;
+        _key = false;
         _type = XPATH;
         _xmlfield = fmd;
     }
@@ -330,7 +331,7 @@
         action.data = meta.getFieldMapping(name);
         _actions.add(action);
         _cast = null;
-        _key = false;;
+        _key = false;
         _type = XPATH;
     }
     
@@ -789,7 +790,8 @@
     /**
      * Helper class representing an action.
      */
-    private static class Action {
+    private static class Action
+        implements Serializable {
 
         public static final int GET = 0;
         public static final int GET_OUTER = 1;

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SelectConstructor.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SelectConstructor.java?rev=570948&r1=570947&r2=570948&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SelectConstructor.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SelectConstructor.java Wed Aug 29 15:07:44 2007
@@ -18,6 +18,7 @@
  */
 package org.apache.openjpa.jdbc.kernel.exps;
 
+import java.io.Serializable;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -38,7 +39,8 @@
  * @author Abe White
  * @nojavadoc
  */
-public class SelectConstructor {
+public class SelectConstructor
+    implements Serializable {
 
     private boolean _extent = false;
 

Added: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/CacheMarshaller.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/CacheMarshaller.java?rev=570948&view=auto
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/CacheMarshaller.java (added)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/CacheMarshaller.java Wed Aug 29 15:07:44 2007
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.conf;
+
+
+import org.apache.openjpa.lib.conf.Configurable;
+import org.apache.openjpa.lib.conf.Configuration;
+
+/**
+ * Responsible for marshalling and unmarshalling objects between memory and
+ * durable cache.
+ *
+ * @since 1.1.0
+ */
+public interface CacheMarshaller {
+
+    /**
+     * Load and return an instance of the type handled by this marshaller.
+     * If the type implements {@link Configurable}, then this method will invoke
+     * {@link Configurable#setConfiguration}, 
+     * {@link Configurable#startConfiguration()}, and
+     * {@link Configurable#endConfiguration()} on the instance before returning.
+     */
+    public Object load();
+
+    /**
+     * Store <code>o</code> into the cache.
+     */
+    public void store(Object o);
+
+    /**
+     * The id that this marshaller is responsible for.
+     * A value for this parameter is required.
+     */
+    public void setId(String id);
+
+    /**
+     * The id that this marshaller is responsible for.
+     */
+    public String getId();
+
+    /**
+     * The {@link ValidationPolicy} that this marshaller should use.
+     * A value for this parameter is required. The class will be instantiated
+     * via the {@link org.apache.openjpa.lib.conf.Configurations} mechanism, ensuring that if the class
+     * implements {@link Configurable} or {@link org.apache.openjpa.lib.conf.GenericConfigurable}, it will
+     * be taken through the appropriate lifecycle.
+     */
+    public void setValidationPolicy(String policy)
+        throws InstantiationException, IllegalAccessException;
+
+    /**
+     * Validation policies are responsible for computing whether or not a
+     * cached data structure is valid for the current context.
+     * <p/>
+     * <code>getValidCachedData(getCacheableData(o), conf)</code> should
+     * return an object equivalent to <code>o</code> in the expected case.
+     * <p/>
+     * Implementations of this class will often also implement
+     * {@link Configurable} in order to receive the current
+     * {@link Configuration}.
+     */
+    public interface ValidationPolicy {
+        /**
+         * Returns an object that this policy considers to be valid, based
+         * on <code>o</code>. If <code>o</code> is not valid, this method
+         * will return <code>null</code>.
+         */
+        public Object getValidData(Object o);
+
+        /**
+         * Return an object that the {@link CacheMarshaller} should store.
+         */
+        public Object getCacheableData(Object o);
+    }
+}
\ No newline at end of file

Added: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/CacheMarshallerImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/CacheMarshallerImpl.java?rev=570948&view=auto
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/CacheMarshallerImpl.java (added)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/CacheMarshallerImpl.java Wed Aug 29 15:07:44 2007
@@ -0,0 +1,237 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.conf;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.net.URL;
+import java.util.Enumeration;
+
+import org.apache.openjpa.lib.conf.Configurable;
+import org.apache.openjpa.lib.conf.Configuration;
+import org.apache.openjpa.lib.conf.Configurations;
+import org.apache.openjpa.lib.log.Log;
+import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.util.InternalException;
+
+/**
+ * Default {@link CacheMarshaller} implementation that writes data
+ * to a specified file and reads data from a specified file or URL.
+ *
+ * @since 1.1.0
+ */
+public class CacheMarshallerImpl
+    implements CacheMarshaller, Configurable {
+
+    private static final Localizer _loc =
+        Localizer.forPackage(CacheMarshallerImpl.class);
+
+    private String _id;
+    private ValidationPolicy _validationPolicy;
+    private OpenJPAConfiguration _conf;
+    private Log _log;
+    private File _outputFile;
+    private URL _inputURL;
+
+    // temporary storage for resource location specification
+    private String _inputResourceLocation;
+    
+    private boolean _consumeErrors = true;
+
+    public Object load() {
+        if (_inputURL == null) {
+            _log.trace(_loc.get("cache-marshaller-no-inputs", getId()));
+            return null;
+        }
+
+        Object o = null;
+        ObjectInputStream in = null;
+        try {
+            in = new ObjectInputStream(new BufferedInputStream(
+                _inputURL.openStream()));
+
+            o = in.readObject();
+            o = _validationPolicy.getValidData(o);
+
+            if (o != null && o.getClass().isArray()) {
+                Object[] array = (Object[]) o;
+                for (int i = 0; i < array.length; i++)
+                    configure(array[i]);
+            } else {
+                configure(o);
+            }
+
+            if (_log.isTraceEnabled())
+                _log.trace(_loc.get("cache-marshaller-loaded",
+                    o == null ? null : o.getClass().getName(), _inputURL));
+        } catch (Exception e) {
+            if (_consumeErrors) {
+                if (_log.isWarnEnabled())
+                    _log.warn(_loc.get("cache-marshaller-load-exception",
+                        _inputURL), e);
+            } else {
+                throw new InternalException(
+                    _loc.get("cache-marshaller-load-exception",
+                        _inputURL),
+                    e);
+            }
+        } finally {
+            if (in != null)
+                try { in.close(); } catch (IOException e) { }
+        }
+
+        return o;
+    }
+
+    private void configure(Object o) {
+        if (o instanceof Configurable) {
+            ((Configurable) o).setConfiguration(_conf);
+            ((Configurable) o).startConfiguration();
+            ((Configurable) o).endConfiguration();
+        }
+    }
+
+    public void store(Object o) {
+        if (_outputFile == null) {
+            _log.trace(_loc.get("cache-marshaller-no-output-file", getId()));
+            return;
+        }
+        OutputStream out = null;
+        try {
+            out = new FileOutputStream(_outputFile);
+            ObjectOutputStream oos =
+                new ObjectOutputStream(new BufferedOutputStream(out));
+            Object toStore = _validationPolicy.getCacheableData(o);
+            oos.writeObject(toStore);
+            oos.flush();
+            out.flush();
+            if (_log.isTraceEnabled())
+                _log.trace(_loc.get("cache-marshaller-stored",
+                    o.getClass().getName(), _outputFile));
+        } catch (Exception e) {
+            if (_consumeErrors) {
+                if (_log.isWarnEnabled())
+                    _log.warn(_loc.get("cache-marshaller-store-exception",
+                        o.getClass().getName(), _outputFile), e);
+            } else {
+                throw new InternalException(
+                    _loc.get("cache-marshaller-store-exception",
+                        o.getClass().getName(), _outputFile),
+                    e);
+            }
+        } finally {
+            if (out != null) {
+                try { out.close(); } catch (IOException ioe) { }
+            }
+        }
+    }
+
+    public void setOutputFile(File file) {
+        _outputFile = file;
+    }
+
+    public File getOutputFile() {
+        return _outputFile;
+    }
+
+    public void setInputURL(URL url) {
+        _inputURL = url;
+    }
+
+    public void setInputResource(String resource) {
+        _inputResourceLocation = resource;
+    }
+
+    public void setConsumeSerializationErrors(boolean consume) {
+        _consumeErrors = consume;
+    }
+
+    public String getId() {
+        return _id;
+    }
+
+    public void setId(String id) {
+        _id = id;
+    }
+
+    public void setValidationPolicy(String policy)
+        throws InstantiationException, IllegalAccessException {
+        String name = Configurations.getClassName(policy);
+        String props = Configurations.getProperties(policy);
+        _validationPolicy = (ValidationPolicy)
+            Configurations.newInstance(name, _conf, props, null);
+    }
+
+    public ValidationPolicy getValidationPolicy() {
+        return _validationPolicy;
+    }
+
+    public void setConfiguration(Configuration conf) {
+        _conf = (OpenJPAConfiguration) conf;
+        _log = conf.getConfigurationLog();
+    }
+
+    public void startConfiguration() {
+    }
+
+    public void endConfiguration() {
+        if (_inputResourceLocation != null && _inputURL != null)
+            throw new IllegalStateException(
+                _loc.get("cache-marshaller-input-url-and-resource-specified")
+                    .getMessage());
+        if (_inputResourceLocation != null)
+            setInputUrlFromResourceLocation();
+
+        if (_validationPolicy == null)
+            throw new IllegalStateException(
+                _loc.get("cache-marshaller-null-validation-policy",
+                    getClass().getName()).getMessage());
+        if (_id == null)
+            throw new IllegalStateException(
+                _loc.get("cache-marshaller-null-id",
+                    getClass().getName()).getMessage());
+    }
+
+    private void setInputUrlFromResourceLocation() {
+        try {
+            ClassLoader cl = _conf.getClassResolverInstance()
+                .getClassLoader(getClass(), null);
+            for (Enumeration e = cl.getResources(_inputResourceLocation);
+                e.hasMoreElements(); ) {
+                if (_inputURL == null)
+                    _inputURL = (URL) e.nextElement();
+                else
+                    throw new IllegalStateException(
+                        _loc.get("cache-marshaller-multiple-resources",
+                            getId(), _inputResourceLocation).getMessage());
+            }
+        } catch (IOException ioe) {
+            throw new IllegalStateException(
+                _loc.get("cache-marshaller-bad-url", getId(),
+                    _inputResourceLocation)
+                    .getMessage(), ioe);
+        }
+    }
+}

Added: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/CacheMarshallersValue.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/CacheMarshallersValue.java?rev=570948&view=auto
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/CacheMarshallersValue.java (added)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/CacheMarshallersValue.java Wed Aug 29 15:07:44 2007
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.conf;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.openjpa.lib.log.Log;
+import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.lib.conf.PluginListValue;
+import org.apache.openjpa.conf.NoOpCacheMarshaller;
+import org.apache.openjpa.lib.conf.Configuration;
+
+/**
+ * A configuration value for handling and accessing cache marshallers.
+ *
+ * @since 1.1.0
+ */
+public class CacheMarshallersValue
+    extends PluginListValue {
+
+    private static final String KEY = "CacheMarshallers";
+    private static final CacheMarshaller NO_OP_CACHE_MARSHALLER
+        = new NoOpCacheMarshaller();
+    private static final Localizer _loc =
+        Localizer.forPackage(CacheMarshallersValue.class);
+
+    private Configuration _conf;
+    private Map _marshallers;
+    private boolean _initialized;
+
+    public CacheMarshallersValue(Configuration conf) {
+        super(KEY);
+        _conf = conf;
+        setAlias("default", CacheMarshallerImpl.class.getName());
+        setAlias("none", null);
+        setDefault("none");
+        setString("none");
+        setScope(getClass());
+    }
+
+    public Object instantiate(Class elemType, Configuration conf,
+        boolean fatal) {
+        CacheMarshaller[] ms = (CacheMarshaller[])
+            super.instantiate(elemType, conf, fatal);
+        if (ms != null) {
+            _marshallers = new HashMap();
+            for (int i = 0; i < ms.length; i++) {
+                String mid = ms[i].getId();
+                if (mid != null)
+                    _marshallers.put(mid, ms[i]);
+            }
+        } else {
+            _marshallers = null;
+        }
+        return ms;
+    }
+
+    /**
+     * Return the {@link CacheMarshaller} to use for caching metadata of id
+     * <code>id</code>. If no marshaller exists for the id, returns
+     * {@link NoOpCacheMarshaller}.
+     */
+    public CacheMarshaller getMarshallerById(String id) {
+        initialize();
+
+        CacheMarshaller cm = (CacheMarshaller) _marshallers.get(id);
+        if (cm == null) {
+            if (getLog().isTraceEnabled())
+                getLog().trace(_loc.get("cache-marshaller-not-found", id));
+            return NO_OP_CACHE_MARSHALLER;
+        } else {
+            if (getLog().isTraceEnabled())
+                getLog().trace(_loc.get("cache-marshaller-found", id,
+                    cm.getClass().getName()));
+            return cm;
+        }
+    }
+
+    private Log getLog() {
+        return _conf.getConfigurationLog();
+    }
+
+    /**
+     * Return the {@link CacheMarshaller} to use for caching metadata of id
+     * <code>id</code>. If no marshaller exists for the id, returns
+     * {@link NoOpCacheMarshaller}.
+     */
+    public static CacheMarshaller getMarshallerById(Configuration c, String id){
+        CacheMarshallersValue v =
+            ((OpenJPAConfigurationImpl) c).cacheMarshallerPlugins;
+        return v.getMarshallerById(id);
+    }
+
+    public Map getInstancesAsMap() {
+        return _marshallers;
+    }
+
+    protected synchronized void initialize() {
+        if (!_initialized) {
+            instantiate(CacheMarshaller.class, _conf);
+            _initialized = true;
+        }
+    }
+}

Added: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/MetaDataCacheMaintenance.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/MetaDataCacheMaintenance.java?rev=570948&view=auto
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/MetaDataCacheMaintenance.java (added)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/MetaDataCacheMaintenance.java Wed Aug 29 15:07:44 2007
@@ -0,0 +1,183 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.conf;
+
+import java.io.PrintStream;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.openjpa.kernel.Bootstrap;
+import org.apache.openjpa.kernel.Broker;
+import org.apache.openjpa.kernel.BrokerFactory;
+import org.apache.openjpa.kernel.Query;
+import org.apache.openjpa.conf.CacheMarshallersValue;
+import org.apache.openjpa.lib.util.Options;
+import org.apache.openjpa.meta.ClassMetaData;
+import org.apache.openjpa.meta.MetaDataRepository;
+import org.apache.openjpa.meta.QueryMetaData;
+import org.apache.openjpa.meta.SequenceMetaData;
+
+/**
+ * Performs maintenance tasks on the metadata caches accessible via the
+ * {@link CacheMarshaller} architecture.
+ *
+ * @since 1.1.0
+ */
+public class MetaDataCacheMaintenance {
+
+    private final BrokerFactory factory;
+    private final OpenJPAConfiguration conf;
+    private final boolean devpath;
+    private final boolean verbose;
+    private PrintStream out = System.out;
+
+    public MetaDataCacheMaintenance(BrokerFactory factory, boolean devpath,
+        boolean verbose) {
+        this.factory = factory;
+        this.conf = factory.getConfiguration();
+        this.devpath = devpath;
+        this.verbose = verbose;
+    }
+
+    public void setOutputStream(PrintStream out) {
+        this.out = out;
+    }
+
+    public static void main(String[] args) {
+        Options opts = new Options();
+        args = opts.setFromCmdLine(args);
+        boolean devpath = opts.getBooleanProperty("scanDevPath", "ScanDevPath",
+            true);
+        boolean verbose = opts.getBooleanProperty("verbose", "verbose",
+            false);
+
+        BrokerFactory factory = Bootstrap.newBrokerFactory();
+        try {
+            MetaDataCacheMaintenance maint = new MetaDataCacheMaintenance(
+                factory, devpath, verbose);
+
+            if (args.length != 1)
+                usage();
+
+            if ("store".equals(args[0]))
+                maint.store();
+            else if ("dump".equals(args[0]))
+                maint.dump();
+            else
+                usage();
+        } finally {
+            factory.close();
+        }
+    }
+
+    private static int usage() {
+        System.err.println("Usage: java MetaDataCacheMaintenance "
+            + "[-scanDevPath t|f] [-verbose t|f] store | dump");
+        return -1;
+    }
+
+    public void store() {
+        MetaDataRepository repos = conf.getMetaDataRepositoryInstance();
+        repos.setSourceMode(MetaDataRepository.MODE_META
+            | MetaDataRepository.MODE_MAPPING
+            | MetaDataRepository.MODE_QUERY);
+        Collection types = repos.loadPersistentTypes(devpath, null);
+        for (Iterator iter = types.iterator(); iter.hasNext(); )
+            repos.getMetaData((Class) iter.next(), null, true);
+
+        loadQueries();
+
+        out.println("The following data will be stored: ");
+        log(repos, conf.getQueryCompilationCacheInstance(), verbose, out);
+
+        CacheMarshallersValue.getMarshallerById(conf, getClass().getName())
+            .store(new Object[] {
+                repos, conf.getQueryCompilationCacheInstance()
+            });
+    }
+
+    private void loadQueries() {
+        Broker broker = factory.newBroker();
+        try {
+            QueryMetaData[] qmds =
+                conf.getMetaDataRepositoryInstance().getQueryMetaDatas();
+            for (int i = 0; i < qmds.length; i++)
+                loadQuery(broker, qmds[i]);
+        } finally {
+            broker.close();
+        }
+    }
+
+    private void loadQuery(Broker broker, QueryMetaData qmd) {
+        try {
+            Query q = broker.newQuery(qmd.getLanguage(), null);
+            qmd.setInto(q);
+            q.compile();
+        } catch (Exception e) {
+            out.println("Skipping named query " + qmd.getName() + ": "
+                + e.getMessage());
+            if (verbose)
+                e.printStackTrace(out);
+        }
+    }
+
+    public void dump() {
+        Object[] os = (Object[])
+            CacheMarshallersValue.getMarshallerById(conf, getClass().getName())
+            .load();
+        if (os == null) {
+            out.println("No cached data was found");
+            return;
+        }
+        MetaDataRepository repos = (MetaDataRepository) os[0];
+        Map qcc = (Map) os[1];
+
+        out.println("The following data was found: ");
+        log(repos, qcc, verbose, out);
+    }
+
+    private static void log(MetaDataRepository repos, Map qcc,
+        boolean verbose, PrintStream out) {
+        ClassMetaData[] metas = repos.getMetaDatas();
+        out.println("  Types: " + metas.length);
+        if (verbose)
+            for (int i = 0; i < metas.length; i++)
+                out.println("    " + metas[i].getDescribedType().getName());
+
+        QueryMetaData[] qmds = repos.getQueryMetaDatas();
+        out.println("  Queries: " + qmds.length);
+        if (verbose)
+            for (int i = 0; i < qmds.length; i++)
+                out.println("    " + qmds[i].getName() + ": "
+                    + qmds[i].getQueryString());
+
+        SequenceMetaData[] smds = repos.getSequenceMetaDatas();
+        out.println("  Sequences: " + smds.length);
+        if (verbose)
+            for (int i = 0; i < smds.length; i++)
+                out.println("    " + smds[i].getName());
+
+        out.println("  Compiled queries: "
+            + (qcc == null ? "0" : "" + qcc.size()));
+        if (verbose && qcc != null)
+            for (Iterator iter = qcc.keySet().iterator(); iter.hasNext(); )
+                out.println("    " + iter.next());
+    }
+}

Added: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/MetaDataRepositoryValue.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/MetaDataRepositoryValue.java?rev=570948&view=auto
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/MetaDataRepositoryValue.java (added)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/MetaDataRepositoryValue.java Wed Aug 29 15:07:44 2007
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.conf;
+
+import java.util.Map;
+
+import org.apache.openjpa.lib.conf.Configuration;
+import org.apache.openjpa.lib.conf.PluginValue;
+import org.apache.openjpa.conf.CacheMarshallersValue;
+import org.apache.openjpa.meta.MetaDataRepository;
+
+/**
+ * A {@link PluginValue} that interacts with the {@link CacheMarshaller}
+ * to cache the metadata repository between executions.
+ *
+ * @since 1.1.0
+ */
+public class MetaDataRepositoryValue
+    extends PluginValue {
+
+    private static final String KEY = "MetaDataRepository";
+
+    public MetaDataRepositoryValue() {
+        super(KEY, false);
+        String[] aliases = new String[] {
+            "default",
+            MetaDataRepository.class.getName()
+        };
+        setAliases(aliases);
+        setDefault(aliases[0]);
+        setString(aliases[0]);
+    }
+
+    public Object instantiate(Class type, Configuration c, boolean fatal) {
+        MetaDataRepository repos = null;
+        OpenJPAConfiguration conf = (OpenJPAConfiguration) c;
+
+        Object[] os = (Object[]) CacheMarshallersValue.getMarshallerById(
+            conf, MetaDataCacheMaintenance.class.getName())
+            .load();
+        if (os != null) {
+            repos = (MetaDataRepository) os[0];
+            if (os[1] != null)
+                // It's a bit odd that we do this in MetaDataRepositoryValue.
+                // We need to serialize all the various bits of configuration
+                // together; maybe we can move the caching logic somewhere
+                // else?
+                conf.getQueryCompilationCacheInstance().putAll((Map) os[1]);
+        }
+
+        if (repos == null)
+            return super.instantiate(type, c, fatal);
+        else
+            return repos;
+    }
+
+
+}

Added: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/NoOpCacheMarshaller.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/NoOpCacheMarshaller.java?rev=570948&view=auto
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/NoOpCacheMarshaller.java (added)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/NoOpCacheMarshaller.java Wed Aug 29 15:07:44 2007
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.conf;
+
+/**
+ * Implementation of {@link CacheMarshaller} that does nothing.
+ *
+ * @since 1.1.0
+ */
+public class NoOpCacheMarshaller
+    implements CacheMarshaller {
+
+    private String id;
+
+    public Object load() {
+        return null;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public void setValidationPolicy(String policy) {
+    }
+
+    public void store(Object o) {
+    }
+}

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java?rev=570948&r1=570947&r2=570948&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java Wed Aug 29 15:07:44 2007
@@ -1448,4 +1448,27 @@
      * @since 1.0.0
      */
     public void setRuntimeUnenhancedClasses(int mode);
+
+    /**
+     * A comma-separted list of the plugin strings specifying the
+     * {@link CacheMarshaller}s to use.
+     *
+     * @since 1.1.0
+     */
+    public String getCacheMarshallers();
+
+    /**
+     * A comma-separted list of the plugin strings specifying the
+     * {@link CacheMarshaller}s to use.
+     *
+     * @since 1.1.0
+     */
+    public void setCacheMarshallers(String marshallers);
+
+    /**
+     * Return the cache marshaller listeners.
+     *
+     * @since 1.1.0 
+     */
+    public Map getCacheMarshallerInstances();
 }

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java?rev=570948&r1=570947&r2=570948&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java Wed Aug 29 15:07:44 2007
@@ -133,6 +133,7 @@
     public ObjectValue compatibilityPlugin;
     public QueryCompilationCacheValue queryCompilationCachePlugin;
     public IntValue runtimeUnenhancedClasses;
+    public CacheMarshallersValue cacheMarshallerPlugins;
 
     // custom values
     public BrokerFactoryValue brokerFactoryPlugin;
@@ -295,13 +296,8 @@
         mapping = addString("Mapping");
         metaFactoryPlugin = addPlugin("MetaDataFactory", false);
 
-        metaRepositoryPlugin = addPlugin("MetaDataRepository", false);
-        aliases =
-            new String[] { "default",
-                "org.apache.openjpa.meta.MetaDataRepository" };
-        metaRepositoryPlugin.setAliases(aliases);
-        metaRepositoryPlugin.setDefault(aliases[0]);
-        metaRepositoryPlugin.setString(aliases[0]);
+        metaRepositoryPlugin = (ObjectValue)
+            addValue(new MetaDataRepositoryValue());
 
         connectionFactory = addObject("ConnectionFactory");
         connectionFactory.setInstantiatingGetter("getConnectionFactory");
@@ -494,6 +490,9 @@
         runtimeUnenhancedClasses.setString("supported");
         runtimeUnenhancedClasses.setAliasListComprehensive(true);
 
+        cacheMarshallerPlugins = (CacheMarshallersValue)
+            addValue(new CacheMarshallersValue(this));
+
         // initialize supported options that some runtimes may not support
         supportedOptions.add(OPTION_NONTRANS_READ);
         supportedOptions.add(OPTION_OPTIMISTIC);
@@ -1450,6 +1449,19 @@
         runtimeUnenhancedClasses.set(mode);
     }
 
+    public String getCacheMarshallers() {
+        return cacheMarshallerPlugins.getString();
+    }
+
+    public void setCacheMarshallers(String marshallers) {
+        assertNotReadOnly();
+        cacheMarshallerPlugins.setString(marshallers);
+    }
+
+    public Map getCacheMarshallerInstances() {
+        return cacheMarshallerPlugins.getInstancesAsMap();
+    }
+
     public void setRuntimeUnenhancedClasses(String mode) {
         assertNotReadOnly();
         runtimeUnenhancedClasses.setString(mode);
@@ -1459,6 +1471,7 @@
         super.instantiateAll();
         getMetaDataRepositoryInstance();
         getRemoteCommitEventManager();
+        cacheMarshallerPlugins.initialize();
     }
 
     protected void preClose() {

Added: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAVersionAndConfigurationTypeValidationPolicy.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAVersionAndConfigurationTypeValidationPolicy.java?rev=570948&view=auto
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAVersionAndConfigurationTypeValidationPolicy.java (added)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAVersionAndConfigurationTypeValidationPolicy.java Wed Aug 29 15:07:44 2007
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.conf;
+
+import org.apache.openjpa.conf.CacheMarshaller.ValidationPolicy;
+import org.apache.openjpa.lib.conf.Configurable;
+import org.apache.openjpa.lib.conf.Configuration;
+
+/**
+ * Compute validity based on whether or not the cached data is from the same
+ * version of Kodo as the current install. This also checks OpenJPA version
+ * information in case the OpenJPA jars were independently updated.
+ *
+ * @since 1.1.0
+ */
+public class OpenJPAVersionAndConfigurationTypeValidationPolicy
+    implements ValidationPolicy, Configurable {
+
+    private String confClassName;
+
+    public Object getCacheableData(Object o) {
+        return new Object[] {
+            OpenJPAVersion.VERSION_ID,
+            confClassName,
+            o,
+        };
+    }
+
+    public Object getValidData(Object o) {
+        Object[] array = (Object[]) o;
+        if (array.length != 3)
+            return null;
+
+        if (OpenJPAVersion.VERSION_ID.equals(array[0])
+            && confClassName.equals(array[1]))
+            return array[2];
+        else
+            return null;
+    }
+
+    public void setConfiguration(Configuration conf) {
+        confClassName = conf.getClass().getName();
+    }
+
+    public void startConfiguration() {
+    }
+
+    public void endConfiguration() {
+    }
+}

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/QueryCompilationCacheValue.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/QueryCompilationCacheValue.java?rev=570948&r1=570947&r2=570948&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/QueryCompilationCacheValue.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/QueryCompilationCacheValue.java Wed Aug 29 15:07:44 2007
@@ -87,7 +87,8 @@
 
         if (map != null && !(map instanceof Hashtable)
             && !(map instanceof CacheMap)
-            && !(map instanceof ConcurrentMap))
+            && !(map instanceof ConcurrentMap)
+            && !(map.getClass().getName().startsWith("java.util.concurrent")))
             map = Collections.synchronizedMap(map);
         return map;
 	}

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/ReflectingPersistenceCapable.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/ReflectingPersistenceCapable.java?rev=570948&r1=570947&r2=570948&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/ReflectingPersistenceCapable.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/ReflectingPersistenceCapable.java Wed Aug 29 15:07:44 2007
@@ -73,45 +73,45 @@
     }
 
     public void pcProvideField(int i) {
+        Object value = getValue(i, o);
         switch (meta.getField(i).getTypeCode()) {
             case JavaTypes.BOOLEAN:
-                sm.providedBooleanField(this, i,
-                    ((Boolean) getValue(i, o)).booleanValue());
+                sm.providedBooleanField(this, i, value == null ? false :
+                    ((Boolean) value).booleanValue());
                 break;
             case JavaTypes.BYTE:
-                sm.providedByteField(this, i,
-                    ((Byte) getValue(i, o)).byteValue());
+                sm.providedByteField(this, i, value == null ? 0 :
+                    ((Byte) value).byteValue());
                 break;
             case JavaTypes.CHAR:
-                sm.providedCharField(this, i,
-                    ((Character) getValue(i, o)).charValue());
+                sm.providedCharField(this, i, value == null ? 0 :
+                    ((Character) value).charValue());
                 break;
             case JavaTypes.DOUBLE:
-                sm.providedDoubleField(this, i,
-                    ((Double) getValue(i, o)).doubleValue());
+                sm.providedDoubleField(this, i, value == null ? 0 :
+                    ((Double) value).doubleValue());
                 break;
             case JavaTypes.FLOAT:
-                sm.providedFloatField(this, i,
-                    ((Float) getValue(i, o)).floatValue());
+                sm.providedFloatField(this, i, value == null ? 0 :
+                    ((Float) value).floatValue());
                 break;
             case JavaTypes.INT:
-                sm.providedIntField(this, i,
-                    ((Integer) getValue(i, o)).intValue());
+                sm.providedIntField(this, i, value == null ? 0 :
+                    ((Integer) value).intValue());
                 break;
             case JavaTypes.LONG:
-                sm.providedLongField(this, i,
-                    ((Long) getValue(i, o)).longValue());
+                sm.providedLongField(this, i, value == null ? 0 :
+                    ((Long) value).longValue());
                 break;
             case JavaTypes.SHORT:
-                sm.providedShortField(this, i,
-                    ((Short) getValue(i, o)).shortValue());
+                sm.providedShortField(this, i, value == null ? 0 :
+                    ((Short) value).shortValue());
                 break;
             case JavaTypes.STRING:
-                sm.providedStringField(this, i,
-                    (String) getValue(i, o));
+                sm.providedStringField(this, i, (String) value);
                 break;
             default:
-                sm.providedObjectField(this, i, getValue(i, o));
+                sm.providedObjectField(this, i, value);
                 break;
         }
     }

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ExpressionStoreQuery.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ExpressionStoreQuery.java?rev=570948&r1=570947&r2=570948&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ExpressionStoreQuery.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ExpressionStoreQuery.java Wed Aug 29 15:07:44 2007
@@ -18,6 +18,7 @@
  */
 package org.apache.openjpa.kernel;
 
+import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
@@ -277,7 +278,7 @@
      *
      * @author Marc Prud'hommeaux
      */
-    private static abstract class AbstractExpressionExecutor
+    public static abstract class AbstractExpressionExecutor
         extends AbstractExecutor
         implements Executor {
 
@@ -471,7 +472,7 @@
      */
     private static class InMemoryExecutor
         extends AbstractExpressionExecutor
-        implements Executor {
+        implements Executor, Serializable {
 
         private final ClassMetaData _meta;
         private final boolean _subs;
@@ -624,17 +625,17 @@
      *
      * @author Marc Prud'hommeaux
      */
-    private static class DataStoreExecutor
+    public static class DataStoreExecutor
         extends AbstractExpressionExecutor
-        implements Executor {
+        implements Executor, Serializable {
 
-        private final ClassMetaData _meta;
-        private final ClassMetaData[] _metas;
-        private final boolean _subs;
-        private final ExpressionParser _parser;
-        private final ExpressionFactory[] _facts;
-        private final QueryExpressions[] _exps;
-        private final Class[] _projTypes;
+        private ClassMetaData _meta;
+        private ClassMetaData[] _metas;
+        private boolean _subs;
+        private ExpressionParser _parser;
+        private ExpressionFactory[] _facts;
+        private QueryExpressions[] _exps;
+        private Class[] _projTypes;
         private Value[] _inMemOrdering;
 
         public DataStoreExecutor(ExpressionStoreQuery q,

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java?rev=570948&r1=570947&r2=570948&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java Wed Aug 29 15:07:44 2007
@@ -74,7 +74,7 @@
 public class QueryImpl
     implements Query {
 
-    private static Localizer _loc = Localizer.forPackage(QueryImpl.class);
+    private static final Localizer _loc = Localizer.forPackage(QueryImpl.class);
 
     private final String _language;
     private final StoreQuery _storeQuery;
@@ -1693,7 +1693,8 @@
     /**
      * Struct of compiled query properties.
      */
-    protected static class Compilation {
+    protected static class Compilation
+        implements Serializable {
 
         public StoreQuery.Executor memory = null;
         public StoreQuery.Executor datastore = null;

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Expression.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Expression.java?rev=570948&r1=570947&r2=570948&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Expression.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Expression.java Wed Aug 29 15:07:44 2007
@@ -18,13 +18,16 @@
  */
 package org.apache.openjpa.kernel.exps;
 
+import java.io.Serializable;
+
 /**
  * Interface for a set of conditions that must be met for the query
  * to be true.
  *
  * @author Abe White
  */
-public interface Expression {
+public interface Expression
+    extends Serializable {
 
     /**
      * Accept a visit from a tree visitor.

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/QueryExpressions.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/QueryExpressions.java?rev=570948&r1=570947&r2=570948&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/QueryExpressions.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/QueryExpressions.java Wed Aug 29 15:07:44 2007
@@ -18,6 +18,7 @@
  */
 package org.apache.openjpa.kernel.exps;
 
+import java.io.Serializable;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
@@ -35,7 +36,8 @@
  * @since 0.3.2
  * @nojavadoc
  */
-public class QueryExpressions {
+public class QueryExpressions
+    implements Serializable {
 
     public static final int DISTINCT_AUTO = 2 << 0;
     public static final int DISTINCT_TRUE = 2 << 1;

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Value.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Value.java?rev=570948&r1=570947&r2=570948&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Value.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Value.java Wed Aug 29 15:07:44 2007
@@ -18,6 +18,8 @@
  */
 package org.apache.openjpa.kernel.exps;
 
+import java.io.Serializable;
+
 import org.apache.openjpa.meta.ClassMetaData;
 
 /**
@@ -26,7 +28,8 @@
  *
  * @author Abe White
  */
-public interface Value {
+public interface Value
+    extends Serializable {
 
     /**
      * Return the expected type for this value, or <code>Object</code> if

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java?rev=570948&r1=570947&r2=570948&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java Wed Aug 29 15:07:44 2007
@@ -22,7 +22,6 @@
 import java.io.Serializable;
 import java.lang.reflect.Field;
 import java.math.BigDecimal;
-import java.security.AccessController;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashSet;
@@ -44,7 +43,6 @@
 import org.apache.openjpa.kernel.exps.QueryExpressions;
 import org.apache.openjpa.kernel.exps.Subquery;
 import org.apache.openjpa.kernel.exps.Value;
-import org.apache.openjpa.lib.util.J2DoPrivHelper;
 import org.apache.openjpa.lib.util.Localizer;
 import org.apache.openjpa.meta.ClassMetaData;
 import org.apache.openjpa.meta.FieldMetaData;
@@ -70,7 +68,7 @@
     private static final int VAR_PATH = 1;
     private static final int VAR_ERROR = 2;
 
-    private static Localizer _loc = Localizer.forPackage
+    private static final Localizer _loc = Localizer.forPackage
         (JPQLExpressionBuilder.class);
 
     private final Stack contexts = new Stack();
@@ -261,7 +259,7 @@
 
         Expression filter = null;
         filter = and(evalFromClause(root().id == JJTSELECT), filter);
-        filter = and(evalWhereClause(exps), filter);
+        filter = and(evalWhereClause(), filter);
         filter = and(evalSelectClause(exps), filter);
 
         exps.filter = filter == null ? factory.emptyExpression() : filter;
@@ -469,7 +467,7 @@
         }
     }
 
-    private Expression evalWhereClause(QueryExpressions exps) {
+    private Expression evalWhereClause() {
         // evaluate the WHERE clause
         JPQLNode whereNode = root().findChildByID(JJTWHERE, false);
         if (whereNode == null)
@@ -529,10 +527,10 @@
             exp =  and(exp, factory.equal(path, subpath));
         }
 
-        return addJoin(path, alias, inner, exp);
+        return addJoin(path, alias, exp);
     }
 
-    private Expression addJoin(Path path, JPQLNode aliasNode, boolean inner,
+    private Expression addJoin(Path path, JPQLNode aliasNode,
         Expression exp) {
         FieldMetaData fmd = path.last();
 
@@ -1634,8 +1632,11 @@
     public static class ParsedJPQL
         implements Serializable {
 
-        protected final JPQLNode root;
-        protected final String query;
+        // This is only ever used during parse; when ParsedJPQL instances
+        // are serialized, they will have already been parsed.
+        private final transient JPQLNode root;
+
+        private final String query;
         
         // cache of candidate type data. This is stored here in case this  
         // parse tree is reused in a context that does not know what the 
@@ -1651,7 +1652,7 @@
             this.query = query;
         }
 
-        private static final JPQLNode parse(String jpql) {
+        private static JPQLNode parse(String jpql) {
             if (jpql == null)
                 jpql = "";
 

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/FieldMetaData.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/FieldMetaData.java?rev=570948&r1=570947&r2=570948&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/FieldMetaData.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/FieldMetaData.java Wed Aug 29 15:07:44 2007
@@ -178,9 +178,8 @@
 
     // Members aren't serializable. Use a proxy that can provide a Member
     // to avoid writing the full Externalizable implementation.
-    private transient MemberProvider _backingMember = null;
-    private String _backingFieldName = null;
-    
+    private MemberProvider _backingMember = null;
+
     // Members aren't serializable. Initializing _extMethod and _factMethod to
     // DEFAULT_METHOD is sufficient to trigger lazy population of these fields.
     private transient Method _extMethod = DEFAULT_METHOD;
@@ -1996,18 +1995,22 @@
      * Serializable wrapper around a {@link Method} or {@link Field}. For 
      * space considerations, this does not support {@link Constructor}s.
      */
-	private static class MemberProvider 
+	public static class MemberProvider
         implements Externalizable {
 
         private transient Member _member;
-        
-        private MemberProvider(Member member) {
+
+        public MemberProvider() {
+            // for externalization
+        }
+
+        MemberProvider(Member member) {
             if (member instanceof Constructor)
                 throw new IllegalArgumentException();
 
             _member = member;
         }
-        
+
         public Member getMember() {
             return _member;
         }
@@ -2015,13 +2018,13 @@
         public void readExternal(ObjectInput in)
             throws IOException, ClassNotFoundException {
             boolean isField = in.readBoolean();
-            Class cls = _member.getDeclaringClass();
+            Class cls = (Class) in.readObject();
             String memberName = (String) in.readObject();
             try {
                 if (isField)
                     _member = (Field) AccessController.doPrivileged(
                         J2DoPrivHelper.getDeclaredFieldAction(
-                            cls,memberName)); 
+                            cls, memberName)); 
                 else {
                     Class[] parameterTypes = (Class[]) in.readObject();
                     _member = (Method) AccessController.doPrivileged(

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataRepository.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataRepository.java?rev=570948&r1=570947&r2=570948&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataRepository.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataRepository.java Wed Aug 29 15:07:44 2007
@@ -25,6 +25,7 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
@@ -35,10 +36,10 @@
 
 import org.apache.commons.lang.StringUtils;
 import org.apache.openjpa.conf.OpenJPAConfiguration;
+import org.apache.openjpa.enhance.DynamicPersistenceCapable;
 import org.apache.openjpa.enhance.PCRegistry;
 import org.apache.openjpa.enhance.PCRegistry.RegisterClassListener;
 import org.apache.openjpa.enhance.PersistenceCapable;
-import org.apache.openjpa.enhance.DynamicPersistenceCapable;
 import org.apache.openjpa.event.LifecycleEventManager;
 import org.apache.openjpa.lib.conf.Configurable;
 import org.apache.openjpa.lib.conf.Configuration;
@@ -46,10 +47,10 @@
 import org.apache.openjpa.lib.util.Closeable;
 import org.apache.openjpa.lib.util.J2DoPrivHelper;
 import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.util.ImplHelper;
 import org.apache.openjpa.util.InternalException;
 import org.apache.openjpa.util.MetaDataException;
 import org.apache.openjpa.util.OpenJPAId;
-import org.apache.openjpa.util.ImplHelper;
 import serp.util.Strings;
 
 /**
@@ -132,7 +133,7 @@
 
     // we buffer up any classes that register themselves to prevent
     // reentrancy errors if classes register during a current parse (common)
-    private final Collection _registered = new ArrayList();
+    private final Collection _registered = new HashSet();
 
     // set of metadatas we're in the process of resolving
     private final SortedSet _resolving = new TreeSet

Modified: openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/conf/localizer.properties
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/conf/localizer.properties?rev=570948&r1=570947&r2=570948&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/conf/localizer.properties (original)
+++ openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/conf/localizer.properties Wed Aug 29 15:07:44 2007
@@ -552,3 +552,30 @@
 diff-specs: Attempt to configure for multiple specifications.  Was configured \
 	for "{0}".  Attempt to now configure for "{1}".  This attempt will be \
 	ignored.
+
+cache-marshaller-loaded: Loaded cached data of type {0} from file {1}.
+cache-marshaller-no-inputs: No InputURL or InputResource was specified for \
+    CacheMarshaller {0}. Cannot load data if no input was specified.
+cache-marshaller-load-exception: An error occurred while loading cached data \
+	from {0}. The exception is logged with this message; it will be consumed \
+	and ignored.
+cache-marshaller-stored: Stored data of type {0} to file {1}.
+cache-marshaller-no-output-file: No OutputFile was specified for \
+    CacheMarshaller {0}. Cannot store data if no output was specified.
+cache-marshaller-store-exception: An error occurred while storing data \
+	to cache in {0}. The exception is logged with this message; it will be \
+	consumed and ignored.
+cache-marshaller-input-url-and-resource-specified: An InputURL and an \
+    InputResource were specified for CacheMarshaller {0}. At most one of these \
+    can be specified.
+cache-marshaller-multiple-resources: Multiple resources exist for resource \
+    location {1} for CacheMarshaller {0}.
+cache-marshaller-bad-url: An error occurred while loading resource location \
+    {1} for CacheMarshaller {0}.
+cache-marshaller-null-validation-policy: No ValidationPolicy was set for \
+	cache marshaller of type {0}.
+cache-marshaller-null-id: No id was set for cache marshaller of type {0}. The \
+	id value is used by the subsystems within Kodo that use marshallers to \
+	find the right marshaller to use to load and store cached data.
+cache-marshaller-not-found: No cache marshaller found for id {0}.
+cache-marshaller-found: Cache marshaller of type {1} found for id {0}.

Added: openjpa/trunk/openjpa-kernel/src/test/java/org/apache/openjpa/meta/TestMemberProvider.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/test/java/org/apache/openjpa/meta/TestMemberProvider.java?rev=570948&view=auto
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/test/java/org/apache/openjpa/meta/TestMemberProvider.java (added)
+++ openjpa/trunk/openjpa-kernel/src/test/java/org/apache/openjpa/meta/TestMemberProvider.java Wed Aug 29 15:07:44 2007
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.meta;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.IOException;
+
+import junit.framework.TestCase;
+import org.apache.openjpa.meta.FieldMetaData.MemberProvider;
+
+public class TestMemberProvider
+    extends TestCase {
+
+    private String field;
+
+    public void testField()
+        throws NoSuchFieldException, IOException, ClassNotFoundException {
+        MemberProvider b = new MemberProvider(
+            getClass().getDeclaredField("field"));
+        MemberProvider b2 = roundtrip(b);
+        assertEquals(b.getMember(), b2.getMember());
+    }
+
+    public void testMethod()
+        throws NoSuchMethodException, IOException, ClassNotFoundException {
+        MemberProvider b = new MemberProvider(
+            getClass().getDeclaredMethod("testMethod", null));
+        MemberProvider b2 = roundtrip(b);
+        assertEquals(b.getMember(), b2.getMember());
+    }
+
+    private MemberProvider roundtrip(MemberProvider other)
+        throws IOException, ClassNotFoundException {
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        new ObjectOutputStream(out).writeObject(other);
+        out.flush();
+        byte[] bytes = out.toByteArray();
+        out.close();
+
+        ByteArrayInputStream in = new ByteArrayInputStream(bytes);
+        return (MemberProvider) new ObjectInputStream(in).readObject();
+    }
+}

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/conf/TestCacheMarshaller.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/conf/TestCacheMarshaller.java?rev=570948&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/conf/TestCacheMarshaller.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/conf/TestCacheMarshaller.java Wed Aug 29 15:07:44 2007
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.conf;
+
+import org.apache.openjpa.conf.CacheMarshaller.ValidationPolicy;
+import org.apache.openjpa.persistence.test.SingleEMFTestCase;
+
+public class TestCacheMarshaller
+    extends SingleEMFTestCase {
+
+    private CacheMarshaller cm;
+
+    public void setUp() {
+        setUp(new Object[] { "openjpa.CacheMarshallers",
+            "default(Id=" + getClass().getName() + ", ValidationPolicy="
+                + OpenJPAVersionAndConfigurationTypeValidationPolicy.class
+                    .getName()
+                + ", InputURL=file:" + getClass().getName() + ".ser, OutputFile="
+                + getClass().getName() + ".ser)"
+        });
+        emf.createEntityManager().close();
+        cm = CacheMarshallersValue.getMarshallerById(emf.getConfiguration(),
+            getClass().getName());
+    }
+
+    public void testCacheMarshallerType() {
+        assertEquals(CacheMarshallerImpl.class, cm.getClass());
+    }
+
+    public void testConfiguration() {
+        assertEquals(getClass().getName(), cm.getId());
+    }
+
+    public void testValidation() {
+        ValidationPolicy vp = ((CacheMarshallerImpl) cm).getValidationPolicy();
+        assertEquals(OpenJPAVersionAndConfigurationTypeValidationPolicy.class,
+            vp.getClass());
+        Object[] cached = (Object[]) vp.getCacheableData(this);
+
+        assertEquals(3, cached.length);
+        assertEquals(OpenJPAVersion.VERSION_ID, cached[0]);
+        assertEquals(emf.getConfiguration().getClass().getName(), cached[1]);
+        assertEquals(this, cached[2]);
+
+        assertEquals(this, vp.getValidData(cached));
+    }
+
+    public void testRoundTrip() {
+        Object o = "foo";
+        cm.store(o);
+        assertEquals(o, cm.load());
+    }
+}

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/conf/TestCacheMarshallerEndToEnd.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/conf/TestCacheMarshallerEndToEnd.java?rev=570948&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/conf/TestCacheMarshallerEndToEnd.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/conf/TestCacheMarshallerEndToEnd.java Wed Aug 29 15:07:44 2007
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.conf;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.List;
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+import org.apache.openjpa.persistence.JPAFacadeHelper;
+import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI;
+import org.apache.openjpa.persistence.query.NamedQueryEntity;
+import org.apache.openjpa.persistence.simple.AllFieldTypes;
+import org.apache.openjpa.persistence.test.PersistenceTestCase;
+
+public class TestCacheMarshallerEndToEnd
+    extends PersistenceTestCase {
+
+    private static final Object[] STORE_PROPS = new Object[] {
+        "openjpa.CacheMarshallers",
+        "default(Id=" + MetaDataCacheMaintenance.class.getName()
+            + ", OutputFile=" + MetaDataCacheMaintenance.class.getName() +".ser"
+            + ", ConsumeSerializationErrors=false"
+            + ", ValidationPolicy="
+            + OpenJPAVersionAndConfigurationTypeValidationPolicy.class.getName()
+            + ")",
+        "openjpa.QueryCompilationCache",
+        "java.util.concurrent.ConcurrentHashMap",
+        AllFieldTypes.class,
+        NamedQueryEntity.class,
+        CLEAR_TABLES
+    };
+
+    private static final Object[] LOAD_PROPS = new Object[] {
+        "openjpa.CacheMarshallers",
+        "default(Id=" + MetaDataCacheMaintenance.class.getName()
+            + ", InputURL=file:" + MetaDataCacheMaintenance.class.getName()
+                + ".ser"
+            + ", ConsumeSerializationErrors=false"
+            + ", ValidationPolicy="
+            + OpenJPAVersionAndConfigurationTypeValidationPolicy.class.getName()
+            + ")",
+        "openjpa.QueryCompilationCache",
+        "java.util.concurrent.ConcurrentHashMap",
+        AllFieldTypes.class,
+        NamedQueryEntity.class
+    };
+
+
+    public void testCacheMarshallerEndToEnd()
+        throws IOException {
+        OpenJPAEntityManagerFactorySPI emf = createEMF(STORE_PROPS);
+        CacheMarshallerImpl cm = (CacheMarshallerImpl)
+            CacheMarshallersValue.getMarshallerById(
+            emf.getConfiguration(), MetaDataCacheMaintenance.class.getName());
+        cm.getOutputFile().delete();
+        MetaDataCacheMaintenance maint = new MetaDataCacheMaintenance(
+            JPAFacadeHelper.toBrokerFactory(emf), false, true);
+        final List<String> lines = new ArrayList<String>();
+        PrintStream out = new PrintStream(new ByteArrayOutputStream()) {
+            public void println(String line) {
+                lines.add(line);
+            }
+
+            public void println(Object line) {
+                println(line.toString());
+            }
+        };
+        maint.setOutputStream(out);
+        maint.store();
+        assertContains(lines, "    " + AllFieldTypes.class.getName());
+        assertContains(lines, "    " + NamedQueryEntity.class.getName());
+        assertContains(lines, "    NamedQueryEntity.namedQuery");
+        emf.close();
+
+        emf = createEMF(LOAD_PROPS);
+        EntityManager em = emf.createEntityManager();
+        em.getTransaction().begin();
+        em.persist(new NamedQueryEntity("foo"));
+        em.flush();
+        Query q = em.createNamedQuery("NamedQueryEntity.namedQuery");
+        assertEquals(1, q.getResultList().size());
+        em.getTransaction().rollback();
+        em.close();
+        emf.close();
+    }
+
+    private void assertContains(List<String> lines, String prefix) {
+        for (String line : lines)
+            if (line.startsWith(prefix))
+                return;
+        fail("should contain a line starting with " + prefix
+            + ": " + lines);
+    }
+}

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/NamedQueryEntity.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/NamedQueryEntity.java?rev=570948&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/NamedQueryEntity.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/NamedQueryEntity.java Wed Aug 29 15:07:44 2007
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.persistence.query;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.NamedQuery;
+
+@Entity
+@NamedQuery(name="NamedQueryEntity.namedQuery",
+    query="select o from NamedQueryEntity o where o.stringField = 'foo'")
+public class NamedQueryEntity {
+    @Id @GeneratedValue
+    private Integer id;
+
+    private String stringField;
+
+    public NamedQueryEntity(String stringField) {
+        this.stringField = stringField;
+    }
+
+    public NamedQueryEntity() {
+        // for JPA
+    }
+}



Mime
View raw message