Coverage Report - com.jeantessier.classreader.ClassfileLoaderEventSource
 
Classes in this File Line Coverage Branch Coverage Complexity
ClassfileLoaderEventSource
90%
131/145
80%
32/40
2.19
ClassfileLoaderEventSource$1
100%
1/1
N/A
2.19
 
 1  
 /*
 2  
  *  Copyright (c) 2001-2009, Jean Tessier
 3  
  *  All rights reserved.
 4  
  *  
 5  
  *  Redistribution and use in source and binary forms, with or without
 6  
  *  modification, are permitted provided that the following conditions
 7  
  *  are met:
 8  
  *  
 9  
  *      * Redistributions of source code must retain the above copyright
 10  
  *        notice, this list of conditions and the following disclaimer.
 11  
  *  
 12  
  *      * Redistributions in binary form must reproduce the above copyright
 13  
  *        notice, this list of conditions and the following disclaimer in the
 14  
  *        documentation and/or other materials provided with the distribution.
 15  
  *  
 16  
  *      * Neither the name of Jean Tessier nor the names of his contributors
 17  
  *        may be used to endorse or promote products derived from this software
 18  
  *        without specific prior written permission.
 19  
  *  
 20  
  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 21  
  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 22  
  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 23  
  *  A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR
 24  
  *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 25  
  *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 26  
  *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 27  
  *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 28  
  *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 29  
  *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 30  
  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 31  
  */
 32  
 
 33  
 package com.jeantessier.classreader;
 34  
 
 35  
 import java.io.*;
 36  
 import java.util.*;
 37  
 
 38  
 import org.apache.log4j.*;
 39  
 
 40  
 public abstract class ClassfileLoaderEventSource extends ClassfileLoader {
 41  2
     public static final ClassfileLoaderDispatcher DEFAULT_DISPATCHER = new PermissiveDispatcher();
 42  
     
 43  
     private ClassfileFactory factory;
 44  
     private ClassfileLoaderDispatcher dispatcher;
 45  
     
 46  310
     private ClassfileLoader dirLoader = new DirectoryClassfileLoader(this);
 47  310
     private ClassfileLoader jarLoader = new JarClassfileLoader(this);
 48  310
     private ClassfileLoader zipLoader = new ZipClassfileLoader(this);
 49  
 
 50  310
     private HashSet<LoadListener> loadListeners = new HashSet<LoadListener>();
 51  
 
 52  310
     private LinkedList<String> groupNames = new LinkedList<String>();
 53  310
     private LinkedList<Integer> groupSizes = new LinkedList<Integer>();
 54  
 
 55  
     private ClassfileLoaderAction previousDispatch;
 56  
     
 57  
     public ClassfileLoaderEventSource(ClassfileFactory factory) {
 58  291
         this(factory, DEFAULT_DISPATCHER);
 59  291
     }
 60  
 
 61  310
     public ClassfileLoaderEventSource(ClassfileFactory factory, ClassfileLoaderDispatcher dispatcher) {
 62  310
         this.factory = factory;
 63  310
         this.dispatcher = dispatcher;
 64  310
     }
 65  
 
 66  
     protected ClassfileFactory getFactory() {
 67  1142
         return factory;
 68  
     }
 69  
 
 70  
     protected void load(String filename) {
 71  247
         ClassfileLoaderAction dispatch = dispatcher.dispatch(filename);
 72  
 
 73  247
         previousDispatch = dispatch;
 74  
         
 75  2
         switch (dispatch) {
 76  
             case IGNORE:
 77  0
                 Logger.getLogger(getClass()).debug("IGNORE \"" + filename + "\"");
 78  0
                 break;
 79  
 
 80  
             case CLASS:
 81  
             case DIRECTORY:
 82  227
                 Logger.getLogger(getClass()).debug("DIRECTORY or CLASS \"" + filename + "\"");
 83  227
                 dirLoader.load(filename);
 84  227
                 break;
 85  
 
 86  
             case ZIP:
 87  11
                 Logger.getLogger(getClass()).debug("ZIP \"" + filename + "\"");
 88  11
                 zipLoader.load(filename);
 89  11
                 break;
 90  
 
 91  
             case JAR:
 92  9
                 Logger.getLogger(getClass()).debug("JAR \"" + filename + "\"");
 93  9
                 jarLoader.load(filename);
 94  9
                 break;
 95  
 
 96  
             default:
 97  0
                 Logger.getLogger(getClass()).debug("default (IGNORE) \"" + filename + "\"");
 98  
                 break;
 99  
         }
 100  247
     }
 101  
 
 102  
     protected void load(String filename, InputStream in) {
 103  2214
         ClassfileLoaderAction dispatch = dispatcher.dispatch(filename);
 104  
 
 105  2214
         if (dispatch == ClassfileLoaderAction.IGNORE && getTopGroupSize() == 1 &&  filename.equals(getTopGroupName())) {
 106  4
             dispatch = previousDispatch;
 107  
         }
 108  
         
 109  2214
         switch (dispatch) {
 110  
             case IGNORE:
 111  978
                 Logger.getLogger(getClass()).debug("IGNORE \"" + filename + "\"");
 112  978
                 break;
 113  
 
 114  
             case DIRECTORY:
 115  2
                 Logger.getLogger(getClass()).debug("DIRECTORY \"" + filename + "\"");
 116  2
                 dirLoader.load(filename, in);
 117  2
                 break;
 118  
 
 119  
             case ZIP:
 120  9
                 Logger.getLogger(getClass()).debug("ZIP \"" + filename + "\"");
 121  9
                 zipLoader.load(filename, in);
 122  9
                 break;
 123  
 
 124  
             case JAR:
 125  0
                 Logger.getLogger(getClass()).debug("JAR \"" + filename + "\"");
 126  0
                 jarLoader.load(filename, in);
 127  0
                 break;
 128  
 
 129  
             case CLASS:
 130  1225
                 Logger.getLogger(getClass()).debug("CLASS \"" + filename + "\"");
 131  
                 try {
 132  1225
                     fireBeginClassfile(filename);
 133  1225
                     Classfile classfile = load(new DataInputStream(in));
 134  1225
                     fireEndClassfile(filename, classfile);
 135  0
                 } catch (IOException ex) {
 136  0
                     Logger.getLogger(getClass()).warn("Cannot load class from file \"" + filename + "\"", ex);
 137  1225
                 }
 138  0
                 break;
 139  
                 
 140  
             default:
 141  0
                 Logger.getLogger(getClass()).debug("default (IGNORE) \"" + filename + "\"");
 142  
                 break;
 143  
         }
 144  2214
     }
 145  
 
 146  
     public void addLoadListener(LoadListener listener) {
 147  64
         synchronized(loadListeners) {
 148  64
             loadListeners.add(listener);
 149  64
         }
 150  64
     }
 151  
 
 152  
     public void removeLoadListener(LoadListener listener) {
 153  0
         synchronized(loadListeners) {
 154  0
             loadListeners.remove(listener);
 155  0
         }
 156  0
     }
 157  
 
 158  
     protected void fireBeginSession() {
 159  188
         Logger.getLogger(getClass()).debug("Begin session");
 160  
         
 161  188
         LoadEvent event = new LoadEvent(this, null, null, null);
 162  
 
 163  
         HashSet<LoadListener> listeners;
 164  188
         synchronized(loadListeners) {
 165  188
             listeners = (HashSet<LoadListener>) loadListeners.clone();
 166  188
         }
 167  
 
 168  188
         for (LoadListener listener : listeners) {
 169  46
             listener.beginSession(event);
 170  
         }
 171  188
     }
 172  
 
 173  
     protected void fireBeginGroup(String groupName, int size) {
 174  270
         Logger.getLogger(getClass()).debug("Begin group \"" + groupName + "\" of size " + size);
 175  
 
 176  270
         LoadEvent event = new LoadEvent(this, groupName, size);
 177  
 
 178  
         HashSet<LoadListener> listeners;
 179  270
         synchronized(loadListeners) {
 180  270
             listeners = (HashSet<LoadListener>) loadListeners.clone();
 181  270
         }
 182  
 
 183  270
         for (LoadListener listener : listeners) {
 184  68
             listener.beginGroup(event);
 185  
         }
 186  
 
 187  270
         pushGroupName(groupName);
 188  270
         pushGroupSize(size);
 189  270
     }
 190  
     
 191  
     protected void fireBeginFile(String filename) {
 192  2390
         Logger.getLogger(getClass()).debug("Begin file \"" + filename + "\"");
 193  
         
 194  2390
         LoadEvent event = new LoadEvent(this, getTopGroupName(), filename, null);
 195  
 
 196  
         HashSet<LoadListener> listeners;
 197  2390
         synchronized(loadListeners) {
 198  2390
             listeners = (HashSet<LoadListener>) loadListeners.clone();
 199  2390
         }
 200  
 
 201  2390
         for (LoadListener listener : listeners) {
 202  1221
             listener.beginFile(event);
 203  
         }
 204  2390
     }
 205  
     
 206  
     protected void fireBeginClassfile(String filename) {
 207  1225
         Logger.getLogger(getClass()).debug("Begin classfile \"" + filename + "\"");
 208  
         
 209  1225
         LoadEvent event = new LoadEvent(this, getTopGroupName(), filename, null);
 210  
 
 211  
         HashSet<LoadListener> listeners;
 212  1225
         synchronized(loadListeners) {
 213  1225
             listeners = (HashSet<LoadListener>) loadListeners.clone();
 214  1225
         }
 215  
 
 216  1225
         for (LoadListener listener : listeners) {
 217  560
             listener.beginClassfile(event);
 218  
         }
 219  1225
     }
 220  
 
 221  
     protected void fireEndClassfile(String filename, Classfile classfile) {
 222  1225
         Logger.getLogger(getClass()).debug("End classfile \"" + filename + "\": " + ((classfile != null) ? classfile.getClassName() : "nothing"));
 223  
         
 224  1225
         LoadEvent event = new LoadEvent(this, getTopGroupName(), filename, classfile);
 225  
 
 226  
         HashSet<LoadListener> listeners;
 227  1225
         synchronized(loadListeners) {
 228  1225
             listeners = (HashSet<LoadListener>) loadListeners.clone();
 229  1225
         }
 230  
 
 231  1225
         for (LoadListener listener : listeners) {
 232  560
             listener.endClassfile(event);
 233  
         }
 234  1225
     }
 235  
 
 236  
     protected void fireEndFile(String filename) {
 237  2390
         Logger.getLogger(getClass()).debug("End file \"" + filename + "\"");
 238  
         
 239  2390
         LoadEvent event = new LoadEvent(this, getTopGroupName(), filename, null);
 240  
 
 241  
         HashSet<LoadListener> listeners;
 242  2390
         synchronized(loadListeners) {
 243  2390
             listeners = (HashSet<LoadListener>) loadListeners.clone();
 244  2390
         }
 245  
 
 246  2390
         for (LoadListener listener : listeners) {
 247  1221
             listener.endFile(event);
 248  
         }
 249  2390
     }
 250  
 
 251  
     protected void fireEndGroup(String groupName) {
 252  270
         Logger.getLogger(getClass()).debug("End group \"" + groupName + "\"");
 253  
         
 254  270
         LoadEvent event = new LoadEvent(this, groupName, null, null);
 255  
 
 256  
         HashSet<LoadListener> listeners;
 257  270
         synchronized(loadListeners) {
 258  270
             listeners = (HashSet<LoadListener>) loadListeners.clone();
 259  270
         }
 260  
 
 261  270
         for (LoadListener listener : listeners) {
 262  68
             listener.endGroup(event);
 263  
         }
 264  
 
 265  270
         popGroupName();
 266  270
         popGroupSize();
 267  270
     }
 268  
 
 269  
     protected void fireEndSession() {
 270  188
         Logger.getLogger(getClass()).debug("End session");
 271  
         
 272  188
         LoadEvent event = new LoadEvent(this, null, null, null);
 273  
 
 274  
         HashSet<LoadListener> listeners;
 275  188
         synchronized(loadListeners) {
 276  188
             listeners = (HashSet<LoadListener>) loadListeners.clone();
 277  188
         }
 278  
 
 279  188
         for (LoadListener listener : listeners) {
 280  46
             listener.endSession(event);
 281  
         }
 282  188
     }
 283  
 
 284  
     private String getTopGroupName() {
 285  7234
         String result = null;
 286  
 
 287  7234
         if (!groupNames.isEmpty()) {
 288  7234
             result = groupNames.getLast();
 289  
         }
 290  
 
 291  7234
         return result;
 292  
     }
 293  
 
 294  
     private void pushGroupName(String groupName) {
 295  270
         groupNames.addLast(groupName);
 296  270
     }
 297  
 
 298  
     private String popGroupName() {
 299  270
         return groupNames.removeLast();
 300  
     }
 301  
 
 302  
     private int getTopGroupSize() {
 303  982
         int result = 0;
 304  
 
 305  982
         if (!groupSizes.isEmpty()) {
 306  982
             result = groupSizes.getLast();
 307  
         }
 308  
 
 309  982
         return result;
 310  
     }
 311  
 
 312  
     private void pushGroupSize(int size) {
 313  270
         groupSizes.addLast(size);
 314  270
     }
 315  
 
 316  
     private int popGroupSize() {
 317  270
         return groupSizes.removeLast();
 318  
     }
 319  
 }