<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head> <!-- Generated by HsColour, http://www.cs.york.ac.uk/fp/darcs/hscolour/ --> <title>src/System/Log/Handler/Log4jXML.hs</title> <link type='text/css' rel='stylesheet' href='hscolour.css' /> </head> <body> <pre><a name="line-1"></a><span class='hs-comment'>{- arch-tag: log4j XMLLayout log handler <a name="line-2"></a>Copyright (C) 2007-2008 John Goerzen <jgoerzen@complete.org> <a name="line-3"></a> <a name="line-4"></a>This program is free software; you can redistribute it and/or modify <a name="line-5"></a>it under the terms of the GNU Lesser General Public License as published by <a name="line-6"></a>the Free Software Foundation; either version 2.1 of the License, or <a name="line-7"></a>(at your option) any later version. <a name="line-8"></a> <a name="line-9"></a>This program is distributed in the hope that it will be useful, <a name="line-10"></a>but WITHOUT ANY WARRANTY; without even the implied warranty of <a name="line-11"></a>MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the <a name="line-12"></a>GNU Lesser General Public License for more details. <a name="line-13"></a> <a name="line-14"></a>You should have received a copy of the GNU Lesser General Public License <a name="line-15"></a>along with this program; if not, write to the Free Software <a name="line-16"></a>Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA <a name="line-17"></a>-}</span> <a name="line-18"></a> <a name="line-19"></a><span class='hs-comment'>{- | <a name="line-20"></a> Module : System.Log.Handler.Log4jXML <a name="line-21"></a> Copyright : Copyright (C) 2007-2008 John Goerzen <a name="line-22"></a> License : GNU LGPL, version 2.1 or above <a name="line-23"></a> <a name="line-24"></a> Maintainer : bjorn.buckwalter@gmail.com <a name="line-25"></a> Stability : experimental <a name="line-26"></a> Portability: GHC only? <a name="line-27"></a> <a name="line-28"></a>log4j[1] XMLLayout log handlers. <a name="line-29"></a> <a name="line-30"></a>Written by Bjorn Buckwalter, bjorn.buckwalter\@gmail.com <a name="line-31"></a>-}</span> <a name="line-32"></a> <a name="line-33"></a> <a name="line-34"></a><span class='hs-keyword'>module</span> <span class='hs-conid'>System</span><span class='hs-varop'>.</span><span class='hs-conid'>Log</span><span class='hs-varop'>.</span><span class='hs-conid'>Handler</span><span class='hs-varop'>.</span><span class='hs-conid'>Log4jXML</span> <span class='hs-layout'>(</span> <a name="line-35"></a> <a name="line-36"></a> <span class='hs-comment'>-- * Introduction</span> <a name="line-37"></a> <a name="line-38"></a> <span class='hs-comment'>{- | This module provides handlers for hslogger that are <a name="line-39"></a> compatible with log4j's XMLLayout. In particular log messages <a name="line-40"></a> created by the handlers can be published directly to the GUI-based <a name="line-41"></a> log viewer Chainsaw v2[2]. <a name="line-42"></a> <a name="line-43"></a> The set of log levels in hslogger is richer than the basic set <a name="line-44"></a> of log4j levels. Two sets of handlers are provided with hslogger4j, <a name="line-45"></a> one which produces logs with hslogger's levels and one which <a name="line-46"></a> \"demotes\" them to the basic log4j levels. If full hslogger <a name="line-47"></a> levels are used some Java installation (see below) is necessary <a name="line-48"></a> to make Chainsaw aware of them. <a name="line-49"></a> <a name="line-50"></a> Usage of the handlers in hslogger4j is analoguous to usage of <a name="line-51"></a> the 'System.Log.Handler.Simple.StreamHandler' and <a name="line-52"></a> 'System.Log.Handler.Simple.FileHandler' in "System.Log.Handler.Simple". <a name="line-53"></a> The following handlers are provided: -}</span> <a name="line-54"></a> <a name="line-55"></a> <span class='hs-comment'>-- ** Handlers with hslogger levels </span> <a name="line-56"></a> <span class='hs-varid'>log4jStreamHandler</span><span class='hs-layout'>,</span> <a name="line-57"></a> <span class='hs-varid'>log4jFileHandler</span><span class='hs-layout'>,</span> <a name="line-58"></a> <a name="line-59"></a> <span class='hs-comment'>-- ** Handlers with log4j levels</span> <a name="line-60"></a> <span class='hs-varid'>log4jStreamHandler'</span><span class='hs-layout'>,</span> <a name="line-61"></a> <span class='hs-varid'>log4jFileHandler'</span> <a name="line-62"></a> <a name="line-63"></a> <a name="line-64"></a> <span class='hs-comment'>-- * Java install process</span> <a name="line-65"></a> <a name="line-66"></a> <span class='hs-comment'>{- | This is only necessary if you want to use the hslogger levels. <a name="line-67"></a> <a name="line-68"></a> Add @hslogger4j.jar@ from @contrib\/java@ to your classpath. <a name="line-69"></a> To use you will also need to have the jars @log4j-1.3alpha-7.jar@ <a name="line-70"></a> and @log4j-xml-1.3alpha-7.jar@ that are distributed with Chainsaw <a name="line-71"></a> on your classpath. <a name="line-72"></a> <a name="line-73"></a> (On Mac OS X I added all three jars to @~\/Library\/Java\/Extensions@. <a name="line-74"></a> It seems that it is not sufficient that Chainsaw already includes <a name="line-75"></a> its jars in the classpath when launching - perhaps the plugin <a name="line-76"></a> classloader does not inherit Chainsaw's classpath. Adding the <a name="line-77"></a> jars to @~\/.chainsaw\/plugins@ wouldn't work either.) <a name="line-78"></a> <a name="line-79"></a> If for whatever reason you have to rebuild the hslogger4j jar <a name="line-80"></a> just run @ant@[3] in the @contrib\/java@ directory. The new jar <a name="line-81"></a> will be created in the @contrib\/java\/dist@ directory. The Java <a name="line-82"></a> source code is copyright The Apache Software Foundation and <a name="line-83"></a> licensed under the Apache Licence version 2.0. -}</span> <a name="line-84"></a> <a name="line-85"></a> <a name="line-86"></a> <span class='hs-comment'>-- * Chainsaw setup</span> <a name="line-87"></a> <a name="line-88"></a> <span class='hs-comment'>{- | If you are only using the basic log4j levels just use <a name="line-89"></a> Chainsaw's regular facilities to browse logs or listen for log <a name="line-90"></a> messages (e.g. @XMLSocketReceiver@). <a name="line-91"></a> <a name="line-92"></a> If you want to use the hslogger levels the easiest way to set <a name="line-93"></a> up Chainsaw is to load the plugins in @hslogger4j-plugins.xml@ <a name="line-94"></a> in @contrib\/java@ when launching Chainsaw. Two receivers will <a name="line-95"></a> be defined, one that listens for logmessages and one for reading <a name="line-96"></a> log files. Edit the properties of those receivers as needed <a name="line-97"></a> (e.g. @port@, @fileURL@) and restart them. You will also want <a name="line-98"></a> to modify Chainsaw's formatting preferences to display levels <a name="line-99"></a> as text instead of icons. -}</span> <a name="line-100"></a> <a name="line-101"></a> <a name="line-102"></a> <span class='hs-comment'>-- * Example usage</span> <a name="line-103"></a> <a name="line-104"></a> <span class='hs-comment'>{- | In the IO monad: <a name="line-105"></a> <a name="line-106"></a> > lh2 <- log4jFileHandler "log.xml" DEBUG <a name="line-107"></a> > updateGlobalLogger rootLoggerName (addHandler lh2) <a name="line-108"></a> <a name="line-109"></a> > h <- connectTo "localhost" (PortNumber 4448) <a name="line-110"></a> > lh <- log4jStreamHandler h NOTICE <a name="line-111"></a> > updateGlobalLogger rootLoggerName (addHandler lh) <a name="line-112"></a> -}</span> <a name="line-113"></a> <a name="line-114"></a> <span class='hs-comment'>-- * References</span> <a name="line-115"></a> <a name="line-116"></a> <span class='hs-comment'>{- | <a name="line-117"></a> (1) <<a href="http://logging.apache.org/log4j/">http://logging.apache.org/log4j/</a>> <a name="line-118"></a> <a name="line-119"></a> (2) <<a href="http://logging.apache.org/chainsaw/">http://logging.apache.org/chainsaw/</a>> <a name="line-120"></a> <a name="line-121"></a> (3) <<a href="http://ant.apache.org/">http://ant.apache.org/</a>> <a name="line-122"></a> -}</span> <a name="line-123"></a> <a name="line-124"></a> <span class='hs-layout'>)</span> <span class='hs-keyword'>where</span> <a name="line-125"></a> <a name="line-126"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Concurrent</span> <span class='hs-layout'>(</span><span class='hs-conid'>ThreadId</span><span class='hs-layout'>,</span> <span class='hs-varid'>myThreadId</span><span class='hs-layout'>)</span> <span class='hs-comment'>-- myThreadId is GHC only!</span> <a name="line-127"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Concurrent</span><span class='hs-varop'>.</span><span class='hs-conid'>MVar</span> <a name="line-128"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>List</span> <span class='hs-layout'>(</span><span class='hs-varid'>isPrefixOf</span><span class='hs-layout'>)</span> <a name="line-129"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>System</span><span class='hs-varop'>.</span><span class='hs-conid'>IO</span> <a name="line-130"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>System</span><span class='hs-varop'>.</span><span class='hs-conid'>Locale</span> <span class='hs-layout'>(</span><span class='hs-varid'>defaultTimeLocale</span><span class='hs-layout'>)</span> <a name="line-131"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Time</span> <a name="line-132"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>System</span><span class='hs-varop'>.</span><span class='hs-conid'>Log</span> <a name="line-133"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>System</span><span class='hs-varop'>.</span><span class='hs-conid'>Log</span><span class='hs-varop'>.</span><span class='hs-conid'>Handler</span> <a name="line-134"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>System</span><span class='hs-varop'>.</span><span class='hs-conid'>Log</span><span class='hs-varop'>.</span><span class='hs-conid'>Handler</span><span class='hs-varop'>.</span><span class='hs-conid'>Simple</span> <span class='hs-layout'>(</span><span class='hs-varid'>streamHandler</span><span class='hs-layout'>,</span> <span class='hs-conid'>GenericHandler</span><span class='hs-layout'>(</span><span class='hs-keyglyph'>..</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <a name="line-135"></a> <a name="line-136"></a> <a name="line-137"></a><a name="log4jHandler"></a><span class='hs-comment'>-- Handler that logs to a handle rendering message priorities according</span> <a name="line-138"></a><span class='hs-comment'>-- to the supplied function.</span> <a name="line-139"></a><span class='hs-definition'>log4jHandler</span> <span class='hs-keyglyph'>::</span> <span class='hs-layout'>(</span><span class='hs-conid'>Priority</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>String</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>Handle</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>Priority</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-layout'>(</span><span class='hs-conid'>GenericHandler</span> <span class='hs-conid'>Handle</span><span class='hs-layout'>)</span> <a name="line-140"></a><span class='hs-definition'>log4jHandler</span> <span class='hs-varid'>showPrio</span> <span class='hs-varid'>h</span> <span class='hs-varid'>pri</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span> <a name="line-141"></a> <span class='hs-varid'>hndlr</span> <span class='hs-keyglyph'><-</span> <span class='hs-varid'>streamHandler</span> <span class='hs-varid'>h</span> <span class='hs-varid'>pri</span> <a name="line-142"></a> <span class='hs-varid'>return</span> <span class='hs-varop'>$</span> <span class='hs-varid'>setFormatter</span> <span class='hs-varid'>hndlr</span> <span class='hs-varid'>xmlFormatter</span> <a name="line-143"></a> <a name="line-144"></a> <span class='hs-keyword'>where</span> <a name="line-145"></a> <span class='hs-comment'>-- A Log Formatter that creates an XML element representing a log4j event/message.</span> <a name="line-146"></a> <span class='hs-varid'>xmlFormatter</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-></span> <span class='hs-layout'>(</span><span class='hs-conid'>Priority</span><span class='hs-layout'>,</span><span class='hs-conid'>String</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>String</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-conid'>String</span> <a name="line-147"></a> <span class='hs-varid'>xmlFormatter</span> <span class='hs-keyword'>_</span> <span class='hs-layout'>(</span><span class='hs-varid'>prio</span><span class='hs-layout'>,</span><span class='hs-varid'>msg</span><span class='hs-layout'>)</span> <span class='hs-varid'>logger</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span> <a name="line-148"></a> <span class='hs-varid'>time</span> <span class='hs-keyglyph'><-</span> <span class='hs-varid'>getCurrentTime</span> <a name="line-149"></a> <span class='hs-varid'>thread</span> <span class='hs-keyglyph'><-</span> <span class='hs-varid'>myThreadId</span> <a name="line-150"></a> <span class='hs-varid'>return</span> <span class='hs-varop'>.</span> <span class='hs-varid'>show</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Elem</span> <span class='hs-str'>"log4j:event"</span> <a name="line-151"></a> <span class='hs-keyglyph'>[</span> <span class='hs-layout'>(</span><span class='hs-str'>"logger"</span> <span class='hs-layout'>,</span> <span class='hs-varid'>logger</span> <span class='hs-layout'>)</span> <a name="line-152"></a> <span class='hs-layout'>,</span> <span class='hs-layout'>(</span><span class='hs-str'>"timestamp"</span><span class='hs-layout'>,</span> <span class='hs-varid'>millis</span> <span class='hs-varid'>time</span> <span class='hs-layout'>)</span> <a name="line-153"></a> <span class='hs-layout'>,</span> <span class='hs-layout'>(</span><span class='hs-str'>"level"</span> <span class='hs-layout'>,</span> <span class='hs-varid'>showPrio</span> <span class='hs-varid'>prio</span><span class='hs-layout'>)</span> <a name="line-154"></a> <span class='hs-layout'>,</span> <span class='hs-layout'>(</span><span class='hs-str'>"thread"</span> <span class='hs-layout'>,</span> <span class='hs-varid'>show</span> <span class='hs-varid'>thread</span> <span class='hs-layout'>)</span> <a name="line-155"></a> <span class='hs-keyglyph'>]</span> <a name="line-156"></a> <span class='hs-layout'>(</span><span class='hs-conid'>Just</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Elem</span> <span class='hs-str'>"log4j:message"</span> <span class='hs-conid'>[]</span> <span class='hs-layout'>(</span><span class='hs-conid'>Just</span> <span class='hs-varop'>$</span> <span class='hs-conid'>CDATA</span> <span class='hs-varid'>msg</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <a name="line-157"></a> <span class='hs-keyword'>where</span> <a name="line-158"></a> <span class='hs-comment'>-- This is an ugly hack to get a unix epoch with milliseconds.</span> <a name="line-159"></a> <span class='hs-comment'>-- The use of "take 3" causes the milliseconds to always be</span> <a name="line-160"></a> <span class='hs-comment'>-- rounded downwards, which I suppose may be the expected</span> <a name="line-161"></a> <span class='hs-comment'>-- behaviour for time.</span> <a name="line-162"></a> <span class='hs-varid'>millis</span> <span class='hs-varid'>t</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>formatTime</span> <span class='hs-varid'>defaultTimeLocale</span> <span class='hs-str'>"%s"</span> <span class='hs-varid'>t</span> <a name="line-163"></a> <span class='hs-varop'>++</span> <span class='hs-layout'>(</span><span class='hs-varid'>take</span> <span class='hs-num'>3</span> <span class='hs-varop'>$</span> <span class='hs-varid'>formatTime</span> <span class='hs-varid'>defaultTimeLocale</span> <span class='hs-str'>"%q"</span> <span class='hs-varid'>t</span><span class='hs-layout'>)</span> <a name="line-164"></a> <a name="line-165"></a> <a name="line-166"></a><a name="log4jStreamHandler"></a><span class='hs-comment'>-- | Create a stream log handler that uses hslogger priorities.</span> <a name="line-167"></a><span class='hs-definition'>log4jStreamHandler</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Handle</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>Priority</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-layout'>(</span><span class='hs-conid'>GenericHandler</span> <span class='hs-conid'>Handle</span><span class='hs-layout'>)</span> <a name="line-168"></a><span class='hs-definition'>log4jStreamHandler</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>log4jHandler</span> <span class='hs-varid'>show</span> <a name="line-169"></a> <a name="line-170"></a><a name="log4jStreamHandler'"></a><span class='hs-comment'>{- | Create a stream log handler that uses log4j levels (priorities). The <a name="line-171"></a> priorities of messages are shoehorned into log4j levels as follows: <a name="line-172"></a> <a name="line-173"></a>@ <a name="line-174"></a> DEBUG -> DEBUG <a name="line-175"></a> INFO, NOTICE -> INFO <a name="line-176"></a> WARNING -> WARN <a name="line-177"></a> ERROR, CRITICAL, ALERT -> ERROR <a name="line-178"></a> EMERGENCY -> FATAL <a name="line-179"></a>@ <a name="line-180"></a> <a name="line-181"></a> This is useful when the log will only be consumed by log4j tools and <a name="line-182"></a> you don't want to go out of your way transforming the log or configuring <a name="line-183"></a> the tools. -}</span> <a name="line-184"></a><span class='hs-definition'>log4jStreamHandler'</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Handle</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>Priority</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-layout'>(</span><span class='hs-conid'>GenericHandler</span> <span class='hs-conid'>Handle</span><span class='hs-layout'>)</span> <a name="line-185"></a><span class='hs-definition'>log4jStreamHandler'</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>log4jHandler</span> <span class='hs-varid'>show'</span> <span class='hs-keyword'>where</span> <a name="line-186"></a> <span class='hs-varid'>show'</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Priority</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>String</span> <a name="line-187"></a> <span class='hs-varid'>show'</span> <span class='hs-conid'>NOTICE</span> <span class='hs-keyglyph'>=</span> <span class='hs-str'>"INFO"</span> <a name="line-188"></a> <span class='hs-varid'>show'</span> <span class='hs-conid'>WARNING</span> <span class='hs-keyglyph'>=</span> <span class='hs-str'>"WARN"</span> <a name="line-189"></a> <span class='hs-varid'>show'</span> <span class='hs-conid'>CRITICAL</span> <span class='hs-keyglyph'>=</span> <span class='hs-str'>"ERROR"</span> <a name="line-190"></a> <span class='hs-varid'>show'</span> <span class='hs-conid'>ALERT</span> <span class='hs-keyglyph'>=</span> <span class='hs-str'>"ERROR"</span> <a name="line-191"></a> <span class='hs-varid'>show'</span> <span class='hs-conid'>EMERGENCY</span> <span class='hs-keyglyph'>=</span> <span class='hs-str'>"FATAL"</span> <a name="line-192"></a> <span class='hs-varid'>show'</span> <span class='hs-varid'>p</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>show</span> <span class='hs-varid'>p</span> <span class='hs-comment'>-- Identical for DEBUG, INFO, ERROR.</span> <a name="line-193"></a> <a name="line-194"></a> <a name="line-195"></a><a name="log4jFileHandler"></a><span class='hs-comment'>-- | Create a file log handler that uses hslogger priorities.</span> <a name="line-196"></a><span class='hs-definition'>log4jFileHandler</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>FilePath</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>Priority</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-layout'>(</span><span class='hs-conid'>GenericHandler</span> <span class='hs-conid'>Handle</span><span class='hs-layout'>)</span> <a name="line-197"></a><span class='hs-definition'>log4jFileHandler</span> <span class='hs-varid'>fp</span> <span class='hs-varid'>pri</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span> <a name="line-198"></a> <span class='hs-varid'>h</span> <span class='hs-keyglyph'><-</span> <span class='hs-varid'>openFile</span> <span class='hs-varid'>fp</span> <span class='hs-conid'>AppendMode</span> <a name="line-199"></a> <span class='hs-varid'>sh</span> <span class='hs-keyglyph'><-</span> <span class='hs-varid'>log4jStreamHandler</span> <span class='hs-varid'>h</span> <span class='hs-varid'>pri</span> <a name="line-200"></a> <span class='hs-varid'>return</span> <span class='hs-layout'>(</span><span class='hs-varid'>sh</span><span class='hs-layout'>{</span><span class='hs-varid'>closeFunc</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>hClose</span><span class='hs-layout'>}</span><span class='hs-layout'>)</span> <a name="line-201"></a> <a name="line-202"></a><a name="log4jFileHandler'"></a><span class='hs-comment'>{- | Create a file log handler that uses log4j levels (see <a name="line-203"></a> 'log4jStreamHandler'' for mappings). -}</span> <a name="line-204"></a><span class='hs-definition'>log4jFileHandler'</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>FilePath</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>Priority</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-layout'>(</span><span class='hs-conid'>GenericHandler</span> <span class='hs-conid'>Handle</span><span class='hs-layout'>)</span> <a name="line-205"></a><span class='hs-definition'>log4jFileHandler'</span> <span class='hs-varid'>fp</span> <span class='hs-varid'>pri</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span> <a name="line-206"></a> <span class='hs-varid'>h</span> <span class='hs-keyglyph'><-</span> <span class='hs-varid'>openFile</span> <span class='hs-varid'>fp</span> <span class='hs-conid'>AppendMode</span> <a name="line-207"></a> <span class='hs-varid'>sh</span> <span class='hs-keyglyph'><-</span> <span class='hs-varid'>log4jStreamHandler'</span> <span class='hs-varid'>h</span> <span class='hs-varid'>pri</span> <a name="line-208"></a> <span class='hs-varid'>return</span> <span class='hs-layout'>(</span><span class='hs-varid'>sh</span><span class='hs-layout'>{</span><span class='hs-varid'>closeFunc</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>hClose</span><span class='hs-layout'>}</span><span class='hs-layout'>)</span> <a name="line-209"></a> <a name="line-210"></a> <a name="line-211"></a><a name="XML"></a><span class='hs-comment'>-- A type for building and showing XML elements. Could use a fancy XML</span> <a name="line-212"></a><a name="XML"></a><span class='hs-comment'>-- library but am reluctant to introduce dependencies.</span> <a name="line-213"></a><a name="XML"></a><span class='hs-keyword'>data</span> <span class='hs-conid'>XML</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Elem</span> <span class='hs-conid'>String</span> <span class='hs-keyglyph'>[</span><span class='hs-layout'>(</span><span class='hs-conid'>String</span><span class='hs-layout'>,</span> <span class='hs-conid'>String</span><span class='hs-layout'>)</span><span class='hs-keyglyph'>]</span> <span class='hs-layout'>(</span><span class='hs-conid'>Maybe</span> <span class='hs-conid'>XML</span><span class='hs-layout'>)</span> <a name="line-214"></a> <span class='hs-keyglyph'>|</span> <span class='hs-conid'>CDATA</span> <span class='hs-conid'>String</span> <a name="line-215"></a> <a name="line-216"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>Show</span> <span class='hs-conid'>XML</span> <span class='hs-keyword'>where</span> <a name="line-217"></a> <span class='hs-varid'>show</span> <span class='hs-layout'>(</span><span class='hs-conid'>CDATA</span> <span class='hs-varid'>s</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-str'>"<![CDATA["</span> <span class='hs-varop'>++</span> <span class='hs-varid'>escapeCDATA</span> <span class='hs-varid'>s</span> <span class='hs-varop'>++</span> <span class='hs-str'>"]]>"</span> <span class='hs-keyword'>where</span> <a name="line-218"></a> <span class='hs-varid'>escapeCDATA</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>replace</span> <span class='hs-str'>"]]>"</span> <span class='hs-str'>"]]&lt;"</span> <span class='hs-comment'>-- The best we can do, I guess.</span> <a name="line-219"></a> <span class='hs-varid'>show</span> <span class='hs-layout'>(</span><span class='hs-conid'>Elem</span> <span class='hs-varid'>name</span> <span class='hs-varid'>attrs</span> <span class='hs-varid'>child</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-str'>"<"</span> <span class='hs-varop'>++</span> <span class='hs-varid'>name</span> <span class='hs-varop'>++</span> <span class='hs-varid'>showAttrs</span> <span class='hs-varid'>attrs</span> <span class='hs-varop'>++</span> <span class='hs-varid'>showChild</span> <span class='hs-varid'>child</span> <span class='hs-keyword'>where</span> <a name="line-220"></a> <span class='hs-varid'>showAttrs</span> <span class='hs-conid'>[]</span> <span class='hs-keyglyph'>=</span> <span class='hs-str'>""</span> <a name="line-221"></a> <span class='hs-varid'>showAttrs</span> <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-varid'>k</span><span class='hs-layout'>,</span><span class='hs-varid'>v</span><span class='hs-layout'>)</span><span class='hs-conop'>:</span><span class='hs-keyword'>as</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-str'>" "</span> <span class='hs-varop'>++</span> <span class='hs-varid'>k</span> <span class='hs-varop'>++</span> <span class='hs-str'>"=\""</span> <span class='hs-varop'>++</span> <span class='hs-varid'>escapeAttr</span> <span class='hs-varid'>v</span> <span class='hs-varop'>++</span> <span class='hs-str'>"\""</span> <a name="line-222"></a> <span class='hs-varop'>++</span> <span class='hs-varid'>showAttrs</span> <span class='hs-keyword'>as</span> <a name="line-223"></a> <span class='hs-keyword'>where</span> <span class='hs-varid'>escapeAttr</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>replace</span> <span class='hs-str'>"\""</span> <span class='hs-str'>"&quot;"</span> <a name="line-224"></a> <span class='hs-varop'>.</span> <span class='hs-varid'>replace</span> <span class='hs-str'>"<"</span> <span class='hs-str'>"&lt;"</span> <a name="line-225"></a> <span class='hs-varop'>.</span> <span class='hs-varid'>replace</span> <span class='hs-str'>"&"</span> <span class='hs-str'>"&amp;"</span> <a name="line-226"></a> <span class='hs-varid'>showChild</span> <span class='hs-conid'>Nothing</span> <span class='hs-keyglyph'>=</span> <span class='hs-str'>"/>"</span> <a name="line-227"></a> <span class='hs-varid'>showChild</span> <span class='hs-layout'>(</span><span class='hs-conid'>Just</span> <span class='hs-varid'>c</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-str'>">"</span> <span class='hs-varop'>++</span> <span class='hs-varid'>show</span> <span class='hs-varid'>c</span> <span class='hs-varop'>++</span> <span class='hs-str'>"</"</span> <span class='hs-varop'>++</span> <span class='hs-varid'>name</span> <span class='hs-varop'>++</span> <span class='hs-str'>">"</span> <a name="line-228"></a> <a name="line-229"></a> <a name="line-230"></a><a name="replace"></a><span class='hs-comment'>-- Replaces instances of first list by second list in third list.</span> <a name="line-231"></a><span class='hs-comment'>-- Definition blatantly stoled from jethr0's comment at</span> <a name="line-232"></a><span class='hs-comment'>-- <a href="http://bluebones.net/2007/01/replace-in-haskell/.">http://bluebones.net/2007/01/replace-in-haskell/.</a> Can be swapped</span> <a name="line-233"></a><span class='hs-comment'>-- with definition (or import) from MissingH.</span> <a name="line-234"></a><span class='hs-definition'>replace</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Eq</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=></span> <span class='hs-keyglyph'>[</span><span class='hs-varid'>a</span><span class='hs-keyglyph'>]</span> <span class='hs-keyglyph'>-></span> <span class='hs-keyglyph'>[</span><span class='hs-varid'>a</span><span class='hs-keyglyph'>]</span> <span class='hs-keyglyph'>-></span> <span class='hs-keyglyph'>[</span><span class='hs-varid'>a</span><span class='hs-keyglyph'>]</span> <span class='hs-keyglyph'>-></span> <span class='hs-keyglyph'>[</span><span class='hs-varid'>a</span><span class='hs-keyglyph'>]</span> <a name="line-235"></a><span class='hs-definition'>replace</span> <span class='hs-keyword'>_</span> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>[</span> <span class='hs-keyglyph'>]</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>[]</span> <a name="line-236"></a><span class='hs-definition'>replace</span> <span class='hs-varid'>from</span> <span class='hs-varid'>to</span> <span class='hs-varid'>xs</span><span class='hs-keyglyph'>@</span><span class='hs-layout'>(</span><span class='hs-varid'>a</span><span class='hs-conop'>:</span><span class='hs-keyword'>as</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>if</span> <span class='hs-varid'>isPrefixOf</span> <span class='hs-varid'>from</span> <span class='hs-varid'>xs</span> <a name="line-237"></a> <span class='hs-keyword'>then</span> <span class='hs-varid'>to</span> <span class='hs-varop'>++</span> <span class='hs-varid'>drop</span> <span class='hs-layout'>(</span><span class='hs-varid'>length</span> <span class='hs-varid'>from</span><span class='hs-layout'>)</span> <span class='hs-varid'>xs</span> <span class='hs-keyword'>else</span> <span class='hs-varid'>a</span> <span class='hs-conop'>:</span> <span class='hs-varid'>replace</span> <span class='hs-varid'>from</span> <span class='hs-varid'>to</span> <span class='hs-keyword'>as</span> <a name="line-238"></a> </pre></body> </html>