View Javadoc

1   /*
2    * $HeadURL: $
3    * $Date: $
4    * $Revision: $
5    * $Author: $
6    * 
7    * Copyright (c) 2005 MindTree Consulting Ltd. 
8    * 
9    * This file is part of Insight.
10   * 
11   * Insight is free software: you can redistribute it and/or modify it under the 
12   * terms of the GNU General Public License as published by the Free Software 
13   * Foundation, either version 3 of the License, or (at your option) any later 
14   * version.
15   * 
16   * Insight is distributed in the hope that it will be useful, but 
17   * WITHOUT ANY WARRANTY; without even the implied warranty of 
18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General 
19   * Public License for more details.
20   * 
21   * You should have received a copy of the GNU General Public License along with 
22   * Insight.  If not, see <http://www.gnu.org/licenses/>.
23   */
24  package com.mindtree.techworks.insight.gui.action;
25  
26  import java.awt.event.ActionEvent;
27  import java.io.File;
28  import java.net.InetAddress;
29  import java.net.UnknownHostException;
30  import java.util.LinkedList;
31  import java.util.ArrayList;
32  import java.util.List;
33  
34  import javax.swing.AbstractAction;
35  import javax.swing.JFileChooser;
36  import javax.swing.JOptionPane;
37  
38  import com.mindtree.techworks.insight.InsightConstants;
39  import com.mindtree.techworks.insight.appender.ParsedEventAppender;
40  import com.mindtree.techworks.insight.gui.Insight;
41  import com.mindtree.techworks.insight.gui.widgets.StatusBar;
42  import com.mindtree.techworks.insight.model.ReceiverFormat;
43  import com.mindtree.techworks.insight.preferences.util.Log4JPatternInterpeter;
44  import com.mindtree.techworks.insight.preferences.util.PreferenceInterpreter;
45  import com.mindtree.techworks.insight.receiver.AbstractReceiver;
46  import com.mindtree.techworks.insight.receiver.FileStreamReceiver;
47  import com.mindtree.techworks.insight.receiver.ReceiverInitializationException;
48  import com.mindtree.techworks.insight.receiver.ReceiverInterpreter;
49  import com.mindtree.techworks.insight.receiver.ReceiverListener;
50  import com.mindtree.techworks.insight.receiver.RuntimeNamespaceContainer;
51  import com.mindtree.techworks.insight.receiver.WildCardMatcher;
52  import com.mindtree.techworks.insight.spi.LogNamespace;
53  
54  /**
55  *
56  * The <code>LoadLocalFileAction</code> class is an AbstractAction derivative that
57  * provides ability to load files from the local or mounted file systems.
58  * Provide a file chooser that may be used to load log files into the Insight.
59  *
60  * @author  Regunath B
61  * @version 1.0, 04/10/25
62  * @see     com.mindtree.techworks.insight.gui.Insight
63  */
64  
65  public class LoadLocalFileAction extends AbstractAction implements ReceiverListener {
66  	
67  	/**
68  	 * UID for the serialized form
69  	 */
70  	private static final long serialVersionUID = -6169872455620799521L;
71  
72  	/**
73  	 * Singleton instance of this class
74  	 */
75  	private static LoadLocalFileAction instance;
76  	
77  	/**
78  	 * FIFO LinkedList containing the namespaces that need to be loaded one after the other completes
79  	 */
80  	private LinkedList namespacesToBeLoaded = new LinkedList();		
81  	
82  	/**
83  	 * The AbstractReceiver instance, if any
84  	 */
85  	private AbstractReceiver receiver;
86  
87  	/**
88  	 * The file chooser used for allowing users to pick a file from local and
89  	 * mounted file systems
90  	 * 
91  	 */
92  	private final JFileChooser fileChooser = new JFileChooser(System.getProperty(InsightConstants.INSIGHT_HOME));    {
93      	fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
94      	fileChooser.setMultiSelectionEnabled(true);
95      }
96  
97  	/**
98  	 * The Insight instance that created this Action class
99  	 */
100 	private Insight insight;
101 	
102 	/**
103 	 * Constructor for this class. Made private to prevent multiple instances.
104 	 * Use @see#getInstance() to obtain instance of this class
105 	 */
106 	private LoadLocalFileAction() {
107 		// do nothing
108 	}
109 	
110 	/**
111 	 * Accessor method to obtain instance of this class
112 	 * @return singleton instance of this class
113 	 */
114 	public static synchronized final LoadLocalFileAction getInstance() {
115 		if (instance == null) {
116 			instance = new LoadLocalFileAction();
117 		}
118 		return instance;
119 	}
120 
121 	/**
122 	 * Initializes this LoadFileAction the first time.
123 	 * Subsequent calls are ignored
124 	 * @param insightInstance the Insight that created an instance of this class
125 	 */
126 	public void initialize(Insight insightInstance) {
127 		if (this.insight == null) {
128 			this.insight = insightInstance;
129 		}
130 		RuntimeNamespaceContainer.initializeAvailableNamespaceColorList();
131 	}
132 
133 	/**
134 	 * Overriden super class method
135 	 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
136 	 */
137 	public void actionPerformed(ActionEvent e) {
138 		browseAndLoadLocalFiles();
139 	}
140 	
141 	/**
142 	 * Starts up the Receiver with the specified parameters
143 	 * @param namespace the LogNamespace for load
144 	 */
145 	public void startupReceiver(LogNamespace namespace) {
146 		boolean isReceiverTailing = PreferenceInterpreter.getTailingStatus();
147 		// Set tailing to true only if its is a local file and tailing has been
148 		// enabled in preferences
149 		try {
150 			boolean isLocalNamespace = (namespace.getNodeId().equalsIgnoreCase(InetAddress.getLocalHost().getHostName()));
151 			isReceiverTailing = isReceiverTailing && isLocalNamespace;
152 		} catch(UnknownHostException uhe) {
153 			// do nothing
154 		}
155 		if (RuntimeNamespaceContainer.getLoadedNamespaces().contains(namespace)) {
156 			StatusBar.getInstance().setDisplayText(0,InsightConstants.getLiteral("FILE_ALREADY_LOADED"), false);
157 			//This is the method added for analyzing the wild cards.
158 			analyzeWildCardEntries(namespacesToBeLoaded);
159 			loadNextAvailableNamespace();
160 			return;
161 		}
162 		StatusBar.getInstance().clearDisplay(0);			
163 		StatusBar.getInstance().setDisplayText(1,InsightConstants.getLiteral("LOAD_FILE_STATUS") + namespace.getNamespaceAsString(), true);
164 		try{
165 			this.receiver = new FileStreamReceiver(namespace, isReceiverTailing);
166 		}catch(ReceiverInitializationException rie){
167 			StatusBar.getInstance().setDisplayText(1,rie.getMessage(),false);
168 			return;
169 		}
170 		this.receiver.addAppender(ParsedEventAppender.getInstance(this.insight.getController()));
171 		this.receiver.addReceiverListener(this);
172 		this.receiver.addMutatorListener(this.insight.getController());
173 		this.receiver.addMutatorListener(this.insight.getController().getCurrentLogEventModel().getPageSet());
174 		this.receiver.startup();
175 	}
176 
177 	/**
178 	 * ReceiverListener interface method implementation.
179 	 * @see ReceiverListener#startLoadEventNotification(LogNamespace[])
180 	 */
181 	public void startLoadEventNotification(LogNamespace[] namespaces) {
182 		// do nothing because the isActive status is proactivley set in startupReceiver already
183 	}
184 
185 	/**
186 	 * ReceiverListener interface method implementation.
187 	 * @see ReceiverListener#endLoadEventNotification(LogNamespace[], int)
188 	 */
189 	public void endLoadEventNotification(LogNamespace[] namespaces, int infoFlag) {
190 		StatusBar.getInstance().clearDisplay(1);
191 		if (infoFlag == ReceiverInterpreter.SUCCESS) {
192 			for (int i = 0; i < namespaces.length; i++ ) {
193 				RuntimeNamespaceContainer.getLoadedNamespaces().add(namespaces[i]);
194 			}
195 //			RuntimeNamespaceContainer.getLoadedNamespaces().add(namespace);
196 		} else {
197 			StringBuffer namespaceNames = new StringBuffer();
198 			for (int i = 0; i < namespaces.length; i++ ) {
199 				namespaceNames.append(namespaces[i].getNamespaceAsString());
200 				if ((i + 1) < namespaces.length) {
201 					namespaceNames.append(", ");
202 				}
203 			}
204 			 JOptionPane.showMessageDialog(insight, InsightConstants.getLiteral("ERROR_NO_MATCHING_ENTRIES") +  "\n" + namespaceNames.toString(), 
205 			 		InsightConstants.getLiteral("ERROR"), JOptionPane.ERROR_MESSAGE);
206 		}
207 		
208 		analyzeWildCardEntries(namespacesToBeLoaded);
209 		// load next available namespace, if any, and if they had been selected in multiples
210 		loadNextAvailableNamespace();
211 	}	
212 	
213 	/**
214 	 * Adds the specified LogNamespace for load
215 	 * @param namespace the LogNamespace for load
216 	 */
217 	public void addNamespaceForLoad(LogNamespace namespace) {
218 		this.namespacesToBeLoaded.addLast(namespace);
219 	}
220 	
221 	/**
222 	 * Loads the LogNamespace(s) that have been added for load
223 	 * @see #addNamespaceForLoad(LogNamespace)
224 	 */
225 	public void loadNamespaces() {
226 		analyzeWildCardEntries(namespacesToBeLoaded);
227 		loadNextAvailableNamespace();
228 	}
229 	
230 	/**
231 	 * Displays a JFileChooser for loacl and mounted file systems.
232 	 * The selected files are loaded into Insight.
233 	 */
234 	public void browseAndLoadLocalFiles() {
235 		// clear the LinkedList before populating files to be loaded
236 		this.namespacesToBeLoaded.clear();
237 		String nodeId = null;
238 		ReceiverFormat[] receiverFormat = Log4JPatternInterpeter.getInterpretedRecieverFormat();
239 		try {
240 			nodeId = InetAddress.getLocalHost().getHostName();
241 		} catch(UnknownHostException uhe) {
242 			uhe.printStackTrace();
243 		}
244 		fileChooser.setMultiSelectionEnabled(!PreferenceInterpreter.getTailingStatus());
245         if (fileChooser.showOpenDialog(insight) == JFileChooser.APPROVE_OPTION) {
246         	if(!fileChooser.isMultiSelectionEnabled()){
247                 //In Case when Multiselection is not enabled then JFileChooser#getSelectedFile() gives the 
248             	// absolute path of selected file.
249         		String fileAbsPath = fileChooser.getSelectedFile().getAbsolutePath();
250         		//  add files to the last to enable FIFO when they are processed
251         		this.namespacesToBeLoaded.addLast(new LogNamespace(fileAbsPath,InsightConstants.FILE_PROTOCOL_PREFIX+fileAbsPath,receiverFormat,nodeId));
252             }else{
253                 //In Case when Multiselection is enabled then JFileChooser#getSelectedFiles() gives the 
254             	// array of selected files.
255             	File[] chosenFiles = fileChooser.getSelectedFiles();
256 	            for (int i = 0; i < chosenFiles.length; i++) {
257 	            	// add files to the last to enable FIFO when they are processed
258 	            	this.namespacesToBeLoaded.addLast(new LogNamespace(chosenFiles[i].getAbsolutePath(), 
259 	            			InsightConstants.FILE_PROTOCOL_PREFIX + chosenFiles[i].getAbsolutePath(), 
260 	            			receiverFormat, nodeId));
261 	            }
262             	
263             }
264         	analyzeWildCardEntries(namespacesToBeLoaded);
265             loadNextAvailableNamespace();
266         }		
267 	}
268 	/**
269 	 * Launches insight with  the log file passed. 
270 	 * @param fileName - log file's absolute path.
271 	 */
272 	public void LoadOnFileSelection(String fileName) {
273 		String nodeId = null;
274 		ReceiverFormat[] receiverFormat = Log4JPatternInterpeter.getInterpretedRecieverFormat();
275 		try {
276 			nodeId = InetAddress.getLocalHost().getHostName();
277 		} catch(UnknownHostException uhe) {
278 			uhe.printStackTrace();
279 		}
280 		String fileAbsPath = fileName;
281 		this.namespacesToBeLoaded.addLast(new LogNamespace(fileAbsPath,InsightConstants.FILE_PROTOCOL_PREFIX+fileAbsPath,receiverFormat,nodeId));
282 		analyzeWildCardEntries(namespacesToBeLoaded);
283         loadNextAvailableNamespace();
284 	}
285 	/**
286 	 * Helper method that loads the next available namespace, if any.
287 	 */
288 	private final void loadNextAvailableNamespace() {
289 		if (namespacesToBeLoaded.size() == 0) {
290 			return;
291 		}
292 		// Process namespaces in FIFO form
293 		LogNamespace nextNamespace = (LogNamespace)namespacesToBeLoaded.removeFirst();
294     	startupReceiver(nextNamespace);		
295 	}
296 	
297 	/**
298 	 * Analyzes the wild cards and converts them into full text paths in the given namespace's list.
299 	 * @param namespacesToBeLoaded	The list of namespaces
300 	 */
301 	private void analyzeWildCardEntries(LinkedList namespacesToBeLoaded){
302 		
303 		List namespacesList = new ArrayList(10);
304 		
305 		for(int i = 0; i < namespacesToBeLoaded.size(); i++){
306 		
307 			String filePath = ((LogNamespace)(namespacesToBeLoaded.get(i))).getSourceString();
308 			//Checks for the last file separator and extracts the file name
309 			int lastFileSeparatorIndex = (filePath.lastIndexOf(File.separatorChar));
310 			String fileName = filePath.substring(lastFileSeparatorIndex + 1);
311 			String parentDirectoryPath = filePath.substring(0, lastFileSeparatorIndex);
312 			//Supports only the wild card '*'
313 			if(WildCardMatcher.hasWildCardEntries(fileName)){
314 				String wildCard = fileName;
315 				File parentDirectory = new File(parentDirectoryPath);
316 				if(parentDirectory.isDirectory()){
317 					//Takes the wild card entry and returns the matching files
318 					List matchingFiles = getMatchingFiles(parentDirectory, wildCard);
319 					for(int j = 0; j < matchingFiles.size(); j++){
320 						LogNamespace thisNamespace = (LogNamespace)namespacesToBeLoaded.get(i);
321 						String newFilePath = ((File)(matchingFiles.get(j))).getAbsolutePath();
322 						String newFileLocalPath = InsightConstants.FILE_PROTOCOL_PREFIX + newFilePath;
323 						namespacesList.add(new LogNamespace(newFilePath, newFileLocalPath, thisNamespace.getReceiverFormat(), thisNamespace.getNodeId()));
324 					}
325 					namespacesToBeLoaded.remove(i);
326 				}
327 			}
328 		}
329 		for(int i = 0; i < namespacesList.size(); i++){
330 			namespacesToBeLoaded.addFirst((LogNamespace)namespacesList.get(i));
331 		}
332 	}
333 	
334 	/**
335 	 * Matches all the files in the directory (parentDirectory) with the given
336 	 *  pattern and returns all the matching files as a vector.
337 	 * @param parentDirectory	The directory from which the file list has to be taken.
338 	 * @param pattern	The wild card pattern.
339 	 * @return	A vector of matching files.
340 	 */
341 	private List getMatchingFiles(File parentDirectory, String pattern){
342 		//Vector for storing all the file paths matching the given pattern
343 		List filesList = new ArrayList(parentDirectory.listFiles().length); 
344 		File[] files = parentDirectory.listFiles();
345 		
346 		for(int i = 0; i < files.length; i++){
347 			if(files[i].isDirectory()){
348 				//Uncomment this for support of nested directories.
349 				//getMatchingFiles(files[i], pattern);
350 			}
351 			else{
352 				String filePath = files[i].getAbsolutePath();
353 				String fileName = filePath.substring(filePath.lastIndexOf('/') == -1 ? filePath.lastIndexOf('\\') + 1 : filePath.lastIndexOf('/') + 1);
354 				WildCardMatcher matcher = new WildCardMatcher(pattern);
355 				if(matcher.matches(fileName)){
356 					filesList.add(files[i]);
357 				}
358 				else{
359 				}
360 			}
361 		}
362 		return filesList;
363 	}
364 
365 	/**
366 	 * Returns the currently active AbstractReceiver, if any, or null otherwise
367 	 * @return Returns null or the receiver.
368 	 */
369 	public AbstractReceiver getReceiver() {
370 		return receiver;
371 	}
372 }