diff options
Diffstat (limited to 'src/java/org/apache/fop/events')
24 files changed, 2145 insertions, 0 deletions
diff --git a/src/java/org/apache/fop/events/CompositeEventListener.java b/src/java/org/apache/fop/events/CompositeEventListener.java new file mode 100644 index 000000000..a65728b71 --- /dev/null +++ b/src/java/org/apache/fop/events/CompositeEventListener.java @@ -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. + */ + +/* $Id$ */ + +package org.apache.fop.events; + +import java.util.List; + +/** + * EventListener implementation forwards events to possibly multiple other EventListeners. + */ +public class CompositeEventListener implements EventListener { + + private List listeners = new java.util.ArrayList(); + + /** + * Adds an event listener to the broadcaster. It is appended to the list of previously + * registered listeners (the order of registration defines the calling order). + * @param listener the listener to be added + */ + public synchronized void addEventListener(EventListener listener) { + this.listeners.add(listener); + } + + /** + * Removes an event listener from the broadcaster. If the event listener is not registered, + * nothing happens. + * @param listener the listener to be removed + */ + public synchronized void removeEventListener(EventListener listener) { + this.listeners.remove(listener); + } + + private synchronized int getListenerCount() { + return this.listeners.size(); + } + + /** + * Indicates whether any listeners have been registered with the broadcaster. + * @return true if listeners are present, false otherwise + */ + public boolean hasEventListeners() { + return (getListenerCount() > 0); + } + + /** {@inheritDoc} */ + public synchronized void processEvent(Event event) { + for (int i = 0, c = getListenerCount(); i < c; i++) { + EventListener listener = (EventListener)this.listeners.get(i); + listener.processEvent(event); + } + } + +} 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; + } + }); + } + +} diff --git a/src/java/org/apache/fop/events/Event.java b/src/java/org/apache/fop/events/Event.java new file mode 100644 index 000000000..d3da1809e --- /dev/null +++ b/src/java/org/apache/fop/events/Event.java @@ -0,0 +1,150 @@ +/* + * 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.util.Collections; +import java.util.EventObject; +import java.util.Map; + +import org.apache.fop.events.model.EventSeverity; + +/** + * This is the default event class used by this package. Each event has a unique event identifier + * (a String), a severity indicator and a map of name/value pairs. + */ +public class Event extends EventObject { + + private static final long serialVersionUID = -1310594422868258083L; + + private String eventID; + private EventSeverity severity; + private Map params; + + /** + * Creates a new Event. + * @param source the object that creates the event + * @param eventID the unique identifier of the event + * @param severity the severity level + * @param params the event parameters (a map of name/value pairs) + */ + public Event(Object source, String eventID, EventSeverity severity, Map params) { + super(source); + this.eventID = eventID; + setSeverity(severity); + this.params = params; + } + + /** + * Returns the event identifier. + * @return the event identifier + */ + public String getEventID() { + return this.eventID; + } + + /** + * Returns the event group identifier. + * @return the event group identifier (or null if there is no group identifier) + */ + public String getEventGroupID() { + int pos = this.eventID.lastIndexOf('.'); + if (pos > 0) { + return this.eventID.substring(0, pos); + } else { + return null; + } + } + + /** + * Returns the severity level. + * @return the severity level + */ + public EventSeverity getSeverity() { + return this.severity; + } + + /** + * Sets the event's severity level. This method can be used to increase or decrease the + * severity level in a listener. + * @param severity the new event severity + */ + public void setSeverity(EventSeverity severity) { + this.severity = severity; + } + + /** + * Returns a parameter. + * @param key the key to the parameter + * @return the parameter value or null if no value with this key is found + */ + public Object getParam(String key) { + if (this.params != null) { + return this.params.get(key); + } else { + return null; + } + } + + /** + * Returns an unmodifiable {@link java.util.Map} with all event parameters. + * @return the parameter map + */ + public Map getParams() { + return Collections.unmodifiableMap(this.params); + } + + /** + * Creates and returns a fluent builder object for building up the parameter map. + * @return the parameter builder + */ + public static ParamsBuilder paramsBuilder() { + return new ParamsBuilder(); + } + + /** + * This class is a fluent builder class for building up the parameter map. + */ + public static class ParamsBuilder { + private Map params; + + /** + * Adds a new parameter (a name/value pair). + * @param name the name of the parameter + * @param value the value of the parameter + * @return this instance + */ + public ParamsBuilder param(String name, Object value) { + if (this.params == null) { + this.params = new java.util.HashMap(); + } + this.params.put(name, value); + return this; + } + + /** + * Returns the accumulated parameter map. + * @return the accumulated parameter map + */ + public Map build() { + return this.params; + } + } + +} diff --git a/src/java/org/apache/fop/events/EventBroadcaster.java b/src/java/org/apache/fop/events/EventBroadcaster.java new file mode 100644 index 000000000..6c8df7375 --- /dev/null +++ b/src/java/org/apache/fop/events/EventBroadcaster.java @@ -0,0 +1,61 @@ +/* + * 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; + +/** + * The EventBroadcaster is the central relay point for events. It receives events from various + * parts of the application and forwards them to any registered EventListener. + */ +public interface EventBroadcaster { + + /** + * Adds an event listener to the broadcaster. It is appended to the list of previously + * registered listeners (the order of registration defines the calling order). + * @param listener the listener to be added + */ + void addEventListener(EventListener listener); + + /** + * Removes an event listener from the broadcaster. If the event listener is not registered, + * nothing happens. + * @param listener the listener to be removed + */ + void removeEventListener(EventListener listener); + + /** + * Indicates whether any listeners have been registered with the broadcaster. + * @return true if listeners are present, false otherwise + */ + boolean hasEventListeners(); + + /** + * Broadcasts an event. This method is usually called from within the observed component. + * @param event the event to be broadcast + */ + void broadcastEvent(Event event); + + /** + * Returns an event producer instance for the given interface class. + * @param clazz the Class object identifying an {@link EventProducer} interface + * @return the event producer instance + */ + EventProducer getEventProducerFor(Class clazz); + +} diff --git a/src/java/org/apache/fop/events/EventExceptionManager.java b/src/java/org/apache/fop/events/EventExceptionManager.java new file mode 100644 index 000000000..093ae7010 --- /dev/null +++ b/src/java/org/apache/fop/events/EventExceptionManager.java @@ -0,0 +1,84 @@ +/* + * 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.util.Iterator; +import java.util.Map; + +import org.apache.xmlgraphics.util.Service; + +/** + * This class is reponsible for converting events into exceptions. + */ +public class EventExceptionManager { + + private static final Map EXCEPTION_FACTORIES = new java.util.HashMap(); + + static { + Iterator iter; + iter = Service.providers(ExceptionFactory.class, true); + while (iter.hasNext()) { + ExceptionFactory factory = (ExceptionFactory)iter.next(); + EXCEPTION_FACTORIES.put(factory.getExceptionClass().getName(), factory); + } + } + + /** + * Converts an event into an exception and throws that. If the exception class is null, + * a {@link RuntimeException} will be thrown. + * @param event the event to be converted + * @param exceptionClass the exception class to be thrown + * @throws Throwable this happens always + */ + public static void throwException(Event event, String exceptionClass) throws Throwable { + if (exceptionClass != null) { + ExceptionFactory factory = (ExceptionFactory)EXCEPTION_FACTORIES.get(exceptionClass); + if (factory != null) { + throw factory.createException(event); + } else { + throw new IllegalArgumentException( + "No such ExceptionFactory available: " + exceptionClass); + } + } else { + String msg = EventFormatter.format(event); + throw new RuntimeException(msg); + } + } + + /** + * This interface is implementation by exception factories that can create exceptions from + * events. + */ + public interface ExceptionFactory { + + /** + * Creates an exception from an event. + * @param event the event + * @return the newly created exception + */ + Throwable createException(Event event); + + /** + * Returns the {@link Exception} class created by this factory. + * @return the exception class + */ + Class getExceptionClass(); + } +} diff --git a/src/java/org/apache/fop/events/EventFormatter.java b/src/java/org/apache/fop/events/EventFormatter.java new file mode 100644 index 000000000..56964039b --- /dev/null +++ b/src/java/org/apache/fop/events/EventFormatter.java @@ -0,0 +1,196 @@ +/* + * 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.util.Locale; +import java.util.Map; +import java.util.MissingResourceException; +import java.util.ResourceBundle; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.fop.util.XMLResourceBundle; +import org.apache.fop.util.text.AdvancedMessageFormat; +import org.apache.fop.util.text.AdvancedMessageFormat.Part; +import org.apache.fop.util.text.AdvancedMessageFormat.PartFactory; + +/** + * Converts events into human-readable, localized messages. + */ +public final class EventFormatter { + + private static final Pattern INCLUDES_PATTERN = Pattern.compile("\\{\\{.+\\}\\}"); + + private static ResourceBundle defaultBundle = XMLResourceBundle.getXMLBundle( + EventFormatter.class.getName(), EventFormatter.class.getClassLoader()); + + private static Log log = LogFactory.getLog(EventFormatter.class); + + private EventFormatter() { + //utility class + } + + /** + * Formats an event using the default locale. + * @param event the event + * @return the formatted message + */ + public static String format(Event event) { + ResourceBundle bundle = null; + String groupID = event.getEventGroupID(); + if (groupID != null) { + try { + bundle = XMLResourceBundle.getXMLBundle( + groupID, + EventFormatter.class.getClassLoader()); + } catch (MissingResourceException mre) { + if (log.isTraceEnabled()) { + log.trace("No XMLResourceBundle for " + groupID + " available."); + } + } + } + if (bundle == null) { + bundle = defaultBundle; + } + return format(event, bundle); + } + + /** + * Formats an event using a given locale. + * @param event the event + * @param locale the locale + * @return the formatted message + */ + public static String format(Event event, Locale locale) { + ResourceBundle bundle = null; + String groupID = event.getEventGroupID(); + if (groupID != null) { + try { + bundle = XMLResourceBundle.getXMLBundle( + groupID, locale, + EventFormatter.class.getClassLoader()); + } catch (MissingResourceException mre) { + if (log.isTraceEnabled()) { + log.trace("No XMLResourceBundle for " + groupID + " available."); + } + } + } + if (bundle == null) { + bundle = XMLResourceBundle.getXMLBundle( + EventFormatter.class.getName(), + locale, + EventFormatter.class.getClassLoader()); + } + return format(event, bundle); + } + + private static String format(Event event, ResourceBundle bundle) { + String template = bundle.getString(event.getEventID()); + return format(event, processIncludes(template, bundle)); + } + + private static String processIncludes(String template, ResourceBundle bundle) { + CharSequence input = template; + int replacements; + StringBuffer sb; + do { + sb = new StringBuffer(Math.max(16, input.length())); + replacements = processIncludesInner(input, sb, bundle); + input = sb; + } while (replacements > 0); + String s = sb.toString(); + return s; + } + + private static int processIncludesInner(CharSequence template, StringBuffer sb, + ResourceBundle bundle) { + int replacements = 0; + Matcher m = INCLUDES_PATTERN.matcher(template); + while (m.find()) { + String include = m.group(); + include = include.substring(2, include.length() - 2); + m.appendReplacement(sb, bundle.getString(include)); + replacements++; + } + m.appendTail(sb); + return replacements; + } + + /** + * Formats the event using a given pattern. The pattern needs to be compatible with + * {@link AdvancedMessageFormat}. + * @param event the event + * @param pattern the pattern (compatible with {@link AdvancedMessageFormat}) + * @return the formatted message + */ + public static String format(Event event, String pattern) { + AdvancedMessageFormat format = new AdvancedMessageFormat(pattern); + Map params = new java.util.HashMap(event.getParams()); + params.put("source", event.getSource()); + params.put("severity", event.getSeverity()); + return format.format(params); + } + + private static class LookupFieldPart implements Part { + + private String fieldName; + + public LookupFieldPart(String fieldName) { + this.fieldName = fieldName; + } + + public boolean isGenerated(Map params) { + return getKey(params) != null; + } + + public void write(StringBuffer sb, Map params) { + sb.append(defaultBundle.getString(getKey(params))); + } + + private String getKey(Map params) { + return (String)params.get(fieldName); + } + + /** {@inheritDoc} */ + public String toString() { + return "{" + this.fieldName + ", lookup}"; + } + + } + + /** PartFactory for lookups. */ + public static class LookupFieldPartFactory implements PartFactory { + + /** {@inheritDoc} */ + public Part newPart(String fieldName, String values) { + return new LookupFieldPart(fieldName); + } + + /** {@inheritDoc} */ + public String getFormat() { + return "lookup"; + } + + } + +} diff --git a/src/java/org/apache/fop/events/EventFormatter.xml b/src/java/org/apache/fop/events/EventFormatter.xml new file mode 100644 index 000000000..f17da1161 --- /dev/null +++ b/src/java/org/apache/fop/events/EventFormatter.xml @@ -0,0 +1,101 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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$ --> +<catalogue xml:lang="en"> + <message key="locator">[ (See position {loc})| (See {#gatherContextInfo})| (No context info available)]</message> + <message key="rule.markerDescendantOfFlow">An fo:marker is permitted only as the descendant of an fo:flow.</message> + <message key="rule.retrieveMarkerDescendatOfStaticContent">An fo:retrieve-marker is permitted only as the descendant of an fo:static-content.</message> + <message key="rule.bidiOverrideContent">An fo:bidi-override that is a descendant of an fo:leader or of the fo:inline child of an fo:footnote may not have block-level children, unless it has a nearer ancestor that is an fo:inline-container.</message> + <message key="rule.inlineContent">An fo:inline that is a descendant of an fo:leader or fo:footnote may not have block-level children, unless it has a nearer ancestor that is an fo:inline-container.</message> + <message key="rule.childOfSPM">The element must be a child of fo:simple-page-master.</message> + <message key="rule.childOfDeclarations">The element must be a child of fo:declarations.</message> + <message key="rule.childOfSPMorDeclarations">The element must be a child of fo:declarations or fo:simple-page-master.</message> + <message key="org.apache.fop.fo.FOValidationEventProducer.tooManyNodes">For "{elementName}", only one "{offendingNode}" may be declared.{{locator}}</message> + <message key="org.apache.fop.fo.FOValidationEventProducer.nodeOutOfOrder">For "{elementName}", "{tooLateNode}" must be declared before "{tooEarlyNode}"!{{locator}}</message> + <message key="org.apache.fop.fo.FOValidationEventProducer.invalidChild">"{offendingNode}" is not a valid child element of "{elementName}"![ {ruleViolated,lookup}]{{locator}}</message> + <message key="org.apache.fop.fo.FOValidationEventProducer.missingChildElement">"{elementName}" is missing child elements.[ +Required content model: {contentModel}]{{locator}}</message> + <message key="org.apache.fop.fo.FOValidationEventProducer.missingProperty">Element "{elementName}" is missing required property "{propertyName}"!{{locator}}</message> + <message key="org.apache.fop.fo.FOValidationEventProducer.idNotUnique">Property ID "{id}" (found on "{elementName}") previously used; ID values must be unique within a document!{severity,equals,EventSeverity:FATAL,, +Any reference to it will be considered a reference to the first occurrence in the document.}{{locator}}</message> + <message key="org.apache.fop.fo.FOValidationEventProducer.markerNotInitialChild">fo:marker must be an initial child: {mcname}{{locator}}</message> + <message key="org.apache.fop.fo.FOValidationEventProducer.markerNotUniqueForSameParent">fo:marker "marker-class-name" must be unique for same parent: {mcname}{{locator}}</message> + <message key="org.apache.fop.fo.FOValidationEventProducer.invalidProperty">Invalid property encountered on "{elementName}": {attr}{{locator}}</message> + <message key="org.apache.fop.fo.FOValidationEventProducer.invalidPropertyValue">Invalid property value encountered in {propName}="{propValue}"[: {e}]{{locator}}</message> + <message key="org.apache.fop.fo.FOValidationEventProducer.unimplementedFeature">The following feature isn't implemented by Apache FOP, yet: {feature} (on {elementName}){{locator}}</message> + <message key="org.apache.fop.fo.FOValidationEventProducer.missingLinkDestination">Missing attribute on {elementName}: Either external-destination or internal-destination must be specified.{{locator}}</message> + <message key="org.apache.fop.fo.FOValidationEventProducer.markerCloningFailed">Unable to clone subtree of fo:marker (marker-class-name="{markerClassName}") for fo:retrieve-marker.{{locator}}</message> + <message key="org.apache.fop.fo.FOValidationEventProducer.colorProfileNameNotUnique">Duplicate color profile profile name: {name}{{locator}}</message> + <message key="org.apache.fop.fo.FOValidationEventProducer.regionNameMappedToMultipleRegionClasses">Region-name ("{regionName}") is being mapped to multiple region-classes ({defaultRegionClass1} and {defaultRegionClass2}).{{locator}}</message> + <message key="org.apache.fop.fo.FOValidationEventProducer.masterNameNotUnique">The page master name ("{name}") must be unique across page-masters and page-sequence-masters.{{locator}}</message> + <message key="org.apache.fop.fo.FOValidationEventProducer.duplicateFlowNameInPageSequence">Duplicate flow-name "{flowName}" found within {elementName}.{{locator}}</message> + <message key="org.apache.fop.fo.FOValidationEventProducer.flowNameNotMapped">The flow-name "{flowName}" on {elementName} could not be mapped to a region-name in the layout-master-set.{{locator}}</message> + <message key="org.apache.fop.fo.FOValidationEventProducer.masterNotFound">The master-reference "{masterReference}" on {elementName} matches no simple-page-master or page-sequence-master.{{locator}}</message> + <message key="org.apache.fop.fo.FOValidationEventProducer.illegalRegionName">The region-name "{regionName}" for {elementName} is not permitted.{{locator}}</message> + <message key="org.apache.fop.fo.FOValidationEventProducer.nonZeroBorderPaddingOnRegion">Border and padding for {elementName} "{regionName}" must be '0' (See 6.4.13 in XSL 1.0).{{locator}}</message> + <message key="org.apache.fop.fo.FOValidationEventProducer.columnCountErrorOnRegionBodyOverflowScroll">If overflow property is set to "scroll" on {elementName}, a column-count other than "1" may not be specified.{{locator}}</message> + <message key="org.apache.fop.fo.FOValidationEventProducer.invalidFORoot">First element must be the fo:root formatting object. Found {elementName} instead. Please make sure you're producing a valid XSL-FO document.</message> + <message key="org.apache.fop.fo.FOValidationEventProducer.emptyDocument">Document is empty (something might be wrong with your XSLT stylesheet).</message> + <message key="org.apache.fop.fo.FOValidationEventProducer.unknownFormattingObject">Unknown formatting object "{offendingNode}" encountered (a child of {elementName}}.{{locator}}</message> + <message key="org.apache.fop.fo.flow.table.TableEventProducer.nonAutoBPDOnTable">Only a value of "auto" for block-progression-dimension has a well-specified behavior on fo:table. Falling back to "auto".{{locator}}</message> + <message key="org.apache.fop.fo.flow.table.TableEventProducer.noTablePaddingWithCollapsingBorderModel">In collapsing border model a table does not have padding (see http://www.w3.org/TR/REC-CSS2/tables.html#collapsing-borders), but a non-zero value for padding was found. The padding will be ignored.{{locator}}</message> + <message key="org.apache.fop.fo.flow.table.TableEventProducer.noMixRowsAndCells">Either fo:table-rows or fo:table-cells may be children of an {elementName} but not both.{{locator}}</message> + <message key="org.apache.fop.fo.flow.table.TableEventProducer.footerOrderCannotRecover">This table uses the collapsing border model. In order to resolve borders in an efficient way the table-footer must be known before any table-body is parsed. Either put the footer at the correct place or switch to the separate border model.{{locator}}</message> + <message key="org.apache.fop.fo.flow.table.TableEventProducer.startEndRowUnderTableRowWarning">starts-row/ends-row for fo:table-cells non-applicable for children of an fo:table-row.{{locator}}</message> + <message key="org.apache.fop.fo.flow.table.TableEventProducer.tooManyCells">The column-number or number of cells in the row overflows the number of fo:table-columns specified for the table.{{locator}}</message> + <message key="org.apache.fop.fo.flow.table.TableEventProducer.valueMustBeBiggerGtEqOne">{propName} must be 1 or bigger, but got {actualValue}{{locator}}</message> + <message key="org.apache.fop.fo.flow.table.TableEventProducer.warnImplicitColumns">table-layout=\"fixed\" and column-width unspecified => falling back to proportional-column-width(1){{locator}}</message> + <message key="org.apache.fop.fo.flow.table.TableEventProducer.paddingNotApplicable">padding-* properties are not applicable to {elementName}, but a non-zero value for padding was found.{{locator}}</message> + <message key="org.apache.fop.fo.flow.table.TableEventProducer.cellOverlap">{elementName} overlaps in column {column}.<!-- no locator here, exception will be wrapped --></message> + <message key="org.apache.fop.fo.flow.table.TableEventProducer.breakIgnoredDueToRowSpanning">{breakBefore,if,break-before,break-after} ignored on {elementName} because of row spanning in progress (See XSL 1.1, {breakBefore,if,7.20.2,7.20.1}){{locator}}</message> + <message key="org.apache.fop.events.ResourceEventProducer.imageNotFound">Image not found.[ URI: {uri}.]{{locator}}</message> + <message key="org.apache.fop.events.ResourceEventProducer.imageError">Image not available.[ URI: {uri}.] Reason:[ {reason}][ {e}]{{locator}}</message> + <message key="org.apache.fop.events.ResourceEventProducer.imageIOError">I/O error while loading image.[ URI: {uri}.][ Reason: {ioe}]{{locator}}</message> + <message key="org.apache.fop.events.ResourceEventProducer.ifoNoIntrinsicSize">The intrinsic dimensions of an instream-foreign-object could not be determined.{{locator}}</message> + <message key="org.apache.fop.events.ResourceEventProducer.uriError">Error while handling URI: {uri}. Reason: {e}{{locator}}</message> + <message key="org.apache.fop.events.ResourceEventProducer.foreignXMLProcessingError">Some XML content will be ignored. Could not render XML in namespace "{namespaceURI}".[ Reason: {e}]</message> + <message key="org.apache.fop.events.ResourceEventProducer.foreignXMLNoHandler">Some XML content will be ignored. No handler defined for XML with namespace "{namespaceURI}".</message> + <message key="org.apache.fop.events.ResourceEventProducer.imageWritingError">Error while writing an image to the target file.[ Reason: {e}]</message> + <message key="org.apache.fop.events.ResourceEventProducer.cannotDeleteTempFile">Temporary file could not be deleted: {tempFile}</message> + <message key="org.apache.fop.layoutmgr.inline.InlineLevelEventProducer.leaderWithoutContent">fo:leader is set to "use-content" but has no content.{{locator}}</message> + <message key="org.apache.fop.layoutmgr.inline.InlineLevelEventProducer.lineOverflows">Line {line} of a paragraph overflows the available area by {overflowLength,choice,50000#{overflowLength} millipoints|50000<more than 50 points}.{{locator}}</message> + <message key="org.apache.fop.layoutmgr.BlockLevelEventProducer.rowTooTall">The contents of table-row {row} are taller than they should be (there is a block-progression-dimension or height constraint on the indicated row). Due to its contents the row grows to {effCellBPD} millipoints, but the row shouldn't get any taller than {maxCellBPD} millipoints.{{locator}}</message> + <message key="org.apache.fop.layoutmgr.BlockLevelEventProducer.tableFixedAutoWidthNotSupported">table-layout="fixed" and width="auto", but auto-layout not supported => assuming width="100%".{{locator}}</message> + <message key="org.apache.fop.layoutmgr.BlockLevelEventProducer.objectTooWide">The extent in inline-progression-direction (width) of a {elementName} is bigger than the available space ({effIPD}mpt > {maxIPD}mpt).{{locator}}</message> + <message key="org.apache.fop.layoutmgr.BlockLevelEventProducer.overconstrainedAdjustEndIndent">Adjusting end-indent based on overconstrained geometry rules for {elementName}.{{locator}}</message> + <message key="org.apache.fop.layoutmgr.BlockLevelEventProducer.viewportOverflow">Content overflows the viewport of an {elementName} in block-progression direction by {amount} millipoints.{clip,if, Content will be clipped.}{{locator}}</message> + <message key="org.apache.fop.layoutmgr.BlockLevelEventProducer.regionOverflow">Content overflows the viewport of the {elementName} on page {page} in block-progression direction by {amount} millipoints.{clip,if, Content will be clipped.}{{locator}}</message> + <message key="org.apache.fop.layoutmgr.BlockLevelEventProducer.flowNotMappingToRegionBody">Flow "{flowName}" does not map to the region-body in page-master "{masterName}". FOP presently does not support this.{{locator}}</message> + <message key="org.apache.fop.layoutmgr.BlockLevelEventProducer.pageSequenceMasterExhausted">Subsequences exhausted in page-sequence-master "{pageSequenceMasterName}", {canRecover,if,using previous subsequence,cannot recover}.{{locator}}</message> + <message key="org.apache.fop.layoutmgr.BlockLevelEventProducer.missingSubsequencesInPageSequenceMaster">No subsequences in page-sequence-master "{pageSequenceMasterName}".{{locator}}</message> + <message key="org.apache.fop.layoutmgr.BlockLevelEventProducer.noMatchingPageMaster">No simple-page-master matching "{pageMasterName}" in page-sequence-master "{pageSequenceMasterName}".{{locator}}</message> + <message key="org.apache.fop.svg.SVGEventProducer.error">SVG error: {message}</message> + <message key="org.apache.fop.svg.SVGEventProducer.alert">SVG alert: {message}</message> + <message key="org.apache.fop.svg.SVGEventProducer.info">SVG info: {message}</message> + <message key="org.apache.fop.svg.SVGEventProducer.svgNotBuilt">SVG graphic could not be built. Reason: {e}</message> + <message key="org.apache.fop.svg.SVGEventProducer.svgRenderingError">SVG graphic could not be rendered. Reason: {e}</message> + <message key="org.apache.fop.render.RendererEventProducer.ioError">I/O error while writing to target file.[ Reason: {ioe}]</message> + <message key="org.apache.fop.area.AreaEventProducer.unresolvedIDReference">{type}: Unresolved ID reference "{id}" found.</message> + <message key="org.apache.fop.area.AreaEventProducer.unresolvedIDReferenceOnPage">Page {page}: Unresolved ID reference "{id}" found.</message> + <message key="org.apache.fop.area.AreaEventProducer.pageLoadError">Error while deserializing page {page}.[ Reason: {e}]</message> + <message key="org.apache.fop.area.AreaEventProducer.pageSaveError">Error while serializing page {page}.[ Reason: {e}]</message> + <message key="org.apache.fop.area.AreaEventProducer.pageRenderingError">Error while rendering page {page}.[ Reason: {e}]</message> + <message key="org.apache.fop.fonts.FontEventAdapter.fontSubstituted">Font "{requested}" not found. Substituting with "{effective}".</message> + <message key="org.apache.fop.fonts.FontEventAdapter.fontLoadingErrorAtAutoDetection">Unable to load font file: {fontURL}.[ Reason: {e}]</message> + <message key="org.apache.fop.fonts.FontEventAdapter.glyphNotAvailable">Glyph "{ch}" (0x{ch,hex}[, {ch,glyph-name}]) not available in font "{fontName}".</message> +</catalogue> diff --git a/src/java/org/apache/fop/events/EventFormatter_de.xml b/src/java/org/apache/fop/events/EventFormatter_de.xml new file mode 100644 index 000000000..c65d24f73 --- /dev/null +++ b/src/java/org/apache/fop/events/EventFormatter_de.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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$ -->
+<catalogue xml:lang="de">
+ <message key="locator">[ (Siehe Position {loc})| (Siehe {#gatherContextInfo})| (Keine Kontextinformationen verfügbar)]</message>
+ <message key="org.apache.fop.fo.FOValidationEventProducer.tooManyNodes">In "{elementName}" darf nur ein einziges "{offendingNode}" vorkommen!{{locator}}</message>
+ <message key="org.apache.fop.fo.FOValidationEventProducer.missingProperty">Dem Element "{elementName}" fehlt ein verlangtes Property "{propertyName}"!{{locator}}</message>
+</catalogue>
diff --git a/src/java/org/apache/fop/events/EventListener.java b/src/java/org/apache/fop/events/EventListener.java new file mode 100644 index 000000000..f8293aed9 --- /dev/null +++ b/src/java/org/apache/fop/events/EventListener.java @@ -0,0 +1,37 @@ +/* + * 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; + +/** + * This interface is implemented by clients who want to listen for events. + */ +public interface EventListener extends java.util.EventListener { + + /** + * This method is called for each event that is generated. With the event's ID it is possible + * to react to certain events. Events can also simply be recorded and presented to a user. + * It is possible to throw an (unchecked) exception if the processing needs to be aborted + * because some special event occured. This way the client can configure the behaviour of + * the observed application. + * @param event the event + */ + void processEvent(Event event); + +} diff --git a/src/java/org/apache/fop/events/EventProducer.java b/src/java/org/apache/fop/events/EventProducer.java new file mode 100644 index 000000000..88da771a4 --- /dev/null +++ b/src/java/org/apache/fop/events/EventProducer.java @@ -0,0 +1,31 @@ +/* + * 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; + +/** + * This is a marker interface which all event producer interfaces need to extend. These interfaces + * must agree to the following convention: + * <ul> + * <li>The first parameter of each method must be: <code>Object source</code> + * </ul> + */ +public interface EventProducer { + +} diff --git a/src/java/org/apache/fop/events/FOPEventListenerProxy.java b/src/java/org/apache/fop/events/FOPEventListenerProxy.java new file mode 100644 index 000000000..d4c237844 --- /dev/null +++ b/src/java/org/apache/fop/events/FOPEventListenerProxy.java @@ -0,0 +1,73 @@ +/* + * 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 org.apache.fop.apps.FOUserAgent; +import org.apache.fop.events.model.EventSeverity; +import org.apache.fop.fo.FOValidationEventProducer; +import org.apache.fop.layoutmgr.BlockLevelEventProducer; + +/** + * EventListener proxy that inspects all events and adjusts severity levels where necessary. + * For validation events, it reacts on each event based on the strict validation setting in + * the user agent. + * For layout events, it reduces the default severity level if FOP signals that it can recover + * from the event. + */ +public class FOPEventListenerProxy implements EventListener { + + private static final String FOVALIDATION_EVENT_ID_PREFIX + = FOValidationEventProducer.class.getName(); + + private static final String BLOCK_LEVEL_EVENT_ID_PREFIX + = BlockLevelEventProducer.class.getName(); + + private EventListener delegate; + private FOUserAgent userAgent; + + /** + * Main constructor. + * @param delegate the event listener to delegate events to + * @param userAgent the FO user agent + */ + public FOPEventListenerProxy(EventListener delegate, FOUserAgent userAgent) { + this.delegate = delegate; + this.userAgent = userAgent; + } + + /** {@inheritDoc} */ + public synchronized void processEvent(Event event) { + if (event.getEventID().startsWith(FOVALIDATION_EVENT_ID_PREFIX)) { + Boolean canRecover = (Boolean)event.getParam("canRecover"); + if (Boolean.TRUE.equals(canRecover) && !userAgent.validateStrictly()) { + //Reduce severity if FOP can recover + event.setSeverity(EventSeverity.WARN); + } + } else if (event.getEventID().startsWith(BLOCK_LEVEL_EVENT_ID_PREFIX)) { + Boolean canRecover = (Boolean)event.getParam("canRecover"); + if (Boolean.TRUE.equals(canRecover)) { + //Reduce severity if FOP can recover + event.setSeverity(EventSeverity.WARN); + } + } + this.delegate.processEvent(event); + } + +} diff --git a/src/java/org/apache/fop/events/FOPEventModelFactory.java b/src/java/org/apache/fop/events/FOPEventModelFactory.java new file mode 100644 index 000000000..5a75042fa --- /dev/null +++ b/src/java/org/apache/fop/events/FOPEventModelFactory.java @@ -0,0 +1,37 @@ +/* + * 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 org.apache.fop.events.model.AbstractEventModelFactory; +import org.apache.fop.events.model.EventModel; + +/** + * Factory for FOP's main event model. + */ +public class FOPEventModelFactory extends AbstractEventModelFactory { + + private static final String EVENT_MODEL_FILENAME = "event-model.xml"; + + /** {@inheritDoc} */ + public EventModel createEventModel() { + return loadModel(getClass(), EVENT_MODEL_FILENAME); + } + +} diff --git a/src/java/org/apache/fop/events/LoggingEventListener.java b/src/java/org/apache/fop/events/LoggingEventListener.java new file mode 100644 index 000000000..9ba8ed2df --- /dev/null +++ b/src/java/org/apache/fop/events/LoggingEventListener.java @@ -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. + */ + +/* $Id$ */ + +package org.apache.fop.events; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.fop.events.model.EventSeverity; + +/** + * EventListener implementation that redirects events to Commons Logging. The events are + * converted to localized messages. + */ +public class LoggingEventListener implements EventListener { + + /** Default logger instance */ + private static Log defaultLog = LogFactory.getLog(LoggingEventListener.class); + + private Log log; + private boolean skipFatal; + + /** + * Creates an instance logging to the default log category of this class. + */ + public LoggingEventListener() { + this(defaultLog); + } + + /** + * Creates an instance logging to a given logger. Events with fatal severity level will be + * skipped. + * @param log the target logger + */ + public LoggingEventListener(Log log) { + this(log, true); + } + + /** + * Creates an instance logging to a given logger. + * @param log the target logger + * @param skipFatal true if events with fatal severity level should be skipped (i.e. not logged) + */ + public LoggingEventListener(Log log, boolean skipFatal) { + this.log = log; + this.skipFatal = skipFatal; + } + + /** + * Returns the target logger for this instance. + * @return the target logger + */ + public Log getLog() { + return this.log; + } + + /** {@inheritDoc} */ + public void processEvent(Event event) { + String msg = EventFormatter.format(event); + EventSeverity severity = event.getSeverity(); + if (severity == EventSeverity.INFO) { + log.info(msg); + } else if (severity == EventSeverity.WARN) { + log.warn(msg); + } else if (severity == EventSeverity.ERROR) { + log.error(msg); + } else if (severity == EventSeverity.FATAL) { + if (!skipFatal) { + log.fatal(msg); + } + } else { + assert false; + } + } + +} diff --git a/src/java/org/apache/fop/events/PropertyExceptionFactory.java b/src/java/org/apache/fop/events/PropertyExceptionFactory.java new file mode 100644 index 000000000..667c4a16e --- /dev/null +++ b/src/java/org/apache/fop/events/PropertyExceptionFactory.java @@ -0,0 +1,47 @@ +/* + * 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.util.Locale; + +import org.apache.fop.events.EventExceptionManager.ExceptionFactory; +import org.apache.fop.fo.expr.PropertyException; + +/** + * Exception factory for {@link PropertyException}. + */ +public class PropertyExceptionFactory implements ExceptionFactory { + + /** {@inheritDoc} */ + public Throwable createException(Event event) { + String msg = EventFormatter.format(event, Locale.ENGLISH); + PropertyException ex = new PropertyException(msg); + if (!Locale.ENGLISH.equals(Locale.getDefault())) { + ex.setLocalizedMessage(EventFormatter.format(event)); + } + return ex; + } + + /** {@inheritDoc} */ + public Class getExceptionClass() { + return PropertyException.class; + } + +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/events/ResourceEventProducer.java b/src/java/org/apache/fop/events/ResourceEventProducer.java new file mode 100644 index 000000000..21da4f1d7 --- /dev/null +++ b/src/java/org/apache/fop/events/ResourceEventProducer.java @@ -0,0 +1,136 @@ +/* + * 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.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; + +import org.w3c.dom.Document; + +import org.xml.sax.Locator; + +import org.apache.xmlgraphics.image.loader.ImageException; + +/** + * Event producer interface for resource events (missing images, fonts etc.). + */ +public interface ResourceEventProducer extends EventProducer { + + /** + * Provider class for the event producer. + */ + class Provider { + + /** + * Returns an event producer. + * @param broadcaster the event broadcaster to use + * @return the requested event producer + */ + public static ResourceEventProducer get(EventBroadcaster broadcaster) { + return (ResourceEventProducer)broadcaster.getEventProducerFor( + ResourceEventProducer.class); + } + } + + /** + * Image not found. + * @param source the event source + * @param uri the original URI of the image + * @param fnfe the "file not found" exception + * @param loc the location of the error or null + * @event.severity ERROR + */ + void imageNotFound(Object source, String uri, FileNotFoundException fnfe, Locator loc); + + /** + * Error while processing image. + * @param source the event source + * @param uri the original URI of the image + * @param e the image exception + * @param loc the location of the error or null + * @event.severity ERROR + */ + void imageError(Object source, String uri, ImageException e, Locator loc); + + /** + * I/O error while loading an image. + * @param source the event source + * @param uri the original URI of the image + * @param ioe the I/O exception + * @param loc the location of the error or null + * @event.severity ERROR + */ + void imageIOError(Object source, String uri, IOException ioe, Locator loc); + + /** + * Error while writing/serializing an image to an output format. + * @param source the event source + * @param e the original exception + * @event.severity ERROR + */ + void imageWritingError(Object source, Exception e); + + /** + * Error while handling a URI. + * @param source the event source + * @param uri the original URI of the image + * @param e the original exception + * @param loc the location of the error or null + * @event.severity ERROR + */ + void uriError(Object source, String uri, Exception e, Locator loc); + + /** + * Intrinsic size of fo:instream-foreign-object could not be determined. + * @param source the event source + * @param loc the location of the error or null + * @event.severity ERROR + */ + void ifoNoIntrinsicSize(Object source, Locator loc); + + /** + * Error processing foreign XML content. + * @param source the event source + * @param doc the foreign XML + * @param namespaceURI the namespace URI of the foreign XML + * @param e the original exception + * @event.severity ERROR + */ + void foreignXMLProcessingError(Object source, Document doc, String namespaceURI, Exception e); + + /** + * No handler for foreign XML content. + * @param source the event source + * @param doc the foreign XML + * @param namespaceURI the namespace URI of the foreign XML + * @event.severity ERROR + */ + void foreignXMLNoHandler(Object source, Document doc, String namespaceURI); + + /** + * Cannot delete a temporary file. + * @param source the event source + * @param tempFile the temporary file + * @event.severity ERROR + */ + void cannotDeleteTempFile(Object source, File tempFile); + +} diff --git a/src/java/org/apache/fop/events/UnsupportedOperationExceptionFactory.java b/src/java/org/apache/fop/events/UnsupportedOperationExceptionFactory.java new file mode 100644 index 000000000..06ce8dd25 --- /dev/null +++ b/src/java/org/apache/fop/events/UnsupportedOperationExceptionFactory.java @@ -0,0 +1,43 @@ +/* + * 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.util.Locale; + +import org.apache.fop.events.EventExceptionManager.ExceptionFactory; + +/** + * Exception factory for {@link UnsupportedOperationException}. + */ +public class UnsupportedOperationExceptionFactory implements ExceptionFactory { + + /** {@inheritDoc} */ + public Throwable createException(Event event) { + String msg = EventFormatter.format(event, Locale.ENGLISH); + UnsupportedOperationException ex = new UnsupportedOperationException(msg); + return ex; + } + + /** {@inheritDoc} */ + public Class getExceptionClass() { + return UnsupportedOperationException.class; + } + +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/events/ValidationExceptionFactory.java b/src/java/org/apache/fop/events/ValidationExceptionFactory.java new file mode 100644 index 000000000..9dba84007 --- /dev/null +++ b/src/java/org/apache/fop/events/ValidationExceptionFactory.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. + */ + +/* $Id$ */ + +package org.apache.fop.events; + +import java.util.Locale; + +import org.xml.sax.Locator; + +import org.apache.fop.events.EventExceptionManager.ExceptionFactory; +import org.apache.fop.fo.ValidationException; + +/** + * Exception factory for {@link ValidationException}. + */ +public class ValidationExceptionFactory implements ExceptionFactory { + + /** {@inheritDoc} */ + public Throwable createException(Event event) { + Locator loc = (Locator)event.getParam("loc"); + String msg = EventFormatter.format(event, Locale.ENGLISH); + ValidationException ex = new ValidationException(msg, loc); + if (!Locale.ENGLISH.equals(Locale.getDefault())) { + ex.setLocalizedMessage(EventFormatter.format(event)); + } + return ex; + } + + /** {@inheritDoc} */ + public Class getExceptionClass() { + return ValidationException.class; + } + + +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/events/model/AbstractEventModelFactory.java b/src/java/org/apache/fop/events/model/AbstractEventModelFactory.java new file mode 100644 index 000000000..ee980f34e --- /dev/null +++ b/src/java/org/apache/fop/events/model/AbstractEventModelFactory.java @@ -0,0 +1,61 @@ +/* + * 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.model; + +import java.io.InputStream; +import java.util.MissingResourceException; + +import javax.xml.transform.TransformerException; +import javax.xml.transform.stream.StreamSource; + +import org.apache.commons.io.IOUtils; + +import org.apache.fop.events.DefaultEventBroadcaster; + +/** + * This interface is used to instantiate (load, parse) event models. + */ +public abstract class AbstractEventModelFactory implements EventModelFactory { + + /** + * Loads an event model and returns its instance. + * @param resourceBaseClass base class to use for loading resources + * @param resourceName the resource name pointing to the event model to be loaded + * @return the newly loaded event model. + */ + public EventModel loadModel(Class resourceBaseClass, String resourceName) { + InputStream in = resourceBaseClass.getResourceAsStream(resourceName); + if (in == null) { + throw new MissingResourceException( + "File " + resourceName + " not found", + DefaultEventBroadcaster.class.getName(), ""); + } + try { + return EventModelParser.parse(new StreamSource(in)); + } catch (TransformerException e) { + throw new MissingResourceException( + "Error reading " + resourceName + ": " + e.getMessage(), + DefaultEventBroadcaster.class.getName(), ""); + } finally { + IOUtils.closeQuietly(in); + } + } + +} diff --git a/src/java/org/apache/fop/events/model/EventMethodModel.java b/src/java/org/apache/fop/events/model/EventMethodModel.java new file mode 100644 index 000000000..930cda53d --- /dev/null +++ b/src/java/org/apache/fop/events/model/EventMethodModel.java @@ -0,0 +1,198 @@ +/* + * 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.model; + +import java.io.Serializable; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.AttributesImpl; + +import org.apache.xmlgraphics.util.XMLizable; + +/** + * Represents an event method. Each method in an event producer interface will result in one + * instance of <code>EventMethodModel</code>. + */ +public class EventMethodModel implements Serializable, XMLizable { + + private static final long serialVersionUID = -7548882973341444354L; + + private String methodName; + private EventSeverity severity; + private List params = new java.util.ArrayList(); + private String exceptionClass; + + /** + * Creates an new instance. + * @param methodName the event method's name + * @param severity the event severity + */ + public EventMethodModel(String methodName, EventSeverity severity) { + this.methodName = methodName; + this.severity = severity; + } + + /** + * Adds a method parameter. + * @param param the method parameter + */ + public void addParameter(Parameter param) { + this.params.add(param); + } + + /** + * Adds a method parameter. + * @param type the type of the parameter + * @param name the name of the parameter + * @return the resulting Parameter instance + */ + public Parameter addParameter(Class type, String name) { + Parameter param = new Parameter(type, name); + addParameter(param); + return param; + } + + /** + * Sets the event method name. + * @param name the event name + */ + public void setMethodName(String name) { + this.methodName = name; + } + + /** + * Returns the event method name + * @return the event name + */ + public String getMethodName() { + return this.methodName; + } + + /** + * Sets the event's severity level. + * @param severity the severity + */ + public void setSeverity(EventSeverity severity) { + this.severity = severity; + } + + /** + * Returns the event's severity level. + * @return the severity + */ + public EventSeverity getSeverity() { + return this.severity; + } + + /** + * Returns an unmodifiable list of parameters for this event method. + * @return the list of parameters + */ + public List getParameters() { + return Collections.unmodifiableList(this.params); + } + + /** + * Sets the primary exception class for this event method. Note: Not all event methods throw + * exceptions! + * @param exceptionClass the exception class + */ + public void setExceptionClass(String exceptionClass) { + this.exceptionClass = exceptionClass; + } + + /** + * Returns the primary exception class for this event method. This method returns null if + * the event is only informational or just a warning. + * @return the primary exception class or null + */ + public String getExceptionClass() { + return this.exceptionClass; + } + + /** {@inheritDoc} */ + public void toSAX(ContentHandler handler) throws SAXException { + AttributesImpl atts = new AttributesImpl(); + atts.addAttribute(null, "name", "name", "CDATA", getMethodName()); + atts.addAttribute(null, "severity", "severity", "CDATA", getSeverity().getName()); + if (getExceptionClass() != null) { + atts.addAttribute(null, "exception", "exception", "CDATA", getExceptionClass()); + } + String elName = "method"; + handler.startElement(null, elName, elName, atts); + Iterator iter = this.params.iterator(); + while (iter.hasNext()) { + ((XMLizable)iter.next()).toSAX(handler); + } + handler.endElement(null, elName, elName); + } + + /** + * Represents an event parameter. + */ + public static class Parameter implements Serializable, XMLizable { + + private static final long serialVersionUID = 6062500277953887099L; + + private Class type; + private String name; + + /** + * Creates a new event parameter. + * @param type the parameter type + * @param name the parameter name + */ + public Parameter(Class type, String name) { + this.type = type; + this.name = name; + } + + /** + * Returns the parameter type. + * @return the parameter type + */ + public Class getType() { + return this.type; + } + + /** + * Returns the parameter name. + * @return the parameter name + */ + public String getName() { + return this.name; + } + + /** {@inheritDoc} */ + public void toSAX(ContentHandler handler) throws SAXException { + AttributesImpl atts = new AttributesImpl(); + atts.addAttribute(null, "type", "type", "CDATA", getType().getName()); + atts.addAttribute(null, "name", "name", "CDATA", getName()); + String elName = "parameter"; + handler.startElement(null, elName, elName, atts); + handler.endElement(null, elName, elName); + } + + } +} diff --git a/src/java/org/apache/fop/events/model/EventModel.java b/src/java/org/apache/fop/events/model/EventModel.java new file mode 100644 index 000000000..61e221b3b --- /dev/null +++ b/src/java/org/apache/fop/events/model/EventModel.java @@ -0,0 +1,135 @@ +/* + * 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.model; + +import java.io.File; +import java.io.IOException; +import java.io.Serializable; +import java.util.Iterator; +import java.util.Map; + +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Result; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerFactoryConfigurationError; +import javax.xml.transform.sax.SAXTransformerFactory; +import javax.xml.transform.sax.TransformerHandler; +import javax.xml.transform.stream.StreamResult; + +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.AttributesImpl; + +import org.apache.xmlgraphics.util.XMLizable; + +/** + * Represents a whole event model that supports multiple event producers. + */ +public class EventModel implements Serializable, XMLizable { + + private static final long serialVersionUID = 7468592614934605082L; + + private Map producers = new java.util.LinkedHashMap(); + + /** + * Creates a new, empty event model + */ + public EventModel() { + } + + /** + * Adds the model of an event producer to the event model. + * @param producer the event producer model + */ + public void addProducer(EventProducerModel producer) { + this.producers.put(producer.getInterfaceName(), producer); + } + + /** + * Returns an iterator over the contained event producer models. + * @return an iterator (Iterator<EventProducerModel>) + */ + public Iterator getProducers() { + return this.producers.values().iterator(); + } + + /** + * Returns the model of an event producer with the given interface name. + * @param interfaceName the fully qualified name of the event producer + * @return the model instance for the event producer (or null if it wasn't found) + */ + public EventProducerModel getProducer(String interfaceName) { + return (EventProducerModel)this.producers.get(interfaceName); + } + + /** + * Returns the model of an event producer with the given interface. + * @param clazz the interface of the event producer + * @return the model instance for the event producer (or null if it wasn't found) + */ + public EventProducerModel getProducer(Class clazz) { + return getProducer(clazz.getName()); + } + + /** {@inheritDoc} */ + public void toSAX(ContentHandler handler) throws SAXException { + AttributesImpl atts = new AttributesImpl(); + String elName = "event-model"; + handler.startElement(null, elName, elName, atts); + Iterator iter = getProducers(); + while (iter.hasNext()) { + ((XMLizable)iter.next()).toSAX(handler); + } + handler.endElement(null, elName, elName); + } + + private void writeXMLizable(XMLizable object, File outputFile) throws IOException { + Result res = new StreamResult(outputFile); + + try { + SAXTransformerFactory tFactory + = (SAXTransformerFactory)SAXTransformerFactory.newInstance(); + TransformerHandler handler = tFactory.newTransformerHandler(); + Transformer transformer = handler.getTransformer(); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + handler.setResult(res); + handler.startDocument(); + object.toSAX(handler); + handler.endDocument(); + } catch (TransformerConfigurationException e) { + throw new IOException(e.getMessage()); + } catch (TransformerFactoryConfigurationError e) { + throw new IOException(e.getMessage()); + } catch (SAXException e) { + throw new IOException(e.getMessage()); + } + } + + /** + * Saves this event model to an XML file. + * @param modelFile the target file + * @throws IOException if an I/O error occurs + */ + public void saveToXML(File modelFile) throws IOException { + writeXMLizable(this, modelFile); + } + +} diff --git a/src/java/org/apache/fop/events/model/EventModelFactory.java b/src/java/org/apache/fop/events/model/EventModelFactory.java new file mode 100644 index 000000000..cd760501c --- /dev/null +++ b/src/java/org/apache/fop/events/model/EventModelFactory.java @@ -0,0 +1,33 @@ +/* + * 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.model; + +/** + * This interface is used to instantiate (load, parse) event models. + */ +public interface EventModelFactory { + + /** + * Creates a new EventModel instance. + * @return the new EventModel instance + */ + EventModel createEventModel(); + +} diff --git a/src/java/org/apache/fop/events/model/EventModelParser.java b/src/java/org/apache/fop/events/model/EventModelParser.java new file mode 100644 index 000000000..600e495c5 --- /dev/null +++ b/src/java/org/apache/fop/events/model/EventModelParser.java @@ -0,0 +1,140 @@ +/* + * 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.model; + +import java.util.Stack; + +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.sax.SAXResult; +import javax.xml.transform.sax.SAXTransformerFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.fop.util.DefaultErrorListener; + +/** + * This is a parser for the event model XML. + */ +public class EventModelParser { + + /** Logger instance */ + protected static Log log = LogFactory.getLog(EventModelParser.class); + + private static SAXTransformerFactory tFactory + = (SAXTransformerFactory)SAXTransformerFactory.newInstance(); + + /** + * Parses an event model file into an EventModel instance. + * @param src the Source instance pointing to the XML file + * @return the created event model structure + * @throws TransformerException if an error occurs while parsing the XML file + */ + public static EventModel parse(Source src) + throws TransformerException { + Transformer transformer = tFactory.newTransformer(); + transformer.setErrorListener(new DefaultErrorListener(log)); + + EventModel model = new EventModel(); + SAXResult res = new SAXResult(getContentHandler(model)); + + transformer.transform(src, res); + return model; + } + + /** + * Creates a new ContentHandler instance that you can send the event model XML to. The parsed + * content is accumulated in the model structure. + * @param model the EventModel + * @return the ContentHandler instance to receive the SAX stream from the XML file + */ + public static ContentHandler getContentHandler(EventModel model) { + return new Handler(model); + } + + private static class Handler extends DefaultHandler { + + private EventModel model; + private Stack objectStack = new Stack(); + + public Handler(EventModel model) { + this.model = model; + } + + /** {@inheritDoc} */ + public void startElement(String uri, String localName, String qName, Attributes attributes) + throws SAXException { + try { + if ("event-model".equals(localName)) { + if (objectStack.size() > 0) { + throw new SAXException("event-model must be the root element"); + } + objectStack.push(model); + } else if ("producer".equals(localName)) { + EventProducerModel producer = new EventProducerModel( + attributes.getValue("name")); + EventModel parent = (EventModel)objectStack.peek(); + parent.addProducer(producer); + objectStack.push(producer); + } else if ("method".equals(localName)) { + EventSeverity severity = EventSeverity.valueOf(attributes.getValue("severity")); + String ex = attributes.getValue("exception"); + EventMethodModel method = new EventMethodModel( + attributes.getValue("name"), severity); + if (ex != null && ex.length() > 0) { + method.setExceptionClass(ex); + } + EventProducerModel parent = (EventProducerModel)objectStack.peek(); + parent.addMethod(method); + objectStack.push(method); + } else if ("parameter".equals(localName)) { + String className = attributes.getValue("type"); + Class type; + try { + type = Class.forName(className); + } catch (ClassNotFoundException e) { + throw new SAXException("Could not find Class for: " + className, e); + } + String name = attributes.getValue("name"); + EventMethodModel parent = (EventMethodModel)objectStack.peek(); + objectStack.push(parent.addParameter(type, name)); + } else { + throw new SAXException("Invalid element: " + qName); + } + } catch (ClassCastException cce) { + throw new SAXException("XML format error: " + qName, cce); + } + } + + /** {@inheritDoc} */ + public void endElement(String uri, String localName, String qName) throws SAXException { + objectStack.pop(); + } + + } + +} diff --git a/src/java/org/apache/fop/events/model/EventProducerModel.java b/src/java/org/apache/fop/events/model/EventProducerModel.java new file mode 100644 index 000000000..938609cd9 --- /dev/null +++ b/src/java/org/apache/fop/events/model/EventProducerModel.java @@ -0,0 +1,105 @@ +/* + * 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.model; + +import java.io.Serializable; +import java.util.Iterator; +import java.util.Map; + +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.AttributesImpl; + +import org.apache.xmlgraphics.util.XMLizable; + +/** + * Represents the model of an event producer with multiple event methods. + */ +public class EventProducerModel implements Serializable, XMLizable { + + private static final long serialVersionUID = 122267104123721902L; + + private String interfaceName; + private Map methods = new java.util.LinkedHashMap(); + + /** + * Creates a new instance. + * @param interfaceName the fully qualified interface name of the event producer + */ + public EventProducerModel(String interfaceName) { + this.interfaceName = interfaceName; + } + + /** + * Returns the fully qualified interface name of the event producer. + * @return the fully qualified interface name + */ + public String getInterfaceName() { + return this.interfaceName; + } + + /** + * Sets the fully qualified interface name of the event producer. + * @param name the fully qualified interface name + */ + public void setInterfaceName(String name) { + this.interfaceName = name; + } + + /** + * Adds a model instance of an event method. + * @param method the event method model + */ + public void addMethod(EventMethodModel method) { + this.methods.put(method.getMethodName(), method); + } + + /** + * Returns the model instance of an event method for the given method name. + * @param methodName the method name + * @return the model instance (or null if no method with the given name exists) + */ + public EventMethodModel getMethod(String methodName) { + return (EventMethodModel)this.methods.get(methodName); + } + + /** + * Returns an iterator over the contained event producer methods. + * @return an iterator (Iterator<EventMethodModel>) + */ + public Iterator getMethods() { + return this.methods.values().iterator(); + } + + /** {@inheritDoc} */ + public void toSAX(ContentHandler handler) throws SAXException { + AttributesImpl atts = new AttributesImpl(); + atts.addAttribute(null, "name", "name", "CDATA", getInterfaceName()); + String elName = "producer"; + handler.startElement(null, elName, elName, atts); + Iterator iter = getMethods(); + while (iter.hasNext()) { + ((XMLizable)iter.next()).toSAX(handler); + } + handler.endElement(null, elName, elName); + } + + +} diff --git a/src/java/org/apache/fop/events/model/EventSeverity.java b/src/java/org/apache/fop/events/model/EventSeverity.java new file mode 100644 index 000000000..d37c53c1e --- /dev/null +++ b/src/java/org/apache/fop/events/model/EventSeverity.java @@ -0,0 +1,82 @@ +/* + * 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.model; + +import java.io.ObjectStreamException; +import java.io.Serializable; + +/** Enumeration class for event severities. */ +public final class EventSeverity implements Serializable { + + private static final long serialVersionUID = 4108175215810759243L; + + /** info level */ + public static final EventSeverity INFO = new EventSeverity("INFO"); + /** warning level */ + public static final EventSeverity WARN = new EventSeverity("WARN"); + /** error level */ + public static final EventSeverity ERROR = new EventSeverity("ERROR"); + /** fatal error */ + public static final EventSeverity FATAL = new EventSeverity("FATAL"); + + private String name; + + /** + * Constructor to add a new named item. + * @param name Name of the item. + */ + private EventSeverity(String name) { + this.name = name; + } + + /** @return the name of the enumeration */ + public String getName() { + return this.name; + } + + /** + * Returns the enumeration/singleton object based on its name. + * @param name the name of the enumeration value + * @return the enumeration object + */ + public static EventSeverity valueOf(String name) { + if (INFO.getName().equalsIgnoreCase(name)) { + return INFO; + } else if (WARN.getName().equalsIgnoreCase(name)) { + return WARN; + } else if (ERROR.getName().equalsIgnoreCase(name)) { + return ERROR; + } else if (FATAL.getName().equalsIgnoreCase(name)) { + return FATAL; + } else { + throw new IllegalArgumentException("Illegal value for enumeration: " + name); + } + } + + private Object readResolve() throws ObjectStreamException { + return valueOf(getName()); + } + + /** {@inheritDoc} */ + public String toString() { + return "EventSeverity:" + name; + } + +} |