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 private transient LogType.AttributeInfo attributeInfo;
042
043 public Match( String attribute, String type, String reference )
044 {
045 this.attribute = attribute;
046 this.not = type.startsWith( "!" );
047 if ( not )
048 {
049 type = type.substring( 1 );
050 }
051 this.function = Match.Function.getInstance( type, reference );
052 }
053
054 public boolean match( LogEvent le )
055 {
056 // initialize attributeInfo if necessary
057 if ( attributeInfo == null )
058 {
059 LogType.Description description = le.getFactory().getDescription();
060 attributeInfo = description.getAttributeInfo( attribute );
061 }
062
063 String value = le.getValue( attributeInfo );
064 boolean result = function.checkValue( value );
065 return ( not ? !result : result );
066 }
067
068 public Element dump()
069 {
070 Element elmt = new Element( "match" );
071 elmt.setAttribute( "attribute", attribute );
072 elmt.setAttribute( "type", ( not ? "!" : "" ) + function.getId() );
073 elmt.setText( function.reference );
074 return elmt;
075 }
076
077 private static abstract class Function
078 implements Serializable
079 {
080 private static final long serialVersionUID = 1072441995042764838L;
081
082 public final static Map FUNCTIONS;
083 static
084 {
085 Map map = new HashMap();
086 map.put( Contains.ID, Contains.class );
087 map.put( Equals.ID, Equals.class );
088 map.put( StartsWith.ID, StartsWith.class );
089 map.put( EndsWith.ID, EndsWith.class );
090 map.put( Regexp.ID, Regexp.class );
091 FUNCTIONS = Collections.unmodifiableMap( map );
092 }
093
094 public static Function getInstance( String type, String reference )
095 {
096 Class functionClass = (Class) FUNCTIONS.get( type );
097 if ( functionClass == null )
098 {
099 throw new IllegalArgumentException( "function type not supported '" + type + "'" );
100 }
101 try
102 {
103 Function function = (Function) functionClass.newInstance();
104 function.setReference( reference );
105 return function;
106 }
107 catch ( IllegalAccessException iae )
108 {
109 // can't happen
110 throw new RuntimeException( "an impossible condition has arrived...", iae );
111 }
112 catch ( InstantiationException ie )
113 {
114 // can't happen
115 throw new RuntimeException( "an impossible condition has arrived...", ie );
116 }
117 }
118
119 protected String reference;
120
121 public void setReference( String reference )
122 {
123 this.reference = reference;
124 }
125
126 public abstract String getId();
127
128 /**
129 * check if the given value matches the reference.
130 *
131 * @param value String the value to compare to reference
132 * @return boolean
133 */
134 public abstract boolean checkValue( String value );
135 }
136
137 protected static class Contains
138 extends Function
139 {
140 private static final long serialVersionUID = 4613611844726287358L;
141
142 public static final String ID = "contains";
143
144 public String getId()
145 {
146 return ID;
147 }
148
149 public boolean checkValue( String value )
150 {
151 return ( value.indexOf( reference ) >= 0 );
152 }
153 }
154
155 protected static class Equals
156 extends Function
157 {
158 private static final long serialVersionUID = -6539918940865536415L;
159
160 public static final String ID = "equals";
161
162 public String getId()
163 {
164 return ID;
165 }
166
167 public boolean checkValue( String value )
168 {
169 return reference.equals( value );
170 }
171 }
172
173 protected static class StartsWith
174 extends Function
175 {
176 private static final long serialVersionUID = 5014914695776363132L;
177
178 public static final String ID = "startsWith";
179
180 public String getId()
181 {
182 return ID;
183 }
184
185 public boolean checkValue( String value )
186 {
187 return value.startsWith( reference );
188 }
189 }
190
191 protected static class EndsWith
192 extends Function
193 {
194 private static final long serialVersionUID = 1819477635452601804L;
195
196 public static final String ID = "endsWith";
197
198 public String getId()
199 {
200 return ID;
201 }
202
203 public boolean checkValue( String value )
204 {
205 return value.endsWith( reference );
206 }
207 }
208
209 protected static class Regexp
210 extends Function
211 {
212 private static final long serialVersionUID = -2067188055591690252L;
213
214 public static final String ID = "regexp";
215
216 public String getId()
217 {
218 return ID;
219 }
220
221 private transient Pattern pattern;
222
223 public void setReference( String reference )
224 {
225 super.setReference( reference );
226 updatePattern();
227 }
228
229 private void updatePattern()
230 {
231 pattern = Pattern.compile( reference );
232 }
233
234 private void readObject( ObjectInputStream in )
235 throws IOException, ClassNotFoundException
236 {
237 in.defaultReadObject();
238 updatePattern();
239 }
240
241 public boolean checkValue( String value )
242 {
243 return pattern.matcher( value ).find();
244 }
245 }
246 }