diff -r ed1c9f64298a -r 5b9d4d8641ce trace/traceviewer/com.nokia.traceviewer/src/com/nokia/traceviewer/action/ReloadDecodeFilesAction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trace/traceviewer/com.nokia.traceviewer/src/com/nokia/traceviewer/action/ReloadDecodeFilesAction.java Wed Jun 23 14:49:59 2010 +0300 @@ -0,0 +1,405 @@ +/* + * Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies). + * All rights reserved. + * This component and the accompanying materials are made available + * under the terms of "Eclipse Public License v1.0" + * which accompanies this distribution, and is available + * at the URL "http://www.eclipse.org/legal/epl-v10.html". + * + * Initial Contributors: + * Nokia Corporation - initial contribution. + * + * Contributors: + * + * Description: + * + * Reload changed decode files Action + * + */ +package com.nokia.traceviewer.action; + +import java.io.File; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Timer; +import java.util.TimerTask; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.ui.PlatformUI; + +import com.nokia.traceviewer.TraceViewerPlugin; +import com.nokia.traceviewer.engine.TraceViewerGlobals; +import com.nokia.traceviewer.engine.TraceViewerUtils; +import com.nokia.traceviewer.engine.activation.TraceActivationComponentItem; +import com.nokia.traceviewer.engine.preferences.PreferenceConstants; + +/** + * Reload changed decode files Action + */ +public final class ReloadDecodeFilesAction extends TraceViewerAction { + + /** + * Maximum number of times to try to open the decode file + */ + private static final int MAX_TRIES = 5; + + /** + * Polling interval in milliseconds + */ + private static final int POLLING_INTERVAL = 4000; + + /** + * Waiting time for model to be loaded + */ + private static final int WAITING_TIME = 50; + + /** + * Empty image + */ + private static ImageDescriptor emptyImage; + + /** + * Exclamation image + */ + private static ImageDescriptor exclamationImage; + + /** + * Timer to use to check the files + */ + private Timer timer; + + /** + * Map of component items and last modified times to watch in case of + * changes + */ + private volatile Map files; + + /** + * Changed components + */ + private final List changedComponents; + + /** + * List of missing dictionaries so we only inform about disappearance once + */ + private final List missingDictionaries; + + /** + * Empty String + */ + private static final String EMPTY = ""; //$NON-NLS-1$ + + /** + * Number of times we have tried to open decode file + */ + private int triesToOpenDecodeFile; + + /** + * Category for events + */ + private final static String EVENT_CATEGORY = Messages + .getString("ReloadDecodeFilesAction.DictionaryReloaderCategory"); //$NON-NLS-1$ + + static { + URL url = null; + URL url2 = null; + url = TraceViewerPlugin.getDefault().getBundle().getEntry( + "/icons/empty.gif"); //$NON-NLS-1$ + emptyImage = ImageDescriptor.createFromURL(url); + url2 = TraceViewerPlugin.getDefault().getBundle().getEntry( + "/icons/exclamation.gif"); //$NON-NLS-1$ + exclamationImage = ImageDescriptor.createFromURL(url2); + } + + /** + * Constructor + */ + ReloadDecodeFilesAction() { + files = new HashMap(); + changedComponents = new ArrayList(); + missingDictionaries = new ArrayList(); + changeToEmptyImage(); + } + + /* + * (non-Javadoc) + * + * @see com.nokia.traceviewer.action.TraceViewerAction#doRun() + */ + @Override + protected void doRun() { + TraceViewerGlobals.postUiEvent("ReloadDecodeFilesButton", "1"); //$NON-NLS-1$ //$NON-NLS-2$ + + reloadFiles(true); + + // Change back to empty image + changeToEmptyImage(); + TraceViewerGlobals.postUiEvent("ReloadDecodeFilesButton", "0"); //$NON-NLS-1$ //$NON-NLS-2$ + } + + /** + * Reload files + * + * @param showProgressBar + * if true, show progressbar while reloading + */ + private void reloadFiles(boolean showProgressBar) { + + // Start copying the files from the array + List filesToLoad = new ArrayList(); + + // Copy the files from the map to a String array and remove components + // from the model + for (int i = 0; i < changedComponents.size(); i++) { + TraceActivationComponentItem comp = changedComponents.get(i); + File file = new File(comp.getFilePath()); + + if (file.exists()) { + filesToLoad.add(file.getAbsolutePath()); + + // Remove component from the model + TraceViewerGlobals.getDecodeProvider() + .removeComponentFromModel(comp.getId()); + + // Insert info about reloading to trace events + String msg = Messages + .getString("ReloadDecodeFilesAction.ReloadDescriptionMsg"); //$NON-NLS-1$ + + msg += TraceViewerUtils.constructTimeString(); + TraceViewerGlobals.postInfoEvent(msg, EVENT_CATEGORY, file + .getAbsolutePath()); + + // File doesn't exist + } else { + // Insert info about disappeared Dictionary + String msg = Messages + .getString("ReloadDecodeFilesAction.DictionaryDisappearedMsg"); //$NON-NLS-1$ + + TraceViewerGlobals.postInfoEvent(msg, EVENT_CATEGORY, file + .getAbsolutePath()); + } + } + + changedComponents.clear(); + + // Show progressbar + if (showProgressBar) { + + // Load the new files + OpenDecodeFileAction openAction = (OpenDecodeFileAction) TraceViewerGlobals + .getTraceViewer().getView().getActionFactory() + .getOpenDecodeFileAction(); + openAction.loadFilesToModel(getStringArrayFromList(filesToLoad), + false); + + // Don't show progressbar + } else { + + // Go through the files + for (int i = 0; i < filesToLoad.size(); i++) { + + // Open the decode file + TraceViewerGlobals.getDecodeProvider().openDecodeFile( + filesToLoad.get(i), null, false); + } + updateFilesToBeWatched(); + + } + } + + /** + * Changes image to empty + */ + private void changeToEmptyImage() { + setImageDescriptor(emptyImage); + setText(EMPTY); + setToolTipText(EMPTY); + setEnabled(false); + } + + /** + * Changes image to exclamation + */ + private void changeToExclamationImage() { + setImageDescriptor(exclamationImage); + setText(Messages.getString("ReloadDecodeFilesAction.Title")); //$NON-NLS-1$ + setToolTipText(Messages.getString("ReloadDecodeFilesAction.Tooltip")); //$NON-NLS-1$ + setEnabled(true); + } + + /** + * Update files to be watched from the model + */ + public void updateFilesToBeWatched() { + try { + if (timer == null) { + + // Create the timer as a daemon + timer = new Timer(true); + timer.schedule(new FileMonitorNotifier(), POLLING_INTERVAL, + POLLING_INTERVAL); + } + + // Remove old watched files + files.clear(); + + // Wait for a while + Thread.sleep(WAITING_TIME); + + List components = TraceViewerGlobals + .getDecodeProvider().getActivationInformation(false); + + // Add files to the list. If they already exist, update + for (int i = 0; i < components.size(); i++) { + TraceActivationComponentItem comp = components.get(i); + File file = new File(comp.getFilePath()); + if (file.exists()) { + files.put(comp, Long.valueOf((file.lastModified()))); + } else { + files.put(comp, Long.valueOf(-1)); + } + } + + // Set activation dialog to changed + TraceActivationAction activationAction = (TraceActivationAction) TraceViewerGlobals + .getTraceViewer().getView().getActionFactory() + .getTraceActivationAction(); + if (activationAction.getDialog() != null) { + activationAction.getDialog().setModelChanged(true); + } + triesToOpenDecodeFile = 0; + + } catch (Exception e) { + e.printStackTrace(); + + // Something went wrong, try again + if (triesToOpenDecodeFile < MAX_TRIES) { + triesToOpenDecodeFile++; + updateFilesToBeWatched(); + } else { + triesToOpenDecodeFile = 0; + } + } + } + + /** + * Stops file monitor + */ + public void stopFileMonitor() { + if (timer != null) { + timer.cancel(); + } + } + + /** + * This is the timer thread which is executed every n milliseconds according + * to the setting of the file monitor. It investigates the file in question + * and notify listeners if changed. + * + */ + private class FileMonitorNotifier extends TimerTask { + + /* + * (non-Javadoc) + * + * @see java.util.TimerTask#run() + */ + @Override + public void run() { + + // Check if Dictionaries should be auto-reloaded + boolean autoReload = TraceViewerPlugin + .getDefault() + .getPreferenceStore() + .getBoolean( + PreferenceConstants.AUTO_RELOAD_DICTIONARIES_CHECKBOX); + + // Loop over the registered files and see which have changed. + for (Iterator i = files.keySet() + .iterator(); i.hasNext();) { + TraceActivationComponentItem comp = i.next(); + File file = new File(comp.getFilePath()); + String filePath = file.getAbsolutePath(); + long lastModifiedTime = files.get(comp).longValue(); + boolean fileExists = false; + boolean fileMissingForTheFirstTime = false; + + long newModifiedTime = -1; + if (file.exists()) { + fileExists = true; + newModifiedTime = file.lastModified(); + + // If file was previously missing, remove it from the + // missing list + if (missingDictionaries.contains(filePath)) { + missingDictionaries.remove(filePath); + } + + // File doesn't exist and it's not yet added to the missing + // Dictionaries list + } else { + if (!missingDictionaries.contains(filePath)) { + missingDictionaries.add(filePath); + fileMissingForTheFirstTime = true; + } + } + + // Check if file has changed + if (newModifiedTime != lastModifiedTime) { + + if (!autoReload && fileExists) { + changeToExclamationImage(); + } + + // File exists or file is missing for the first time and we + // are using Auto-reload, let's add the component to changed + // list + if (fileExists + || (autoReload && fileMissingForTheFirstTime)) { + + // Add to changed components + if (!changedComponents.contains(comp)) { + changedComponents.add(comp); + } + + } + } + } + + // Reload automatically. Must be synced with UI thread + if (autoReload && !changedComponents.isEmpty()) { + PlatformUI.getWorkbench().getDisplay().asyncExec( + new Runnable() { + public void run() { + + // Re-check to be sure + if (!changedComponents.isEmpty()) { + reloadFiles(false); + } + } + }); + } + } + } + + /** + * Gets string array from list + * + * @param list + * list + * @return string array + */ + private String[] getStringArrayFromList(List list) { + String[] arr = new String[list.size()]; + + for (int i = 0; i < arr.length; i++) { + arr[i] = list.get(i); + } + + return arr; + } +} \ No newline at end of file