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    }