001    // This file is part of the program FRYSK.
002    //
003    // Copyright 2005, 2006, 2007, 2008, Red Hat Inc.
004    //
005    // FRYSK is free software; you can redistribute it and/or modify it
006    // under the terms of the GNU General Public License as published by
007    // the Free Software Foundation; version 2 of the License.
008    //
009    // FRYSK is distributed in the hope that it will be useful, but
010    // WITHOUT ANY WARRANTY; without even the implied warranty of
011    // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012    // General Public License for more details.
013    // 
014    // You should have received a copy of the GNU General Public License
015    // along with FRYSK; if not, write to the Free Software Foundation,
016    // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
017    // 
018    // In addition, as a special exception, Red Hat, Inc. gives You the
019    // additional right to link the code of FRYSK with code not covered
020    // under the GNU General Public License ("Non-GPL Code") and to
021    // distribute linked combinations including the two, subject to the
022    // limitations in this paragraph. Non-GPL Code permitted under this
023    // exception must only link to the code of FRYSK through those well
024    // defined interfaces identified in the file named EXCEPTION found in
025    // the source code files (the "Approved Interfaces"). The files of
026    // Non-GPL Code may instantiate templates or use macros or inline
027    // functions from the Approved Interfaces without causing the
028    // resulting work to be covered by the GNU General Public
029    // License. Only Red Hat, Inc. may make changes or additions to the
030    // list of Approved Interfaces. You must obey the GNU General Public
031    // License in all respects for all of the FRYSK code and other code
032    // used in conjunction with FRYSK except the Non-GPL Code covered by
033    // this exception. If you modify this file, you may extend this
034    // exception to your version of the file, but you are not obligated to
035    // do so. If you do not wish to provide this exception without
036    // modification, you must delete this exception statement from your
037    // version and license this file solely under the GPL without
038    // exception.
039    
040    package frysk.ftrace;
041    
042    import java.util.Collection;
043    import java.util.Iterator;
044    import java.util.Set;
045    import frysk.rsl.Log;
046    
047    public abstract class Rule {
048        private static final Log fine = Log.fine(Rule.class);
049    
050        final public boolean addition;
051        final public RuleOptions options;
052    
053        protected Rule(boolean addition, RuleOptions options) {
054            this.addition = addition;
055            this.options = options;
056        }
057    
058        public String toString() {
059            return (this.addition ? "" : "-")  + "/" +
060                (this.options.stackTrace ? "s" : "");
061        }
062    
063        public boolean apply(Collection candidates,
064                             Set workingSet, Set stackTraceSet)
065        {
066            boolean matched = false;
067    
068            if (this.addition) {
069                // For '+' rules iterate over candidates,
070                // and add what matches to workingSet, and
071                // maybe to stackTraceSet.
072                for (Iterator jt = candidates.iterator(); jt.hasNext(); ) {
073                    Object candidate = jt.next();
074                    if (this.matches(candidate)) {
075                        matched = true;
076                        if (workingSet.add(candidate))
077                            fine.log(this, "add", candidate);
078                        if (options.stackTrace
079                            && stackTraceSet.add(candidate))
080                            fine.log(this, "stack trace on", candidate);
081                    }
082                }
083            }
084            else {
085                // For '-' or '-/s' rules iterate over
086                // workingSet or stackTraceSet, and remove
087                // what matches.
088                Set iterateOver = options.stackTrace ? stackTraceSet : workingSet;
089                for (Iterator jt = iterateOver.iterator(); jt.hasNext(); ) {
090                    Object candidate = jt.next();
091                    if (this.matches(candidate)) {
092                        matched = true;
093                        jt.remove();
094                        if (!options.stackTrace)
095                            stackTraceSet.remove(candidate);
096                        fine.log(this, "remove", candidate);
097                    }
098                }
099            }
100    
101            return matched;
102        }
103    
104        abstract public boolean matches(Object traceable);
105    }