OPENJPA-262

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@550185 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Patrick Linskey 2007-06-24 09:16:57 +00:00
parent cbb7bded12
commit 39f1071085
10 changed files with 218 additions and 152 deletions

View File

@ -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();
}

View File

@ -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.
@ -1409,6 +1412,10 @@ public class OpenJPAConfigurationImpl
return _storeFacadeRegistry;
}
public BrokerFactoryEventManager getBrokerFactoryEventManager() {
return _brokerFactoryEventManager;
}
public void instantiateAll() {
super.instantiateAll();
getMetaDataRepositoryInstance();

View File

@ -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;
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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.

View File

@ -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();
}
}

View File

@ -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();

View File

@ -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;
}
}
}