You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

RendererFactory.java 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. /*
  2. * Copyright 2004-2005 The Apache Software Foundation.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /* $Id$ */
  17. package org.apache.fop.render;
  18. import java.io.OutputStream;
  19. import java.util.Collections;
  20. import java.util.Iterator;
  21. import java.util.List;
  22. import java.util.Map;
  23. //Avalon
  24. import org.apache.avalon.framework.configuration.Configuration;
  25. import org.apache.avalon.framework.configuration.ConfigurationException;
  26. import org.apache.avalon.framework.container.ContainerUtil;
  27. import org.apache.commons.logging.Log;
  28. import org.apache.commons.logging.LogFactory;
  29. //FOP
  30. import org.apache.fop.apps.FOPException;
  31. import org.apache.fop.apps.FOUserAgent;
  32. import org.apache.fop.area.AreaTreeHandler;
  33. import org.apache.fop.fo.FOEventHandler;
  34. import org.apache.fop.util.Service;
  35. /**
  36. * Factory for FOEventHandlers and Renderers.
  37. */
  38. public class RendererFactory {
  39. /** the logger */
  40. private static Log log = LogFactory.getLog(RendererFactory.class);
  41. private Map rendererMakerMapping = new java.util.HashMap();
  42. private Map eventHandlerMakerMapping = new java.util.HashMap();
  43. /**
  44. * Main constructor.
  45. */
  46. public RendererFactory() {
  47. registerStandardRenderers();
  48. discoverRenderers();
  49. registerStandardEventHandlers();
  50. discoverFOEventHandlers();
  51. }
  52. private void registerStandardRenderers() {
  53. addRendererMaker(new org.apache.fop.render.pdf.PDFRendererMaker());
  54. addRendererMaker(new org.apache.fop.render.ps.PSRendererMaker());
  55. addRendererMaker(new org.apache.fop.render.txt.TXTRendererMaker());
  56. addRendererMaker(new org.apache.fop.render.bitmap.PNGRendererMaker());
  57. addRendererMaker(new org.apache.fop.render.bitmap.TIFFRendererMaker());
  58. addRendererMaker(new org.apache.fop.render.bitmap.TIFFRendererMaker());
  59. addRendererMaker(new org.apache.fop.render.xml.XMLRendererMaker());
  60. addRendererMaker(new org.apache.fop.render.awt.AWTRendererMaker());
  61. addRendererMaker(new org.apache.fop.render.print.PrintRendererMaker());
  62. }
  63. private void registerStandardEventHandlers() {
  64. addFOEventHandlerMaker(new org.apache.fop.render.rtf.RTFFOEventHandlerMaker());
  65. }
  66. /**
  67. * Add a new RendererMaker. If another maker has already been registered for a
  68. * particular MIME type, this call overwrites the existing one.
  69. * @param maker the RendererMaker
  70. */
  71. public void addRendererMaker(AbstractRendererMaker maker) {
  72. String[] mimes = maker.getSupportedMimeTypes();
  73. for (int i = 0; i < mimes.length; i++) {
  74. //This overrides any renderer previously set for a MIME type
  75. if (rendererMakerMapping.get(mimes[i]) != null) {
  76. log.trace("Overriding renderer for " + mimes[i]
  77. + " with " + maker.getClass().getName());
  78. }
  79. rendererMakerMapping.put(mimes[i], maker);
  80. }
  81. }
  82. /**
  83. * Add a new FOEventHandlerMaker. If another maker has already been registered for a
  84. * particular MIME type, this call overwrites the existing one.
  85. * @param maker the FOEventHandlerMaker
  86. */
  87. public void addFOEventHandlerMaker(AbstractFOEventHandlerMaker maker) {
  88. String[] mimes = maker.getSupportedMimeTypes();
  89. for (int i = 0; i < mimes.length; i++) {
  90. //This overrides any event handler previously set for a MIME type
  91. if (eventHandlerMakerMapping.get(mimes[i]) != null) {
  92. log.trace("Overriding FOEventHandler for " + mimes[i]
  93. + " with " + maker.getClass().getName());
  94. }
  95. eventHandlerMakerMapping.put(mimes[i], maker);
  96. }
  97. }
  98. /**
  99. * Add a new RendererMaker. If another maker has already been registered for a
  100. * particular MIME type, this call overwrites the existing one.
  101. * @param className the fully qualified class name of the RendererMaker
  102. */
  103. public void addRendererMaker(String className) {
  104. try {
  105. AbstractRendererMaker makerInstance
  106. = (AbstractRendererMaker)Class.forName(className).newInstance();
  107. addRendererMaker(makerInstance);
  108. } catch (ClassNotFoundException e) {
  109. throw new IllegalArgumentException("Could not find "
  110. + className);
  111. } catch (InstantiationException e) {
  112. throw new IllegalArgumentException("Could not instantiate "
  113. + className);
  114. } catch (IllegalAccessException e) {
  115. throw new IllegalArgumentException("Could not access "
  116. + className);
  117. } catch (ClassCastException e) {
  118. throw new IllegalArgumentException(className
  119. + " is not an "
  120. + AbstractRendererMaker.class.getName());
  121. }
  122. }
  123. /**
  124. * Add a new FOEventHandlerMaker. If another maker has already been registered for a
  125. * particular MIME type, this call overwrites the existing one.
  126. * @param className the fully qualified class name of the FOEventHandlerMaker
  127. */
  128. public void addFOEventHandlerMaker(String className) {
  129. try {
  130. AbstractFOEventHandlerMaker makerInstance
  131. = (AbstractFOEventHandlerMaker)Class.forName(className).newInstance();
  132. addFOEventHandlerMaker(makerInstance);
  133. } catch (ClassNotFoundException e) {
  134. throw new IllegalArgumentException("Could not find "
  135. + className);
  136. } catch (InstantiationException e) {
  137. throw new IllegalArgumentException("Could not instantiate "
  138. + className);
  139. } catch (IllegalAccessException e) {
  140. throw new IllegalArgumentException("Could not access "
  141. + className);
  142. } catch (ClassCastException e) {
  143. throw new IllegalArgumentException(className
  144. + " is not an "
  145. + AbstractFOEventHandlerMaker.class.getName());
  146. }
  147. }
  148. /**
  149. * Returns a RendererMaker which handles the given MIME type.
  150. * @param mime the requested output format
  151. * @return the requested RendererMaker or null if none is available
  152. */
  153. public AbstractRendererMaker getRendererMaker(String mime) {
  154. AbstractRendererMaker maker
  155. = (AbstractRendererMaker)rendererMakerMapping.get(mime);
  156. return maker;
  157. }
  158. /**
  159. * Returns a FOEventHandlerMaker which handles the given MIME type.
  160. * @param mime the requested output format
  161. * @return the requested FOEventHandlerMaker or null if none is available
  162. */
  163. public AbstractFOEventHandlerMaker getFOEventHandlerMaker(String mime) {
  164. AbstractFOEventHandlerMaker maker
  165. = (AbstractFOEventHandlerMaker)eventHandlerMakerMapping.get(mime);
  166. return maker;
  167. }
  168. /**
  169. * Creates a Renderer object based on render-type desired
  170. * @param userAgent the user agent for access to configuration
  171. * @param outputFormat the MIME type of the output format to use (ex. "application/pdf").
  172. * @return the new Renderer instance
  173. * @throws FOPException if the renderer cannot be properly constructed
  174. */
  175. public Renderer createRenderer(FOUserAgent userAgent, String outputFormat)
  176. throws FOPException {
  177. if (userAgent.getRendererOverride() != null) {
  178. return userAgent.getRendererOverride();
  179. } else {
  180. AbstractRendererMaker maker = getRendererMaker(outputFormat);
  181. if (maker == null) {
  182. throw new UnsupportedOperationException(
  183. "No renderer for the requested format available: " + outputFormat);
  184. }
  185. Renderer rend = maker.makeRenderer(userAgent);
  186. rend.setUserAgent(userAgent);
  187. String mimeType = rend.getMimeType(); //Always use main MIME type for this
  188. Configuration userRendererConfig = null;
  189. if (mimeType != null) {
  190. userRendererConfig
  191. = userAgent.getUserRendererConfig(mimeType);
  192. }
  193. if (userRendererConfig != null) {
  194. try {
  195. ContainerUtil.configure(rend, userRendererConfig);
  196. } catch (ConfigurationException e) {
  197. throw new FOPException(e);
  198. }
  199. }
  200. return rend;
  201. }
  202. }
  203. /**
  204. * Creates FOEventHandler instances based on the desired output.
  205. * @param userAgent the user agent for access to configuration
  206. * @param outputFormat the MIME type of the output format to use (ex. "application/pdf").
  207. * @param out the OutputStream where the output is written to (if applicable)
  208. * @return the newly constructed FOEventHandler
  209. * @throws FOPException if the FOEventHandler cannot be properly constructed
  210. */
  211. public FOEventHandler createFOEventHandler(FOUserAgent userAgent,
  212. String outputFormat, OutputStream out) throws FOPException {
  213. if (userAgent.getFOEventHandlerOverride() != null) {
  214. return userAgent.getFOEventHandlerOverride();
  215. } else {
  216. AbstractFOEventHandlerMaker maker = getFOEventHandlerMaker(outputFormat);
  217. if (maker == null) {
  218. AbstractRendererMaker rendMaker = getRendererMaker(outputFormat);
  219. if (rendMaker == null && userAgent.getRendererOverride() == null) {
  220. throw new UnsupportedOperationException(
  221. "Don't know how to handle \"" + outputFormat + "\" as an output format."
  222. + " Neither an FOEventHandler, nor a Renderer could be found"
  223. + " for this output format.");
  224. } else {
  225. if (out == null
  226. && userAgent.getRendererOverride() == null
  227. && rendMaker.needsOutputStream()) {
  228. throw new IllegalStateException(
  229. "OutputStream has not been set");
  230. }
  231. //Found a Renderer so we need to construct an AreaTreeHandler.
  232. return new AreaTreeHandler(userAgent, outputFormat, out);
  233. }
  234. } else {
  235. return maker.makeFOEventHandler(userAgent, out);
  236. }
  237. }
  238. }
  239. /**
  240. * @return an array of all supported MIME types
  241. */
  242. public String[] listSupportedMimeTypes() {
  243. List lst = new java.util.ArrayList();
  244. Iterator iter = this.rendererMakerMapping.keySet().iterator();
  245. while (iter.hasNext()) {
  246. lst.add(((String)iter.next()));
  247. }
  248. iter = this.eventHandlerMakerMapping.keySet().iterator();
  249. while (iter.hasNext()) {
  250. lst.add(((String)iter.next()));
  251. }
  252. Collections.sort(lst);
  253. return (String[])lst.toArray(new String[lst.size()]);
  254. }
  255. /**
  256. * Discovers Renderer implementations through the classpath and dynamically
  257. * registers them.
  258. */
  259. private void discoverRenderers() {
  260. // add mappings from available services
  261. Iterator providers
  262. = Service.providers(Renderer.class);
  263. if (providers != null) {
  264. while (providers.hasNext()) {
  265. String str = (String)providers.next();
  266. try {
  267. if (log.isDebugEnabled()) {
  268. log.debug("Dynamically adding maker for Renderer: " + str);
  269. }
  270. addRendererMaker(str);
  271. } catch (IllegalArgumentException e) {
  272. log.error("Error while adding maker for Renderer", e);
  273. }
  274. }
  275. }
  276. }
  277. /**
  278. * Discovers FOEventHandler implementations through the classpath and dynamically
  279. * registers them.
  280. */
  281. private void discoverFOEventHandlers() {
  282. // add mappings from available services
  283. Iterator providers
  284. = Service.providers(FOEventHandler.class);
  285. if (providers != null) {
  286. while (providers.hasNext()) {
  287. String str = (String)providers.next();
  288. try {
  289. if (log.isDebugEnabled()) {
  290. log.debug("Dynamically adding maker for FOEventHandler: " + str);
  291. }
  292. addFOEventHandlerMaker(str);
  293. } catch (IllegalArgumentException e) {
  294. log.error("Error while adding maker for FOEventHandler", e);
  295. }
  296. }
  297. }
  298. }
  299. }