diff --git a/bundles/org.eclipse.rap.pde.runtime/META-INF/MANIFEST.MF b/bundles/org.eclipse.rap.pde.runtime/META-INF/MANIFEST.MF
index 68dff1c..0f647f3 100644
--- a/bundles/org.eclipse.rap.pde.runtime/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.rap.pde.runtime/META-INF/MANIFEST.MF
@@ -1,23 +1,23 @@
-Manifest-Version: 1.0
-Bundle-ManifestVersion: 2
-Bundle-Name: %name
-Bundle-SymbolicName: org.eclipse.rap.pde.runtime;singleton:=true
-Bundle-Version: 0.1.0.qualifier
-Bundle-Activator: org.eclipse.pde.internal.runtime.PDERuntimePlugin
-Bundle-Vendor: %provider-name
-Bundle-Localization: plugin
-Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.2.0,4.0.0)",
- org.eclipse.help;bundle-version="[3.3.0,4.0.0)";resolution:=optional,
- org.eclipse.rap.ui;bundle-version="[2.0.0,3.0.0)",
- org.eclipse.rap.ui.forms;bundle-version="[2.0.0,3.0.0)",
- org.eclipse.rap.rwt.supplemental.filedialog;bundle-version="[1.5.100,3.0.0)"
-Eclipse-LazyStart: true
-Export-Package: org.eclipse.pde.internal.runtime;x-internal:=true,
- org.eclipse.pde.internal.runtime.registry;x-internal:=true,
- org.eclipse.pde.internal.runtime.registry.model;x-internal:=true,
- org.eclipse.pde.internal.runtime.spy;x-internal:=true,
- org.eclipse.pde.internal.runtime.spy.dialogs;x-internal:=true,
- org.eclipse.pde.internal.runtime.spy.handlers;x-internal:=true,
- org.eclipse.pde.internal.runtime.spy.sections;x-internal:=true
-Bundle-RequiredExecutionEnvironment: JavaSE-1.6
-Bundle-ActivationPolicy: lazy
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %name
+Bundle-SymbolicName: org.eclipse.rap.pde.runtime;singleton:=true
+Bundle-Version: 0.1.0.qualifier
+Bundle-Activator: org.eclipse.pde.internal.runtime.PDERuntimePlugin
+Bundle-Vendor: %provider-name
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.2.0,4.0.0)",
+ org.eclipse.help;bundle-version="[3.3.0,4.0.0)";resolution:=optional,
+ org.eclipse.rap.ui;bundle-version="[2.0.0,3.0.0)",
+ org.eclipse.rap.ui.forms;bundle-version="[2.0.0,3.0.0)",
+ org.eclipse.rap.addons.filedialog;bundle-version="[0.5.0,1.0.0)"
+Eclipse-LazyStart: true
+Export-Package: org.eclipse.pde.internal.runtime;x-internal:=true,
+ org.eclipse.pde.internal.runtime.registry;x-internal:=true,
+ org.eclipse.pde.internal.runtime.registry.model;x-internal:=true,
+ org.eclipse.pde.internal.runtime.spy;x-internal:=true,
+ org.eclipse.pde.internal.runtime.spy.dialogs;x-internal:=true,
+ org.eclipse.pde.internal.runtime.spy.handlers;x-internal:=true,
+ org.eclipse.pde.internal.runtime.spy.sections;x-internal:=true
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Bundle-ActivationPolicy: lazy
diff --git a/bundles/org.eclipse.rap.pde.runtime/src/org/eclipse/pde/internal/runtime/spy/SpyFormToolkit.java b/bundles/org.eclipse.rap.pde.runtime/src/org/eclipse/pde/internal/runtime/spy/SpyFormToolkit.java
index 23be9bf..de060a0 100644
--- a/bundles/org.eclipse.rap.pde.runtime/src/org/eclipse/pde/internal/runtime/spy/SpyFormToolkit.java
+++ b/bundles/org.eclipse.rap.pde.runtime/src/org/eclipse/pde/internal/runtime/spy/SpyFormToolkit.java
@@ -1,324 +1,326 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2013 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     Chris Aniszczyk <zx@us.ibm.com> - initial API and implementation
- *     Willian Mitsuda <wmitsuda@gmail.com> - bug 209841
- *     Benjamin Cabe <benjamin.cabe@anyware-tech.com> - bug 209487
- *     Arnaud Mergey <a_mergey@yahoo.fr>              - RAP port
- *******************************************************************************/
-package org.eclipse.pde.internal.runtime.spy;
-
-import java.util.HashMap;
-import java.util.Map;
-import org.eclipse.help.IContext;
-import org.eclipse.help.internal.context.Context;
-import org.eclipse.jface.action.Action;
-import org.eclipse.jface.action.ToolBarManager;
-import org.eclipse.jface.dialogs.PopupDialog;
-import org.eclipse.osgi.util.NLS;
-import org.eclipse.pde.internal.runtime.*;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.*;
-import org.eclipse.swt.graphics.*;
-import org.eclipse.swt.widgets.*;
-import org.eclipse.ui.forms.events.HyperlinkAdapter;
-import org.eclipse.ui.forms.events.HyperlinkEvent;
-import org.eclipse.ui.forms.widgets.*;
-import org.osgi.framework.Bundle;
-
-
-/**
- * @since 3.4
- */
-public class SpyFormToolkit extends FormToolkit {
-
-  private static final String CLASS_PROTOCOL_PREFIX = "class://"; //$NON-NLS-1$
-  private static final String BUNDLE_PROTOCOL_PREFIX = "bundle://"; //$NON-NLS-1$
-
-  private class SpyHyperlinkAdapter extends HyperlinkAdapter {
-
-    private PopupDialog fDialog;
-
-    public SpyHyperlinkAdapter( PopupDialog dialog ) {
-      this.fDialog = dialog;
-    }
-
-    public void linkActivated( HyperlinkEvent e ) {
-      String href = ( String )e.getHref();
-      if( href.startsWith( CLASS_PROTOCOL_PREFIX ) ) {
-        String clazz = href.substring( CLASS_PROTOCOL_PREFIX.length() );
-        Bundle bundle = ( Bundle )bundleClassByName.get( clazz );
-// SpyIDEUtil.openClass(bundle.getSymbolicName(), clazz);
-        fDialog.close();
-      } else if( href.startsWith( BUNDLE_PROTOCOL_PREFIX ) ) {
-        String bundle = href.substring( BUNDLE_PROTOCOL_PREFIX.length() );
-// / SpyIDEUtil.openBundleManifest(bundle);
-        fDialog.close();
-      }
-    }
-  }
-  private class SaveImageAction extends Action {
-
-    private Image image;
-
-    public SaveImageAction( Image image ) {
-      this.image = image;
-    }
-
-    public void run() {
-      FileDialog fileChooser = new FileDialog( PDERuntimePlugin.getActiveWorkbenchShell(), SWT.SAVE );
-      fileChooser.setFileName( "image" ); //$NON-NLS-1$
-      fileChooser.setFilterExtensions( new String[] {
-        "*.png"} ); //$NON-NLS-1$
-      fileChooser.setFilterNames( new String[] {
-        "PNG (*.png)"} ); //$NON-NLS-1$
-      String filename = fileChooser.open();
-      if( filename == null )
-        return;
-      int filetype = determineFileType( filename );
-      if( filetype == SWT.IMAGE_UNDEFINED ) {
-        return;
-      }
-      ImageLoader loader = new ImageLoader();
-      loader.data = new ImageData[] {
-        image.getImageData()
-      };
-      loader.save( filename, filetype );
-    }
-
-    private int determineFileType( String filename ) {
-      String ext = filename.substring( filename.lastIndexOf( '.' ) + 1 );
-      if( ext.equalsIgnoreCase( "gif" ) ) //$NON-NLS-1$
-        return SWT.IMAGE_GIF;
-      if( ext.equalsIgnoreCase( "ico" ) ) //$NON-NLS-1$
-        return SWT.IMAGE_ICO;
-      if( ext.equalsIgnoreCase( "jpg" ) || ext.equalsIgnoreCase( "jpeg" ) ) //$NON-NLS-1$//$NON-NLS-2$
-        return SWT.IMAGE_JPEG;
-      if( ext.equalsIgnoreCase( "png" ) ) //$NON-NLS-1$
-        return SWT.IMAGE_PNG;
-      return SWT.IMAGE_UNDEFINED;
-    }
-  }
-
-  private Map bundleClassByName = new HashMap();
-  private PopupDialog dialog;
-  private static String HELP_KEY = "org.eclipse.ui.help"; //$NON-NLS-1$
-
-  public SpyFormToolkit( PopupDialog dialog ) {
-    super( Display.getDefault() );
-    this.dialog = dialog;
-  }
-
-  public FormText createFormText( Composite parent, boolean trackFocus ) {
-    FormText text = super.createFormText( parent, trackFocus );
-// if (PDERuntimePlugin.HAS_IDE_BUNDLES) {
-// text.addHyperlinkListener(new SpyHyperlinkAdapter(dialog));
-// addCopyQNameMenuItem(text);
-// }
-    return text;
-  }
-
-  private void addCopyQNameMenuItem( final FormText formText ) {
-    Menu menu = formText.getMenu();
-    final MenuItem copyQNameItem = new MenuItem( menu, SWT.PUSH );
-    copyQNameItem.setImage( PDERuntimePluginImages.get( PDERuntimePluginImages.IMG_COPY_QNAME ) );
-    copyQNameItem.setText( PDERuntimeMessages.get().SpyFormToolkit_copyQualifiedName );
-// SelectionListener listener = new SelectionAdapter() {
-// public void widgetSelected(SelectionEvent e) {
-// if (e.widget == copyQNameItem) {
-// Clipboard clipboard = null;
-// try {
-// clipboard = new Clipboard(formText.getDisplay());
-// clipboard.setContents(new Object[] {((String)
-// formText.getSelectedLinkHref()).substring(CLASS_PROTOCOL_PREFIX.length())}, new Transfer[]
-// {TextTransfer.getInstance()});
-// } finally {
-// if (clipboard != null)
-// clipboard.dispose();
-// }
-// }
-// }
-// };
-// copyQNameItem.addSelectionListener(listener);
-    menu.addMenuListener( new MenuAdapter() {
-
-      public void menuShown( MenuEvent e ) {
-        String href = ( String )formText.getSelectedLinkHref();
-        copyQNameItem.setEnabled( href != null && href.startsWith( CLASS_PROTOCOL_PREFIX ) );
-      }
-    } );
-  }
-
-  public String createInterfaceSection( FormText text, String title, Class[] clazzes ) {
-    StringBuffer buffer = new StringBuffer();
-    if( clazzes.length > 0 ) {
-      buffer.append( "<p>" ); //$NON-NLS-1$
-      buffer.append( title );
-      buffer.append( "</p>" ); //$NON-NLS-1$
-      for( int i = 0; i < clazzes.length; i++ ) {
-        buffer.append( "<li bindent=\"20\" style=\"image\" value=\"interface\">" ); //$NON-NLS-1$
-        createClassReference( buffer, clazzes[ i ] );
-        buffer.append( "</li>" ); //$NON-NLS-1$
-      }
-      Image image = PDERuntimePluginImages.get( PDERuntimePluginImages.IMG_INTERFACE_OBJ );
-      text.setImage( "interface", image ); //$NON-NLS-1$
-    }
-    return buffer.toString();
-  }
-
-  public String createClassSection( FormText text, String title, Class[] clazzes ) {
-    StringBuffer buffer = new StringBuffer();
-    if( clazzes.length > 0 ) {
-      buffer.append( "<p>" ); //$NON-NLS-1$
-      buffer.append( title );
-      buffer.append( "</p>" ); //$NON-NLS-1$
-      for( int i = 0; i < clazzes.length; i++ ) {
-        buffer.append( "<li bindent=\"20\" style=\"image\" value=\"class\">" ); //$NON-NLS-1$
-        createClassReference( buffer, clazzes[ i ] );
-        buffer.append( "</li>" ); //$NON-NLS-1$
-      }
-      Image image = PDERuntimePluginImages.get( PDERuntimePluginImages.IMG_CLASS_OBJ );
-      text.setImage( "class", image ); //$NON-NLS-1$
-    }
-    return buffer.toString();
-  }
-
-  public String createIdentifierSection( FormText text, String title, String[] ids ) {
-    StringBuffer buffer = new StringBuffer();
-    if( ids.length > 0 ) {
-      buffer.append( "<p>" ); //$NON-NLS-1$
-      buffer.append( title );
-      buffer.append( "</p>" ); //$NON-NLS-1$
-      for( int i = 0; i < ids.length; i++ ) {
-        buffer.append( "<li bindent=\"20\" style=\"image\" value=\"id\">" ); //$NON-NLS-1$
-        buffer.append( ids[ i ] );
-        buffer.append( "</li>" ); //$NON-NLS-1$
-      }
-      Image image = PDERuntimePluginImages.get( PDERuntimePluginImages.IMG_ID_OBJ );
-      text.setImage( "id", image ); //$NON-NLS-1$
-    }
-    return buffer.toString();
-  }
-
-  public String createHelpIdentifierSection( Widget widget ) {
-    return createHelpIdentifierSection( widget.getData( HELP_KEY ) );
-  }
-
-  public String createHelpIdentifierSection( IContext context ) {
-    if( context instanceof Context )
-      return createHelpIdentifierSection( ( ( Context )context ).getId() );
-    return new String();
-  }
-
-  private String createHelpIdentifierSection( Object help ) {
-    StringBuffer buffer = new StringBuffer();
-    if( help != null ) {
-      buffer.append( "<li bindent=\"20\" style=\"image\" value=\"contextid\">" ); //$NON-NLS-1$
-      buffer.append( help );
-      buffer.append( "</li>" ); //$NON-NLS-1$
-    }
-    return buffer.toString();
-  }
-
-  private void createClassReference( StringBuffer buffer, Class clazz ) {
-// Bundle bundle = PDERuntimePlugin.HAS_IDE_BUNDLES ?
-// PDERuntimePlugin.getDefault().getPackageAdmin().getBundle(clazz) : null;
-// if (bundle != null) {
-// bundleClassByName.put(clazz.getName(), bundle);
-//			buffer.append("<a href=\"").append(CLASS_PROTOCOL_PREFIX).append( //$NON-NLS-1$
-//					clazz.getName()).append("\">") //$NON-NLS-1$
-//					.append(getSimpleName(clazz)).append("</a>"); //$NON-NLS-1$
-// } else {
-    buffer.append( clazz.getName() );
-// }
-  }
-
-  // TODO refactor me, I'm ugly
-  public void generatePluginDetailsText( Bundle bundle,
-                                         String objectId,
-                                         String objectType,
-                                         StringBuffer buffer,
-                                         FormText text )
-  {
-    if( bundle != null ) {
-      String version = ( String )( bundle.getHeaders().get( org.osgi.framework.Constants.BUNDLE_VERSION ) );
-      buffer.append( "<p>" ); //$NON-NLS-1$
-      buffer.append( PDERuntimeMessages.get().SpyDialog_contributingPluginId_title );
-      buffer.append( "</p>" ); //$NON-NLS-1$
-      buffer.append( "<li bindent=\"20\" style=\"image\" value=\"plugin\">" ); //$NON-NLS-1$
-// if (PDERuntimePlugin.HAS_IDE_BUNDLES) {
-//				buffer.append("<a href=\""); //$NON-NLS-1$
-// buffer.append(BUNDLE_PROTOCOL_PREFIX);
-// buffer.append(bundle.getSymbolicName());
-//				buffer.append("\">"); //$NON-NLS-1$
-// }
-      buffer.append( bundle.getSymbolicName() );
-      buffer.append( " (" ); //$NON-NLS-1$
-      buffer.append( version );
-      buffer.append( ")" ); //$NON-NLS-1$
-// if (PDERuntimePlugin.HAS_IDE_BUNDLES) {
-//				buffer.append("</a>"); //$NON-NLS-1$
-// }
-      buffer.append( "</li>" ); //$NON-NLS-1$
-      Image pluginImage = PDERuntimePluginImages.get( PDERuntimePluginImages.IMG_PLUGIN_OBJ );
-      text.setImage( "plugin", pluginImage ); //$NON-NLS-1$
-      if( objectId != null ) {
-        buffer.append( "<p>" ); //$NON-NLS-1$
-        buffer.append( NLS.bind( PDERuntimeMessages.get().SpyDialog_contributingPluginId_desc,
-                                 objectType ) );
-        buffer.append( "</p>" ); //$NON-NLS-1$
-        buffer.append( "<li bindent=\"20\" style=\"image\" value=\"id\">" ); //$NON-NLS-1$
-        buffer.append( objectId );
-        buffer.append( "</li>" ); //$NON-NLS-1$
-      }
-    }
-  }
-
-  private String getSimpleName( Class clazz ) {
-    String fullName = clazz.getName();
-    int index = fullName.lastIndexOf( '.' );
-    String name = fullName.substring( index + 1, fullName.length() );
-    if( name != null )
-      return name;
-    return fullName;
-  }
-
-  private ToolBarManager createSectionToolbar( Section section ) {
-    Object object = section.getData( "toolbarmanager" ); //$NON-NLS-1$
-    if( object instanceof ToolBarManager ) {
-      return ( ToolBarManager )object;
-    }
-    ToolBarManager manager = new ToolBarManager( SWT.FLAT );
-    ToolBar toolbar = manager.createControl( section );
-    final Cursor handCursor = new Cursor( Display.getCurrent(), SWT.CURSOR_HAND );
-    toolbar.setCursor( handCursor );
-    // Cursor needs to be explicitly disposed
-    toolbar.addDisposeListener( new DisposeListener() {
-
-      public void widgetDisposed( DisposeEvent e ) {
-        if( ( handCursor != null ) && ( handCursor.isDisposed() == false ) ) {
-          handCursor.dispose();
-        }
-      }
-    } );
-    section.setTextClient( toolbar );
-    section.setData( "toolbarmanager", manager ); //$NON-NLS-1$
-    return manager;
-  }
-
-  public void createImageAction( Section section, Image image ) {
-    if( image == null )
-      return;
-    ToolBarManager manager = createSectionToolbar( section );
-    SaveImageAction action = new SaveImageAction( image );
-    action.setText( PDERuntimeMessages.get().SpyFormToolkit_saveImageAs_title );
-    action.setImageDescriptor( PDERuntimePluginImages.SAVE_IMAGE_AS_OBJ );
-    manager.add( action );
-    manager.update( true );
-  }
-}
+/*******************************************************************************
+ * Copyright (c) 2007, 2013 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Chris Aniszczyk <zx@us.ibm.com> - initial API and implementation
+ *     Willian Mitsuda <wmitsuda@gmail.com> - bug 209841
+ *     Benjamin Cabe <benjamin.cabe@anyware-tech.com> - bug 209487
+ *     Arnaud Mergey <a_mergey@yahoo.fr>              - RAP port
+ *******************************************************************************/
+package org.eclipse.pde.internal.runtime.spy;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.eclipse.help.IContext;
+import org.eclipse.help.internal.context.Context;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.ToolBarManager;
+import org.eclipse.jface.dialogs.PopupDialog;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.pde.internal.runtime.*;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.ui.forms.events.HyperlinkAdapter;
+import org.eclipse.ui.forms.events.HyperlinkEvent;
+import org.eclipse.ui.forms.widgets.*;
+import org.osgi.framework.Bundle;
+
+
+/**
+ * @since 3.4
+ */
+public class SpyFormToolkit extends FormToolkit {
+
+  private static final String CLASS_PROTOCOL_PREFIX = "class://"; //$NON-NLS-1$
+  private static final String BUNDLE_PROTOCOL_PREFIX = "bundle://"; //$NON-NLS-1$
+
+  private class SpyHyperlinkAdapter extends HyperlinkAdapter {
+
+    private PopupDialog fDialog;
+
+    public SpyHyperlinkAdapter( PopupDialog dialog ) {
+      this.fDialog = dialog;
+    }
+
+    public void linkActivated( HyperlinkEvent e ) {
+      String href = ( String )e.getHref();
+      if( href.startsWith( CLASS_PROTOCOL_PREFIX ) ) {
+        String clazz = href.substring( CLASS_PROTOCOL_PREFIX.length() );
+        Bundle bundle = ( Bundle )bundleClassByName.get( clazz );
+// SpyIDEUtil.openClass(bundle.getSymbolicName(), clazz);
+        fDialog.close();
+      } else if( href.startsWith( BUNDLE_PROTOCOL_PREFIX ) ) {
+        String bundle = href.substring( BUNDLE_PROTOCOL_PREFIX.length() );
+// / SpyIDEUtil.openBundleManifest(bundle);
+        fDialog.close();
+      }
+    }
+  }
+  private class SaveImageAction extends Action {
+
+    private Image image;
+
+    public SaveImageAction( Image image ) {
+      this.image = image;
+    }
+
+    public void run() {
+      FileDialog fileChooser = new FileDialog( PDERuntimePlugin.getActiveWorkbenchShell(), SWT.SAVE );
+      // RAP [if] Missing API
+//      fileChooser.setFileName( "image" ); //$NON-NLS-1$
+//      fileChooser.setFilterExtensions( new String[] {
+//        "*.png"} ); //$NON-NLS-1$
+//      fileChooser.setFilterNames( new String[] {
+//        "PNG (*.png)"} ); //$NON-NLS-1$
+      // ENDRAP
+      String filename = fileChooser.open();
+      if( filename == null )
+        return;
+      int filetype = determineFileType( filename );
+      if( filetype == SWT.IMAGE_UNDEFINED ) {
+        return;
+      }
+      ImageLoader loader = new ImageLoader();
+      loader.data = new ImageData[] {
+        image.getImageData()
+      };
+      loader.save( filename, filetype );
+    }
+
+    private int determineFileType( String filename ) {
+      String ext = filename.substring( filename.lastIndexOf( '.' ) + 1 );
+      if( ext.equalsIgnoreCase( "gif" ) ) //$NON-NLS-1$
+        return SWT.IMAGE_GIF;
+      if( ext.equalsIgnoreCase( "ico" ) ) //$NON-NLS-1$
+        return SWT.IMAGE_ICO;
+      if( ext.equalsIgnoreCase( "jpg" ) || ext.equalsIgnoreCase( "jpeg" ) ) //$NON-NLS-1$//$NON-NLS-2$
+        return SWT.IMAGE_JPEG;
+      if( ext.equalsIgnoreCase( "png" ) ) //$NON-NLS-1$
+        return SWT.IMAGE_PNG;
+      return SWT.IMAGE_UNDEFINED;
+    }
+  }
+
+  private Map bundleClassByName = new HashMap();
+  private PopupDialog dialog;
+  private static String HELP_KEY = "org.eclipse.ui.help"; //$NON-NLS-1$
+
+  public SpyFormToolkit( PopupDialog dialog ) {
+    super( Display.getDefault() );
+    this.dialog = dialog;
+  }
+
+  public FormText createFormText( Composite parent, boolean trackFocus ) {
+    FormText text = super.createFormText( parent, trackFocus );
+// if (PDERuntimePlugin.HAS_IDE_BUNDLES) {
+// text.addHyperlinkListener(new SpyHyperlinkAdapter(dialog));
+// addCopyQNameMenuItem(text);
+// }
+    return text;
+  }
+
+  private void addCopyQNameMenuItem( final FormText formText ) {
+    Menu menu = formText.getMenu();
+    final MenuItem copyQNameItem = new MenuItem( menu, SWT.PUSH );
+    copyQNameItem.setImage( PDERuntimePluginImages.get( PDERuntimePluginImages.IMG_COPY_QNAME ) );
+    copyQNameItem.setText( PDERuntimeMessages.get().SpyFormToolkit_copyQualifiedName );
+// SelectionListener listener = new SelectionAdapter() {
+// public void widgetSelected(SelectionEvent e) {
+// if (e.widget == copyQNameItem) {
+// Clipboard clipboard = null;
+// try {
+// clipboard = new Clipboard(formText.getDisplay());
+// clipboard.setContents(new Object[] {((String)
+// formText.getSelectedLinkHref()).substring(CLASS_PROTOCOL_PREFIX.length())}, new Transfer[]
+// {TextTransfer.getInstance()});
+// } finally {
+// if (clipboard != null)
+// clipboard.dispose();
+// }
+// }
+// }
+// };
+// copyQNameItem.addSelectionListener(listener);
+    menu.addMenuListener( new MenuAdapter() {
+
+      public void menuShown( MenuEvent e ) {
+        String href = ( String )formText.getSelectedLinkHref();
+        copyQNameItem.setEnabled( href != null && href.startsWith( CLASS_PROTOCOL_PREFIX ) );
+      }
+    } );
+  }
+
+  public String createInterfaceSection( FormText text, String title, Class[] clazzes ) {
+    StringBuffer buffer = new StringBuffer();
+    if( clazzes.length > 0 ) {
+      buffer.append( "<p>" ); //$NON-NLS-1$
+      buffer.append( title );
+      buffer.append( "</p>" ); //$NON-NLS-1$
+      for( int i = 0; i < clazzes.length; i++ ) {
+        buffer.append( "<li bindent=\"20\" style=\"image\" value=\"interface\">" ); //$NON-NLS-1$
+        createClassReference( buffer, clazzes[ i ] );
+        buffer.append( "</li>" ); //$NON-NLS-1$
+      }
+      Image image = PDERuntimePluginImages.get( PDERuntimePluginImages.IMG_INTERFACE_OBJ );
+      text.setImage( "interface", image ); //$NON-NLS-1$
+    }
+    return buffer.toString();
+  }
+
+  public String createClassSection( FormText text, String title, Class[] clazzes ) {
+    StringBuffer buffer = new StringBuffer();
+    if( clazzes.length > 0 ) {
+      buffer.append( "<p>" ); //$NON-NLS-1$
+      buffer.append( title );
+      buffer.append( "</p>" ); //$NON-NLS-1$
+      for( int i = 0; i < clazzes.length; i++ ) {
+        buffer.append( "<li bindent=\"20\" style=\"image\" value=\"class\">" ); //$NON-NLS-1$
+        createClassReference( buffer, clazzes[ i ] );
+        buffer.append( "</li>" ); //$NON-NLS-1$
+      }
+      Image image = PDERuntimePluginImages.get( PDERuntimePluginImages.IMG_CLASS_OBJ );
+      text.setImage( "class", image ); //$NON-NLS-1$
+    }
+    return buffer.toString();
+  }
+
+  public String createIdentifierSection( FormText text, String title, String[] ids ) {
+    StringBuffer buffer = new StringBuffer();
+    if( ids.length > 0 ) {
+      buffer.append( "<p>" ); //$NON-NLS-1$
+      buffer.append( title );
+      buffer.append( "</p>" ); //$NON-NLS-1$
+      for( int i = 0; i < ids.length; i++ ) {
+        buffer.append( "<li bindent=\"20\" style=\"image\" value=\"id\">" ); //$NON-NLS-1$
+        buffer.append( ids[ i ] );
+        buffer.append( "</li>" ); //$NON-NLS-1$
+      }
+      Image image = PDERuntimePluginImages.get( PDERuntimePluginImages.IMG_ID_OBJ );
+      text.setImage( "id", image ); //$NON-NLS-1$
+    }
+    return buffer.toString();
+  }
+
+  public String createHelpIdentifierSection( Widget widget ) {
+    return createHelpIdentifierSection( widget.getData( HELP_KEY ) );
+  }
+
+  public String createHelpIdentifierSection( IContext context ) {
+    if( context instanceof Context )
+      return createHelpIdentifierSection( ( ( Context )context ).getId() );
+    return new String();
+  }
+
+  private String createHelpIdentifierSection( Object help ) {
+    StringBuffer buffer = new StringBuffer();
+    if( help != null ) {
+      buffer.append( "<li bindent=\"20\" style=\"image\" value=\"contextid\">" ); //$NON-NLS-1$
+      buffer.append( help );
+      buffer.append( "</li>" ); //$NON-NLS-1$
+    }
+    return buffer.toString();
+  }
+
+  private void createClassReference( StringBuffer buffer, Class clazz ) {
+// Bundle bundle = PDERuntimePlugin.HAS_IDE_BUNDLES ?
+// PDERuntimePlugin.getDefault().getPackageAdmin().getBundle(clazz) : null;
+// if (bundle != null) {
+// bundleClassByName.put(clazz.getName(), bundle);
+//			buffer.append("<a href=\"").append(CLASS_PROTOCOL_PREFIX).append( //$NON-NLS-1$
+//					clazz.getName()).append("\">") //$NON-NLS-1$
+//					.append(getSimpleName(clazz)).append("</a>"); //$NON-NLS-1$
+// } else {
+    buffer.append( clazz.getName() );
+// }
+  }
+
+  // TODO refactor me, I'm ugly
+  public void generatePluginDetailsText( Bundle bundle,
+                                         String objectId,
+                                         String objectType,
+                                         StringBuffer buffer,
+                                         FormText text )
+  {
+    if( bundle != null ) {
+      String version = ( String )( bundle.getHeaders().get( org.osgi.framework.Constants.BUNDLE_VERSION ) );
+      buffer.append( "<p>" ); //$NON-NLS-1$
+      buffer.append( PDERuntimeMessages.get().SpyDialog_contributingPluginId_title );
+      buffer.append( "</p>" ); //$NON-NLS-1$
+      buffer.append( "<li bindent=\"20\" style=\"image\" value=\"plugin\">" ); //$NON-NLS-1$
+// if (PDERuntimePlugin.HAS_IDE_BUNDLES) {
+//				buffer.append("<a href=\""); //$NON-NLS-1$
+// buffer.append(BUNDLE_PROTOCOL_PREFIX);
+// buffer.append(bundle.getSymbolicName());
+//				buffer.append("\">"); //$NON-NLS-1$
+// }
+      buffer.append( bundle.getSymbolicName() );
+      buffer.append( " (" ); //$NON-NLS-1$
+      buffer.append( version );
+      buffer.append( ")" ); //$NON-NLS-1$
+// if (PDERuntimePlugin.HAS_IDE_BUNDLES) {
+//				buffer.append("</a>"); //$NON-NLS-1$
+// }
+      buffer.append( "</li>" ); //$NON-NLS-1$
+      Image pluginImage = PDERuntimePluginImages.get( PDERuntimePluginImages.IMG_PLUGIN_OBJ );
+      text.setImage( "plugin", pluginImage ); //$NON-NLS-1$
+      if( objectId != null ) {
+        buffer.append( "<p>" ); //$NON-NLS-1$
+        buffer.append( NLS.bind( PDERuntimeMessages.get().SpyDialog_contributingPluginId_desc,
+                                 objectType ) );
+        buffer.append( "</p>" ); //$NON-NLS-1$
+        buffer.append( "<li bindent=\"20\" style=\"image\" value=\"id\">" ); //$NON-NLS-1$
+        buffer.append( objectId );
+        buffer.append( "</li>" ); //$NON-NLS-1$
+      }
+    }
+  }
+
+  private String getSimpleName( Class clazz ) {
+    String fullName = clazz.getName();
+    int index = fullName.lastIndexOf( '.' );
+    String name = fullName.substring( index + 1, fullName.length() );
+    if( name != null )
+      return name;
+    return fullName;
+  }
+
+  private ToolBarManager createSectionToolbar( Section section ) {
+    Object object = section.getData( "toolbarmanager" ); //$NON-NLS-1$
+    if( object instanceof ToolBarManager ) {
+      return ( ToolBarManager )object;
+    }
+    ToolBarManager manager = new ToolBarManager( SWT.FLAT );
+    ToolBar toolbar = manager.createControl( section );
+    final Cursor handCursor = new Cursor( Display.getCurrent(), SWT.CURSOR_HAND );
+    toolbar.setCursor( handCursor );
+    // Cursor needs to be explicitly disposed
+    toolbar.addDisposeListener( new DisposeListener() {
+
+      public void widgetDisposed( DisposeEvent e ) {
+        if( ( handCursor != null ) && ( handCursor.isDisposed() == false ) ) {
+          handCursor.dispose();
+        }
+      }
+    } );
+    section.setTextClient( toolbar );
+    section.setData( "toolbarmanager", manager ); //$NON-NLS-1$
+    return manager;
+  }
+
+  public void createImageAction( Section section, Image image ) {
+    if( image == null )
+      return;
+    ToolBarManager manager = createSectionToolbar( section );
+    SaveImageAction action = new SaveImageAction( image );
+    action.setText( PDERuntimeMessages.get().SpyFormToolkit_saveImageAs_title );
+    action.setImageDescriptor( PDERuntimePluginImages.SAVE_IMAGE_AS_OBJ );
+    manager.add( action );
+    manager.update( true );
+  }
+}
diff --git a/bundles/org.eclipse.rap.ui.views.log/META-INF/MANIFEST.MF b/bundles/org.eclipse.rap.ui.views.log/META-INF/MANIFEST.MF
index bdb30db..ab2b5c3 100644
--- a/bundles/org.eclipse.rap.ui.views.log/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.rap.ui.views.log/META-INF/MANIFEST.MF
@@ -1,17 +1,17 @@
-Manifest-Version: 1.0
-Bundle-ManifestVersion: 2
-Bundle-Name: %name
-Bundle-SymbolicName: org.eclipse.rap.ui.views.log;singleton:=true
-Bundle-Version: 0.1.0.qualifier
-Bundle-Activator: org.eclipse.ui.internal.views.log.Activator
-Bundle-Vendor: %provider-name
-Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.2.0,4.0.0)",
- org.eclipse.rap.ui;bundle-version="[2.0.0,3.0.0)",
- org.eclipse.rap.rwt.supplemental.filedialog;bundle-version="[1.5.100,3.0.0)"
-Eclipse-LazyStart: true
-Bundle-RequiredExecutionEnvironment: JavaSE-1.6
-Bundle-Localization: plugin
-Export-Package: org.eclipse.ui.internal.views.log;x-friends:="org.eclipse.pde.ui"
-Bundle-ActivationPolicy: lazy
-Import-Package: javax.servlet;version="[2.3.0,4.0.0)",
- javax.servlet.http;version="[2.3.0,4.0.0)"
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %name
+Bundle-SymbolicName: org.eclipse.rap.ui.views.log;singleton:=true
+Bundle-Version: 0.1.0.qualifier
+Bundle-Activator: org.eclipse.ui.internal.views.log.Activator
+Bundle-Vendor: %provider-name
+Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.2.0,4.0.0)",
+ org.eclipse.rap.ui;bundle-version="[2.0.0,3.0.0)",
+ org.eclipse.rap.addons.filedialog;bundle-version="[0.5.0,1.0.0)"
+Eclipse-LazyStart: true
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Bundle-Localization: plugin
+Export-Package: org.eclipse.ui.internal.views.log;x-friends:="org.eclipse.pde.ui"
+Bundle-ActivationPolicy: lazy
+Import-Package: javax.servlet;version="[2.3.0,4.0.0)",
+ javax.servlet.http;version="[2.3.0,4.0.0)"
diff --git a/bundles/org.eclipse.rap.ui.views.log/src/org/eclipse/ui/internal/views/log/LogView.java b/bundles/org.eclipse.rap.ui.views.log/src/org/eclipse/ui/internal/views/log/LogView.java
index b38c8f8..062c036 100644
--- a/bundles/org.eclipse.rap.ui.views.log/src/org/eclipse/ui/internal/views/log/LogView.java
+++ b/bundles/org.eclipse.rap.ui.views.log/src/org/eclipse/ui/internal/views/log/LogView.java
@@ -1,1705 +1,1707 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     IBM Corporation - initial API and implementation
- *     Jacek Pospychala <jacek.pospychala@pl.ibm.com> - bugs 202583, 202584, 207344
- *     													bugs 207323, 207931, 207101
- *     													bugs 172658, 216341, 216657
- *     Benjamin Cabe <benjamin.cabe@anyware-tech.com> - bug 218648 
- *     Tuukka Lehtonen <tuukka.lehtonen@semantum.fi>  - bug 247907
- *     Arnaud Mergey <a_mergey@yahoo.fr> 			  - RAP port
- *******************************************************************************/
-
-package org.eclipse.ui.internal.views.log;
-
-import java.io.*;
-import java.lang.reflect.InvocationTargetException;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.*;
-import java.util.List;
-import org.eclipse.core.runtime.*;
-import org.eclipse.core.runtime.Path;
-import org.eclipse.core.runtime.jobs.Job;
-import org.eclipse.jface.action.*;
-import org.eclipse.jface.dialogs.*;
-import org.eclipse.jface.operation.IRunnableWithProgress;
-import org.eclipse.jface.util.Policy;
-import org.eclipse.jface.viewers.*;
-import org.eclipse.jface.window.Window;
-import org.eclipse.osgi.util.NLS;
-import org.eclipse.rap.rwt.RWT;
-import org.eclipse.rap.rwt.client.service.UrlLauncher;
-import org.eclipse.rap.ui.internal.preferences.SessionScope;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.custom.BusyIndicator;
-import org.eclipse.swt.dnd.*;
-import org.eclipse.swt.events.*;
-import org.eclipse.swt.graphics.*;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.*;
-import org.eclipse.ui.*;
-import org.eclipse.ui.dialogs.FilteredTree;
-import org.eclipse.ui.dialogs.PatternFilter;
-import org.eclipse.ui.part.ViewPart;
-import org.osgi.service.prefs.BackingStoreException;
-import org.osgi.service.prefs.Preferences;
-
-public class LogView extends ViewPart implements ILogListener {
-	public static final String DOWNLOAD_SERVICE_HANDLER_ID = "org.eclipse.rap.ui.view.log.downloadLogFile"; //$NON-NLS-1$
-
-	public static final String P_LOG_WARNING = "warning"; //$NON-NLS-1$
-	public static final String P_LOG_ERROR = "error"; //$NON-NLS-1$
-	public static final String P_LOG_INFO = "info"; //$NON-NLS-1$
-	public static final String P_LOG_OK = "ok"; //$NON-NLS-1$
-	public static final String P_LOG_LIMIT = "limit"; //$NON-NLS-1$
-	public static final String P_USE_LIMIT = "useLimit"; //$NON-NLS-1$
-	public static final String P_SHOW_ALL_SESSIONS = "allSessions"; //$NON-NLS-1$
-	protected static final String P_COLUMN_1 = "column2"; //$NON-NLS-1$
-	protected static final String P_COLUMN_2 = "column3"; //$NON-NLS-1$
-	protected static final String P_COLUMN_3 = "column4"; //$NON-NLS-1$
-	public static final String P_ACTIVATE = "activate"; //$NON-NLS-1$
-	public static final String P_SHOW_FILTER_TEXT = "show_filter_text"; //$NON-NLS-1$
-	public static final String P_ORDER_TYPE = "orderType"; //$NON-NLS-1$
-	public static final String P_ORDER_VALUE = "orderValue"; //$NON-NLS-1$
-	public static final String P_IMPORT_LOG = "importLog"; //$NON-NLS-1$
-	public static final String P_GROUP_BY = "groupBy"; //$NON-NLS-1$
-
-	private int MESSAGE_ORDER;
-	private int PLUGIN_ORDER;
-	private int DATE_ORDER;
-
-	public final static byte MESSAGE = 0x0;
-	public final static byte PLUGIN = 0x1;
-	public final static byte DATE = 0x2;
-	public static int ASCENDING = 1;
-	public static int DESCENDING = -1;
-
-	public static final int GROUP_BY_NONE = 0;
-	public static final int GROUP_BY_SESSION = 1;
-	public static final int GROUP_BY_PLUGIN = 2;
-
-	private List elements;
-	private Map groups;
-	private LogSession currentSession;
-
-	private List batchedEntries;
-	private boolean batchEntries;
-
-//	private Clipboard fClipboard;
-
-	private IMemento fMemento;
-	private File fInputFile;
-	private String fDirectory;
-
-	private Comparator fComparator;
-
-	// hover text
-	private boolean fCanOpenTextShell;
-	private Text fTextLabel;
-	private Shell fTextShell;
-
-	private boolean fFirstEvent = true;
-
-	private TreeColumn fColumn1;
-	private TreeColumn fColumn2;
-	private TreeColumn fColumn3;
-
-	private Tree fTree;
-	private FilteredTree fFilteredTree;
-	private LogViewLabelProvider fLabelProvider;
-
-	private Action fPropertiesAction;
-	private Action fDeleteLogAction;
-	private Action fReadLogAction;
-//	private Action fCopyAction;
-	private Action fActivateViewAction;
-	private Action fOpenLogAction;
-	private Action fExportLogAction;
-	private Action fExportLogEntryAction;
-
-	private Display fDisplay = null;
-
-	/**
-	 * Action called when user selects "Group by -> ..." from menu.
-	 */
-	class GroupByAction extends Action {
-		private int groupBy;
-
-		public GroupByAction(String text, int groupBy) {
-			super(text, IAction.AS_RADIO_BUTTON);
-
-			this.groupBy = groupBy;
-
-			if (fMemento.getInteger(LogView.P_GROUP_BY).intValue() == groupBy) {
-				setChecked(true);
-			}
-		}
-
-		public void run() {
-			if (fMemento.getInteger(LogView.P_GROUP_BY).intValue() != groupBy) {
-				fMemento.putInteger(LogView.P_GROUP_BY, groupBy);
-				reloadLog();
-			}
-		}
-	}
-
-	/**
-	 * Constructor
-	 */
-	public LogView() {
-		elements = new ArrayList();
-		groups = new HashMap();
-		batchedEntries = new ArrayList();
-		fInputFile = Platform.getLogFileLocation().toFile();
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
-	 */
-	public void createPartControl(Composite parent) {
-		fDisplay = getSite().getShell().getDisplay();
-		Composite composite = new Composite(parent, SWT.NONE);
-		GridLayout layout = new GridLayout();
-		layout.horizontalSpacing = 0;
-		layout.verticalSpacing = 0;
-		layout.marginWidth = 0;
-		layout.marginHeight = 0;
-		composite.setLayout(layout);
-//		composite.setLayoutData(new GridData(GridData.FILL_BOTH));
-
-		readLogFile();
-		createViewer(composite);
-		getSite().setSelectionProvider(fFilteredTree.getViewer());
-		createActions();
-//		fClipboard = new Clipboard(fTree.getDisplay());
-		fTree.setToolTipText(""); //$NON-NLS-1$
-		initializeViewerSorter();
-
-		makeHoverShell();
-
-		Platform.addLogListener(this);
-		PlatformUI.getWorkbench().getHelpSystem().setHelp(fFilteredTree, IHelpContextIds.LOG_VIEW);
-		getSite().getWorkbenchWindow().addPerspectiveListener(new IPerspectiveListener2() {
-
-			public void perspectiveChanged(IWorkbenchPage page, IPerspectiveDescriptor perspective, IWorkbenchPartReference partRef, String changeId) {
-				if (!(partRef instanceof IViewReference))
-					return;
-
-				IWorkbenchPart part = partRef.getPart(false);
-				if (part == null) {
-					return;
-				}
-
-				if (part.equals(LogView.this)) {
-					if (changeId.equals(IWorkbenchPage.CHANGE_VIEW_SHOW)) {
-						if (!batchedEntries.isEmpty()) {
-							pushBatchedEntries();
-						}
-
-						batchEntries = false;
-					} else if (changeId.equals(IWorkbenchPage.CHANGE_VIEW_HIDE)) {
-						batchEntries = true;
-					}
-				}
-			}
-
-			public void perspectiveActivated(IWorkbenchPage page, IPerspectiveDescriptor perspective) {
-				// empty
-			}
-
-			public void perspectiveChanged(IWorkbenchPage page, IPerspectiveDescriptor perspective, String changeId) {
-				// empty
-			}
-
-		});
-	}
-
-	/**
-	 * Creates the actions for the viewsite action bars
-	 */
-	private void createActions() {
-		IActionBars bars = getViewSite().getActionBars();
-
-//		fCopyAction = createCopyAction();
-//		bars.setGlobalActionHandler(ActionFactory.COPY.getId(), fCopyAction);
-
-		IToolBarManager toolBarManager = bars.getToolBarManager();
-
-		fExportLogAction = createExportLogAction();
-		toolBarManager.add(fExportLogAction);
-
-		fExportLogEntryAction = createExportLogEntryAction();
-
-		final Action importLogAction = createImportLogAction();
-		toolBarManager.add(importLogAction);
-
-		toolBarManager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
-
-		final Action clearAction = createClearAction();
-		toolBarManager.add(clearAction);
-
-		fDeleteLogAction = createDeleteLogAction();
-		toolBarManager.add(fDeleteLogAction);
-
-		fOpenLogAction = createOpenLogAction();
-		toolBarManager.add(fOpenLogAction);
-
-		fReadLogAction = createReadLogAction();
-		toolBarManager.add(fReadLogAction);
-
-		toolBarManager.add(new Separator());
-
-		IMenuManager mgr = bars.getMenuManager();
-
-		mgr.add(createGroupByAction());
-		mgr.add(new Separator());
-		mgr.add(createFilterAction());
-		mgr.add(new Separator());
-
-		fActivateViewAction = createActivateViewAction();
-		mgr.add(fActivateViewAction);
-		if (fFilteredTree.getFilterControl() != null)
-			mgr.add(createShowTextFilter());
-
-		fPropertiesAction = createPropertiesAction();
-
-		MenuManager popupMenuManager = new MenuManager("#PopupMenu"); //$NON-NLS-1$
-		IMenuListener listener = new IMenuListener() {
-			public void menuAboutToShow(IMenuManager manager) {
-//				manager.add(fCopyAction);
-//				manager.add(new Separator());
-				manager.add(clearAction);
-				manager.add(fDeleteLogAction);
-				manager.add(fOpenLogAction);
-				manager.add(fReadLogAction);
-				manager.add(new Separator());
-				manager.add(fExportLogAction);
-				manager.add(createImportLogAction());
-				manager.add(new Separator());
-				manager.add(fExportLogEntryAction);
-				manager.add(new Separator());
-
-				((EventDetailsDialogAction) fPropertiesAction).setComparator(fComparator);
-				TreeItem[] selection = fTree.getSelection();
-				if ((selection.length > 0) && (selection[0].getData() instanceof LogEntry)) {
-					manager.add(fPropertiesAction);
-				}
-
-				manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
-			}
-		};
-		popupMenuManager.addMenuListener(listener);
-		popupMenuManager.setRemoveAllWhenShown(true);
-		getSite().registerContextMenu(popupMenuManager, getSite().getSelectionProvider());
-		Menu menu = popupMenuManager.createContextMenu(fTree);
-		fTree.setMenu(menu);
-	}
-
-	private Action createActivateViewAction() {
-		Action action = new Action(Messages.get().LogView_activate) { //       	
-			public void run() {
-				fMemento.putString(P_ACTIVATE, isChecked() ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
-			}
-		};
-		action.setChecked(fMemento.getString(P_ACTIVATE).equals("true")); //$NON-NLS-1$
-		return action;
-	}
-
-	private Action createClearAction() {
-		Action action = new Action(Messages.get().LogView_clear) {
-			public void run() {
-				handleClear();
-			}
-		};
-		action.setImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_CLEAR));
-		action.setDisabledImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_CLEAR_DISABLED));
-		action.setToolTipText(Messages.get().LogView_clear_tooltip);
-		action.setText(Messages.get().LogView_clear);
-		return action;
-	}
-
-//	private Action createCopyAction() {
-//		Action action = new Action(Messages.get().LogView_copy) {
-//			public void run() {
-//				copyToClipboard(fFilteredTree.getViewer().getSelection());
-//			}
-//		};
-//		action.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_TOOL_COPY));
-//		return action;
-//	}
-
-	private Action createDeleteLogAction() {
-		Action action = new Action(Messages.get().LogView_delete) {
-			public void run() {
-				doDeleteLog();
-			}
-		};
-		action.setToolTipText(Messages.get().LogView_delete_tooltip);
-		action.setImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_REMOVE_LOG));
-		action.setDisabledImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_REMOVE_LOG_DISABLED));
-		action.setEnabled(fInputFile.exists() && fInputFile.equals(Platform.getLogFileLocation().toFile()));
-		return action;
-	}
-
-	private Action createExportLogAction() {
-		Action action = new Action(Messages.get().LogView_export) {
-			public void run() {
-				handleExport(true);
-			}
-		};
-		action.setToolTipText(Messages.get().LogView_export_tooltip);
-		action.setImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_EXPORT));
-		action.setDisabledImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_EXPORT_DISABLED));
-		action.setEnabled(fInputFile.exists());
-		return action;
-	}
-
-	private Action createExportLogEntryAction() {
-		Action action = new Action(Messages.get().LogView_exportEntry) {
-			public void run() {
-				handleExport(false);
-			}
-		};
-		action.setToolTipText(Messages.get().LogView_exportEntry_tooltip);
-		action.setImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_EXPORT));
-		action.setDisabledImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_EXPORT_DISABLED));
-		action.setEnabled(!fFilteredTree.getViewer().getSelection().isEmpty());
-		return action;
-	}
-
-	private Action createFilterAction() {
-		Action action = new Action(Messages.get().LogView_filter) {
-			public void run() {
-				handleFilter();
-			}
-		};
-		action.setToolTipText(Messages.get().LogView_filter);
-		action.setImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_FILTER));
-		action.setDisabledImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_FILTER_DISABLED));
-		return action;
-	}
-
-	private Action createImportLogAction() {
-		Action action = new ImportLogAction(this, Messages.get().LogView_import, fMemento);
-		action.setToolTipText(Messages.get().LogView_import_tooltip);
-		action.setImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_IMPORT));
-		action.setDisabledImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_IMPORT_DISABLED));
-		return action;
-	}
-
-	private Action createOpenLogAction() {
-		Action action = null;
-//		try {
-//			// TODO this isn't the best way to check... we should be smarter and use package admin
-//			// check to see if org.eclipse.ui.ide is available
-//			Class.forName("org.eclipse.ui.ide.IDE"); //$NON-NLS-1$
-//			// check to see if org.eclipse.core.filesystem is available
-//			Class.forName("org.eclipse.core.filesystem.IFileStore"); //$NON-NLS-1$
-//			action = new OpenIDELogFileAction(this);
-//		} catch (ClassNotFoundException e) {
-		action = new Action() {
-			public void run() {
-				if (fInputFile.exists()) {
-					Job job = getOpenLogFileJob();
-					job.setUser(false);
-					job.setPriority(Job.SHORT);
-					job.schedule();
-				}
-			}
-		};
-//		}
-		action.setText(Messages.get().LogView_view_currentLog);
-		action.setImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_OPEN_LOG));
-		action.setDisabledImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_OPEN_LOG_DISABLED));
-		action.setEnabled(fInputFile.exists());
-		action.setToolTipText(Messages.get().LogView_view_currentLog_tooltip);
-		return action;
-	}
-
-	private Action createPropertiesAction() {
-		Action action = new EventDetailsDialogAction(fTree, fFilteredTree.getViewer(), fMemento);
-		action.setImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_PROPERTIES));
-		action.setDisabledImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_PROPERTIES_DISABLED));
-		action.setToolTipText(Messages.get().LogView_properties_tooltip);
-		action.setEnabled(false);
-		return action;
-	}
-
-	private Action createReadLogAction() {
-		Action action = new Action(Messages.get().LogView_readLog_restore) {
-			public void run() {
-				fInputFile = Platform.getLogFileLocation().toFile();
-				reloadLog();
-			}
-		};
-		action.setToolTipText(Messages.get().LogView_readLog_restore_tooltip);
-		action.setImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_READ_LOG));
-		action.setDisabledImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_READ_LOG_DISABLED));
-		return action;
-	}
-
-	/**
-	 * Creates the Show Text Filter view menu action 
-	 * @return the new action for the Show Text Filter 
-	 */
-	private Action createShowTextFilter() {
-		Action action = new Action(Messages.get().LogView_show_filter_text) {
-			public void run() {
-				showFilterText(isChecked());
-			}
-		};
-		boolean visible = fMemento.getBoolean(P_SHOW_FILTER_TEXT).booleanValue();
-		action.setChecked(visible);
-		showFilterText(visible);
-		return action;
-	}
-
-	/**
-	 * Shows/hides the filter text control from the filtered tree. This method also sets the 
-	 * P_SHOW_FILTER_TEXT preference to the visible state
-	 * 
-	 * @param visible if the filter text control should be shown or not
-	 */
-	private void showFilterText(boolean visible) {
-		fMemento.putBoolean(P_SHOW_FILTER_TEXT, visible);
-
-		Text filterControl = fFilteredTree.getFilterControl();
-		Composite filterComposite = filterControl.getParent(); // FilteredTree new look lays filter Text on additional composite
-
-		GridData gd = (GridData) filterComposite.getLayoutData();
-		gd.exclude = !visible;
-		filterComposite.setVisible(visible);
-
-		// reset control if we aren't visible and if we get visible again
-		filterControl.setText(Messages.get().LogView_show_filter_initialText);
-
-		if (visible) {
-			filterControl.selectAll();
-			setFocus();
-		}
-
-		fFilteredTree.layout(false);
-	}
-
-	private IContributionItem createGroupByAction() {
-		IMenuManager manager = new MenuManager(Messages.get().LogView_GroupBy);
-		manager.add(new GroupByAction(Messages.get().LogView_GroupBySession, LogView.GROUP_BY_SESSION));
-		manager.add(new GroupByAction(Messages.get().LogView_GroupByPlugin, LogView.GROUP_BY_PLUGIN));
-		manager.add(new GroupByAction(Messages.get().LogView_GroupByNone, LogView.GROUP_BY_NONE));
-		return manager;
-	}
-
-	private void createViewer(Composite parent) {
-		PatternFilter filter = new PatternFilter() {
-			protected boolean isLeafMatch(Viewer viewer, Object element) {
-				if (element instanceof LogEntry) {
-					LogEntry logEntry = (LogEntry) element;
-					String message = logEntry.getMessage();
-					String plugin = logEntry.getPluginId();
-					DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, RWT.getLocale());
-					String date = dateFormat.format(logEntry.getDate());
-					return wordMatches(message) || wordMatches(plugin) || wordMatches(date);
-				}
-				return false;
-			}
-		};
-		filter.setIncludeLeadingWildcard(true);
-		fFilteredTree = new FilteredTree(parent, SWT.FULL_SELECTION, filter, true);
-		// need to give filter Textbox some space from the border
-		if (fFilteredTree.getFilterControl() != null) {
-			Composite filterComposite = fFilteredTree.getFilterControl().getParent(); // FilteredTree new look lays filter Text on additional composite
-			GridData gd = (GridData) filterComposite.getLayoutData();
-			gd.verticalIndent = 2;
-			gd.horizontalIndent = 1;
-		}
-		fFilteredTree.setLayoutData(new GridData(GridData.FILL_BOTH));
-		fFilteredTree.setInitialText(Messages.get().LogView_show_filter_initialText);
-		fTree = fFilteredTree.getViewer().getTree();
-		fTree.setLinesVisible(true);
-		createColumns(fTree);
-		fFilteredTree.getViewer().setAutoExpandLevel(2);
-		fFilteredTree.getViewer().setContentProvider(new LogViewContentProvider(this));
-		fFilteredTree.getViewer().setLabelProvider(fLabelProvider = new LogViewLabelProvider(this));
-		fLabelProvider.connect(this);
-		fFilteredTree.getViewer().addSelectionChangedListener(new ISelectionChangedListener() {
-			public void selectionChanged(SelectionChangedEvent e) {
-				handleSelectionChanged(e.getSelection());
-				if (fPropertiesAction.isEnabled())
-					((EventDetailsDialogAction) fPropertiesAction).resetSelection();
-			}
-		});
-		fFilteredTree.getViewer().addDoubleClickListener(new IDoubleClickListener() {
-			public void doubleClick(DoubleClickEvent event) {
-				((EventDetailsDialogAction) fPropertiesAction).setComparator(fComparator);
-				fPropertiesAction.run();
-			}
-		});
-		fFilteredTree.getViewer().setInput(this);
-		addMouseListeners();
-		addDragSource();
-	}
-
-	private void createColumns(Tree tree) {
-		fColumn1 = new TreeColumn(tree, SWT.LEFT);
-		fColumn1.setText(Messages.get().LogView_column_message);
-		fColumn1.setWidth(fMemento.getInteger(P_COLUMN_1).intValue());
-		fColumn1.addSelectionListener(new SelectionAdapter() {
-			public void widgetSelected(SelectionEvent e) {
-				MESSAGE_ORDER *= -1;
-				ViewerComparator comparator = getViewerComparator(MESSAGE);
-				fFilteredTree.getViewer().setComparator(comparator);
-				boolean isComparatorSet = ((EventDetailsDialogAction) fPropertiesAction).resetSelection(MESSAGE, MESSAGE_ORDER);
-				setComparator(MESSAGE);
-				if (!isComparatorSet)
-					((EventDetailsDialogAction) fPropertiesAction).setComparator(fComparator);
-				fMemento.putInteger(P_ORDER_VALUE, MESSAGE_ORDER);
-				fMemento.putInteger(P_ORDER_TYPE, MESSAGE);
-				setColumnSorting(fColumn1, MESSAGE_ORDER);
-			}
-		});
-
-		fColumn2 = new TreeColumn(tree, SWT.LEFT);
-		fColumn2.setText(Messages.get().LogView_column_plugin);
-		fColumn2.setWidth(fMemento.getInteger(P_COLUMN_2).intValue());
-		fColumn2.addSelectionListener(new SelectionAdapter() {
-			public void widgetSelected(SelectionEvent e) {
-				PLUGIN_ORDER *= -1;
-				ViewerComparator comparator = getViewerComparator(PLUGIN);
-				fFilteredTree.getViewer().setComparator(comparator);
-				boolean isComparatorSet = ((EventDetailsDialogAction) fPropertiesAction).resetSelection(PLUGIN, PLUGIN_ORDER);
-				setComparator(PLUGIN);
-				if (!isComparatorSet)
-					((EventDetailsDialogAction) fPropertiesAction).setComparator(fComparator);
-				fMemento.putInteger(P_ORDER_VALUE, PLUGIN_ORDER);
-				fMemento.putInteger(P_ORDER_TYPE, PLUGIN);
-				setColumnSorting(fColumn2, PLUGIN_ORDER);
-			}
-		});
-
-		fColumn3 = new TreeColumn(tree, SWT.LEFT);
-		fColumn3.setText(Messages.get().LogView_column_date);
-		fColumn3.setWidth(fMemento.getInteger(P_COLUMN_3).intValue());
-		fColumn3.addSelectionListener(new SelectionAdapter() {
-			public void widgetSelected(SelectionEvent e) {
-				DATE_ORDER *= -1;
-				ViewerComparator comparator = getViewerComparator(DATE);
-				fFilteredTree.getViewer().setComparator(comparator);
-				setComparator(DATE);
-				((EventDetailsDialogAction) fPropertiesAction).setComparator(fComparator);
-				fMemento.putInteger(P_ORDER_VALUE, DATE_ORDER);
-				fMemento.putInteger(P_ORDER_TYPE, DATE);
-				setColumnSorting(fColumn3, DATE_ORDER);
-			}
-		});
-
-		tree.setHeaderVisible(true);
-	}
-
-	private void initializeViewerSorter() {
-		byte orderType = fMemento.getInteger(P_ORDER_TYPE).byteValue();
-		ViewerComparator comparator = getViewerComparator(orderType);
-		fFilteredTree.getViewer().setComparator(comparator);
-		if (orderType == MESSAGE)
-			setColumnSorting(fColumn1, MESSAGE_ORDER);
-		else if (orderType == PLUGIN)
-			setColumnSorting(fColumn2, PLUGIN_ORDER);
-		else if (orderType == DATE)
-			setColumnSorting(fColumn3, DATE_ORDER);
-	}
-
-	private void setColumnSorting(TreeColumn column, int order) {
-		fTree.setSortColumn(column);
-		fTree.setSortDirection(order == ASCENDING ? SWT.UP : SWT.DOWN);
-	}
-
-	public void dispose() {
-		writeSettings();
-		Platform.removeLogListener(this);
-//		fClipboard.dispose();
-		if (fTextShell != null)
-			fTextShell.dispose();
-		fLabelProvider.disconnect(this);
-		fFilteredTree.dispose();
-		super.dispose();
-	}
-
-	/**
-	 * Import log from file selected in FileDialog.
-	 */
-	void handleImport() {
-		FileDialog dialog = new FileDialog(getViewSite().getShell());
-		dialog.setFilterExtensions(new String[] {"*.log"}); //$NON-NLS-1$
-		if (fDirectory != null)
-			dialog.setFilterPath(fDirectory);
-		String path = dialog.open();
-		if (path == null) { // cancel
-			return;
-		}
-
-		File file = new Path(path).toFile();
-		if (file.exists()) {
-			handleImportPath(path);
-		} else {
-			String msg = NLS.bind(Messages.get().LogView_FileCouldNotBeFound, file.getName());
-			MessageDialog.openError(getViewSite().getShell(), Messages.get().LogView_OpenFile, msg);
-		}
-	}
-
-	/**
-	 * Import log from given file path. Do nothing if file not exists.
-	 * @param path path to log file.
-	 */
-	public void handleImportPath(String path) {
-		File file = new File(path);
-		if (path != null && file.exists()) {
-			setLogFile(file);
-		}
-	}
-
-	/**
-	 * Import log from given file path.
-	 * @param path path to log file.
-	 */
-	protected void setLogFile(File path) {
-		fInputFile = path;
-		fDirectory = fInputFile.getParent();
-		IRunnableWithProgress op = new IRunnableWithProgress() {
-			public void run(IProgressMonitor monitor) {
-				monitor.beginTask(Messages.get().LogView_operation_importing, IProgressMonitor.UNKNOWN);
-				readLogFile();
-			}
-		};
-		ProgressMonitorDialog pmd = new ProgressMonitorDialog(getViewSite().getShell());
-		try {
-			pmd.run(true, true, op);
-		} catch (InvocationTargetException e) { // do nothing
-		} catch (InterruptedException e) { // do nothing
-		} finally {
-			fReadLogAction.setText(Messages.get().LogView_readLog_reload);
-			fReadLogAction.setToolTipText(Messages.get().LogView_readLog_reload);
-			asyncRefresh(false);
-			resetDialogButtons();
-		}
-	}
-
-	private void handleExport(boolean exportWholeLog) {
-//		FileDialog dialog = new FileDialog(getViewSite().getShell(), SWT.SAVE);
-//		dialog.setFilterExtensions(new String[] {"*.log"}); //$NON-NLS-1$
-//		if (fDirectory != null)
-//			dialog.setFilterPath(fDirectory);
-//		String path = dialog.open();
-//		if (path != null) {
-//			if (path.indexOf('.') == -1 && !path.endsWith(".log")) //$NON-NLS-1$
-//				path += ".log"; //$NON-NLS-1$
-//			File outputFile = new Path(path).toFile();
-//			fDirectory = outputFile.getParent();
-//			if (outputFile.exists()) {
-//				String message = NLS.bind(Messages.get().LogView_confirmOverwrite_message, outputFile.toString());
-//				if (!MessageDialog.openQuestion(getViewSite().getShell(), (exportWholeLog ? Messages.get().LogView_exportLog : Messages.get().LogView_exportLogEntry), message))
-//					return;
-//			}
-//
-//			BufferedReader in = null;
-//			BufferedWriter out = null;
-//			try {
-//				out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outputFile), "UTF-8")); //$NON-NLS-1$
-//				if (exportWholeLog)
-//					in = new BufferedReader(new InputStreamReader(new FileInputStream(fInputFile), "UTF-8")); //$NON-NLS-1$
-//				else {
-//					String selectedEntryAsString = selectionToString(fFilteredTree.getViewer().getSelection());
-//					in = new BufferedReader(new StringReader(selectedEntryAsString));
-//				}
-//				copy(in, out);
-//			} catch (IOException ex) {
-//				// do nothing
-//			} finally {
-//				try {
-//					if (in != null)
-//						in.close();
-//				} catch (IOException e) {
-//					// do nothing
-//				}
-//				try {
-//					if (out != null)
-//						out.close();
-//				} catch (IOException e) {
-//					// do nothing
-//				}
-//			}
-//		}
-		String encodedURL = RWT.getServiceManager().getServiceHandlerUrl(DOWNLOAD_SERVICE_HANDLER_ID);
-
-		UrlLauncher launcher = (UrlLauncher) RWT.getClient().getService(UrlLauncher.class);
-		launcher.openURL(encodedURL);
-	}
-
-//	private void copy(BufferedReader reader, BufferedWriter writer) throws IOException {
-//		String line;
-//		while (reader.ready() && ((line = reader.readLine()) != null)) {
-//			writer.write(line);
-//			writer.newLine();
-//		}
-//	}
-
-	private void handleFilter() {
-		FilterDialog dialog = new FilterDialog(getSite().getShell(), fMemento);
-		dialog.create();
-		dialog.getShell().setText(Messages.get().LogView_FilterDialog_title);
-		if (dialog.open() == Window.OK)
-			reloadLog();
-	}
-
-	private void doDeleteLog() {
-		String title = Messages.get().LogView_confirmDelete_title;
-		String message = Messages.get().LogView_confirmDelete_message;
-		if (!MessageDialog.openConfirm(fTree.getShell(), title, message))
-			return;
-		if (fInputFile.delete() || elements.size() > 0) {
-			handleClear();
-		}
-	}
-
-	public void fillContextMenu(IMenuManager manager) { // nothing
-	}
-
-	public AbstractEntry[] getElements() {
-		return (AbstractEntry[]) elements.toArray(new AbstractEntry[elements.size()]);
-	}
-
-	protected void handleClear() {
-		BusyIndicator.showWhile(fTree.getDisplay(), new Runnable() {
-			public void run() {
-				elements.clear();
-				groups.clear();
-				if (currentSession != null) {
-					currentSession.removeAllChildren();
-				}
-				asyncRefresh(false);
-				resetDialogButtons();
-			}
-		});
-	}
-
-	/**
-	 * Reloads the log
-	 */
-	protected void reloadLog() {
-		IRunnableWithProgress op = new IRunnableWithProgress() {
-			public void run(IProgressMonitor monitor) {
-				monitor.beginTask(Messages.get().LogView_operation_reloading, IProgressMonitor.UNKNOWN);
-				readLogFile();
-			}
-		};
-		ProgressMonitorDialog pmd = new ProgressMonitorDialog(getViewSite().getShell());
-		try {
-			pmd.run(true, true, op);
-		} catch (InvocationTargetException e) { // do nothing
-		} catch (InterruptedException e) { // do nothing
-		} finally {
-			fReadLogAction.setText(Messages.get().LogView_readLog_restore);
-			fReadLogAction.setToolTipText(Messages.get().LogView_readLog_restore);
-			asyncRefresh(false);
-			resetDialogButtons();
-		}
-	}
-
-	/**
-	 * Reads the chosen backing log file
-	 */
-	void readLogFile() {
-		elements.clear();
-		groups.clear();
-
-		List result = new ArrayList();
-		LogSession lastLogSession = LogReader.parseLogFile(fInputFile, result, fMemento);
-		if ((lastLogSession != null) && isEclipseStartTime(lastLogSession.getDate())) {
-			currentSession = lastLogSession;
-		} else {
-			currentSession = null;
-		}
-
-		group(result);
-		limitEntriesCount();
-
-		if (fDisplay != null) {
-			fDisplay.asyncExec(new Runnable() {
-				public void run() {
-					setContentDescription(getTitleSummary());
-				}
-			});
-		}
-
-	}
-
-	private boolean isEclipseStartTime(Date date) {
-		String ts = System.getProperty("eclipse.startTime"); //$NON-NLS-1$
-		try {
-			return (ts != null && date != null && date.getTime() == Long.parseLong(ts));
-		} catch (NumberFormatException e) {
-			// empty
-		}
-		return false;
-	}
-
-	private String getTitleSummary() {
-		String path = ""; //$NON-NLS-1$
-		try {
-			path = fInputFile.getCanonicalPath();
-		} catch (IOException e) { // log nothing
-		}
-
-		if (isPlatformLogOpen()) {
-			return Messages.get().LogView_WorkspaceLogFile;
-		}
-
-		Map sources = LogFilesManager.getLogSources();
-		if (sources.containsValue(path)) {
-			for (Iterator i = sources.keySet().iterator(); i.hasNext();) {
-				String key = (String) i.next();
-				if (sources.get(key).equals(path)) {
-					return NLS.bind(Messages.get().LogView_LogFileTitle, new String[] {key, path});
-				}
-			}
-		}
-
-		return path;
-	}
-
-	/**
-	 * Add new entries to correct groups in the view.
-	 * @param entries new entries to show up in groups in the view.
-	 */
-	private void group(List entries) {
-		if (fMemento.getInteger(P_GROUP_BY).intValue() == GROUP_BY_NONE) {
-			elements.addAll(entries);
-		} else {
-			for (Iterator i = entries.iterator(); i.hasNext();) {
-				LogEntry entry = (LogEntry) i.next();
-				Group group = getGroup(entry);
-				group.addChild(entry);
-			}
-		}
-	}
-
-	/**
-	 * Limits the number of entries according to the max entries limit set in
-	 * memento.
-	 */
-	private void limitEntriesCount() {
-		int limit = Integer.MAX_VALUE;
-		if (fMemento.getString(LogView.P_USE_LIMIT).equals("true")) {//$NON-NLS-1$
-			limit = fMemento.getInteger(LogView.P_LOG_LIMIT).intValue();
-		}
-
-		int entriesCount = getEntriesCount();
-
-		if (entriesCount <= limit) {
-			return;
-		}
-		Comparator dateComparator = new Comparator() {
-			public int compare(Object o1, Object o2) {
-				Date l1 = ((LogEntry) o1).getDate();
-				Date l2 = ((LogEntry) o2).getDate();
-				if ((l1 != null) && (l2 != null)) {
-					return l1.before(l2) ? -1 : 1;
-				} else if ((l1 == null) && (l2 == null)) {
-					return 0;
-				} else
-					return (l1 == null) ? -1 : 1;
-			}
-		};
-
-		if (fMemento.getInteger(P_GROUP_BY).intValue() == GROUP_BY_NONE) {
-			elements.subList(0, elements.size() - limit).clear();
-		} else {
-			List copy = new ArrayList(entriesCount);
-			for (Iterator i = elements.iterator(); i.hasNext();) {
-				AbstractEntry group = (AbstractEntry) i.next();
-				copy.addAll(Arrays.asList(group.getChildren(group)));
-			}
-
-			Collections.sort(copy, dateComparator);
-			List toRemove = copy.subList(0, copy.size() - limit);
-
-			for (Iterator i = elements.iterator(); i.hasNext();) {
-				AbstractEntry group = (AbstractEntry) i.next();
-				group.removeChildren(toRemove);
-			}
-		}
-
-	}
-
-	private int getEntriesCount() {
-		if (fMemento.getInteger(P_GROUP_BY).intValue() == GROUP_BY_NONE) {
-			return elements.size();
-		}
-		int size = 0;
-		for (Iterator i = elements.iterator(); i.hasNext();) {
-			AbstractEntry group = (AbstractEntry) i.next();
-			size += group.size();
-		}
-		return size;
-	}
-
-	/**
-	 * Returns group appropriate for the entry. Group depends on P_GROUP_BY
-	 * preference, or is null if grouping is disabled (GROUP_BY_NONE), or group
-	 * could not be determined. May create group if it haven't existed before.
-	 * 
-	 * @param entry entry to be grouped
-	 * @return group or null if grouping is disabled
-	 */
-	protected Group getGroup(LogEntry entry) {
-		int groupBy = fMemento.getInteger(P_GROUP_BY).intValue();
-		Object elementGroupId = null;
-		String groupName = null;
-
-		switch (groupBy) {
-			case GROUP_BY_PLUGIN :
-				groupName = entry.getPluginId();
-				elementGroupId = groupName;
-				break;
-
-			case GROUP_BY_SESSION :
-				elementGroupId = entry.getSession();
-				break;
-
-			default : // grouping is disabled
-				return null;
-		}
-
-		if (elementGroupId == null) { // could not determine group
-			return null;
-		}
-
-		Group group = (Group) groups.get(elementGroupId);
-		if (group == null) {
-			if (groupBy == GROUP_BY_SESSION) {
-				group = entry.getSession();
-			} else {
-				group = new Group(groupName);
-			}
-			groups.put(elementGroupId, group);
-			elements.add(group);
-		}
-
-		return group;
-	}
-
-	public void logging(IStatus status, String plugin) {
-		if (!isPlatformLogOpen())
-			return;
-
-		if (batchEntries) {
-			// create LogEntry immediately to don't loose IStatus creation date.
-			LogEntry entry = createLogEntry(status);
-			batchedEntries.add(entry);
-			return;
-		}
-
-		if (fFirstEvent || (currentSession == null)) {
-			readLogFile();
-			asyncRefresh(true);
-			fFirstEvent = false;
-		} else {
-			LogEntry entry = createLogEntry(status);
-
-			if (!batchedEntries.isEmpty()) {
-				// batch new entry as well, to have only one asyncRefresh()
-				batchedEntries.add(entry);
-				pushBatchedEntries();
-			} else {
-				pushEntry(entry);
-				asyncRefresh(true);
-			}
-		}
-	}
-
-	/**
-	 * Push batched entries to log view.
-	 */
-	private void pushBatchedEntries() {
-		Job job = new Job(Messages.get().LogView_AddingBatchedEvents) {
-			protected IStatus run(IProgressMonitor monitor) {
-				for (int i = 0; i < batchedEntries.size(); i++) {
-					if (!monitor.isCanceled()) {
-						LogEntry entry = (LogEntry) batchedEntries.get(i);
-						pushEntry(entry);
-						batchedEntries.remove(i);
-					}
-				}
-				asyncRefresh(true);
-				return Status.OK_STATUS;
-			}
-		};
-		job.schedule();
-	}
-
-	private LogEntry createLogEntry(IStatus status) {
-		LogEntry entry = new LogEntry(status);
-		entry.setSession(currentSession);
-		return entry;
-	}
-
-	private synchronized void pushEntry(LogEntry entry) {
-		if (LogReader.isLogged(entry, fMemento)) {
-			group(Collections.singletonList(entry));
-			limitEntriesCount();
-		}
-		asyncRefresh(true);
-	}
-
-	private void asyncRefresh(final boolean activate) {
-		if (fTree.isDisposed())
-			return;
-		Display display = fTree.getDisplay();
-		final ViewPart view = this;
-		if (display != null) {
-			display.asyncExec(new Runnable() {
-				public void run() {
-					if (!fTree.isDisposed()) {
-						TreeViewer viewer = fFilteredTree.getViewer();
-						viewer.refresh();
-						viewer.expandToLevel(2);
-						fDeleteLogAction.setEnabled(fInputFile.exists() && fInputFile.equals(Platform.getLogFileLocation().toFile()));
-						fOpenLogAction.setEnabled(fInputFile.exists());
-						fExportLogAction.setEnabled(fInputFile.exists());
-						fExportLogEntryAction.setEnabled(!viewer.getSelection().isEmpty());
-						IWorkbenchWindow window = Activator.getDefault().getWorkbench().getActiveWorkbenchWindow();
-						if (window != null) {
-							IWorkbenchPage page = window.getActivePage();
-							if (page != null) {
-								page.bringToTop(view);
-							}
-						}
-					}
-				}
-			});
-		}
-	}
-
-	public void setFocus() {
-		if (fFilteredTree != null) {
-			if (fMemento.getBoolean(P_SHOW_FILTER_TEXT).booleanValue()) {
-				Text filterControl = fFilteredTree.getFilterControl();
-				if (filterControl != null && !filterControl.isDisposed()) {
-					filterControl.setFocus();
-				}
-			} else if (!fFilteredTree.isDisposed()) {
-				fFilteredTree.setFocus();
-			}
-		}
-	}
-
-	private void handleSelectionChanged(ISelection selection) {
-		updateStatus(selection);
-//		fCopyAction.setEnabled((!selection.isEmpty()) && ((IStructuredSelection) selection).getFirstElement() != null);
-		fPropertiesAction.setEnabled(!selection.isEmpty());
-		fExportLogEntryAction.setEnabled(!selection.isEmpty());
-	}
-
-	private void updateStatus(ISelection selection) {
-		IStatusLineManager status = getViewSite().getActionBars().getStatusLineManager();
-		if (selection.isEmpty())
-			status.setMessage(null);
-		else {
-			Object element = ((IStructuredSelection) selection).getFirstElement();
-			status.setMessage(((LogViewLabelProvider) fFilteredTree.getViewer().getLabelProvider()).getColumnText(element, 0));
-		}
-	}
-
-	/**
-	 * Converts selected log view element to string.
-	 * @return textual log entry representation or null if selection doesn't contain log entry
-	 */
-	private static String selectionToString(ISelection selection) {
-		StringWriter writer = new StringWriter();
-		PrintWriter pwriter = new PrintWriter(writer);
-		if (selection.isEmpty())
-			return null;
-		AbstractEntry entry = (AbstractEntry) ((IStructuredSelection) selection).getFirstElement();
-		entry.write(pwriter);
-		pwriter.flush();
-		String textVersion = writer.toString();
-		pwriter.close();
-		try {
-			writer.close();
-		} catch (IOException e) {
-			// empty
-		}
-
-		return textVersion;
-	}
-
-//	/**
-//	 * Copies selected element to clipboard.
-//	 */
-//	private void copyToClipboard(ISelection selection) {
-//		String textVersion = selectionToString(selection);
-//		if ((textVersion != null) && (textVersion.trim().length() > 0)) {
-//			// set the clipboard contents
-//			fClipboard.setContents(new Object[] {textVersion}, new Transfer[] {TextTransfer.getInstance()});
-//		}
-//	}
-
-	public void init(IViewSite site, IMemento memento) throws PartInitException {
-		super.init(site, memento);
-		if (memento == null)
-			this.fMemento = XMLMemento.createWriteRoot("LOGVIEW"); //$NON-NLS-1$
-		else
-			this.fMemento = memento;
-		readSettings();
-
-		// initialize column ordering 
-		final byte type = this.fMemento.getInteger(P_ORDER_TYPE).byteValue();
-		switch (type) {
-			case DATE :
-				DATE_ORDER = this.fMemento.getInteger(P_ORDER_VALUE).intValue();
-				MESSAGE_ORDER = DESCENDING;
-				PLUGIN_ORDER = DESCENDING;
-				break;
-			case MESSAGE :
-				MESSAGE_ORDER = this.fMemento.getInteger(P_ORDER_VALUE).intValue();
-				DATE_ORDER = DESCENDING;
-				PLUGIN_ORDER = DESCENDING;
-				break;
-			case PLUGIN :
-				PLUGIN_ORDER = this.fMemento.getInteger(P_ORDER_VALUE).intValue();
-				MESSAGE_ORDER = DESCENDING;
-				DATE_ORDER = DESCENDING;
-				break;
-			default :
-				DATE_ORDER = DESCENDING;
-				MESSAGE_ORDER = DESCENDING;
-				PLUGIN_ORDER = DESCENDING;
-		}
-		setComparator(fMemento.getInteger(P_ORDER_TYPE).byteValue());
-	}
-
-	private void initializeMemento() {
-		if (fMemento.getString(P_USE_LIMIT) == null) {
-			fMemento.putString(P_USE_LIMIT, "true"); //$NON-NLS-1$
-		}
-		if (fMemento.getInteger(P_LOG_LIMIT) == null) {
-			fMemento.putInteger(P_LOG_LIMIT, 50);
-		}
-		if (fMemento.getString(P_LOG_INFO) == null) {
-			fMemento.putString(P_LOG_INFO, "true"); //$NON-NLS-1$
-		}
-		if (fMemento.getString(P_LOG_OK) == null) {
-			fMemento.putString(P_LOG_OK, "true"); //$NON-NLS-1$
-		}
-		if (fMemento.getString(P_LOG_WARNING) == null) {
-			fMemento.putString(P_LOG_WARNING, "true"); //$NON-NLS-1$
-		}
-		if (fMemento.getString(P_LOG_ERROR) == null) {
-			fMemento.putString(P_LOG_ERROR, "true"); //$NON-NLS-1$
-		}
-		if (fMemento.getString(P_SHOW_ALL_SESSIONS) == null) {
-			fMemento.putString(P_SHOW_ALL_SESSIONS, "true"); //$NON-NLS-1$
-		}
-	}
-
-	public void saveState(IMemento memento) {
-		if (this.fMemento == null || memento == null)
-			return;
-		//store some sane values to prevent the view from being broken
-		this.fMemento.putInteger(P_COLUMN_1, getColumnWidth(fColumn1, 300));
-		this.fMemento.putInteger(P_COLUMN_2, getColumnWidth(fColumn2, 150));
-		this.fMemento.putInteger(P_COLUMN_3, getColumnWidth(fColumn3, 150));
-		this.fMemento.putString(P_ACTIVATE, fActivateViewAction.isChecked() ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
-		memento.putMemento(this.fMemento);
-		writeSettings();
-	}
-
-	/**
-	 * Returns the width of the column or the default value if the column has been resized to be not visible
-	 * @param column the column to get the width from
-	 * @param defaultwidth the width to return if the column has been resized to not be visible
-	 * @return the width of the column or the default value
-	 * 
-	 * @since 3.6
-	 */
-	int getColumnWidth(TreeColumn column, int defaultwidth) {
-		int width = column.getWidth();
-		return width < 1 ? defaultwidth : width;
-	}
-
-	private void addMouseListeners() {
-		Listener tableListener = new Listener() {
-			public void handleEvent(Event e) {
-				switch (e.type) {
-//					case SWT.MouseExit :
-//					case SWT.MouseMove :
-//						onMouseMove(e);
-//						break;
-//					case SWT.MouseHover :
-//						onMouseHover(e);
-//						break;
-					case SWT.MouseDown :
-						onMouseDown(e);
-						break;
-				}
-			}
-		};
-		int[] tableEvents = new int[] {SWT.MouseDown/*, SWT.MouseMove, SWT.MouseHover, SWT.MouseExit*/};
-		for (int i = 0; i < tableEvents.length; i++) {
-			fTree.addListener(tableEvents[i], tableListener);
-		}
-	}
-
-	/**
-	 * Adds drag source support to error log tree.
-	 */
-	private void addDragSource() {
-		DragSource source = new DragSource(fTree, DND.DROP_COPY);
-		Transfer[] types = new Transfer[] {TextTransfer.getInstance()};
-		source.setTransfer(types);
-
-		source.addDragListener(new DragSourceAdapter() {
-
-			public void dragStart(DragSourceEvent event) {
-				ISelection selection = fFilteredTree.getViewer().getSelection();
-				if (selection.isEmpty()) {
-					event.doit = false;
-					return;
-				}
-
-				AbstractEntry entry = (AbstractEntry) ((TreeSelection) selection).getFirstElement();
-				if (!(entry instanceof LogEntry)) {
-					event.doit = false;
-					return;
-				}
-			}
-
-			public void dragSetData(DragSourceEvent event) {
-				if (!TextTransfer.getInstance().isSupportedType(event.dataType)) {
-					return;
-				}
-
-				ISelection selection = fFilteredTree.getViewer().getSelection();
-				String textVersion = selectionToString(selection);
-				event.data = textVersion;
-			}
-		});
-	}
-
-	private void makeHoverShell() {
-		// parent it off the workbench window's shell so it will be valid regardless of whether the view is a detached window or not
-		fTextShell = new Shell(getSite().getWorkbenchWindow().getShell(), SWT.NO_FOCUS | SWT.ON_TOP | SWT.TOOL);
-		Display display = fTextShell.getDisplay();
-		fTextShell.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
-		GridLayout layout = new GridLayout(1, false);
-		int border = ((fTree.getShell().getStyle() & SWT.NO_TRIM) == 0) ? 0 : 1;
-		layout.marginHeight = border;
-		layout.marginWidth = border;
-		fTextShell.setLayout(layout);
-		fTextShell.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
-		Composite shellComposite = new Composite(fTextShell, SWT.NONE);
-		layout = new GridLayout();
-		layout.marginHeight = 0;
-		layout.marginWidth = 0;
-		shellComposite.setLayout(layout);
-		shellComposite.setLayoutData(new GridData(GridData.FILL_BOTH | GridData.VERTICAL_ALIGN_BEGINNING));
-		fTextLabel = new Text(shellComposite, SWT.WRAP | SWT.MULTI | SWT.READ_ONLY);
-		GridData gd = new GridData(GridData.FILL_BOTH);
-		gd.widthHint = 100;
-		gd.grabExcessHorizontalSpace = true;
-		fTextLabel.setLayoutData(gd);
-		Color c = fTree.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND);
-		fTextLabel.setBackground(c);
-		c = fTree.getDisplay().getSystemColor(SWT.COLOR_INFO_FOREGROUND);
-		fTextLabel.setForeground(c);
-		fTextLabel.setEditable(false);
-		fTextShell.addDisposeListener(new DisposeListener() {
-			public void widgetDisposed(DisposeEvent e) {
-				onTextShellDispose(e);
-			}
-		});
-	}
-
-	void onTextShellDispose(DisposeEvent e) {
-		fCanOpenTextShell = true;
-		setFocus();
-	}
-
-	void onMouseDown(Event e) {
-		if (fTextShell != null && !fTextShell.isDisposed() && !fTextShell.isFocusControl()) {
-			fTextShell.setVisible(false);
-			fCanOpenTextShell = true;
-		}
-	}
-
-	void onMouseHover(Event e) {
-		if (!fCanOpenTextShell || fTextShell == null || fTextShell.isDisposed())
-			return;
-		fCanOpenTextShell = false;
-		Point point = new Point(e.x, e.y);
-		TreeItem item = fTree.getItem(point);
-		if (item == null)
-			return;
-
-		String message = null;
-		if (item.getData() instanceof LogEntry) {
-			message = ((LogEntry) item.getData()).getStack();
-		} else if (item.getData() instanceof LogSession) {
-			LogSession session = ((LogSession) item.getData());
-			message = Messages.get().LogView_SessionStarted;
-			if (session.getDate() != null) {
-				DateFormat formatter = new SimpleDateFormat(LogEntry.F_DATE_FORMAT);
-				message += formatter.format(session.getDate());
-			}
-		}
-
-		if (message == null)
-			return;
-
-		fTextLabel.setText(message);
-		Rectangle bounds = fTree.getDisplay().getBounds();
-		Point cursorPoint = fTree.getDisplay().getCursorLocation();
-		int x = point.x;
-		int y = point.y + 25;
-		int width = fTree.getColumn(0).getWidth();
-		int height = 125;
-		if (cursorPoint.x + width > bounds.width)
-			x -= width;
-		if (cursorPoint.y + height + 25 > bounds.height)
-			y -= height + 27;
-
-		fTextShell.setLocation(fTree.toDisplay(x, y));
-		fTextShell.setSize(width, height);
-		fTextShell.setVisible(true);
-	}
-
-	void onMouseMove(Event e) {
-		if (fTextShell != null && !fTextShell.isDisposed() && fTextShell.isVisible())
-			fTextShell.setVisible(false);
-
-		Point point = new Point(e.x, e.y);
-		TreeItem item = fTree.getItem(point);
-		if (item == null)
-			return;
-		Image image = item.getImage();
-		Object data = item.getData();
-		if (data instanceof LogEntry) {
-			LogEntry entry = (LogEntry) data;
-			int parentCount = getNumberOfParents(entry);
-			int startRange = 20 + Math.max(image.getBounds().width + 2, 7 + 2) * parentCount;
-			int endRange = startRange + 16;
-			fCanOpenTextShell = e.x >= startRange && e.x <= endRange;
-		}
-	}
-
-	private int getNumberOfParents(AbstractEntry entry) {
-		AbstractEntry parent = (AbstractEntry) entry.getParent(entry);
-		if (parent == null)
-			return 0;
-		return 1 + getNumberOfParents(parent);
-	}
-
-	public Comparator getComparator() {
-		return fComparator;
-	}
-
-	private void setComparator(byte sortType) {
-		if (sortType == DATE) {
-			fComparator = new Comparator() {
-				public int compare(Object e1, Object e2) {
-					long date1 = 0;
-					long date2 = 0;
-					if ((e1 instanceof LogEntry) && (e2 instanceof LogEntry)) {
-						date1 = ((LogEntry) e1).getDate().getTime();
-						date2 = ((LogEntry) e2).getDate().getTime();
-					} else if ((e1 instanceof LogSession) && (e2 instanceof LogSession)) {
-						date1 = ((LogSession) e1).getDate() == null ? 0 : ((LogSession) e1).getDate().getTime();
-						date2 = ((LogSession) e2).getDate() == null ? 0 : ((LogSession) e2).getDate().getTime();
-					}
-					if (date1 == date2) {
-						int result = elements.indexOf(e2) - elements.indexOf(e1);
-						if (DATE_ORDER == DESCENDING)
-							result *= DESCENDING;
-						return result;
-					}
-					if (DATE_ORDER == DESCENDING)
-						return date1 > date2 ? DESCENDING : ASCENDING;
-					return date1 < date2 ? DESCENDING : ASCENDING;
-				}
-			};
-		} else if (sortType == PLUGIN) {
-			fComparator = new Comparator() {
-				public int compare(Object e1, Object e2) {
-					if ((e1 instanceof LogEntry) && (e2 instanceof LogEntry)) {
-						LogEntry entry1 = (LogEntry) e1;
-						LogEntry entry2 = (LogEntry) e2;
-						return getDefaultComparator().compare(entry1.getPluginId(), entry2.getPluginId()) * PLUGIN_ORDER;
-					}
-					return 0;
-				}
-			};
-		} else {
-			fComparator = new Comparator() {
-				public int compare(Object e1, Object e2) {
-					if ((e1 instanceof LogEntry) && (e2 instanceof LogEntry)) {
-						LogEntry entry1 = (LogEntry) e1;
-						LogEntry entry2 = (LogEntry) e2;
-						return getDefaultComparator().compare(entry1.getMessage(), entry2.getMessage()) * MESSAGE_ORDER;
-					}
-					return 0;
-				}
-			};
-		}
-	}
-
-	private Comparator getDefaultComparator() {
-		return Policy.getComparator();
-	}
-
-	private ViewerComparator getViewerComparator(byte sortType) {
-		if (sortType == PLUGIN) {
-			return new ViewerComparator() {
-				public int compare(Viewer viewer, Object e1, Object e2) {
-					if ((e1 instanceof LogEntry) && (e2 instanceof LogEntry)) {
-						LogEntry entry1 = (LogEntry) e1;
-						LogEntry entry2 = (LogEntry) e2;
-						return getComparator().compare(entry1.getPluginId(), entry2.getPluginId()) * PLUGIN_ORDER;
-					}
-					return 0;
-				}
-			};
-		} else if (sortType == MESSAGE) {
-			return new ViewerComparator() {
-				public int compare(Viewer viewer, Object e1, Object e2) {
-					if ((e1 instanceof LogEntry) && (e2 instanceof LogEntry)) {
-						LogEntry entry1 = (LogEntry) e1;
-						LogEntry entry2 = (LogEntry) e2;
-						return getComparator().compare(entry1.getMessage(), entry2.getMessage()) * MESSAGE_ORDER;
-					}
-					return 0;
-				}
-			};
-		} else {
-			return new ViewerComparator() {
-				private int indexOf(Object[] array, Object o) {
-					if (o == null)
-						return -1;
-					for (int i = 0; i < array.length; ++i)
-						if (o.equals(array[i]))
-							return i;
-					return -1;
-				}
-
-				public int compare(Viewer viewer, Object e1, Object e2) {
-					long date1 = 0;
-					long date2 = 0;
-					if ((e1 instanceof LogEntry) && (e2 instanceof LogEntry)) {
-						date1 = ((LogEntry) e1).getDate().getTime();
-						date2 = ((LogEntry) e2).getDate().getTime();
-					} else if ((e1 instanceof LogSession) && (e2 instanceof LogSession)) {
-						date1 = ((LogSession) e1).getDate() == null ? 0 : ((LogSession) e1).getDate().getTime();
-						date2 = ((LogSession) e2).getDate() == null ? 0 : ((LogSession) e2).getDate().getTime();
-					}
-
-					if (date1 == date2) {
-						// Everything that appears in LogView should be an AbstractEntry.
-						AbstractEntry parent = (AbstractEntry) ((AbstractEntry) e1).getParent(null);
-						Object[] children = null;
-						if (parent != null)
-							children = parent.getChildren(parent);
-
-						int result = 0;
-						if (children != null) {
-							// The elements in children seem to be in reverse order,
-							// i.e. latest log message first, therefore index(e2)-index(e1)
-							result = indexOf(children, e2) - indexOf(children, e1);
-						} else {
-							result = elements.indexOf(e1) - elements.indexOf(e2);
-						}
-						if (DATE_ORDER == DESCENDING)
-							result *= DESCENDING;
-						return result;
-					}
-					if (DATE_ORDER == DESCENDING)
-						return date1 > date2 ? DESCENDING : ASCENDING;
-					return date1 < date2 ? DESCENDING : ASCENDING;
-				}
-			};
-		}
-	}
-
-	private void resetDialogButtons() {
-		((EventDetailsDialogAction) fPropertiesAction).resetDialogButtons();
-	}
-
-	/**
-	 * Returns the filter dialog settings object used to maintain
-	 * state between filter dialogs
-	 * @return the dialog settings to be used
-	 */
-	private IDialogSettings getLogSettings() {
-		IDialogSettings settings = Activator.getDefault().getDialogSettings();
-		return settings.getSection(getClass().getName());
-	}
-
-	/**
-	 * Returns the plugin preferences used to maintain
-	 * state of log view
-	 * @return the plugin preferences
-	 */
-	private Preferences getLogPreferences() {
-		return (new SessionScope()).getNode(Activator.PLUGIN_ID);
-	}
-
-	/**
-	 * Loads any saved {@link IDialogSettings} into the backing view memento
-	 */
-	private void readSettings() {
-		IDialogSettings s = getLogSettings();
-		if (s == null) {
-			initializeMemento();
-		} else {
-			fMemento.putString(P_USE_LIMIT, s.getBoolean(P_USE_LIMIT) ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
-			fMemento.putString(P_LOG_INFO, s.getBoolean(P_LOG_INFO) ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
-			fMemento.putString(P_LOG_OK, s.getBoolean(P_LOG_OK) ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
-			fMemento.putString(P_LOG_WARNING, s.getBoolean(P_LOG_WARNING) ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
-			fMemento.putString(P_LOG_ERROR, s.getBoolean(P_LOG_ERROR) ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
-			fMemento.putString(P_SHOW_ALL_SESSIONS, s.getBoolean(P_SHOW_ALL_SESSIONS) ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
-			try {
-				fMemento.putInteger(P_LOG_LIMIT, s.getInt(P_LOG_LIMIT));
-			} catch (NumberFormatException e) {
-				fMemento.putInteger(P_LOG_LIMIT, 50);
-			}
-		}
-
-		Preferences p = getLogPreferences(); // never returns null
-		fMemento.putInteger(P_COLUMN_1, getColumnWidthPreference(p, P_COLUMN_1, 300));
-		fMemento.putInteger(P_COLUMN_2, getColumnWidthPreference(p, P_COLUMN_2, 150));
-		fMemento.putInteger(P_COLUMN_3, getColumnWidthPreference(p, P_COLUMN_3, 150));
-		fMemento.putBoolean(P_ACTIVATE, p.getBoolean(P_ACTIVATE, true));
-		fMemento.putInteger(P_ORDER_VALUE, p.getInt(P_ORDER_VALUE, DESCENDING));
-		fMemento.putInteger(P_ORDER_TYPE, p.getInt(P_ORDER_TYPE, LogView.DATE));
-		fMemento.putBoolean(P_SHOW_FILTER_TEXT, p.getBoolean(P_SHOW_FILTER_TEXT, true));
-		fMemento.putInteger(P_GROUP_BY, p.getInt(P_GROUP_BY, LogView.GROUP_BY_NONE));
-	}
-
-	/**
-	 * Returns the width to use for the column represented by the given key. The default width
-	 * is returned iff:
-	 * <ul>
-	 * <li>There is no preference for the given key</li>
-	 * <li>The returned preference value is too small, making the columns invisible by width.</li>
-	 * </ul>
-	 * @param preferences
-	 * @param key
-	 * @param defaultwidth
-	 * @return the stored width for the a column described by the given key or the default width
-	 * 
-	 * @since 3.6
-	 */
-	int getColumnWidthPreference(Preferences preferences, String key, int defaultwidth) {
-		int width = preferences.getInt(key, defaultwidth);
-		return width < 1 ? defaultwidth : width;
-	}
-
-	private void writeSettings() {
-		writeViewSettings();
-		writeFilterSettings();
-	}
-
-	private void writeFilterSettings() {
-		IDialogSettings settings = getLogSettings();
-		if (settings == null)
-			settings = Activator.getDefault().getDialogSettings().addNewSection(getClass().getName());
-		settings.put(P_USE_LIMIT, fMemento.getString(P_USE_LIMIT).equals("true")); //$NON-NLS-1$
-		settings.put(P_LOG_LIMIT, fMemento.getInteger(P_LOG_LIMIT).intValue());
-		settings.put(P_LOG_INFO, fMemento.getString(P_LOG_INFO).equals("true")); //$NON-NLS-1$
-		settings.put(P_LOG_OK, fMemento.getString(P_LOG_OK).equals("true")); //$NON-NLS-1$
-		settings.put(P_LOG_WARNING, fMemento.getString(P_LOG_WARNING).equals("true")); //$NON-NLS-1$
-		settings.put(P_LOG_ERROR, fMemento.getString(P_LOG_ERROR).equals("true")); //$NON-NLS-1$
-		settings.put(P_SHOW_ALL_SESSIONS, fMemento.getString(P_SHOW_ALL_SESSIONS).equals("true")); //$NON-NLS-1$
-	}
-
-	private void writeViewSettings() {
-		Preferences preferences = getLogPreferences();
-		preferences.putInt(P_COLUMN_1, fMemento.getInteger(P_COLUMN_1).intValue());
-		preferences.putInt(P_COLUMN_2, fMemento.getInteger(P_COLUMN_2).intValue());
-		preferences.putInt(P_COLUMN_3, fMemento.getInteger(P_COLUMN_3).intValue());
-		preferences.putBoolean(P_ACTIVATE, fMemento.getBoolean(P_ACTIVATE).booleanValue());
-		preferences.putInt(P_ORDER_VALUE, fMemento.getInteger(P_ORDER_VALUE).intValue());
-		preferences.putInt(P_ORDER_TYPE, fMemento.getInteger(P_ORDER_TYPE).intValue());
-		preferences.putBoolean(P_SHOW_FILTER_TEXT, fMemento.getBoolean(P_SHOW_FILTER_TEXT).booleanValue());
-		preferences.putInt(P_GROUP_BY, fMemento.getInteger(P_GROUP_BY).intValue());
-		try {
-			preferences.flush();
-		} catch (BackingStoreException e) {
-			// empty
-		}
-	}
-
-	public void sortByDateDescending() {
-		setColumnSorting(fColumn3, DESCENDING);
-	}
-
-	protected Job getOpenLogFileJob() {
-		final Shell shell = getViewSite().getShell();
-		return new Job(Messages.get().OpenLogDialog_message) {
-			protected IStatus run(IProgressMonitor monitor) {
-//				boolean failed = false;
-//				if (fInputFile.length() <= LogReader.MAX_FILE_LENGTH) {
-//					failed = !Program.launch(fInputFile.getAbsolutePath());
-//					if (failed) {
-//						Program p = Program.findProgram(".txt"); //$NON-NLS-1$
-//						if (p != null) {
-//							p.execute(fInputFile.getAbsolutePath());
-//							return Status.OK_STATUS;
-//						}
-//					}
-//				}
-//				if (failed) {
-				final OpenLogDialog openDialog = new OpenLogDialog(shell, fInputFile);
-				shell.getDisplay().asyncExec(new Runnable() {
-					public void run() {
-						openDialog.create();
-						openDialog.open();
-					}
-				});
-//				}
-				return Status.OK_STATUS;
-			}
-		};
-	}
-
-	protected File getLogFile() {
-		return fInputFile;
-	}
-
-	/**
-	 * Returns whether given session equals to currently displayed in LogView.
-	 * @param session LogSession
-	 * @return true if given session equals to currently displayed in LogView
-	 */
-	public boolean isCurrentLogSession(LogSession session) {
-		return isPlatformLogOpen() && (currentSession != null) && (currentSession.equals(session));
-	}
-
-	/**
-	 * Returns whether currently open log is platform log or imported file.
-	 * @return true if currently open log is platform log, false otherwise
-	 */
-	public boolean isPlatformLogOpen() {
-		return (fInputFile.equals(Platform.getLogFileLocation().toFile()));
-	}
-
-	/**
-	 * 
-	 */
-	public void setPlatformLog() {
-		setLogFile(Platform.getLogFileLocation().toFile());
-	}
-}
+/*******************************************************************************
+ * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jacek Pospychala <jacek.pospychala@pl.ibm.com> - bugs 202583, 202584, 207344
+ *     													bugs 207323, 207931, 207101
+ *     													bugs 172658, 216341, 216657
+ *     Benjamin Cabe <benjamin.cabe@anyware-tech.com> - bug 218648 
+ *     Tuukka Lehtonen <tuukka.lehtonen@semantum.fi>  - bug 247907
+ *     Arnaud Mergey <a_mergey@yahoo.fr> 			  - RAP port
+ *******************************************************************************/
+
+package org.eclipse.ui.internal.views.log;
+
+import java.io.*;
+import java.lang.reflect.InvocationTargetException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.List;
+import org.eclipse.core.runtime.*;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.action.*;
+import org.eclipse.jface.dialogs.*;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.util.Policy;
+import org.eclipse.jface.viewers.*;
+import org.eclipse.jface.window.Window;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.rap.rwt.RWT;
+import org.eclipse.rap.rwt.client.service.UrlLauncher;
+import org.eclipse.rap.ui.internal.preferences.SessionScope;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.BusyIndicator;
+import org.eclipse.swt.dnd.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.ui.*;
+import org.eclipse.ui.dialogs.FilteredTree;
+import org.eclipse.ui.dialogs.PatternFilter;
+import org.eclipse.ui.part.ViewPart;
+import org.osgi.service.prefs.BackingStoreException;
+import org.osgi.service.prefs.Preferences;
+
+public class LogView extends ViewPart implements ILogListener {
+	public static final String DOWNLOAD_SERVICE_HANDLER_ID = "org.eclipse.rap.ui.view.log.downloadLogFile"; //$NON-NLS-1$
+
+	public static final String P_LOG_WARNING = "warning"; //$NON-NLS-1$
+	public static final String P_LOG_ERROR = "error"; //$NON-NLS-1$
+	public static final String P_LOG_INFO = "info"; //$NON-NLS-1$
+	public static final String P_LOG_OK = "ok"; //$NON-NLS-1$
+	public static final String P_LOG_LIMIT = "limit"; //$NON-NLS-1$
+	public static final String P_USE_LIMIT = "useLimit"; //$NON-NLS-1$
+	public static final String P_SHOW_ALL_SESSIONS = "allSessions"; //$NON-NLS-1$
+	protected static final String P_COLUMN_1 = "column2"; //$NON-NLS-1$
+	protected static final String P_COLUMN_2 = "column3"; //$NON-NLS-1$
+	protected static final String P_COLUMN_3 = "column4"; //$NON-NLS-1$
+	public static final String P_ACTIVATE = "activate"; //$NON-NLS-1$
+	public static final String P_SHOW_FILTER_TEXT = "show_filter_text"; //$NON-NLS-1$
+	public static final String P_ORDER_TYPE = "orderType"; //$NON-NLS-1$
+	public static final String P_ORDER_VALUE = "orderValue"; //$NON-NLS-1$
+	public static final String P_IMPORT_LOG = "importLog"; //$NON-NLS-1$
+	public static final String P_GROUP_BY = "groupBy"; //$NON-NLS-1$
+
+	private int MESSAGE_ORDER;
+	private int PLUGIN_ORDER;
+	private int DATE_ORDER;
+
+	public final static byte MESSAGE = 0x0;
+	public final static byte PLUGIN = 0x1;
+	public final static byte DATE = 0x2;
+	public static int ASCENDING = 1;
+	public static int DESCENDING = -1;
+
+	public static final int GROUP_BY_NONE = 0;
+	public static final int GROUP_BY_SESSION = 1;
+	public static final int GROUP_BY_PLUGIN = 2;
+
+	private List elements;
+	private Map groups;
+	private LogSession currentSession;
+
+	private List batchedEntries;
+	private boolean batchEntries;
+
+//	private Clipboard fClipboard;
+
+	private IMemento fMemento;
+	private File fInputFile;
+//	private String fDirectory;
+
+	private Comparator fComparator;
+
+	// hover text
+	private boolean fCanOpenTextShell;
+	private Text fTextLabel;
+	private Shell fTextShell;
+
+	private boolean fFirstEvent = true;
+
+	private TreeColumn fColumn1;
+	private TreeColumn fColumn2;
+	private TreeColumn fColumn3;
+
+	private Tree fTree;
+	private FilteredTree fFilteredTree;
+	private LogViewLabelProvider fLabelProvider;
+
+	private Action fPropertiesAction;
+	private Action fDeleteLogAction;
+	private Action fReadLogAction;
+//	private Action fCopyAction;
+	private Action fActivateViewAction;
+	private Action fOpenLogAction;
+	private Action fExportLogAction;
+	private Action fExportLogEntryAction;
+
+	private Display fDisplay = null;
+
+	/**
+	 * Action called when user selects "Group by -> ..." from menu.
+	 */
+	class GroupByAction extends Action {
+		private int groupBy;
+
+		public GroupByAction(String text, int groupBy) {
+			super(text, IAction.AS_RADIO_BUTTON);
+
+			this.groupBy = groupBy;
+
+			if (fMemento.getInteger(LogView.P_GROUP_BY).intValue() == groupBy) {
+				setChecked(true);
+			}
+		}
+
+		public void run() {
+			if (fMemento.getInteger(LogView.P_GROUP_BY).intValue() != groupBy) {
+				fMemento.putInteger(LogView.P_GROUP_BY, groupBy);
+				reloadLog();
+			}
+		}
+	}
+
+	/**
+	 * Constructor
+	 */
+	public LogView() {
+		elements = new ArrayList();
+		groups = new HashMap();
+		batchedEntries = new ArrayList();
+		fInputFile = Platform.getLogFileLocation().toFile();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
+	 */
+	public void createPartControl(Composite parent) {
+		fDisplay = getSite().getShell().getDisplay();
+		Composite composite = new Composite(parent, SWT.NONE);
+		GridLayout layout = new GridLayout();
+		layout.horizontalSpacing = 0;
+		layout.verticalSpacing = 0;
+		layout.marginWidth = 0;
+		layout.marginHeight = 0;
+		composite.setLayout(layout);
+//		composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+		readLogFile();
+		createViewer(composite);
+		getSite().setSelectionProvider(fFilteredTree.getViewer());
+		createActions();
+//		fClipboard = new Clipboard(fTree.getDisplay());
+		fTree.setToolTipText(""); //$NON-NLS-1$
+		initializeViewerSorter();
+
+		makeHoverShell();
+
+		Platform.addLogListener(this);
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(fFilteredTree, IHelpContextIds.LOG_VIEW);
+		getSite().getWorkbenchWindow().addPerspectiveListener(new IPerspectiveListener2() {
+
+			public void perspectiveChanged(IWorkbenchPage page, IPerspectiveDescriptor perspective, IWorkbenchPartReference partRef, String changeId) {
+				if (!(partRef instanceof IViewReference))
+					return;
+
+				IWorkbenchPart part = partRef.getPart(false);
+				if (part == null) {
+					return;
+				}
+
+				if (part.equals(LogView.this)) {
+					if (changeId.equals(IWorkbenchPage.CHANGE_VIEW_SHOW)) {
+						if (!batchedEntries.isEmpty()) {
+							pushBatchedEntries();
+						}
+
+						batchEntries = false;
+					} else if (changeId.equals(IWorkbenchPage.CHANGE_VIEW_HIDE)) {
+						batchEntries = true;
+					}
+				}
+			}
+
+			public void perspectiveActivated(IWorkbenchPage page, IPerspectiveDescriptor perspective) {
+				// empty
+			}
+
+			public void perspectiveChanged(IWorkbenchPage page, IPerspectiveDescriptor perspective, String changeId) {
+				// empty
+			}
+
+		});
+	}
+
+	/**
+	 * Creates the actions for the viewsite action bars
+	 */
+	private void createActions() {
+		IActionBars bars = getViewSite().getActionBars();
+
+//		fCopyAction = createCopyAction();
+//		bars.setGlobalActionHandler(ActionFactory.COPY.getId(), fCopyAction);
+
+		IToolBarManager toolBarManager = bars.getToolBarManager();
+
+		fExportLogAction = createExportLogAction();
+		toolBarManager.add(fExportLogAction);
+
+		fExportLogEntryAction = createExportLogEntryAction();
+
+		final Action importLogAction = createImportLogAction();
+		toolBarManager.add(importLogAction);
+
+		toolBarManager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
+
+		final Action clearAction = createClearAction();
+		toolBarManager.add(clearAction);
+
+		fDeleteLogAction = createDeleteLogAction();
+		toolBarManager.add(fDeleteLogAction);
+
+		fOpenLogAction = createOpenLogAction();
+		toolBarManager.add(fOpenLogAction);
+
+		fReadLogAction = createReadLogAction();
+		toolBarManager.add(fReadLogAction);
+
+		toolBarManager.add(new Separator());
+
+		IMenuManager mgr = bars.getMenuManager();
+
+		mgr.add(createGroupByAction());
+		mgr.add(new Separator());
+		mgr.add(createFilterAction());
+		mgr.add(new Separator());
+
+		fActivateViewAction = createActivateViewAction();
+		mgr.add(fActivateViewAction);
+		if (fFilteredTree.getFilterControl() != null)
+			mgr.add(createShowTextFilter());
+
+		fPropertiesAction = createPropertiesAction();
+
+		MenuManager popupMenuManager = new MenuManager("#PopupMenu"); //$NON-NLS-1$
+		IMenuListener listener = new IMenuListener() {
+			public void menuAboutToShow(IMenuManager manager) {
+//				manager.add(fCopyAction);
+//				manager.add(new Separator());
+				manager.add(clearAction);
+				manager.add(fDeleteLogAction);
+				manager.add(fOpenLogAction);
+				manager.add(fReadLogAction);
+				manager.add(new Separator());
+				manager.add(fExportLogAction);
+				manager.add(createImportLogAction());
+				manager.add(new Separator());
+				manager.add(fExportLogEntryAction);
+				manager.add(new Separator());
+
+				((EventDetailsDialogAction) fPropertiesAction).setComparator(fComparator);
+				TreeItem[] selection = fTree.getSelection();
+				if ((selection.length > 0) && (selection[0].getData() instanceof LogEntry)) {
+					manager.add(fPropertiesAction);
+				}
+
+				manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
+			}
+		};
+		popupMenuManager.addMenuListener(listener);
+		popupMenuManager.setRemoveAllWhenShown(true);
+		getSite().registerContextMenu(popupMenuManager, getSite().getSelectionProvider());
+		Menu menu = popupMenuManager.createContextMenu(fTree);
+		fTree.setMenu(menu);
+	}
+
+	private Action createActivateViewAction() {
+		Action action = new Action(Messages.get().LogView_activate) { //       	
+			public void run() {
+				fMemento.putString(P_ACTIVATE, isChecked() ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+		};
+		action.setChecked(fMemento.getString(P_ACTIVATE).equals("true")); //$NON-NLS-1$
+		return action;
+	}
+
+	private Action createClearAction() {
+		Action action = new Action(Messages.get().LogView_clear) {
+			public void run() {
+				handleClear();
+			}
+		};
+		action.setImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_CLEAR));
+		action.setDisabledImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_CLEAR_DISABLED));
+		action.setToolTipText(Messages.get().LogView_clear_tooltip);
+		action.setText(Messages.get().LogView_clear);
+		return action;
+	}
+
+//	private Action createCopyAction() {
+//		Action action = new Action(Messages.get().LogView_copy) {
+//			public void run() {
+//				copyToClipboard(fFilteredTree.getViewer().getSelection());
+//			}
+//		};
+//		action.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_TOOL_COPY));
+//		return action;
+//	}
+
+	private Action createDeleteLogAction() {
+		Action action = new Action(Messages.get().LogView_delete) {
+			public void run() {
+				doDeleteLog();
+			}
+		};
+		action.setToolTipText(Messages.get().LogView_delete_tooltip);
+		action.setImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_REMOVE_LOG));
+		action.setDisabledImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_REMOVE_LOG_DISABLED));
+		action.setEnabled(fInputFile.exists() && fInputFile.equals(Platform.getLogFileLocation().toFile()));
+		return action;
+	}
+
+	private Action createExportLogAction() {
+		Action action = new Action(Messages.get().LogView_export) {
+			public void run() {
+				handleExport(true);
+			}
+		};
+		action.setToolTipText(Messages.get().LogView_export_tooltip);
+		action.setImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_EXPORT));
+		action.setDisabledImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_EXPORT_DISABLED));
+		action.setEnabled(fInputFile.exists());
+		return action;
+	}
+
+	private Action createExportLogEntryAction() {
+		Action action = new Action(Messages.get().LogView_exportEntry) {
+			public void run() {
+				handleExport(false);
+			}
+		};
+		action.setToolTipText(Messages.get().LogView_exportEntry_tooltip);
+		action.setImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_EXPORT));
+		action.setDisabledImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_EXPORT_DISABLED));
+		action.setEnabled(!fFilteredTree.getViewer().getSelection().isEmpty());
+		return action;
+	}
+
+	private Action createFilterAction() {
+		Action action = new Action(Messages.get().LogView_filter) {
+			public void run() {
+				handleFilter();
+			}
+		};
+		action.setToolTipText(Messages.get().LogView_filter);
+		action.setImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_FILTER));
+		action.setDisabledImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_FILTER_DISABLED));
+		return action;
+	}
+
+	private Action createImportLogAction() {
+		Action action = new ImportLogAction(this, Messages.get().LogView_import, fMemento);
+		action.setToolTipText(Messages.get().LogView_import_tooltip);
+		action.setImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_IMPORT));
+		action.setDisabledImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_IMPORT_DISABLED));
+		return action;
+	}
+
+	private Action createOpenLogAction() {
+		Action action = null;
+//		try {
+//			// TODO this isn't the best way to check... we should be smarter and use package admin
+//			// check to see if org.eclipse.ui.ide is available
+//			Class.forName("org.eclipse.ui.ide.IDE"); //$NON-NLS-1$
+//			// check to see if org.eclipse.core.filesystem is available
+//			Class.forName("org.eclipse.core.filesystem.IFileStore"); //$NON-NLS-1$
+//			action = new OpenIDELogFileAction(this);
+//		} catch (ClassNotFoundException e) {
+		action = new Action() {
+			public void run() {
+				if (fInputFile.exists()) {
+					Job job = getOpenLogFileJob();
+					job.setUser(false);
+					job.setPriority(Job.SHORT);
+					job.schedule();
+				}
+			}
+		};
+//		}
+		action.setText(Messages.get().LogView_view_currentLog);
+		action.setImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_OPEN_LOG));
+		action.setDisabledImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_OPEN_LOG_DISABLED));
+		action.setEnabled(fInputFile.exists());
+		action.setToolTipText(Messages.get().LogView_view_currentLog_tooltip);
+		return action;
+	}
+
+	private Action createPropertiesAction() {
+		Action action = new EventDetailsDialogAction(fTree, fFilteredTree.getViewer(), fMemento);
+		action.setImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_PROPERTIES));
+		action.setDisabledImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_PROPERTIES_DISABLED));
+		action.setToolTipText(Messages.get().LogView_properties_tooltip);
+		action.setEnabled(false);
+		return action;
+	}
+
+	private Action createReadLogAction() {
+		Action action = new Action(Messages.get().LogView_readLog_restore) {
+			public void run() {
+				fInputFile = Platform.getLogFileLocation().toFile();
+				reloadLog();
+			}
+		};
+		action.setToolTipText(Messages.get().LogView_readLog_restore_tooltip);
+		action.setImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_READ_LOG));
+		action.setDisabledImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_READ_LOG_DISABLED));
+		return action;
+	}
+
+	/**
+	 * Creates the Show Text Filter view menu action 
+	 * @return the new action for the Show Text Filter 
+	 */
+	private Action createShowTextFilter() {
+		Action action = new Action(Messages.get().LogView_show_filter_text) {
+			public void run() {
+				showFilterText(isChecked());
+			}
+		};
+		boolean visible = fMemento.getBoolean(P_SHOW_FILTER_TEXT).booleanValue();
+		action.setChecked(visible);
+		showFilterText(visible);
+		return action;
+	}
+
+	/**
+	 * Shows/hides the filter text control from the filtered tree. This method also sets the 
+	 * P_SHOW_FILTER_TEXT preference to the visible state
+	 * 
+	 * @param visible if the filter text control should be shown or not
+	 */
+	private void showFilterText(boolean visible) {
+		fMemento.putBoolean(P_SHOW_FILTER_TEXT, visible);
+
+		Text filterControl = fFilteredTree.getFilterControl();
+		Composite filterComposite = filterControl.getParent(); // FilteredTree new look lays filter Text on additional composite
+
+		GridData gd = (GridData) filterComposite.getLayoutData();
+		gd.exclude = !visible;
+		filterComposite.setVisible(visible);
+
+		// reset control if we aren't visible and if we get visible again
+		filterControl.setText(Messages.get().LogView_show_filter_initialText);
+
+		if (visible) {
+			filterControl.selectAll();
+			setFocus();
+		}
+
+		fFilteredTree.layout(false);
+	}
+
+	private IContributionItem createGroupByAction() {
+		IMenuManager manager = new MenuManager(Messages.get().LogView_GroupBy);
+		manager.add(new GroupByAction(Messages.get().LogView_GroupBySession, LogView.GROUP_BY_SESSION));
+		manager.add(new GroupByAction(Messages.get().LogView_GroupByPlugin, LogView.GROUP_BY_PLUGIN));
+		manager.add(new GroupByAction(Messages.get().LogView_GroupByNone, LogView.GROUP_BY_NONE));
+		return manager;
+	}
+
+	private void createViewer(Composite parent) {
+		PatternFilter filter = new PatternFilter() {
+			protected boolean isLeafMatch(Viewer viewer, Object element) {
+				if (element instanceof LogEntry) {
+					LogEntry logEntry = (LogEntry) element;
+					String message = logEntry.getMessage();
+					String plugin = logEntry.getPluginId();
+					DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, RWT.getLocale());
+					String date = dateFormat.format(logEntry.getDate());
+					return wordMatches(message) || wordMatches(plugin) || wordMatches(date);
+				}
+				return false;
+			}
+		};
+		filter.setIncludeLeadingWildcard(true);
+		fFilteredTree = new FilteredTree(parent, SWT.FULL_SELECTION, filter, true);
+		// need to give filter Textbox some space from the border
+		if (fFilteredTree.getFilterControl() != null) {
+			Composite filterComposite = fFilteredTree.getFilterControl().getParent(); // FilteredTree new look lays filter Text on additional composite
+			GridData gd = (GridData) filterComposite.getLayoutData();
+			gd.verticalIndent = 2;
+			gd.horizontalIndent = 1;
+		}
+		fFilteredTree.setLayoutData(new GridData(GridData.FILL_BOTH));
+		fFilteredTree.setInitialText(Messages.get().LogView_show_filter_initialText);
+		fTree = fFilteredTree.getViewer().getTree();
+		fTree.setLinesVisible(true);
+		createColumns(fTree);
+		fFilteredTree.getViewer().setAutoExpandLevel(2);
+		fFilteredTree.getViewer().setContentProvider(new LogViewContentProvider(this));
+		fFilteredTree.getViewer().setLabelProvider(fLabelProvider = new LogViewLabelProvider(this));
+		fLabelProvider.connect(this);
+		fFilteredTree.getViewer().addSelectionChangedListener(new ISelectionChangedListener() {
+			public void selectionChanged(SelectionChangedEvent e) {
+				handleSelectionChanged(e.getSelection());
+				if (fPropertiesAction.isEnabled())
+					((EventDetailsDialogAction) fPropertiesAction).resetSelection();
+			}
+		});
+		fFilteredTree.getViewer().addDoubleClickListener(new IDoubleClickListener() {
+			public void doubleClick(DoubleClickEvent event) {
+				((EventDetailsDialogAction) fPropertiesAction).setComparator(fComparator);
+				fPropertiesAction.run();
+			}
+		});
+		fFilteredTree.getViewer().setInput(this);
+		addMouseListeners();
+		addDragSource();
+	}
+
+	private void createColumns(Tree tree) {
+		fColumn1 = new TreeColumn(tree, SWT.LEFT);
+		fColumn1.setText(Messages.get().LogView_column_message);
+		fColumn1.setWidth(fMemento.getInteger(P_COLUMN_1).intValue());
+		fColumn1.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				MESSAGE_ORDER *= -1;
+				ViewerComparator comparator = getViewerComparator(MESSAGE);
+				fFilteredTree.getViewer().setComparator(comparator);
+				boolean isComparatorSet = ((EventDetailsDialogAction) fPropertiesAction).resetSelection(MESSAGE, MESSAGE_ORDER);
+				setComparator(MESSAGE);
+				if (!isComparatorSet)
+					((EventDetailsDialogAction) fPropertiesAction).setComparator(fComparator);
+				fMemento.putInteger(P_ORDER_VALUE, MESSAGE_ORDER);
+				fMemento.putInteger(P_ORDER_TYPE, MESSAGE);
+				setColumnSorting(fColumn1, MESSAGE_ORDER);
+			}
+		});
+
+		fColumn2 = new TreeColumn(tree, SWT.LEFT);
+		fColumn2.setText(Messages.get().LogView_column_plugin);
+		fColumn2.setWidth(fMemento.getInteger(P_COLUMN_2).intValue());
+		fColumn2.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				PLUGIN_ORDER *= -1;
+				ViewerComparator comparator = getViewerComparator(PLUGIN);
+				fFilteredTree.getViewer().setComparator(comparator);
+				boolean isComparatorSet = ((EventDetailsDialogAction) fPropertiesAction).resetSelection(PLUGIN, PLUGIN_ORDER);
+				setComparator(PLUGIN);
+				if (!isComparatorSet)
+					((EventDetailsDialogAction) fPropertiesAction).setComparator(fComparator);
+				fMemento.putInteger(P_ORDER_VALUE, PLUGIN_ORDER);
+				fMemento.putInteger(P_ORDER_TYPE, PLUGIN);
+				setColumnSorting(fColumn2, PLUGIN_ORDER);
+			}
+		});
+
+		fColumn3 = new TreeColumn(tree, SWT.LEFT);
+		fColumn3.setText(Messages.get().LogView_column_date);
+		fColumn3.setWidth(fMemento.getInteger(P_COLUMN_3).intValue());
+		fColumn3.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				DATE_ORDER *= -1;
+				ViewerComparator comparator = getViewerComparator(DATE);
+				fFilteredTree.getViewer().setComparator(comparator);
+				setComparator(DATE);
+				((EventDetailsDialogAction) fPropertiesAction).setComparator(fComparator);
+				fMemento.putInteger(P_ORDER_VALUE, DATE_ORDER);
+				fMemento.putInteger(P_ORDER_TYPE, DATE);
+				setColumnSorting(fColumn3, DATE_ORDER);
+			}
+		});
+
+		tree.setHeaderVisible(true);
+	}
+
+	private void initializeViewerSorter() {
+		byte orderType = fMemento.getInteger(P_ORDER_TYPE).byteValue();
+		ViewerComparator comparator = getViewerComparator(orderType);
+		fFilteredTree.getViewer().setComparator(comparator);
+		if (orderType == MESSAGE)
+			setColumnSorting(fColumn1, MESSAGE_ORDER);
+		else if (orderType == PLUGIN)
+			setColumnSorting(fColumn2, PLUGIN_ORDER);
+		else if (orderType == DATE)
+			setColumnSorting(fColumn3, DATE_ORDER);
+	}
+
+	private void setColumnSorting(TreeColumn column, int order) {
+		fTree.setSortColumn(column);
+		fTree.setSortDirection(order == ASCENDING ? SWT.UP : SWT.DOWN);
+	}
+
+	public void dispose() {
+		writeSettings();
+		Platform.removeLogListener(this);
+//		fClipboard.dispose();
+		if (fTextShell != null)
+			fTextShell.dispose();
+		fLabelProvider.disconnect(this);
+		fFilteredTree.dispose();
+		super.dispose();
+	}
+
+	/**
+	 * Import log from file selected in FileDialog.
+	 */
+	void handleImport() {
+		FileDialog dialog = new FileDialog(getViewSite().getShell());
+		// RAP [if] Missing API
+//		dialog.setFilterExtensions(new String[] {"*.log"}); //$NON-NLS-1$
+//		if (fDirectory != null)
+//			dialog.setFilterPath(fDirectory);
+		// RAPEND
+		String path = dialog.open();
+		if (path == null) { // cancel
+			return;
+		}
+
+		File file = new Path(path).toFile();
+		if (file.exists()) {
+			handleImportPath(path);
+		} else {
+			String msg = NLS.bind(Messages.get().LogView_FileCouldNotBeFound, file.getName());
+			MessageDialog.openError(getViewSite().getShell(), Messages.get().LogView_OpenFile, msg);
+		}
+	}
+
+	/**
+	 * Import log from given file path. Do nothing if file not exists.
+	 * @param path path to log file.
+	 */
+	public void handleImportPath(String path) {
+		File file = new File(path);
+		if (path != null && file.exists()) {
+			setLogFile(file);
+		}
+	}
+
+	/**
+	 * Import log from given file path.
+	 * @param path path to log file.
+	 */
+	protected void setLogFile(File path) {
+		fInputFile = path;
+//		fDirectory = fInputFile.getParent();
+		IRunnableWithProgress op = new IRunnableWithProgress() {
+			public void run(IProgressMonitor monitor) {
+				monitor.beginTask(Messages.get().LogView_operation_importing, IProgressMonitor.UNKNOWN);
+				readLogFile();
+			}
+		};
+		ProgressMonitorDialog pmd = new ProgressMonitorDialog(getViewSite().getShell());
+		try {
+			pmd.run(true, true, op);
+		} catch (InvocationTargetException e) { // do nothing
+		} catch (InterruptedException e) { // do nothing
+		} finally {
+			fReadLogAction.setText(Messages.get().LogView_readLog_reload);
+			fReadLogAction.setToolTipText(Messages.get().LogView_readLog_reload);
+			asyncRefresh(false);
+			resetDialogButtons();
+		}
+	}
+
+	private void handleExport(boolean exportWholeLog) {
+//		FileDialog dialog = new FileDialog(getViewSite().getShell(), SWT.SAVE);
+//		dialog.setFilterExtensions(new String[] {"*.log"}); //$NON-NLS-1$
+//		if (fDirectory != null)
+//			dialog.setFilterPath(fDirectory);
+//		String path = dialog.open();
+//		if (path != null) {
+//			if (path.indexOf('.') == -1 && !path.endsWith(".log")) //$NON-NLS-1$
+//				path += ".log"; //$NON-NLS-1$
+//			File outputFile = new Path(path).toFile();
+//			fDirectory = outputFile.getParent();
+//			if (outputFile.exists()) {
+//				String message = NLS.bind(Messages.get().LogView_confirmOverwrite_message, outputFile.toString());
+//				if (!MessageDialog.openQuestion(getViewSite().getShell(), (exportWholeLog ? Messages.get().LogView_exportLog : Messages.get().LogView_exportLogEntry), message))
+//					return;
+//			}
+//
+//			BufferedReader in = null;
+//			BufferedWriter out = null;
+//			try {
+//				out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outputFile), "UTF-8")); //$NON-NLS-1$
+//				if (exportWholeLog)
+//					in = new BufferedReader(new InputStreamReader(new FileInputStream(fInputFile), "UTF-8")); //$NON-NLS-1$
+//				else {
+//					String selectedEntryAsString = selectionToString(fFilteredTree.getViewer().getSelection());
+//					in = new BufferedReader(new StringReader(selectedEntryAsString));
+//				}
+//				copy(in, out);
+//			} catch (IOException ex) {
+//				// do nothing
+//			} finally {
+//				try {
+//					if (in != null)
+//						in.close();
+//				} catch (IOException e) {
+//					// do nothing
+//				}
+//				try {
+//					if (out != null)
+//						out.close();
+//				} catch (IOException e) {
+//					// do nothing
+//				}
+//			}
+//		}
+		String encodedURL = RWT.getServiceManager().getServiceHandlerUrl(DOWNLOAD_SERVICE_HANDLER_ID);
+
+		UrlLauncher launcher = (UrlLauncher) RWT.getClient().getService(UrlLauncher.class);
+		launcher.openURL(encodedURL);
+	}
+
+//	private void copy(BufferedReader reader, BufferedWriter writer) throws IOException {
+//		String line;
+//		while (reader.ready() && ((line = reader.readLine()) != null)) {
+//			writer.write(line);
+//			writer.newLine();
+//		}
+//	}
+
+	private void handleFilter() {
+		FilterDialog dialog = new FilterDialog(getSite().getShell(), fMemento);
+		dialog.create();
+		dialog.getShell().setText(Messages.get().LogView_FilterDialog_title);
+		if (dialog.open() == Window.OK)
+			reloadLog();
+	}
+
+	private void doDeleteLog() {
+		String title = Messages.get().LogView_confirmDelete_title;
+		String message = Messages.get().LogView_confirmDelete_message;
+		if (!MessageDialog.openConfirm(fTree.getShell(), title, message))
+			return;
+		if (fInputFile.delete() || elements.size() > 0) {
+			handleClear();
+		}
+	}
+
+	public void fillContextMenu(IMenuManager manager) { // nothing
+	}
+
+	public AbstractEntry[] getElements() {
+		return (AbstractEntry[]) elements.toArray(new AbstractEntry[elements.size()]);
+	}
+
+	protected void handleClear() {
+		BusyIndicator.showWhile(fTree.getDisplay(), new Runnable() {
+			public void run() {
+				elements.clear();
+				groups.clear();
+				if (currentSession != null) {
+					currentSession.removeAllChildren();
+				}
+				asyncRefresh(false);
+				resetDialogButtons();
+			}
+		});
+	}
+
+	/**
+	 * Reloads the log
+	 */
+	protected void reloadLog() {
+		IRunnableWithProgress op = new IRunnableWithProgress() {
+			public void run(IProgressMonitor monitor) {
+				monitor.beginTask(Messages.get().LogView_operation_reloading, IProgressMonitor.UNKNOWN);
+				readLogFile();
+			}
+		};
+		ProgressMonitorDialog pmd = new ProgressMonitorDialog(getViewSite().getShell());
+		try {
+			pmd.run(true, true, op);
+		} catch (InvocationTargetException e) { // do nothing
+		} catch (InterruptedException e) { // do nothing
+		} finally {
+			fReadLogAction.setText(Messages.get().LogView_readLog_restore);
+			fReadLogAction.setToolTipText(Messages.get().LogView_readLog_restore);
+			asyncRefresh(false);
+			resetDialogButtons();
+		}
+	}
+
+	/**
+	 * Reads the chosen backing log file
+	 */
+	void readLogFile() {
+		elements.clear();
+		groups.clear();
+
+		List result = new ArrayList();
+		LogSession lastLogSession = LogReader.parseLogFile(fInputFile, result, fMemento);
+		if ((lastLogSession != null) && isEclipseStartTime(lastLogSession.getDate())) {
+			currentSession = lastLogSession;
+		} else {
+			currentSession = null;
+		}
+
+		group(result);
+		limitEntriesCount();
+
+		if (fDisplay != null) {
+			fDisplay.asyncExec(new Runnable() {
+				public void run() {
+					setContentDescription(getTitleSummary());
+				}
+			});
+		}
+
+	}
+
+	private boolean isEclipseStartTime(Date date) {
+		String ts = System.getProperty("eclipse.startTime"); //$NON-NLS-1$
+		try {
+			return (ts != null && date != null && date.getTime() == Long.parseLong(ts));
+		} catch (NumberFormatException e) {
+			// empty
+		}
+		return false;
+	}
+
+	private String getTitleSummary() {
+		String path = ""; //$NON-NLS-1$
+		try {
+			path = fInputFile.getCanonicalPath();
+		} catch (IOException e) { // log nothing
+		}
+
+		if (isPlatformLogOpen()) {
+			return Messages.get().LogView_WorkspaceLogFile;
+		}
+
+		Map sources = LogFilesManager.getLogSources();
+		if (sources.containsValue(path)) {
+			for (Iterator i = sources.keySet().iterator(); i.hasNext();) {
+				String key = (String) i.next();
+				if (sources.get(key).equals(path)) {
+					return NLS.bind(Messages.get().LogView_LogFileTitle, new String[] {key, path});
+				}
+			}
+		}
+
+		return path;
+	}
+
+	/**
+	 * Add new entries to correct groups in the view.
+	 * @param entries new entries to show up in groups in the view.
+	 */
+	private void group(List entries) {
+		if (fMemento.getInteger(P_GROUP_BY).intValue() == GROUP_BY_NONE) {
+			elements.addAll(entries);
+		} else {
+			for (Iterator i = entries.iterator(); i.hasNext();) {
+				LogEntry entry = (LogEntry) i.next();
+				Group group = getGroup(entry);
+				group.addChild(entry);
+			}
+		}
+	}
+
+	/**
+	 * Limits the number of entries according to the max entries limit set in
+	 * memento.
+	 */
+	private void limitEntriesCount() {
+		int limit = Integer.MAX_VALUE;
+		if (fMemento.getString(LogView.P_USE_LIMIT).equals("true")) {//$NON-NLS-1$
+			limit = fMemento.getInteger(LogView.P_LOG_LIMIT).intValue();
+		}
+
+		int entriesCount = getEntriesCount();
+
+		if (entriesCount <= limit) {
+			return;
+		}
+		Comparator dateComparator = new Comparator() {
+			public int compare(Object o1, Object o2) {
+				Date l1 = ((LogEntry) o1).getDate();
+				Date l2 = ((LogEntry) o2).getDate();
+				if ((l1 != null) && (l2 != null)) {
+					return l1.before(l2) ? -1 : 1;
+				} else if ((l1 == null) && (l2 == null)) {
+					return 0;
+				} else
+					return (l1 == null) ? -1 : 1;
+			}
+		};
+
+		if (fMemento.getInteger(P_GROUP_BY).intValue() == GROUP_BY_NONE) {
+			elements.subList(0, elements.size() - limit).clear();
+		} else {
+			List copy = new ArrayList(entriesCount);
+			for (Iterator i = elements.iterator(); i.hasNext();) {
+				AbstractEntry group = (AbstractEntry) i.next();
+				copy.addAll(Arrays.asList(group.getChildren(group)));
+			}
+
+			Collections.sort(copy, dateComparator);
+			List toRemove = copy.subList(0, copy.size() - limit);
+
+			for (Iterator i = elements.iterator(); i.hasNext();) {
+				AbstractEntry group = (AbstractEntry) i.next();
+				group.removeChildren(toRemove);
+			}
+		}
+
+	}
+
+	private int getEntriesCount() {
+		if (fMemento.getInteger(P_GROUP_BY).intValue() == GROUP_BY_NONE) {
+			return elements.size();
+		}
+		int size = 0;
+		for (Iterator i = elements.iterator(); i.hasNext();) {
+			AbstractEntry group = (AbstractEntry) i.next();
+			size += group.size();
+		}
+		return size;
+	}
+
+	/**
+	 * Returns group appropriate for the entry. Group depends on P_GROUP_BY
+	 * preference, or is null if grouping is disabled (GROUP_BY_NONE), or group
+	 * could not be determined. May create group if it haven't existed before.
+	 * 
+	 * @param entry entry to be grouped
+	 * @return group or null if grouping is disabled
+	 */
+	protected Group getGroup(LogEntry entry) {
+		int groupBy = fMemento.getInteger(P_GROUP_BY).intValue();
+		Object elementGroupId = null;
+		String groupName = null;
+
+		switch (groupBy) {
+			case GROUP_BY_PLUGIN :
+				groupName = entry.getPluginId();
+				elementGroupId = groupName;
+				break;
+
+			case GROUP_BY_SESSION :
+				elementGroupId = entry.getSession();
+				break;
+
+			default : // grouping is disabled
+				return null;
+		}
+
+		if (elementGroupId == null) { // could not determine group
+			return null;
+		}
+
+		Group group = (Group) groups.get(elementGroupId);
+		if (group == null) {
+			if (groupBy == GROUP_BY_SESSION) {
+				group = entry.getSession();
+			} else {
+				group = new Group(groupName);
+			}
+			groups.put(elementGroupId, group);
+			elements.add(group);
+		}
+
+		return group;
+	}
+
+	public void logging(IStatus status, String plugin) {
+		if (!isPlatformLogOpen())
+			return;
+
+		if (batchEntries) {
+			// create LogEntry immediately to don't loose IStatus creation date.
+			LogEntry entry = createLogEntry(status);
+			batchedEntries.add(entry);
+			return;
+		}
+
+		if (fFirstEvent || (currentSession == null)) {
+			readLogFile();
+			asyncRefresh(true);
+			fFirstEvent = false;
+		} else {
+			LogEntry entry = createLogEntry(status);
+
+			if (!batchedEntries.isEmpty()) {
+				// batch new entry as well, to have only one asyncRefresh()
+				batchedEntries.add(entry);
+				pushBatchedEntries();
+			} else {
+				pushEntry(entry);
+				asyncRefresh(true);
+			}
+		}
+	}
+
+	/**
+	 * Push batched entries to log view.
+	 */
+	private void pushBatchedEntries() {
+		Job job = new Job(Messages.get().LogView_AddingBatchedEvents) {
+			protected IStatus run(IProgressMonitor monitor) {
+				for (int i = 0; i < batchedEntries.size(); i++) {
+					if (!monitor.isCanceled()) {
+						LogEntry entry = (LogEntry) batchedEntries.get(i);
+						pushEntry(entry);
+						batchedEntries.remove(i);
+					}
+				}
+				asyncRefresh(true);
+				return Status.OK_STATUS;
+			}
+		};
+		job.schedule();
+	}
+
+	private LogEntry createLogEntry(IStatus status) {
+		LogEntry entry = new LogEntry(status);
+		entry.setSession(currentSession);
+		return entry;
+	}
+
+	private synchronized void pushEntry(LogEntry entry) {
+		if (LogReader.isLogged(entry, fMemento)) {
+			group(Collections.singletonList(entry));
+			limitEntriesCount();
+		}
+		asyncRefresh(true);
+	}
+
+	private void asyncRefresh(final boolean activate) {
+		if (fTree.isDisposed())
+			return;
+		Display display = fTree.getDisplay();
+		final ViewPart view = this;
+		if (display != null) {
+			display.asyncExec(new Runnable() {
+				public void run() {
+					if (!fTree.isDisposed()) {
+						TreeViewer viewer = fFilteredTree.getViewer();
+						viewer.refresh();
+						viewer.expandToLevel(2);
+						fDeleteLogAction.setEnabled(fInputFile.exists() && fInputFile.equals(Platform.getLogFileLocation().toFile()));
+						fOpenLogAction.setEnabled(fInputFile.exists());
+						fExportLogAction.setEnabled(fInputFile.exists());
+						fExportLogEntryAction.setEnabled(!viewer.getSelection().isEmpty());
+						IWorkbenchWindow window = Activator.getDefault().getWorkbench().getActiveWorkbenchWindow();
+						if (window != null) {
+							IWorkbenchPage page = window.getActivePage();
+							if (page != null) {
+								page.bringToTop(view);
+							}
+						}
+					}
+				}
+			});
+		}
+	}
+
+	public void setFocus() {
+		if (fFilteredTree != null) {
+			if (fMemento.getBoolean(P_SHOW_FILTER_TEXT).booleanValue()) {
+				Text filterControl = fFilteredTree.getFilterControl();
+				if (filterControl != null && !filterControl.isDisposed()) {
+					filterControl.setFocus();
+				}
+			} else if (!fFilteredTree.isDisposed()) {
+				fFilteredTree.setFocus();
+			}
+		}
+	}
+
+	private void handleSelectionChanged(ISelection selection) {
+		updateStatus(selection);
+//		fCopyAction.setEnabled((!selection.isEmpty()) && ((IStructuredSelection) selection).getFirstElement() != null);
+		fPropertiesAction.setEnabled(!selection.isEmpty());
+		fExportLogEntryAction.setEnabled(!selection.isEmpty());
+	}
+
+	private void updateStatus(ISelection selection) {
+		IStatusLineManager status = getViewSite().getActionBars().getStatusLineManager();
+		if (selection.isEmpty())
+			status.setMessage(null);
+		else {
+			Object element = ((IStructuredSelection) selection).getFirstElement();
+			status.setMessage(((LogViewLabelProvider) fFilteredTree.getViewer().getLabelProvider()).getColumnText(element, 0));
+		}
+	}
+
+	/**
+	 * Converts selected log view element to string.
+	 * @return textual log entry representation or null if selection doesn't contain log entry
+	 */
+	private static String selectionToString(ISelection selection) {
+		StringWriter writer = new StringWriter();
+		PrintWriter pwriter = new PrintWriter(writer);
+		if (selection.isEmpty())
+			return null;
+		AbstractEntry entry = (AbstractEntry) ((IStructuredSelection) selection).getFirstElement();
+		entry.write(pwriter);
+		pwriter.flush();
+		String textVersion = writer.toString();
+		pwriter.close();
+		try {
+			writer.close();
+		} catch (IOException e) {
+			// empty
+		}
+
+		return textVersion;
+	}
+
+//	/**
+//	 * Copies selected element to clipboard.
+//	 */
+//	private void copyToClipboard(ISelection selection) {
+//		String textVersion = selectionToString(selection);
+//		if ((textVersion != null) && (textVersion.trim().length() > 0)) {
+//			// set the clipboard contents
+//			fClipboard.setContents(new Object[] {textVersion}, new Transfer[] {TextTransfer.getInstance()});
+//		}
+//	}
+
+	public void init(IViewSite site, IMemento memento) throws PartInitException {
+		super.init(site, memento);
+		if (memento == null)
+			this.fMemento = XMLMemento.createWriteRoot("LOGVIEW"); //$NON-NLS-1$
+		else
+			this.fMemento = memento;
+		readSettings();
+
+		// initialize column ordering 
+		final byte type = this.fMemento.getInteger(P_ORDER_TYPE).byteValue();
+		switch (type) {
+			case DATE :
+				DATE_ORDER = this.fMemento.getInteger(P_ORDER_VALUE).intValue();
+				MESSAGE_ORDER = DESCENDING;
+				PLUGIN_ORDER = DESCENDING;
+				break;
+			case MESSAGE :
+				MESSAGE_ORDER = this.fMemento.getInteger(P_ORDER_VALUE).intValue();
+				DATE_ORDER = DESCENDING;
+				PLUGIN_ORDER = DESCENDING;
+				break;
+			case PLUGIN :
+				PLUGIN_ORDER = this.fMemento.getInteger(P_ORDER_VALUE).intValue();
+				MESSAGE_ORDER = DESCENDING;
+				DATE_ORDER = DESCENDING;
+				break;
+			default :
+				DATE_ORDER = DESCENDING;
+				MESSAGE_ORDER = DESCENDING;
+				PLUGIN_ORDER = DESCENDING;
+		}
+		setComparator(fMemento.getInteger(P_ORDER_TYPE).byteValue());
+	}
+
+	private void initializeMemento() {
+		if (fMemento.getString(P_USE_LIMIT) == null) {
+			fMemento.putString(P_USE_LIMIT, "true"); //$NON-NLS-1$
+		}
+		if (fMemento.getInteger(P_LOG_LIMIT) == null) {
+			fMemento.putInteger(P_LOG_LIMIT, 50);
+		}
+		if (fMemento.getString(P_LOG_INFO) == null) {
+			fMemento.putString(P_LOG_INFO, "true"); //$NON-NLS-1$
+		}
+		if (fMemento.getString(P_LOG_OK) == null) {
+			fMemento.putString(P_LOG_OK, "true"); //$NON-NLS-1$
+		}
+		if (fMemento.getString(P_LOG_WARNING) == null) {
+			fMemento.putString(P_LOG_WARNING, "true"); //$NON-NLS-1$
+		}
+		if (fMemento.getString(P_LOG_ERROR) == null) {
+			fMemento.putString(P_LOG_ERROR, "true"); //$NON-NLS-1$
+		}
+		if (fMemento.getString(P_SHOW_ALL_SESSIONS) == null) {
+			fMemento.putString(P_SHOW_ALL_SESSIONS, "true"); //$NON-NLS-1$
+		}
+	}
+
+	public void saveState(IMemento memento) {
+		if (this.fMemento == null || memento == null)
+			return;
+		//store some sane values to prevent the view from being broken
+		this.fMemento.putInteger(P_COLUMN_1, getColumnWidth(fColumn1, 300));
+		this.fMemento.putInteger(P_COLUMN_2, getColumnWidth(fColumn2, 150));
+		this.fMemento.putInteger(P_COLUMN_3, getColumnWidth(fColumn3, 150));
+		this.fMemento.putString(P_ACTIVATE, fActivateViewAction.isChecked() ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
+		memento.putMemento(this.fMemento);
+		writeSettings();
+	}
+
+	/**
+	 * Returns the width of the column or the default value if the column has been resized to be not visible
+	 * @param column the column to get the width from
+	 * @param defaultwidth the width to return if the column has been resized to not be visible
+	 * @return the width of the column or the default value
+	 * 
+	 * @since 3.6
+	 */
+	int getColumnWidth(TreeColumn column, int defaultwidth) {
+		int width = column.getWidth();
+		return width < 1 ? defaultwidth : width;
+	}
+
+	private void addMouseListeners() {
+		Listener tableListener = new Listener() {
+			public void handleEvent(Event e) {
+				switch (e.type) {
+//					case SWT.MouseExit :
+//					case SWT.MouseMove :
+//						onMouseMove(e);
+//						break;
+//					case SWT.MouseHover :
+//						onMouseHover(e);
+//						break;
+					case SWT.MouseDown :
+						onMouseDown(e);
+						break;
+				}
+			}
+		};
+		int[] tableEvents = new int[] {SWT.MouseDown/*, SWT.MouseMove, SWT.MouseHover, SWT.MouseExit*/};
+		for (int i = 0; i < tableEvents.length; i++) {
+			fTree.addListener(tableEvents[i], tableListener);
+		}
+	}
+
+	/**
+	 * Adds drag source support to error log tree.
+	 */
+	private void addDragSource() {
+		DragSource source = new DragSource(fTree, DND.DROP_COPY);
+		Transfer[] types = new Transfer[] {TextTransfer.getInstance()};
+		source.setTransfer(types);
+
+		source.addDragListener(new DragSourceAdapter() {
+
+			public void dragStart(DragSourceEvent event) {
+				ISelection selection = fFilteredTree.getViewer().getSelection();
+				if (selection.isEmpty()) {
+					event.doit = false;
+					return;
+				}
+
+				AbstractEntry entry = (AbstractEntry) ((TreeSelection) selection).getFirstElement();
+				if (!(entry instanceof LogEntry)) {
+					event.doit = false;
+					return;
+				}
+			}
+
+			public void dragSetData(DragSourceEvent event) {
+				if (!TextTransfer.getInstance().isSupportedType(event.dataType)) {
+					return;
+				}
+
+				ISelection selection = fFilteredTree.getViewer().getSelection();
+				String textVersion = selectionToString(selection);
+				event.data = textVersion;
+			}
+		});
+	}
+
+	private void makeHoverShell() {
+		// parent it off the workbench window's shell so it will be valid regardless of whether the view is a detached window or not
+		fTextShell = new Shell(getSite().getWorkbenchWindow().getShell(), SWT.NO_FOCUS | SWT.ON_TOP | SWT.TOOL);
+		Display display = fTextShell.getDisplay();
+		fTextShell.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+		GridLayout layout = new GridLayout(1, false);
+		int border = ((fTree.getShell().getStyle() & SWT.NO_TRIM) == 0) ? 0 : 1;
+		layout.marginHeight = border;
+		layout.marginWidth = border;
+		fTextShell.setLayout(layout);
+		fTextShell.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		Composite shellComposite = new Composite(fTextShell, SWT.NONE);
+		layout = new GridLayout();
+		layout.marginHeight = 0;
+		layout.marginWidth = 0;
+		shellComposite.setLayout(layout);
+		shellComposite.setLayoutData(new GridData(GridData.FILL_BOTH | GridData.VERTICAL_ALIGN_BEGINNING));
+		fTextLabel = new Text(shellComposite, SWT.WRAP | SWT.MULTI | SWT.READ_ONLY);
+		GridData gd = new GridData(GridData.FILL_BOTH);
+		gd.widthHint = 100;
+		gd.grabExcessHorizontalSpace = true;
+		fTextLabel.setLayoutData(gd);
+		Color c = fTree.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND);
+		fTextLabel.setBackground(c);
+		c = fTree.getDisplay().getSystemColor(SWT.COLOR_INFO_FOREGROUND);
+		fTextLabel.setForeground(c);
+		fTextLabel.setEditable(false);
+		fTextShell.addDisposeListener(new DisposeListener() {
+			public void widgetDisposed(DisposeEvent e) {
+				onTextShellDispose(e);
+			}
+		});
+	}
+
+	void onTextShellDispose(DisposeEvent e) {
+		fCanOpenTextShell = true;
+		setFocus();
+	}
+
+	void onMouseDown(Event e) {
+		if (fTextShell != null && !fTextShell.isDisposed() && !fTextShell.isFocusControl()) {
+			fTextShell.setVisible(false);
+			fCanOpenTextShell = true;
+		}
+	}
+
+	void onMouseHover(Event e) {
+		if (!fCanOpenTextShell || fTextShell == null || fTextShell.isDisposed())
+			return;
+		fCanOpenTextShell = false;
+		Point point = new Point(e.x, e.y);
+		TreeItem item = fTree.getItem(point);
+		if (item == null)
+			return;
+
+		String message = null;
+		if (item.getData() instanceof LogEntry) {
+			message = ((LogEntry) item.getData()).getStack();
+		} else if (item.getData() instanceof LogSession) {
+			LogSession session = ((LogSession) item.getData());
+			message = Messages.get().LogView_SessionStarted;
+			if (session.getDate() != null) {
+				DateFormat formatter = new SimpleDateFormat(LogEntry.F_DATE_FORMAT);
+				message += formatter.format(session.getDate());
+			}
+		}
+
+		if (message == null)
+			return;
+
+		fTextLabel.setText(message);
+		Rectangle bounds = fTree.getDisplay().getBounds();
+		Point cursorPoint = fTree.getDisplay().getCursorLocation();
+		int x = point.x;
+		int y = point.y + 25;
+		int width = fTree.getColumn(0).getWidth();
+		int height = 125;
+		if (cursorPoint.x + width > bounds.width)
+			x -= width;
+		if (cursorPoint.y + height + 25 > bounds.height)
+			y -= height + 27;
+
+		fTextShell.setLocation(fTree.toDisplay(x, y));
+		fTextShell.setSize(width, height);
+		fTextShell.setVisible(true);
+	}
+
+	void onMouseMove(Event e) {
+		if (fTextShell != null && !fTextShell.isDisposed() && fTextShell.isVisible())
+			fTextShell.setVisible(false);
+
+		Point point = new Point(e.x, e.y);
+		TreeItem item = fTree.getItem(point);
+		if (item == null)
+			return;
+		Image image = item.getImage();
+		Object data = item.getData();
+		if (data instanceof LogEntry) {
+			LogEntry entry = (LogEntry) data;
+			int parentCount = getNumberOfParents(entry);
+			int startRange = 20 + Math.max(image.getBounds().width + 2, 7 + 2) * parentCount;
+			int endRange = startRange + 16;
+			fCanOpenTextShell = e.x >= startRange && e.x <= endRange;
+		}
+	}
+
+	private int getNumberOfParents(AbstractEntry entry) {
+		AbstractEntry parent = (AbstractEntry) entry.getParent(entry);
+		if (parent == null)
+			return 0;
+		return 1 + getNumberOfParents(parent);
+	}
+
+	public Comparator getComparator() {
+		return fComparator;
+	}
+
+	private void setComparator(byte sortType) {
+		if (sortType == DATE) {
+			fComparator = new Comparator() {
+				public int compare(Object e1, Object e2) {
+					long date1 = 0;
+					long date2 = 0;
+					if ((e1 instanceof LogEntry) && (e2 instanceof LogEntry)) {
+						date1 = ((LogEntry) e1).getDate().getTime();
+						date2 = ((LogEntry) e2).getDate().getTime();
+					} else if ((e1 instanceof LogSession) && (e2 instanceof LogSession)) {
+						date1 = ((LogSession) e1).getDate() == null ? 0 : ((LogSession) e1).getDate().getTime();
+						date2 = ((LogSession) e2).getDate() == null ? 0 : ((LogSession) e2).getDate().getTime();
+					}
+					if (date1 == date2) {
+						int result = elements.indexOf(e2) - elements.indexOf(e1);
+						if (DATE_ORDER == DESCENDING)
+							result *= DESCENDING;
+						return result;
+					}
+					if (DATE_ORDER == DESCENDING)
+						return date1 > date2 ? DESCENDING : ASCENDING;
+					return date1 < date2 ? DESCENDING : ASCENDING;
+				}
+			};
+		} else if (sortType == PLUGIN) {
+			fComparator = new Comparator() {
+				public int compare(Object e1, Object e2) {
+					if ((e1 instanceof LogEntry) && (e2 instanceof LogEntry)) {
+						LogEntry entry1 = (LogEntry) e1;
+						LogEntry entry2 = (LogEntry) e2;
+						return getDefaultComparator().compare(entry1.getPluginId(), entry2.getPluginId()) * PLUGIN_ORDER;
+					}
+					return 0;
+				}
+			};
+		} else {
+			fComparator = new Comparator() {
+				public int compare(Object e1, Object e2) {
+					if ((e1 instanceof LogEntry) && (e2 instanceof LogEntry)) {
+						LogEntry entry1 = (LogEntry) e1;
+						LogEntry entry2 = (LogEntry) e2;
+						return getDefaultComparator().compare(entry1.getMessage(), entry2.getMessage()) * MESSAGE_ORDER;
+					}
+					return 0;
+				}
+			};
+		}
+	}
+
+	private Comparator getDefaultComparator() {
+		return Policy.getComparator();
+	}
+
+	private ViewerComparator getViewerComparator(byte sortType) {
+		if (sortType == PLUGIN) {
+			return new ViewerComparator() {
+				public int compare(Viewer viewer, Object e1, Object e2) {
+					if ((e1 instanceof LogEntry) && (e2 instanceof LogEntry)) {
+						LogEntry entry1 = (LogEntry) e1;
+						LogEntry entry2 = (LogEntry) e2;
+						return getComparator().compare(entry1.getPluginId(), entry2.getPluginId()) * PLUGIN_ORDER;
+					}
+					return 0;
+				}
+			};
+		} else if (sortType == MESSAGE) {
+			return new ViewerComparator() {
+				public int compare(Viewer viewer, Object e1, Object e2) {
+					if ((e1 instanceof LogEntry) && (e2 instanceof LogEntry)) {
+						LogEntry entry1 = (LogEntry) e1;
+						LogEntry entry2 = (LogEntry) e2;
+						return getComparator().compare(entry1.getMessage(), entry2.getMessage()) * MESSAGE_ORDER;
+					}
+					return 0;
+				}
+			};
+		} else {
+			return new ViewerComparator() {
+				private int indexOf(Object[] array, Object o) {
+					if (o == null)
+						return -1;
+					for (int i = 0; i < array.length; ++i)
+						if (o.equals(array[i]))
+							return i;
+					return -1;
+				}
+
+				public int compare(Viewer viewer, Object e1, Object e2) {
+					long date1 = 0;
+					long date2 = 0;
+					if ((e1 instanceof LogEntry) && (e2 instanceof LogEntry)) {
+						date1 = ((LogEntry) e1).getDate().getTime();
+						date2 = ((LogEntry) e2).getDate().getTime();
+					} else if ((e1 instanceof LogSession) && (e2 instanceof LogSession)) {
+						date1 = ((LogSession) e1).getDate() == null ? 0 : ((LogSession) e1).getDate().getTime();
+						date2 = ((LogSession) e2).getDate() == null ? 0 : ((LogSession) e2).getDate().getTime();
+					}
+
+					if (date1 == date2) {
+						// Everything that appears in LogView should be an AbstractEntry.
+						AbstractEntry parent = (AbstractEntry) ((AbstractEntry) e1).getParent(null);
+						Object[] children = null;
+						if (parent != null)
+							children = parent.getChildren(parent);
+
+						int result = 0;
+						if (children != null) {
+							// The elements in children seem to be in reverse order,
+							// i.e. latest log message first, therefore index(e2)-index(e1)
+							result = indexOf(children, e2) - indexOf(children, e1);
+						} else {
+							result = elements.indexOf(e1) - elements.indexOf(e2);
+						}
+						if (DATE_ORDER == DESCENDING)
+							result *= DESCENDING;
+						return result;
+					}
+					if (DATE_ORDER == DESCENDING)
+						return date1 > date2 ? DESCENDING : ASCENDING;
+					return date1 < date2 ? DESCENDING : ASCENDING;
+				}
+			};
+		}
+	}
+
+	private void resetDialogButtons() {
+		((EventDetailsDialogAction) fPropertiesAction).resetDialogButtons();
+	}
+
+	/**
+	 * Returns the filter dialog settings object used to maintain
+	 * state between filter dialogs
+	 * @return the dialog settings to be used
+	 */
+	private IDialogSettings getLogSettings() {
+		IDialogSettings settings = Activator.getDefault().getDialogSettings();
+		return settings.getSection(getClass().getName());
+	}
+
+	/**
+	 * Returns the plugin preferences used to maintain
+	 * state of log view
+	 * @return the plugin preferences
+	 */
+	private Preferences getLogPreferences() {
+		return (new SessionScope()).getNode(Activator.PLUGIN_ID);
+	}
+
+	/**
+	 * Loads any saved {@link IDialogSettings} into the backing view memento
+	 */
+	private void readSettings() {
+		IDialogSettings s = getLogSettings();
+		if (s == null) {
+			initializeMemento();
+		} else {
+			fMemento.putString(P_USE_LIMIT, s.getBoolean(P_USE_LIMIT) ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
+			fMemento.putString(P_LOG_INFO, s.getBoolean(P_LOG_INFO) ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
+			fMemento.putString(P_LOG_OK, s.getBoolean(P_LOG_OK) ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
+			fMemento.putString(P_LOG_WARNING, s.getBoolean(P_LOG_WARNING) ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
+			fMemento.putString(P_LOG_ERROR, s.getBoolean(P_LOG_ERROR) ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
+			fMemento.putString(P_SHOW_ALL_SESSIONS, s.getBoolean(P_SHOW_ALL_SESSIONS) ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
+			try {
+				fMemento.putInteger(P_LOG_LIMIT, s.getInt(P_LOG_LIMIT));
+			} catch (NumberFormatException e) {
+				fMemento.putInteger(P_LOG_LIMIT, 50);
+			}
+		}
+
+		Preferences p = getLogPreferences(); // never returns null
+		fMemento.putInteger(P_COLUMN_1, getColumnWidthPreference(p, P_COLUMN_1, 300));
+		fMemento.putInteger(P_COLUMN_2, getColumnWidthPreference(p, P_COLUMN_2, 150));
+		fMemento.putInteger(P_COLUMN_3, getColumnWidthPreference(p, P_COLUMN_3, 150));
+		fMemento.putBoolean(P_ACTIVATE, p.getBoolean(P_ACTIVATE, true));
+		fMemento.putInteger(P_ORDER_VALUE, p.getInt(P_ORDER_VALUE, DESCENDING));
+		fMemento.putInteger(P_ORDER_TYPE, p.getInt(P_ORDER_TYPE, LogView.DATE));
+		fMemento.putBoolean(P_SHOW_FILTER_TEXT, p.getBoolean(P_SHOW_FILTER_TEXT, true));
+		fMemento.putInteger(P_GROUP_BY, p.getInt(P_GROUP_BY, LogView.GROUP_BY_NONE));
+	}
+
+	/**
+	 * Returns the width to use for the column represented by the given key. The default width
+	 * is returned iff:
+	 * <ul>
+	 * <li>There is no preference for the given key</li>
+	 * <li>The returned preference value is too small, making the columns invisible by width.</li>
+	 * </ul>
+	 * @param preferences
+	 * @param key
+	 * @param defaultwidth
+	 * @return the stored width for the a column described by the given key or the default width
+	 * 
+	 * @since 3.6
+	 */
+	int getColumnWidthPreference(Preferences preferences, String key, int defaultwidth) {
+		int width = preferences.getInt(key, defaultwidth);
+		return width < 1 ? defaultwidth : width;
+	}
+
+	private void writeSettings() {
+		writeViewSettings();
+		writeFilterSettings();
+	}
+
+	private void writeFilterSettings() {
+		IDialogSettings settings = getLogSettings();
+		if (settings == null)
+			settings = Activator.getDefault().getDialogSettings().addNewSection(getClass().getName());
+		settings.put(P_USE_LIMIT, fMemento.getString(P_USE_LIMIT).equals("true")); //$NON-NLS-1$
+		settings.put(P_LOG_LIMIT, fMemento.getInteger(P_LOG_LIMIT).intValue());
+		settings.put(P_LOG_INFO, fMemento.getString(P_LOG_INFO).equals("true")); //$NON-NLS-1$
+		settings.put(P_LOG_OK, fMemento.getString(P_LOG_OK).equals("true")); //$NON-NLS-1$
+		settings.put(P_LOG_WARNING, fMemento.getString(P_LOG_WARNING).equals("true")); //$NON-NLS-1$
+		settings.put(P_LOG_ERROR, fMemento.getString(P_LOG_ERROR).equals("true")); //$NON-NLS-1$
+		settings.put(P_SHOW_ALL_SESSIONS, fMemento.getString(P_SHOW_ALL_SESSIONS).equals("true")); //$NON-NLS-1$
+	}
+
+	private void writeViewSettings() {
+		Preferences preferences = getLogPreferences();
+		preferences.putInt(P_COLUMN_1, fMemento.getInteger(P_COLUMN_1).intValue());
+		preferences.putInt(P_COLUMN_2, fMemento.getInteger(P_COLUMN_2).intValue());
+		preferences.putInt(P_COLUMN_3, fMemento.getInteger(P_COLUMN_3).intValue());
+		preferences.putBoolean(P_ACTIVATE, fMemento.getBoolean(P_ACTIVATE).booleanValue());
+		preferences.putInt(P_ORDER_VALUE, fMemento.getInteger(P_ORDER_VALUE).intValue());
+		preferences.putInt(P_ORDER_TYPE, fMemento.getInteger(P_ORDER_TYPE).intValue());
+		preferences.putBoolean(P_SHOW_FILTER_TEXT, fMemento.getBoolean(P_SHOW_FILTER_TEXT).booleanValue());
+		preferences.putInt(P_GROUP_BY, fMemento.getInteger(P_GROUP_BY).intValue());
+		try {
+			preferences.flush();
+		} catch (BackingStoreException e) {
+			// empty
+		}
+	}
+
+	public void sortByDateDescending() {
+		setColumnSorting(fColumn3, DESCENDING);
+	}
+
+	protected Job getOpenLogFileJob() {
+		final Shell shell = getViewSite().getShell();
+		return new Job(Messages.get().OpenLogDialog_message) {
+			protected IStatus run(IProgressMonitor monitor) {
+//				boolean failed = false;
+//				if (fInputFile.length() <= LogReader.MAX_FILE_LENGTH) {
+//					failed = !Program.launch(fInputFile.getAbsolutePath());
+//					if (failed) {
+//						Program p = Program.findProgram(".txt"); //$NON-NLS-1$
+//						if (p != null) {
+//							p.execute(fInputFile.getAbsolutePath());
+//							return Status.OK_STATUS;
+//						}
+//					}
+//				}
+//				if (failed) {
+				final OpenLogDialog openDialog = new OpenLogDialog(shell, fInputFile);
+				shell.getDisplay().asyncExec(new Runnable() {
+					public void run() {
+						openDialog.create();
+						openDialog.open();
+					}
+				});
+//				}
+				return Status.OK_STATUS;
+			}
+		};
+	}
+
+	protected File getLogFile() {
+		return fInputFile;
+	}
+
+	/**
+	 * Returns whether given session equals to currently displayed in LogView.
+	 * @param session LogSession
+	 * @return true if given session equals to currently displayed in LogView
+	 */
+	public boolean isCurrentLogSession(LogSession session) {
+		return isPlatformLogOpen() && (currentSession != null) && (currentSession.equals(session));
+	}
+
+	/**
+	 * Returns whether currently open log is platform log or imported file.
+	 * @return true if currently open log is platform log, false otherwise
+	 */
+	public boolean isPlatformLogOpen() {
+		return (fInputFile.equals(Platform.getLogFileLocation().toFile()));
+	}
+
+	/**
+	 * 
+	 */
+	public void setPlatformLog() {
+		setLogFile(Platform.getLogFileLocation().toFile());
+	}
+}
