aboutsummaryrefslogtreecommitdiffstats
path: root/src/java/org/apache/fop/render/XMLHandlerRegistry.java
blob: 533534c4cc23d57a8ce0cae323c212ea34a72dcd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/*
 * 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.render;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.xmlgraphics.util.Service;

/**
 * This class holds references to various XML handlers used by FOP. It also
 * supports automatic discovery of additional XML handlers available through
 * the class path.
 */
public class XMLHandlerRegistry {

    /** the logger */
    private static Log log = LogFactory.getLog(XMLHandlerRegistry.class);
    
    /** Map containing XML handlers for various document types */
    private Map handlers = new java.util.HashMap();
    
    /**
     * Default constructor.
     */
    public XMLHandlerRegistry() {
        discoverXMLHandlers();
    }
    
    /**
     * Add a default XML handler which is able to handle any namespace.
     * @param handler XMLHandler to use
     */
    private void setDefaultXMLHandler(XMLHandler handler) {
        addXMLHandler(XMLHandler.HANDLE_ALL, handler);
    }
    
    /**
     * Add an XML handler. The handler itself is inspected to find out what it supports.
     * @param classname the fully qualified class name
     */
    public void addXMLHandler(String classname) {
        try {
            XMLHandler handlerInstance = (XMLHandler)Class.forName(classname).newInstance();
            addXMLHandler(handlerInstance);
        } catch (ClassNotFoundException e) {
            throw new IllegalArgumentException("Could not find "
                                               + classname);
        } catch (InstantiationException e) {
            throw new IllegalArgumentException("Could not instantiate "
                                               + classname);
        } catch (IllegalAccessException e) {
            throw new IllegalArgumentException("Could not access "
                                               + classname);
        } catch (ClassCastException e) {
            throw new IllegalArgumentException(classname
                                               + " is not an " 
                                               + XMLHandler.class.getName());
        }
    }
    
    /**
     * Add an XML handler. The handler itself is inspected to find out what it supports.
     * @param handler the XMLHandler instance
     */
    public void addXMLHandler(XMLHandler handler) {
        String ns = handler.getNamespace();
        if (ns == null) {
            setDefaultXMLHandler(handler);
        } else {
            addXMLHandler(ns, handler);
        }
    }
    
    /**
     * Add an XML handler for the given MIME type and XML namespace.
     * @param ns Namespace URI
     * @param handler XMLHandler to use
     */
    private void addXMLHandler(String ns,
                              XMLHandler handler) {
        List lst = (List)handlers.get(ns);
        if (lst == null) {
            lst = new java.util.ArrayList();
            handlers.put(ns, lst);
        }
        lst.add(handler);
    }
    
    /**
     * Returns an XMLHandler which handles an XML dialect of the given namespace and for
     * a specified output format defined by its MIME type.
     * @param renderer the Renderer for which to retrieve a Renderer
     * @param ns the XML namespace associated with the XML to be rendered
     * @return the XMLHandler responsible for handling the XML or null if none is available
     */
    public XMLHandler getXMLHandler(Renderer renderer, String ns) {
        XMLHandler handler;

        List lst = (List)handlers.get(ns);
        handler = getXMLHandler(renderer, lst);
        if (handler == null) {
            lst = (List)handlers.get(XMLHandler.HANDLE_ALL);
            handler = getXMLHandler(renderer, lst);
        }
        return handler;
    }

    private XMLHandler getXMLHandler(Renderer renderer, List lst) {
        XMLHandler handler;
        if (lst != null) {
            for (int i = 0, c = lst.size(); i < c; i++) {
                //TODO Maybe add priorities later
                handler = (XMLHandler)lst.get(i);
                if (handler.supportsRenderer(renderer)) {
                    return handler;
                }
            }
        }
        return null; //No handler found
    }
    
    /**
     * Discovers XMLHandler implementations through the classpath and dynamically
     * registers them.
     */
    private void discoverXMLHandlers() {
        // add mappings from available services
        Iterator providers = Service.providers(XMLHandler.class);
        if (providers != null) {
            while (providers.hasNext()) {
                XMLHandler handler = (XMLHandler)providers.next();
                try {
                    if (log.isDebugEnabled()) {
                        log.debug("Dynamically adding XMLHandler: " + handler.getClass().getName());
                    }
                    addXMLHandler(handler);
                } catch (IllegalArgumentException e) {
                    log.error("Error while adding XMLHandler", e);
                }

            }
        }
    }
}