001 package net.sf.logdistiller;
002
003 /*
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 import java.io.*;
018 import java.util.Collections;
019 import java.util.HashMap;
020 import java.util.Map;
021 import java.util.regex.Pattern;
022
023 import org.jdom.Element;
024
025 /**
026 * Match of an attribute of a LogEvent. Match type can be either <code>contains</code>, <code>equals</code>,
027 * <code>startsWith</code>, <code>endsWith</code> or <code>regexp</code>, and can be negated by preceding type with
028 * <code>!</code>.
029 */
030 public class Match
031 implements Serializable
032 {
033 private static final long serialVersionUID = -1809458932445222708L;
034
035 private final String attribute;
036
037 private final boolean not;
038
039 private final Function function;
040
041 public Match( String attribute, String type, String reference )
042 {
043 this.attribute = attribute;
044 this.not = type.startsWith( "!" );
045 if ( not )
046 {
047 type = type.substring( 1 );
048 }
049 this.function = Match.Function.getInstance( type, reference );
050 }
051
052 public boolean match( LogEvent le )
053 {
054 String value = le.getAttribute( attribute );
055 boolean result = function.checkValue( value );
056 return ( not ? !result : result );
057 }
058
059 public Element dump()
060 {
061 Element elmt = new Element( "match" );
062 elmt.setAttribute( "attribute", attribute );
063 elmt.setAttribute( "type", ( not ? "!" : "" ) + function.getId() );
064 elmt.setText( function.reference );
065 return elmt;
066 }
067
068 private static abstract class Function
069 implements Serializable
070 {
071 private static final long serialVersionUID = 1072441995042764838L;
072
073 public final static Map FUNCTIONS;
074 static
075 {
076 Map map = new HashMap();
077 map.put( Contains.ID, Contains.class );
078 map.put( Equals.ID, Equals.class );
079 map.put( StartsWith.ID, StartsWith.class );
080 map.put( EndsWith.ID, EndsWith.class );
081 map.put( Regexp.ID, Regexp.class );
082 FUNCTIONS = Collections.unmodifiableMap( map );
083 }
084
085 public static Function getInstance( String type, String reference )
086 {
087 Class functionClass = (Class) FUNCTIONS.get( type );
088 if ( functionClass == null )
089 {
090 throw new IllegalArgumentException( "function type not supported '" + type + "'" );
091 }
092 try
093 {
094 Function function = (Function) functionClass.newInstance();
095 function.setReference( reference );
096 return function;
097 }
098 catch ( IllegalAccessException iae )
099 {
100 // can't happen
101 throw new RuntimeException( "an impossible condition has arrived...", iae );
102 }
103 catch ( InstantiationException ie )
104 {
105 // can't happen
106 throw new RuntimeException( "an impossible condition has arrived...", ie );
107 }
108 }
109
110 protected String reference;
111
112 public void setReference( String reference )
113 {
114 this.reference = reference;
115 }
116
117 public abstract String getId();
118
119 /**
120 * check if the given value matches the reference.
121 *
122 * @param value String the value to compare to reference
123 * @return boolean
124 */
125 public abstract boolean checkValue( String value );
126 }
127
128 protected static class Contains
129 extends Function
130 {
131 private static final long serialVersionUID = 4613611844726287358L;
132
133 public static final String ID = "contains";
134
135 public String getId()
136 {
137 return ID;
138 }
139
140 public boolean checkValue( String value )
141 {
142 return ( value.indexOf( reference ) >= 0 );
143 }
144 }
145
146 protected static class Equals
147 extends Function
148 {
149 private static final long serialVersionUID = -6539918940865536415L;
150
151 public static final String ID = "equals";
152
153 public String getId()
154 {
155 return ID;
156 }
157
158 public boolean checkValue( String value )
159 {
160 return reference.equals( value );
161 }
162 }
163
164 protected static class StartsWith
165 extends Function
166 {
167 private static final long serialVersionUID = 5014914695776363132L;
168
169 public static final String ID = "startsWith";
170
171 public String getId()
172 {
173 return ID;
174 }
175
176 public boolean checkValue( String value )
177 {
178 return value.startsWith( reference );
179 }
180 }
181
182 protected static class EndsWith
183 extends Function
184 {
185 private static final long serialVersionUID = 1819477635452601804L;
186
187 public static final String ID = "endsWith";
188
189 public String getId()
190 {
191 return ID;
192 }
193
194 public boolean checkValue( String value )
195 {
196 return value.endsWith( reference );
197 }
198 }
199
200 protected static class Regexp
201 extends Function
202 {
203 private static final long serialVersionUID = -2067188055591690252L;
204
205 public static final String ID = "regexp";
206
207 public String getId()
208 {
209 return ID;
210 }
211
212 private transient Pattern pattern;
213
214 public void setReference( String reference )
215 {
216 super.setReference( reference );
217 updatePattern();
218 }
219
220 private void updatePattern()
221 {
222 pattern = Pattern.compile( reference );
223 }
224
225 private void readObject( ObjectInputStream in )
226 throws IOException, ClassNotFoundException
227 {
228 in.defaultReadObject();
229 updatePattern();
230 }
231
232 public boolean checkValue( String value )
233 {
234 return pattern.matcher( value ).find();
235 }
236 }
237 }