View Javadoc

1   /*
2    * $Id$
3    *
4    * The contents of this file are subject to the Mozilla Public License 
5    * Version 1.1 (the "License"); you may not use this file except in 
6    * compliance with the License. You may obtain a copy of the License at 
7    * http://www.mozilla.org/MPL/ 
8    *
9    * Software distributed under the License is distributed on an "AS IS" basis, 
10   * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
11   * for the specific language governing rights and limitations under the License.
12   *
13   * The Original Code is XML Hammer code. (org.xmlhammer.*)
14   *
15   * The Initial Developer of the Original Code is Edwin Dankert. Portions created 
16   * by the Initial Developer are Copyright (C) 2002 - 2006 the Initial Developer. 
17   * All Rights Reserved.
18   *
19   * Contributor(s): Edwin Dankert <edankert@gmail.com>
20   */
21  package org.xmlhammer;
22  
23  import java.io.File;
24  import java.io.FileFilter;
25  import java.net.URI;
26  import java.util.ArrayList;
27  import java.util.List;
28  import java.util.regex.Matcher;
29  import java.util.regex.Pattern;
30  
31  import javax.swing.event.EventListenerList;
32  
33  import org.apache.log4j.Logger;
34  import org.bounce.util.URIUtils;
35  import org.xmlhammer.gui.status.StatusModel;
36  import org.xmlhammer.gui.util.WildcardFileFilter;
37  import org.xmlhammer.model.project.Document;
38  import org.xmlhammer.model.project.Filter;
39  import org.xmlhammer.model.project.Input;
40  
41  /***
42   * Put comment...
43   * 
44   * @version $Revision$, $Date$
45   * @author Edwin Dankert <edankert@gmail.com>
46   */
47  
48  public class ModuleThread extends Thread {
49  	private EventListenerList listeners = null;
50  	private ResultModel result = null;
51  	private Logger logger = null;
52  	private Module module = null;
53  	private Input input = null;
54      private StatusModel status = null;
55  
56  	private boolean cancelled = false;
57  
58  	/***
59  	 * Constructs a module runner.
60  	 * 
61  	 * @param logger
62  	 * @param status
63  	 * @param result
64  	 * @param input
65  	 * @param module
66  	 */
67  	public ModuleThread( Logger logger, StatusModel status, ResultModel result, Input input, Module module) {
68  		listeners = new EventListenerList();
69  
70          this.module = module;
71  		this.logger = logger;
72  		this.input = input;
73  		this.result = result;
74          this.status = status;
75          
76  //        setPriority( MIN_PRIORITY);
77  	}
78  
79  	private List<URI> getURIs() {
80  		if (input.getFilter() != null) {
81  			return getURIs(input.getFilter());
82  		}
83  
84          return getURIs(input.getSourceOrSourceAndResult());
85  	}
86  
87      @Override
88  	public void run() {
89          if (status != null) {
90              status.reset();
91          }
92          
93          fireThreadStarted();
94  
95          try {
96              if (status != null) {
97                  status.setStatus( "Resolving URIs ...");
98              }
99  			List<URI> uris = getURIs();
100 
101             long time = System.currentTimeMillis();
102             
103             for ( int i = 0; !cancelled && i < uris.size(); i++) {
104                 URI sourceURI = uris.get(i);
105 
106                 if (module.isResultEnabled()) {
107     				if (status != null) {
108                         status.setProgress((i/2)+1, uris.size()/2);
109                         status.setStatus( "Processing "+URIUtils.getName(sourceURI)+" ...");
110                     }
111                     
112                     i++;
113                     
114                     URI resultURI = uris.get(i);
115                     
116     				module.execute(status, result, sourceURI, resultURI);
117                 } else {
118                     if (status != null) {
119                         status.setProgress( i+1, uris.size());
120                         status.setStatus( "Processing "+URIUtils.getName(sourceURI)+" ...");
121                     }
122                     
123                     module.execute(status, result, sourceURI);
124                 }
125 			}
126             
127             
128             if (cancelled && status != null) {
129                 status.setStatus( "Cancelled");
130             } else {
131                 time = System.currentTimeMillis() - time;
132                 
133                 if ( time > 60000) {
134                     long seconds = time/1000;
135                     long minutes = seconds/60;
136                     seconds = seconds - (minutes * 60);
137                     logger.info( "Total time: "+minutes+" minutes "+seconds+" seconds");
138                     
139                     if (status != null) {
140                         status.setStatus( "Done ("+minutes+" minutes "+seconds+" seconds)");
141                     }
142                 } else if ( time > 1000) {
143                     logger.info( "Total time: "+time/1000+" seconds");
144 
145                     if (status != null) {
146                         status.setStatus( "Done ("+time/1000+" seconds)");
147                     }
148                 } else {
149                     logger.info( "Total time: "+time+" milliseconds");
150 
151                     if (status != null) {
152                         status.setStatus( "Done ("+time+" milliseconds)");
153                     }
154                 }
155             }
156 
157 		} catch ( Exception e) {
158             if (status != null) {
159                 status.setStatus("Execution Error");
160             }
161             
162 			logger.error("Module Execution Error", e);
163 		} finally {
164             fireThreadFinished();
165         }
166 	}
167 
168 	public synchronized void cancel() {
169 		cancelled = true;
170 	}
171 	
172 	private List<URI> getURIs( List<Document> list) {
173 		ArrayList<URI> uris = new ArrayList<URI>();
174 		
175 		for ( Document document : list) {
176 			uris.add( URIUtils.createURI(document.getSrc()));
177 		}
178 		
179 		return uris;
180 	}
181 
182 	private List<URI> getURIs(Filter filter) {
183 		ArrayList<URI> uris = new ArrayList<URI>();
184 		FileFilter fileFilter = null;
185 
186 		String expression = filter.getPattern();
187 
188 		if (filter.isRegex()) {
189 			fileFilter = new RegexNameFileFilter(expression);
190 		} else {
191 			fileFilter = new WildcardFileFilter(expression);
192 		}
193 
194         URI uri = URIUtils.createURI(filter.getDir());
195         File file = null;
196         
197         if (uri.isAbsolute()) {
198             file = URIUtils.toFile(uri);
199         }
200 
201 		if ( file != null) {
202             if (!file.exists()) {
203                 throw new IllegalArgumentException("Filter directory \""+file.toString()+"\" does not exist!");
204             }
205             
206 			addURIs(uris, filter, file, fileFilter, filter.isIncludeSubdirectories());
207 		}
208 
209 		return uris;
210 	}
211 
212 	private void addURIs(ArrayList<URI> uris, Filter filter, File dir, FileFilter fileFilter, boolean subdirs) {
213         if (cancelled) {
214             return;
215         }
216 
217         for (File file : dir.listFiles( fileFilter)) {
218 			if (cancelled) {
219 				return;
220 			}
221 
222             addURI(uris, filter, file);
223 		}
224 
225 		if (subdirs) {
226 			for (File file : dir.listFiles()) {
227 				if (file.isDirectory()) {
228 					addURIs(uris, filter, file, fileFilter, subdirs);
229 				}
230 			}
231 		}
232 	}
233     
234     private void addURI(ArrayList<URI> uris, Filter filter, File inputFile) {
235         uris.add(inputFile.toURI());
236 
237         if (module.isResultEnabled()) {
238             URI inputURI = URIUtils.createURI(filter.getDir());
239             File inputDir = null;
240             File outputDir = null;
241             
242             if (inputURI.isAbsolute()) {
243                 inputDir = new File(inputURI);
244             }
245 
246             URI uri = URIUtils.createURI(filter.getOutDir());
247             
248             if (uri.isAbsolute()) {
249                 outputDir = new File(uri);
250             }
251 
252             if (outputDir == null) {
253                 outputDir = inputDir;
254             }
255 
256             if (outputDir != null) {
257                 if (!outputDir.exists()) {
258                     throw new IllegalArgumentException("Filter output directory \""+outputDir.toString()+"\" does not exist!");
259                 }
260 
261                 String f1 = inputFile.toString();
262                 f1 = f1.substring(inputDir.toString().length()+1);
263                 
264                 if (filter.getExtension() != null && filter.getExtension().trim().length() > 0) {
265                     int dotIndex = f1.lastIndexOf('.');
266                     
267                     if (dotIndex > 0) {
268                         f1 = f1.substring(0, f1.lastIndexOf('.'));
269                     }
270 
271                     f1 = f1 + "." + filter.getExtension();
272                 }
273                 
274                 File outputFile = new File(outputDir, f1);
275                 uris.add(outputFile.toURI());
276             }
277         }
278     }
279 
280 	private class RegexNameFileFilter implements FileFilter {
281 		private Pattern pattern = null;
282 
283 		public RegexNameFileFilter( String pattern) {
284 			this.pattern = Pattern.compile( pattern);
285 		}
286 
287 		/*
288 		 * (non-Javadoc)
289 		 * 
290 		 * @see java.io.FileFilter#accept(java.io.File)
291 		 */
292 		public boolean accept( File pathname) {
293 			if ( pathname != null && pathname.isFile()) {
294 				String name = pathname.getName();
295 				Matcher matcher = pattern.matcher( name);
296 				return matcher.matches();
297 			}
298 
299 			return false;
300 		}
301 	}
302 	
303 	/*** 
304 	 * Notifies the listeners about the deletion of this document.
305 	 */
306 	protected void fireThreadFinished() {
307 		// Guaranteed to return a non-null array
308 		Object[] list = listeners.getListenerList();
309 		
310 		// Process the listeners last to first, notifying
311 		// those that are interested in this event
312 		for ( int i = list.length-2; i >= 0; i -= 2) {
313 		    if ( list[i] == ModuleThreadListener.class) {
314 				((ModuleThreadListener)list[i+1]).threadFinished( this);
315 		    }
316 		}
317 	}
318 
319     protected void fireThreadStarted() {
320         // Guaranteed to return a non-null array
321         Object[] list = listeners.getListenerList();
322         
323         // Process the listeners last to first, notifying
324         // those that are interested in this event
325         for ( int i = list.length-2; i >= 0; i -= 2) {
326             if ( list[i] == ModuleThreadListener.class) {
327                 ((ModuleThreadListener)list[i+1]).threadStarted( this);
328             }
329         }
330     }
331 
332     /***
333 	 * Adds a thread listener to the module. 
334 	 */	
335 	public void addListener( ModuleThreadListener listener) {
336 		listeners.add( ModuleThreadListener.class, listener);
337 	}
338 
339 	/***
340 	 * Removes a thread listener from the module. 
341 	 */	
342 	public void removeListener( ModuleThreadListener listener) {
343 		listeners.remove( ModuleThreadListener.class, listener);
344 	}
345 }