Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: de/hunsicker/jalopy/plugin/AbstractAppender.java


1   /*
2    * Copyright (c) 2001-2002, Marco Hunsicker. All rights reserved.
3    *
4    * This software is distributable under the BSD license. See the terms of the
5    * BSD license in the documentation provided with this software.
6    */
7   package de.hunsicker.jalopy.plugin;
8   
9   import de.hunsicker.util.ChainingRuntimeException;
10  
11  import org.apache.log4j.AppenderSkeleton;
12  import org.apache.log4j.Level;
13  import org.apache.log4j.spi.LoggingEvent;
14  
15  import org.apache.oro.text.regex.MalformedPatternException;
16  import org.apache.oro.text.regex.MatchResult;
17  import org.apache.oro.text.regex.Pattern;
18  import org.apache.oro.text.regex.PatternCompiler;
19  import org.apache.oro.text.regex.PatternMatcher;
20  import org.apache.oro.text.regex.Perl5Compiler;
21  import org.apache.oro.text.regex.Perl5Matcher;
22  
23  
24  /**
25   * Skeleton implementation of an appender which outputs messages in a visual component.
26   *
27   * @author <a href="http://jalopy.sf.net/contact.html">Marco Hunsicker</a>
28   * @version $Revision: 1.4 $
29   */
30  public abstract class AbstractAppender
31      extends AppenderSkeleton
32      implements SwingAppender
33  {
34      //~ Static variables/initializers ----------------------------------------------------
35  
36      /** Position of the filename in the regex result. */
37      public static final int POS_FILENAME = 1;
38  
39      /** Position of the lineno in the regex result. */
40      public static final int POS_LINE = 2;
41  
42      /** Position of the message text in the regex result. */
43      public static final int POS_TEXT = 4;
44  
45      /** Position of the message text in the regex result. */
46      public static final int POS_COLUMN = 3;
47  
48      /** Name of the appender for output messages. */
49      private static final String APPENDER_NAME = "JalopyAppender" /* NOI18N */;
50  
51      /**
52       * Regex to apply for Emacs-style messages. Messages must comply to the
53       * filename:line:column:text pattern.
54       */
55      private static final String PATTERN = "(.+?):(\\d+):(\\d+):\\s*(.+)" /* NOI18N */;
56  
57      //~ Instance variables ---------------------------------------------------------------
58  
59      /**
60       * The regex to parse the messages. If messages have a format similiar to Emacs
61       * messages (<code>filename:lineno:text</code>) the pattern will match.
62       */
63      protected final Pattern regex;
64  
65      /** Matcher instance. */
66      private PatternMatcher _matcher;
67  
68      //~ Constructors ---------------------------------------------------------------------
69  
70      /**
71       * Creates a new AbstractAppender object.
72       *
73       * @throws ChainingRuntimeException DOCUMENT ME!
74       */
75      public AbstractAppender()
76      {
77          this.name = APPENDER_NAME;
78          this.layout = new SwingLayout();
79          setThreshold(Level.DEBUG);
80          _matcher = new Perl5Matcher();
81  
82          PatternCompiler compiler = new Perl5Compiler();
83  
84          try
85          {
86              this.regex = compiler.compile(PATTERN, Perl5Compiler.SINGLELINE_MASK);
87          }
88          catch (MalformedPatternException ex)
89          {
90              throw new ChainingRuntimeException(ex);
91          }
92      }
93  
94      //~ Methods --------------------------------------------------------------------------
95  
96      /**
97       * Does the actual outputting.
98       *
99       * @param ev logging event.
100      */
101     public abstract void append(LoggingEvent ev);
102 
103 
104     /**
105      * Sets the name of the appender. Overidden so that the initial name can't be
106      * changed.
107      *
108      * @param name appender name (ignored).
109      */
110     public final void setName(String name)
111     {
112     }
113 
114 
115     /**
116      * {@inheritDoc}
117      */
118     public void close()
119     {
120     }
121 
122 
123     /**
124      * {@inheritDoc}
125      */
126     public void done()
127     {
128     }
129 
130 
131     /**
132      * Parses the given message. To access the parsed information one may typically use:
133      * <pre class="snippet">
134      * MatchResult result = parseMessage(message);
135      * if (result == null)
136      * {
137      *     // handle plain message
138      *     ...
139      * }
140      * else
141      * {
142      *     // this is an Emacs style message, you can easily access the
143      *     // information
144      *     String filename = result.group(POS_FILENAME);
145      *     String line = result.group(POS_LINE);
146      *     String column = result.group(POS_COLUMN);
147      *     String text = result.group(POS_TEXT);
148      *     ...
149      * }
150      * </pre>
151      *
152      * @param ev logging event.
153      *
154      * @return parsing result. Returns <code>null</code> if the message doesn't match the
155      *         Emacs format <code>filename:line:column:text</code>.
156      */
157     public MatchResult parseMessage(LoggingEvent ev)
158     {
159         if (_matcher.matches(this.layout.format(ev), this.regex))
160         {
161             return _matcher.getMatch();
162         }
163 
164         return null;
165     }
166 
167 
168     /**
169      * {@inheritDoc}
170      *
171      * @return always <code>true</code>.
172      */
173     public boolean requiresLayout()
174     {
175         return true;
176     }
177 
178 
179     /**
180      * {@inheritDoc}
181      *
182      * @return always <code>true</code>.
183      */
184     protected boolean checkEntryConditions()
185     {
186         return true;
187     }
188 }