aboutsummaryrefslogtreecommitdiffstats
path: root/src/java/org/apache/fop/events/DefaultEventBroadcaster.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/java/org/apache/fop/events/DefaultEventBroadcaster.java')
-rw-r--r--src/java/org/apache/fop/events/DefaultEventBroadcaster.java160
1 files changed, 160 insertions, 0 deletions
diff --git a/src/java/org/apache/fop/events/DefaultEventBroadcaster.java b/src/java/org/apache/fop/events/DefaultEventBroadcaster.java
new file mode 100644
index 000000000..bb1752a72
--- /dev/null
+++ b/src/java/org/apache/fop/events/DefaultEventBroadcaster.java
@@ -0,0 +1,160 @@
+/*
+ * 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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.events;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.xmlgraphics.util.Service;
+
+import org.apache.fop.events.model.EventMethodModel;
+import org.apache.fop.events.model.EventModel;
+import org.apache.fop.events.model.EventModelFactory;
+import org.apache.fop.events.model.EventProducerModel;
+import org.apache.fop.events.model.EventSeverity;
+
+/**
+ * Default implementation of the EventBroadcaster interface. It holds a list of event listeners
+ * and can provide {@link EventProducer} instances for type-safe event production.
+ */
+public class DefaultEventBroadcaster implements EventBroadcaster {
+
+ /** Holds all registered event listeners */
+ protected CompositeEventListener listeners = new CompositeEventListener();
+
+ /** {@inheritDoc} */
+ public void addEventListener(EventListener listener) {
+ this.listeners.addEventListener(listener);
+ }
+
+ /** {@inheritDoc} */
+ public void removeEventListener(EventListener listener) {
+ this.listeners.removeEventListener(listener);
+ }
+
+ /** {@inheritDoc} */
+ public boolean hasEventListeners() {
+ return this.listeners.hasEventListeners();
+ }
+
+ /** {@inheritDoc} */
+ public void broadcastEvent(Event event) {
+ this.listeners.processEvent(event);
+ }
+
+ private static List/*<EventModel>*/ eventModels = new java.util.ArrayList();
+ private Map proxies = new java.util.HashMap();
+
+ static {
+ Iterator iter = Service.providers(EventModelFactory.class, true);
+ while (iter.hasNext()) {
+ EventModelFactory factory = (EventModelFactory)iter.next();
+ addEventModel(factory.createEventModel());
+ }
+ }
+
+ /**
+ * Adds a new {@link EventModel} to the list of registered event models.
+ * @param eventModel the event model instance
+ */
+ public static void addEventModel(EventModel eventModel) {
+ eventModels.add(eventModel);
+ }
+
+ /** {@inheritDoc} */
+ public EventProducer getEventProducerFor(Class clazz) {
+ if (!EventProducer.class.isAssignableFrom(clazz)) {
+ throw new IllegalArgumentException(
+ "Class must be an implementation of the EventProducer interface: "
+ + clazz.getName());
+ }
+ EventProducer producer;
+ producer = (EventProducer)this.proxies.get(clazz);
+ if (producer == null) {
+ producer = createProxyFor(clazz);
+ this.proxies.put(clazz, producer);
+ }
+ return producer;
+ }
+
+ private EventProducerModel getEventProducerModel(Class clazz) {
+ for (int i = 0, c = eventModels.size(); i < c; i++) {
+ EventModel eventModel = (EventModel)eventModels.get(i);
+ EventProducerModel producerModel = eventModel.getProducer(clazz);
+ if (producerModel != null) {
+ return producerModel;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Creates a dynamic proxy for the given EventProducer interface that will handle the
+ * conversion of the method call into the broadcasting of an event instance.
+ * @param clazz a descendant interface of EventProducer
+ * @return the EventProducer instance
+ */
+ protected EventProducer createProxyFor(Class clazz) {
+ final EventProducerModel producerModel = getEventProducerModel(clazz);
+ if (producerModel == null) {
+ throw new IllegalStateException("Event model doesn't contain the definition for "
+ + clazz.getName());
+ }
+ return (EventProducer)Proxy.newProxyInstance(clazz.getClassLoader(),
+ new Class[] {clazz},
+ new InvocationHandler() {
+ public Object invoke(Object proxy, Method method, Object[] args)
+ throws Throwable {
+ String methodName = method.getName();
+ EventMethodModel methodModel = producerModel.getMethod(methodName);
+ String eventID = producerModel.getInterfaceName() + "." + methodName;
+ if (methodModel == null) {
+ throw new IllegalStateException(
+ "Event model isn't consistent"
+ + " with the EventProducer interface. Please rebuild FOP!"
+ + " Affected method: "
+ + eventID);
+ }
+ Map params = new java.util.HashMap();
+ int i = 1;
+ Iterator iter = methodModel.getParameters().iterator();
+ while (iter.hasNext()) {
+ EventMethodModel.Parameter param
+ = (EventMethodModel.Parameter)iter.next();
+ params.put(param.getName(), args[i]);
+ i++;
+ }
+ Event ev = new Event(args[0], eventID, methodModel.getSeverity(), params);
+ broadcastEvent(ev);
+
+ if (ev.getSeverity() == EventSeverity.FATAL) {
+ EventExceptionManager.throwException(ev,
+ methodModel.getExceptionClass());
+ }
+ return null;
+ }
+ });
+ }
+
+}