From 39f1071085c02dfb4a4d94f1f508c2e82dc44cf7 Mon Sep 17 00:00:00 2001 From: Patrick Linskey Date: Sun, 24 Jun 2007 09:16:57 +0000 Subject: [PATCH] OPENJPA-262 git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@550185 13f79535-47bb-0310-9956-ffa450edef68 --- .../openjpa/conf/OpenJPAConfiguration.java | 7 + .../conf/OpenJPAConfigurationImpl.java | 9 +- .../openjpa/event/BrokerFactoryEvent.java | 52 ++++++ .../event/BrokerFactoryEventManager.java | 53 +++++++ .../openjpa/event/BrokerFactoryListener.java | 35 ++++ .../openjpa/kernel/AbstractBrokerFactory.java | 7 + .../apache/openjpa/event/localizer.properties | 2 + .../lib/util/AbstractEventManager.java | 149 ------------------ .../lib/util/TestAbstractEventManager.java | 5 +- .../kernel/TestBrokerFactoryEventManager.java | 51 ++++++ 10 files changed, 218 insertions(+), 152 deletions(-) create mode 100644 openjpa-kernel/src/main/java/org/apache/openjpa/event/BrokerFactoryEvent.java create mode 100644 openjpa-kernel/src/main/java/org/apache/openjpa/event/BrokerFactoryEventManager.java create mode 100644 openjpa-kernel/src/main/java/org/apache/openjpa/event/BrokerFactoryListener.java delete mode 100644 openjpa-lib/src/main/java/org/apache/openjpa/lib/util/AbstractEventManager.java create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/TestBrokerFactoryEventManager.java diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java b/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java index 436606d7a..037a384fd 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java @@ -39,6 +39,7 @@ import org.apache.openjpa.kernel.QueryFlushModes; import org.apache.openjpa.kernel.RestoreState; import org.apache.openjpa.kernel.SavepointManager; import org.apache.openjpa.kernel.Seq; +import org.apache.openjpa.event.BrokerFactoryEventManager; import org.apache.openjpa.kernel.exps.AggregateListener; import org.apache.openjpa.kernel.exps.FilterListener; import org.apache.openjpa.lib.conf.Configuration; @@ -1386,4 +1387,10 @@ public interface OpenJPAConfiguration * configuration. */ public StoreFacadeTypeRegistry getStoreFacadeTypeRegistry(); + + /** + * Return the {@link org.apache.openjpa.event.BrokerFactoryEventManager} associated with this + * configuration. + */ + public BrokerFactoryEventManager getBrokerFactoryEventManager(); } diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java b/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java index 6275c6db0..3c9e11a5c 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java @@ -31,6 +31,7 @@ import org.apache.openjpa.ee.ManagedRuntime; import org.apache.openjpa.event.OrphanedKeyAction; import org.apache.openjpa.event.RemoteCommitEventManager; import org.apache.openjpa.event.RemoteCommitProvider; +import org.apache.openjpa.event.BrokerFactoryEventManager; import org.apache.openjpa.kernel.AutoClear; import org.apache.openjpa.kernel.BrokerImpl; import org.apache.openjpa.kernel.ConnectionRetainModes; @@ -140,6 +141,8 @@ public class OpenJPAConfigurationImpl private String spec = null; private final StoreFacadeTypeRegistry _storeFacadeRegistry = new StoreFacadeTypeRegistry(); + private BrokerFactoryEventManager _brokerFactoryEventManager = + new BrokerFactoryEventManager(this); /** * Default constructor. Attempts to load global properties. @@ -1408,7 +1411,11 @@ public class OpenJPAConfigurationImpl public StoreFacadeTypeRegistry getStoreFacadeTypeRegistry() { return _storeFacadeRegistry; } - + + public BrokerFactoryEventManager getBrokerFactoryEventManager() { + return _brokerFactoryEventManager; + } + public void instantiateAll() { super.instantiateAll(); getMetaDataRepositoryInstance(); diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/event/BrokerFactoryEvent.java b/openjpa-kernel/src/main/java/org/apache/openjpa/event/BrokerFactoryEvent.java new file mode 100644 index 000000000..ea6cc36d5 --- /dev/null +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/event/BrokerFactoryEvent.java @@ -0,0 +1,52 @@ +/* + * 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.event; + +import java.util.EventObject; + +import org.apache.openjpa.kernel.BrokerFactory; + +/** + * Event fired when a {@link BrokerFactory} is created. + * + * @since 1.0.0 + */ +public class BrokerFactoryEvent + extends EventObject { + + public final static int BROKER_FACTORY_CREATED = 0; + + private int eventType; + + public BrokerFactoryEvent(BrokerFactory brokerFactory, int eventType) { + super(brokerFactory); + this.eventType = eventType; + } + + public BrokerFactory getBrokerFactory() { + return (BrokerFactory) getSource(); + } + + /** + * @return one of the event type codes defined in this event class. + */ + public int getEventType() { + return eventType; + } +} diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/event/BrokerFactoryEventManager.java b/openjpa-kernel/src/main/java/org/apache/openjpa/event/BrokerFactoryEventManager.java new file mode 100644 index 000000000..0e34ae945 --- /dev/null +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/event/BrokerFactoryEventManager.java @@ -0,0 +1,53 @@ +/* + * 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.event; + +import org.apache.openjpa.lib.util.concurrent.AbstractConcurrentEventManager; +import org.apache.openjpa.lib.util.Localizer; +import org.apache.openjpa.lib.conf.Configuration; +import org.apache.openjpa.conf.OpenJPAConfiguration; + +/** + * {@link EventManager} responsible for notifying listeners of + * {@link BrokerFactoryEvent}s. + * + * @since 1.0.0 + */ +public class BrokerFactoryEventManager + extends AbstractConcurrentEventManager { + + private static final Localizer _loc = Localizer.forPackage( + BrokerFactoryEventManager.class); + + private final Configuration _conf; + + public BrokerFactoryEventManager(Configuration conf) { + _conf = conf; + } + + protected void fireEvent(Object event, Object listener) { + try { + BrokerFactoryEvent e = (BrokerFactoryEvent) event; + ((BrokerFactoryListener) listener).afterBrokerFactoryCreate(e); + } catch (Exception e) { + _conf.getLog(OpenJPAConfiguration.LOG_RUNTIME).warn( + _loc.get("broker-factory-listener-exception"), e); + } + } +} diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/event/BrokerFactoryListener.java b/openjpa-kernel/src/main/java/org/apache/openjpa/event/BrokerFactoryListener.java new file mode 100644 index 000000000..7172419d0 --- /dev/null +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/event/BrokerFactoryListener.java @@ -0,0 +1,35 @@ +/* + * 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.event; + +/** + * Interface for listening to {@link BrokerFactoryEvent} objects. Should be + * registered with a {@link OpenJPAConfiguration}'s + * {@link BrokerFactoryEventManager}. + * + * @since 1.0.0 + */ +public interface BrokerFactoryListener { + + /** + * Invoked after a {@link AbstractBrokerFactory} has been fully created. + * This happens after the factory has been made read-only. + */ + public void afterBrokerFactoryCreate(BrokerFactoryEvent event); +} diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/AbstractBrokerFactory.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/AbstractBrokerFactory.java index c10d35171..7c2fb1d3e 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/AbstractBrokerFactory.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/AbstractBrokerFactory.java @@ -37,6 +37,7 @@ import org.apache.openjpa.conf.OpenJPAVersion; import org.apache.openjpa.datacache.DataCacheStoreManager; import org.apache.openjpa.enhance.PCRegistry; import org.apache.openjpa.event.RemoteCommitEventManager; +import org.apache.openjpa.event.BrokerFactoryEvent; import org.apache.openjpa.lib.log.Log; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.util.ReferenceHashSet; @@ -545,6 +546,12 @@ public abstract class AbstractBrokerFactory // avoid synchronization _conf.setReadOnly(true); _conf.instantiateAll(); + + // fire an event for all the broker factory listeners + // registered on the configuration. + _conf.getBrokerFactoryEventManager().fireEvent( + new BrokerFactoryEvent(this, + BrokerFactoryEvent.BROKER_FACTORY_CREATED)); } finally { unlock(); } diff --git a/openjpa-kernel/src/main/resources/org/apache/openjpa/event/localizer.properties b/openjpa-kernel/src/main/resources/org/apache/openjpa/event/localizer.properties index 432527d4a..0d8ee774e 100644 --- a/openjpa-kernel/src/main/resources/org/apache/openjpa/event/localizer.properties +++ b/openjpa-kernel/src/main/resources/org/apache/openjpa/event/localizer.properties @@ -95,3 +95,5 @@ bean-constructor: Could not instantiate class {0}. Make sure it has an \ accessible no-args constructor. method-notfound: Method "{1}" with arguments of type: {2} \ not found in class "{0}". +broker-factory-listener-exception: Exception thrown while calling a \ + BrokerFactoryListener. This exception will be ignored. \ No newline at end of file diff --git a/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/AbstractEventManager.java b/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/AbstractEventManager.java deleted file mode 100644 index db073f1ae..000000000 --- a/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/AbstractEventManager.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * 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.lib.util; - -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; - -/** - * Base event manager that handles adding/removing listeners - * and firing events. This class is reentrant-safe; listeners can be added - * and removed by other listeners when they receive events. The changes will - * not be visible until the event fire that initiated the recursive sequence - * of calls completes, however. - * - * @author Abe White - */ -public abstract class AbstractEventManager implements EventManager { - - private static Exception[] EMPTY_EXCEPTIONS = new Exception[0]; - - private boolean _firing = false; - private Collection _listeners = null; - private Collection _newListeners = null; - - /** - * Register an event listener. - */ - public synchronized void addListener(Object listener) { - if (listener == null) - return; - if (_firing) { - if (_newListeners == null) { - _newListeners = newListenerCollection(); - _newListeners.addAll(_listeners); - } - _newListeners.add(listener); - } else { - if (_listeners == null) - _listeners = newListenerCollection(); - _listeners.add(listener); - } - } - - /** - * Remove an event listener. - */ - public synchronized boolean removeListener(Object listener) { - if (listener == null) - return false; - if (_firing && _listeners.contains(listener)) { - if (_newListeners == null) { - _newListeners = newListenerCollection(); - _newListeners.addAll(_listeners); - } - return _newListeners.remove(listener); - } - return _listeners != null && _listeners.remove(listener); - } - - /** - * Return whether the given instance is in the list of listeners. - */ - public synchronized boolean hasListener(Object listener) { - return _listeners != null && _listeners.contains(listener); - } - - /** - * Return true if there are any registered listeners. - */ - public synchronized boolean hasListeners() { - return _listeners != null && !_listeners.isEmpty(); - } - - /** - * Return a read-only list of listeners. - */ - public synchronized Collection getListeners() { - return (_listeners == null) ? Collections.EMPTY_LIST - : Collections.unmodifiableCollection(_listeners); - } - - /** - * Fire the given event to all listeners. - */ - public synchronized Exception[] fireEvent(Object event) { - if (_listeners == null || _listeners.isEmpty()) - return EMPTY_EXCEPTIONS; - - boolean reentrant = _firing; - _firing = true; - List exceptions = null; - for (Iterator itr = _listeners.iterator(); itr.hasNext();) { - try { - fireEvent(event, itr.next()); - } catch (Exception e) { - if (exceptions == null) - exceptions = new LinkedList(); - exceptions.add(e); - } - } - - // if this wasn't a reentrant call, record that we're no longer - // in the process of firing events and replace our initial listener - // list with the set of new listeners - if (!reentrant) { - _firing = false; - if (_newListeners != null) - _listeners = _newListeners; - _newListeners = null; - } - - if (exceptions == null) - return EMPTY_EXCEPTIONS; - return (Exception[]) exceptions.toArray - (new Exception[exceptions.size()]); - } - - /** - * Implement this method to fire the given event to the given listener. - */ - protected abstract void fireEvent(Object event, Object listener) - throws Exception; - - /** - * Return a new container for listeners. Uses a linked list by default. - */ - protected Collection newListenerCollection() { - return new LinkedList(); - } -} diff --git a/openjpa-lib/src/test/java/org/apache/openjpa/lib/util/TestAbstractEventManager.java b/openjpa-lib/src/test/java/org/apache/openjpa/lib/util/TestAbstractEventManager.java index c001bfff5..bfb6538f3 100644 --- a/openjpa-lib/src/test/java/org/apache/openjpa/lib/util/TestAbstractEventManager.java +++ b/openjpa-lib/src/test/java/org/apache/openjpa/lib/util/TestAbstractEventManager.java @@ -22,9 +22,10 @@ import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import junit.textui.TestRunner; +import org.apache.openjpa.lib.util.concurrent.AbstractConcurrentEventManager; /** - * Tests the {@link AbstractEventManager}. + * Tests the {@link AbstractConcurrentEventManager}. * * @author Abe White */ @@ -67,7 +68,7 @@ public class TestAbstractEventManager extends TestCase { TestRunner.run(suite()); } - private static class EventManager extends AbstractEventManager { + private static class EventManager extends AbstractConcurrentEventManager { protected void fireEvent(Object event, Object listener) { ((Listener) listener).fire(); diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/TestBrokerFactoryEventManager.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/TestBrokerFactoryEventManager.java new file mode 100644 index 000000000..4203a5e99 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/TestBrokerFactoryEventManager.java @@ -0,0 +1,51 @@ +/* + * 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.kernel; + +import javax.persistence.Persistence; + +import junit.framework.TestCase; +import org.apache.openjpa.event.BrokerFactoryListener; +import org.apache.openjpa.event.BrokerFactoryEvent; +import org.apache.openjpa.persistence.OpenJPAPersistence; +import org.apache.openjpa.persistence.OpenJPAEntityManagerFactory; + +public class TestBrokerFactoryEventManager + extends TestCase { + + public void testCreateEvent() { + OpenJPAEntityManagerFactory emf = OpenJPAPersistence.cast( + Persistence.createEntityManagerFactory("test")); + ListenerImpl listener = new ListenerImpl(); + emf.getConfiguration().getBrokerFactoryEventManager() + .addListener(listener); + emf.createEntityManager().close(); + assertTrue(listener.createEventReceived); + emf.close(); + } + + private class ListenerImpl implements BrokerFactoryListener { + + boolean createEventReceived = false; + + public void afterBrokerFactoryCreate(BrokerFactoryEvent event) { + createEventReceived = true; + } + } +}