initial commit of error reporting plugin
diff --git a/org.eclipse.emf.emfstore.ui.errorreporting/.checkstyle b/org.eclipse.emf.emfstore.ui.errorreporting/.checkstyle
new file mode 100644
index 0000000..2f2667a
--- /dev/null
+++ b/org.eclipse.emf.emfstore.ui.errorreporting/.checkstyle
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<fileset-config file-format-version="1.2.0" simple-config="true" sync-formatter="false">
+  <fileset name="all" enabled="true" check-config-name="emfstoreStyle" local="false">
+    <file-match-pattern match-pattern="." include-pattern="true"/>
+  </fileset>
+</fileset-config>
diff --git a/org.eclipse.emf.emfstore.ui.errorreporting/.classpath b/org.eclipse.emf.emfstore.ui.errorreporting/.classpath
new file mode 100644
index 0000000..2d1a430
--- /dev/null
+++ b/org.eclipse.emf.emfstore.ui.errorreporting/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<classpath>

+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>

+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>

+	<classpathentry kind="src" path="src"/>

+	<classpathentry kind="output" path="bin"/>

+</classpath>

diff --git a/org.eclipse.emf.emfstore.ui.errorreporting/.project b/org.eclipse.emf.emfstore.ui.errorreporting/.project
new file mode 100644
index 0000000..dd4bfef
--- /dev/null
+++ b/org.eclipse.emf.emfstore.ui.errorreporting/.project
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<projectDescription>

+	<name>org.eclipse.emf.emfstore.ui.errorreporting</name>

+	<comment></comment>

+	<projects>

+	</projects>

+	<buildSpec>

+		<buildCommand>

+			<name>org.eclipse.jdt.core.javabuilder</name>

+			<arguments>

+			</arguments>

+		</buildCommand>

+		<buildCommand>

+			<name>org.eclipse.pde.ManifestBuilder</name>

+			<arguments>

+			</arguments>

+		</buildCommand>

+		<buildCommand>

+			<name>org.eclipse.pde.SchemaBuilder</name>

+			<arguments>

+			</arguments>

+		</buildCommand>

+		<buildCommand>

+			<name>net.sf.eclipsecs.core.CheckstyleBuilder</name>

+			<arguments>

+			</arguments>

+		</buildCommand>

+	</buildSpec>

+	<natures>

+		<nature>org.eclipse.pde.PluginNature</nature>

+		<nature>org.eclipse.jdt.core.javanature</nature>

+		<nature>net.sf.eclipsecs.core.CheckstyleNature</nature>

+	</natures>

+</projectDescription>

diff --git a/org.eclipse.emf.emfstore.ui.errorreporting/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.emf.emfstore.ui.errorreporting/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..ef029ba
--- /dev/null
+++ b/org.eclipse.emf.emfstore.ui.errorreporting/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,8 @@
+#Thu Aug 23 11:06:00 CEST 2012

+eclipse.preferences.version=1

+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled

+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5

+org.eclipse.jdt.core.compiler.compliance=1.5

+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error

+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error

+org.eclipse.jdt.core.compiler.source=1.5

diff --git a/org.eclipse.emf.emfstore.ui.errorreporting/META-INF/MANIFEST.MF b/org.eclipse.emf.emfstore.ui.errorreporting/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..df7b415
--- /dev/null
+++ b/org.eclipse.emf.emfstore.ui.errorreporting/META-INF/MANIFEST.MF
@@ -0,0 +1,15 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Error Diagnosis Plugin
+Bundle-SymbolicName: org.eclipse.emf.emfstore.ui.errorreporting;singleton:=true
+Bundle-Version: 0.9.3.qualifier
+Bundle-Activator: org.eclipse.emf.emfstore.ui.errorreporting.Activator
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.emf.emfstore.client;bundle-version="0.9.3",
+ com.ibm.icu;bundle-version="4.4.2"
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
+Bundle-Vendor: Eclipse Modeling Project
+Export-Package: org.eclipse.emf.emfstore.ui.errorreporting
diff --git a/org.eclipse.emf.emfstore.ui.errorreporting/build.properties b/org.eclipse.emf.emfstore.ui.errorreporting/build.properties
new file mode 100644
index 0000000..73a5119
--- /dev/null
+++ b/org.eclipse.emf.emfstore.ui.errorreporting/build.properties
@@ -0,0 +1,6 @@
+source.. = src/

+output.. = bin/

+bin.includes = META-INF/,\

+               .,\

+               plugin.properties,\

+               plugin.xml

diff --git a/org.eclipse.emf.emfstore.ui.errorreporting/plugin.properties b/org.eclipse.emf.emfstore.ui.errorreporting/plugin.properties
new file mode 100644
index 0000000..09f0eaf
--- /dev/null
+++ b/org.eclipse.emf.emfstore.ui.errorreporting/plugin.properties
@@ -0,0 +1,2 @@
+supportMailURL = mailto:emueller@eclipsesource.com?subject=EMFStore%20Bug%20Report&body=Thank%20you%20for%20reporting%20this%20bug.%20Please%20help%20us%20to%20fix%20the%20problem%20by%20following%20these%20steps%3A%0A%0A1.%20Give%20a%20summary%0A%3CDescription%3E%0A%0A2.%20Describe%20steps%20to%20reproduce%20the%20error%0A%20%201.%20%3CStep%201%3E%0A%20%202.%20%3CStep%202%3E%0A%0A3.%20Paste%20%28Ctrl%2Bv%29%20the%20content%20of%20the%20clipboard%20below%20%28parts%20of%20the%20log%20file%20have%20been%20copied%20to%20it%29%0A%3CContent%20from%20Log%20File%3E

+supportMailURL_errorDiagnosisCaptured = mailto:emueller@eclipsesource.com?subject=EMFStore%20Bug%20Report&body=Thank%20you%20for%20reporting%20this%20bug%3A%0A%0AThe%20error%20diagnosis%20has%20been%20captured%20by%20you.%20Please%20help%20us%20to%20fix%20the%20problem%20by%20following%20these%20steps%3A%0A%0A1.%20Give%20a%20summary%0A%3CDescription%3E%0A%0A2.%20Describe%20steps%20to%20reproduce%20the%20error%0A%20%201.%20%3CStep%201%3E%0A%20%202.%20%3CStep%202%3E
\ No newline at end of file
diff --git a/org.eclipse.emf.emfstore.ui.errorreporting/plugin.xml b/org.eclipse.emf.emfstore.ui.errorreporting/plugin.xml
new file mode 100644
index 0000000..1775e63
--- /dev/null
+++ b/org.eclipse.emf.emfstore.ui.errorreporting/plugin.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<?eclipse version="3.2"?>

+<plugin>

+   <extension-point id="org.eclipse.emf.emfstore.ui.errorreporting" name="customLog" schema="schema/org.eclipse.emf.emfstore.ui.errorreporting.exsd"/>

+   <extension

+         point="org.eclipse.ui.commands">

+      <command

+            id="org.eclipse.emf.emfstore.ui.createErrorLog"

+            name="Create Error Log">

+      </command>

+   </extension>

+   <extension

+         id="org.eclipse.emf.emfstore.ui.createErrorLog"

+         point="org.eclipse.ui.handlers">

+      <handler

+            class="org.eclipse.emf.emfstore.ui.errorreporting.MailBugHandler"

+            commandId="org.eclipse.emf.emfstore.ui.createErrorLog">

+      </handler>

+   </extension>

+   <extension

+         point="org.eclipse.emf.emfstore.client.exceptionObserver">

+      <observer

+            exceptionObserver="org.eclipse.emf.emfstore.ui.errorreporting.EmfStoreExceptionObserver">

+      </observer>

+   </extension>

+   <extension

+         point="org.eclipse.ui.statusHandlers">

+      <statusHandler

+            class="org.eclipse.emf.emfstore.ui.errorreporting.EmfStoreStatusHandler"

+            id="org.eclipse.emf.emfstore.ui.statusHandler">

+      </statusHandler>

+   </extension>
+</plugin>

diff --git a/org.eclipse.emf.emfstore.ui.errorreporting/schema/org.eclipse.emf.emfstore.ui.errorreporting.exsd b/org.eclipse.emf.emfstore.ui.errorreporting/schema/org.eclipse.emf.emfstore.ui.errorreporting.exsd
new file mode 100644
index 0000000..9926e13
--- /dev/null
+++ b/org.eclipse.emf.emfstore.ui.errorreporting/schema/org.eclipse.emf.emfstore.ui.errorreporting.exsd
@@ -0,0 +1,102 @@
+<?xml version='1.0' encoding='UTF-8'?>

+<!-- Schema file written by PDE -->

+<schema targetNamespace="org.eclipse.emf.emfstore.ui.errorreporting" xmlns="http://www.w3.org/2001/XMLSchema">

+<annotation>

+      <appInfo>

+         <meta.schema plugin="org.eclipse.emf.emfstore.ui.errorreporting" id="org.eclipse.emf.emfstore.ui.errorreporting.customLog" name="org.eclipse.emf.emfstore.ui.errorreporting.customLog"/>

+      </appInfo>

+      <documentation>

+         [Enter description of this extension point.]

+      </documentation>

+   </annotation>

+

+   <element name="extension">

+      <annotation>

+         <appInfo>

+            <meta.element />

+         </appInfo>

+      </annotation>

+      <complexType>

+         <sequence>

+            <element ref="loggable"/>

+         </sequence>

+         <attribute name="point" type="string" use="required">

+            <annotation>

+               <documentation>

+                  

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="id" type="string">

+            <annotation>

+               <documentation>

+                  

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string">

+            <annotation>

+               <documentation>

+                  

+               </documentation>

+               <appInfo>

+                  <meta.attribute translatable="true"/>

+               </appInfo>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <element name="loggable">

+      <complexType>

+         <attribute name="class" type="string">

+            <annotation>

+               <documentation>

+                  

+               </documentation>

+               <appInfo>

+                  <meta.attribute kind="java" basedOn=":org.eclipse.emf.emfstore.ui.errorreporting.ILoggable"/>

+               </appInfo>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="since"/>

+      </appInfo>

+      <documentation>

+         [Enter the first release in which this extension point appears.]

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="examples"/>

+      </appInfo>

+      <documentation>

+         [Enter extension point usage example here.]

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="apiinfo"/>

+      </appInfo>

+      <documentation>

+         [Enter API information here.]

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="implementation"/>

+      </appInfo>

+      <documentation>

+         [Enter information about supplied implementation of this extension point.]

+      </documentation>

+   </annotation>

+

+

+</schema>

diff --git a/org.eclipse.emf.emfstore.ui.errorreporting/src/org/eclipse/emf/emfstore/ui/errorreporting/Activator.java b/org.eclipse.emf.emfstore.ui.errorreporting/src/org/eclipse/emf/emfstore/ui/errorreporting/Activator.java
new file mode 100644
index 0000000..6cbdf0d
--- /dev/null
+++ b/org.eclipse.emf.emfstore.ui.errorreporting/src/org/eclipse/emf/emfstore/ui/errorreporting/Activator.java
@@ -0,0 +1,63 @@
+/*******************************************************************************

+ * Copyright (c) 2008-2012 EclipseSource Muenchen GmbH.

+ * 

+ * 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:

+ ******************************************************************************/

+package org.eclipse.emf.emfstore.ui.errorreporting;

+

+import org.eclipse.ui.plugin.AbstractUIPlugin;

+import org.osgi.framework.BundleContext;

+

+/**

+ * Activator class for the error reporting plugin.

+ */

+public class Activator extends AbstractUIPlugin {

+

+	/**

+	 * Error reporting plugin ID.

+	 */

+	public static final String PLUGIN_ID = "org.eclipse.emf.emfstore.ui.errorreporting"; //$NON-NLS-1$

+

+	private static Activator plugin;

+	

+	/**

+	 * Constructor.

+	 */

+	public Activator() {

+	}

+

+	/**

+	 * {@inheritDoc}

+	 */

+	// BEGIN SUPRESS CATCH EXCEPTION

+	public void start(BundleContext context) throws Exception {

+		// END SUPRESS CATCH EXCEPTION

+		super.start(context);

+		plugin = this;

+	}

+

+	/**

+	 * {@inheritDoc}

+	 */

+	// BEGIN SUPRESS CATCH EXCEPTION

+	public void stop(BundleContext context) throws Exception {

+		// END SUPRESS CATCH EXCEPTION

+		plugin = null;

+		super.stop(context);

+	}

+

+	/**

+	 * Returns the shared instance.

+	 *

+	 * @return the shared instance

+	 */

+	public static Activator getDefault() {

+		return plugin;

+	}

+

+}

diff --git a/org.eclipse.emf.emfstore.ui.errorreporting/src/org/eclipse/emf/emfstore/ui/errorreporting/EmfStoreExceptionObserver.java b/org.eclipse.emf.emfstore.ui.errorreporting/src/org/eclipse/emf/emfstore/ui/errorreporting/EmfStoreExceptionObserver.java
new file mode 100644
index 0000000..b48b444
--- /dev/null
+++ b/org.eclipse.emf.emfstore.ui.errorreporting/src/org/eclipse/emf/emfstore/ui/errorreporting/EmfStoreExceptionObserver.java
@@ -0,0 +1,127 @@
+/*******************************************************************************

+ * Copyright (c) 2008-2012 EclipseSource Muenchen GmbH.

+ * 

+ * 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:

+ ******************************************************************************/

+package org.eclipse.emf.emfstore.ui.errorreporting;

+

+import java.util.HashSet;

+import java.util.Set;

+

+import org.eclipse.core.commands.ExecutionEvent;

+import org.eclipse.core.commands.ExecutionException;

+import org.eclipse.core.runtime.Status;

+import org.eclipse.emf.emfstore.client.model.Configuration;

+import org.eclipse.emf.emfstore.client.model.exceptions.MissingCommandException;

+import org.eclipse.emf.emfstore.client.model.observers.ExceptionObserver;

+import org.eclipse.emf.emfstore.client.model.util.WorkspaceUtil;

+import org.eclipse.jface.dialogs.ErrorDialog;

+import org.eclipse.ui.PlatformUI;

+

+import com.ibm.icu.text.MessageFormat;

+

+/**

+ * An exception observer that collects logs.

+ *  

+ * @author Maximilian Koegel

+ */

+public class EmfStoreExceptionObserver implements ExceptionObserver {

+

+	private static EmfStoreExceptionObserver instance;

+	private Set<ExceptionLog> exceptionLogs;

+

+	/**

+	 * Constructor.

+	 */

+	public EmfStoreExceptionObserver() {

+		instance = this;

+		exceptionLogs = new HashSet<ExceptionLog>();

+	}

+

+	/**

+	 * Returns the instance.

+	 * 

+	 * @return the instance

+	 */

+	public static EmfStoreExceptionObserver getInstance() {

+		if (instance == null) {

+			instance = new EmfStoreExceptionObserver();

+		}

+		return instance;

+	}

+

+	/**

+	 * {@inheritDoc}

+	 */

+	public boolean handleError(RuntimeException e) {

+		if (Configuration.isDebugMode()) {

+			

+			MailBugHandler bugHandler = new MailBugHandler();

+			

+			try {

+				bugHandler.execute(new ExecutionEvent());

+			} catch (ExecutionException exception) {

+				WorkspaceUtil.handleException(exception);

+			}

+			

+			ErrorDialog

+				.openError(

+					PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),

+					"DEBUG MODE ACTIVE: An Error Occured",

+					MessageFormat.format(

+						"This error message only appears if debug mode is active. \n"

+							+ "Although this error message might be an error itself, it might help to find bugs faster. \n"

+							+ "The most recent log has been copied to the clipboard, please add it to the bug report. Thanks! \n"

+							+ "To disable, launch without {0}={1} switch.",

+							Configuration.DEBUG_SWITCH, Configuration.DEBUG_SWITCH_ENABLED_VALUE),

+							new Status(Status.ERROR, "org.eclipse.emf.emfstore.client", "An error occured.", e));

+

+			throw e;

+		}

+

+		// MissingCommandException should only be logged if the debug switch is not set

+		if (e.getCause() instanceof MissingCommandException) {

+			return true;

+		}

+

+		for (ExceptionLog exceptionLog : exceptionLogs) {

+			exceptionLog.addException(e);

+		}

+		

+		return true;

+	}

+

+	/**

+	 * Adds a log.

+	 * 

+	 * @param log

+	 * 			the log being added

+	 */

+	public void addLog(ExceptionLog log) {

+		exceptionLogs.add(log);

+	}

+	

+	/**

+	 * Removes a log.

+	 * 

+	 * @param log 

+	 * 			the log to be removed

+	 */

+	public void removeLog(ExceptionLog log) {

+		exceptionLogs.remove(log);

+	}

+

+	/**

+	 * Returns the log. 

+	 * @return the log

+	 */

+	public ExceptionLog getLog() {

+		return new ExceptionLog(this);

+	}

+

+}

diff --git a/org.eclipse.emf.emfstore.ui.errorreporting/src/org/eclipse/emf/emfstore/ui/errorreporting/EmfStoreStatusHandler.java b/org.eclipse.emf.emfstore.ui.errorreporting/src/org/eclipse/emf/emfstore/ui/errorreporting/EmfStoreStatusHandler.java
new file mode 100644
index 0000000..86a6b28
--- /dev/null
+++ b/org.eclipse.emf.emfstore.ui.errorreporting/src/org/eclipse/emf/emfstore/ui/errorreporting/EmfStoreStatusHandler.java
@@ -0,0 +1,29 @@
+/*******************************************************************************

+ * Copyright (c) 2008-2012 EclipseSource Muenchen GmbH.

+ * 

+ * 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:

+ ******************************************************************************/

+package org.eclipse.emf.emfstore.ui.errorreporting;

+

+import org.eclipse.ui.statushandlers.WorkbenchErrorHandler;

+import org.eclipse.ui.statushandlers.WorkbenchStatusDialogManager;

+

+/**

+ * Status handler for enabling the submission of a bug via mail.

+ * 

+ * @author Maximilian Koegel

+ */

+public class EmfStoreStatusHandler extends WorkbenchErrorHandler {

+	

+	@Override

+	protected void configureStatusDialog(WorkbenchStatusDialogManager statusDialog) {

+		super.configureStatusDialog(statusDialog);

+		statusDialog.enableDefaultSupportArea(true);

+		statusDialog.setSupportAreaProvider(new MailBugStatusAreaProvider());

+	}

+}

diff --git a/org.eclipse.emf.emfstore.ui.errorreporting/src/org/eclipse/emf/emfstore/ui/errorreporting/ErrorReportingUtil.java b/org.eclipse.emf.emfstore.ui.errorreporting/src/org/eclipse/emf/emfstore/ui/errorreporting/ErrorReportingUtil.java
new file mode 100644
index 0000000..9edc451
--- /dev/null
+++ b/org.eclipse.emf.emfstore.ui.errorreporting/src/org/eclipse/emf/emfstore/ui/errorreporting/ErrorReportingUtil.java
@@ -0,0 +1,357 @@
+/*******************************************************************************

+ * Copyright (c) 2008-2012 EclipseSource Muenchen GmbH.

+ * 

+ * 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:

+ ******************************************************************************/

+package org.eclipse.emf.emfstore.ui.errorreporting;

+

+import java.awt.AWTException;

+import java.awt.HeadlessException;

+import java.awt.Rectangle;

+import java.awt.Robot;

+import java.awt.Toolkit;

+import java.awt.image.BufferedImage;

+import java.io.BufferedWriter;

+import java.io.File;

+import java.io.FileWriter;

+import java.io.IOException;

+import java.io.PrintWriter;

+import java.lang.management.ManagementFactory;

+import java.lang.management.RuntimeMXBean;

+import java.util.ArrayList;

+import java.util.Arrays;

+import java.util.Date;

+import java.util.List;

+

+import javax.imageio.ImageIO;

+

+import org.apache.commons.io.FileUtils;

+import org.apache.commons.io.output.ByteArrayOutputStream;

+import org.apache.commons.lang.StringUtils;

+import org.eclipse.core.runtime.IStatus;

+import org.eclipse.core.runtime.MultiStatus;

+import org.eclipse.core.runtime.Platform;

+import org.eclipse.emf.emfstore.client.model.Configuration;

+import org.eclipse.emf.emfstore.client.model.util.WorkspaceUtil;

+import org.eclipse.emf.emfstore.common.extensionpoint.ExtensionElement;

+import org.eclipse.emf.emfstore.common.extensionpoint.ExtensionPoint;

+import org.eclipse.swt.dnd.Clipboard;

+import org.eclipse.swt.dnd.TextTransfer;

+import org.eclipse.swt.dnd.Transfer;

+import org.eclipse.ui.IEditorReference;

+import org.eclipse.ui.IWorkbenchPage;

+import org.eclipse.ui.IWorkbenchWindow;

+import org.eclipse.ui.PlatformUI;

+import org.eclipse.ui.statushandlers.StatusAdapter;

+

+import com.ibm.icu.text.MessageFormat;

+import com.ibm.icu.text.SimpleDateFormat;

+

+/**

+ * Utility class for capturing system specific information for debugging purposes.

+ * 

+ * @author emueller

+ */

+public final class ErrorReportingUtil {

+		

+	private static final String CUSTOMLOG_EXTENSION_POINT_ID = "org.eclipse.emf.emfstore.ui.errorreporting";

+	private static final String SCREENSHOT_FOLDER_NAME = "screenshots";

+	private static final String DEFAULT_SCREENSHOT_PREFIX = "emfstore-screenshot-";

+	private static final String DEFAULT_SYSINFO_PREFIX = "emfstore-sysinfo-";

+	private static final String SYSINFO_SUFFIX = "txt";

+	

+	private static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");	

+

+	/**

+	 * Private constructor.

+	 */

+	private ErrorReportingUtil() {

+		

+	}

+	

+	private static String getLogText() {

+		

+		String filename = Platform.getLogFileLocation().toOSString();

+		File log = new File(filename);

+		

+		try {

+			String version = Configuration.getClientVersion().getVersion();

+			String logFileContent = FileUtils.readFileToString(log);

+

+			StringBuffer result = new StringBuffer(16384);

+			result.append(

+				MessageFormat.format("EMFStore client {0}. Log copied at {1}\n\n",

+						version, SimpleDateFormat.getDateTimeInstance().format(new Date())));

+			result.append(logFileContent);

+													

+			return result.toString();

+		} catch (IOException ex) {

+			WorkspaceUtil.logException("Exception while copying log to clipboard", ex);

+		}

+

+		return null;

+	}

+

+	/**

+	 * Copies the content of the current log file to the clipboard.

+	 *  

+	 * @param window

+	 * 			the window that is used to determine which Display to copy to

+	 */

+	public static void copyLogToClipboard(IWorkbenchWindow window) {

+		String text = getLogText();

+		Clipboard clipboard = null;

+		

+		if (text == null) {

+			return;

+		}

+		

+		try {

+			clipboard = new Clipboard(window.getShell().getDisplay());

+			clipboard.setContents(new Object[] { text }, new Transfer[] { TextTransfer.getInstance() });

+		} finally {

+			if (clipboard != null) {

+				clipboard.dispose();

+			}

+		}

+	}	

+

+	/**

+	 * Creates the error diagnosis file.

+	 * 

+	 * @param date

+	 *            the date that will be written to the error diagnosis file in order to indicate when the

+	 *            file was created

+	 * @param path

+	 *            the parent path under which the error diagnosis file will be put

+	 * @param statusAdapter

+	 *            a status adapter that may contain the most recent stack trace, that will be copied

+	 *            into the error diagnosis file 

+	 * @return the absolute path to the created error diagnosis file

+	 */

+	public static String captureSysInfo(Date date, String path, StatusAdapter statusAdapter) {

+

+		File temp = new File(path);

+		FileWriter fileWriter = null;

+		BufferedWriter bufferedWriter = null;

+		

+		temp.deleteOnExit();

+

+		try {

+			Runtime runtime = Runtime.getRuntime();

+			RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();

+			fileWriter = new FileWriter(temp);

+

+			bufferedWriter = new BufferedWriter(fileWriter);

+			bufferedWriter.write(MessageFormat.format("Log file created on {0}\n", new Date()));

+			bufferedWriter.write(MessageFormat.format("Client version: {0} {1}\n", 

+				Configuration.getClientVersion().getName(), Configuration.getClientVersion().getVersion()));

+			bufferedWriter.write("List of open editors:\n");

+

+			if (getOpenEditorIDs().size() == 0) {

+				bufferedWriter.write("\t<None>\n");

+			} else {

+				for (String viewId : getOpenEditorIDs()) {

+					bufferedWriter.write(MessageFormat.format("\t{0}\n", viewId));

+				}

+			}

+

+			bufferedWriter.write(MessageFormat.format("Working directory: {0}", 

+				System.getProperty("user.dir")));

+			bufferedWriter.write(MessageFormat.format("System user: {0}", 

+				System.getProperty("user.name")));

+			bufferedWriter.write(MessageFormat.format("Memory usage: {0}/{1} MB",

+				toMb(runtime.totalMemory() - runtime.freeMemory()), toMb(runtime.maxMemory())));

+			bufferedWriter.write(MessageFormat.format("Available processors (cores): {0}\n", 

+				runtime.availableProcessors()));

+			bufferedWriter.write(MessageFormat.format("Java version: {0}", 

+				System.getProperty("java.version")));

+			bufferedWriter.write(MessageFormat.format("OS version: {0}", 

+				System.getProperty("os.version")));

+			bufferedWriter.write("VM Startup parameters:\n");

+

+			for (String vmArg : runtimeMXBean.getInputArguments()) {

+				bufferedWriter.write(MessageFormat.format("\t{0}\n", vmArg));

+			}

+			

+			ExtensionPoint extPoint = new ExtensionPoint(CUSTOMLOG_EXTENSION_POINT_ID);

+			for (ExtensionElement el : extPoint.getExtensionElements()) {

+				ILoggable loggable = el.getClass("class", ILoggable.class);

+				bufferedWriter.write(loggable.getLoggable());

+			}

+

+			if (statusAdapter != null) {

+				bufferedWriter.write(MessageFormat.format("Stacktrace: {0}\n", getStatus(statusAdapter)));	

+			}

+

+			return temp.getAbsolutePath();

+		} catch (IOException e) {

+			WorkspaceUtil.logException("Error while writing error diagnosis file: ", e);

+		} finally {

+			if (bufferedWriter != null) {

+				try {

+					bufferedWriter.close();

+				} catch (IOException e) {

+					WorkspaceUtil.logException("Error while closing buffered error diagnosis stream.", e);

+				}

+			}

+

+			if (fileWriter != null) {

+				try {

+					fileWriter.close();

+				} catch (IOException e) {

+					WorkspaceUtil.logException("Error while closing error diagnosis stream.", e);

+				}

+			}

+		}

+

+		return null;

+	}

+	

+	/**

+	 * Creates the error diagnosis file.

+	 * 

+	 * @param date

+	 *            the date that will be written to the error diagnosis file in order to indicate when the

+	 *            file was created

+	 * @param path

+	 *            the parent path under which the error diagnosis file will be put

+	 * @return the absolute path to the created error diagnosis file

+	 */

+	public static String captureSysInfo(Date date, String path) {

+		return captureSysInfo(date, path, null);

+	}

+

+	/**

+	 * Returns a list of strings containing the IDs of all opened editors.

+	 * 

+	 * @return a list of strings containing the IDs of all opened editors

+	 */

+	private static List<String> getOpenEditorIDs() {

+

+		List<String> openedEditors = new ArrayList<String>();

+		IWorkbenchPage activePage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();

+

+		for (IEditorReference editorRef : activePage.getEditorReferences()) {

+			openedEditors.add(editorRef.getId());

+		}

+

+		return openedEditors;

+	}

+	

+	private static String getStatus(StatusAdapter statusAdapter) {

+		StringBuilder sb = new StringBuilder();

+		addException(sb, statusAdapter.getStatus());

+		String logText = sb.toString();

+		if (logText == null || logText.length() == 0) {

+			logText = "Could not find exception";

+		}

+		return logText;

+	}

+

+

+	private static void addException(StringBuilder collector, IStatus iStatus) {

+		if (iStatus instanceof MultiStatus) {

+			MultiStatus ms = (MultiStatus) iStatus;

+			IStatus[] children = ms.getChildren();

+			for (IStatus childStatus : children) {

+				addException(collector, childStatus);

+			}

+		} else {

+			Throwable ex = iStatus.getException();

+			if (ex != null) {

+				ByteArrayOutputStream baos = new ByteArrayOutputStream();

+				PrintWriter pw = new PrintWriter(baos);

+				ex.printStackTrace(pw);

+				pw.flush();

+				collector.append(new String(baos.toByteArray()));

+			}

+		}

+	}

+	

+	private static int toMb(long value) {

+		return (int) (value / 1024 / 1024);

+	}

+

+	/**

+	 * Returns the path to the file that contains error diagnosis and system specific information.

+	 * 

+	 * @param date

+	 * 			the date to be used as a part of the constructed path

+	 * @return the constructed path

+	 */

+	public static String getSysInfoPath(Date date) {

+		String errorDiagnosisFilename = DEFAULT_SYSINFO_PREFIX  + formatDate(date) + "." + SYSINFO_SUFFIX;

+		return StringUtils.join(Arrays.asList(Configuration.getErrorLogDirectory(), errorDiagnosisFilename),

+			File.separatorChar);

+	}

+	

+	/**

+	 * Formats the given date.

+	 * @param date

+	 * 			the date to be formatted

+	 * @return the formatted date

+	 */

+	public static String formatDate(Date date) {

+		return format.format(date);

+	}

+

+	/**

+	 * Takes a screenshot.

+	 * @param screenshotPath

+	 * 			the path under which the screenshot will be put

+	 * @param format

+	 * 			the format of the screenshot being created

+	 * @return the path to the taken screenshot

+	 */

+	public static String makeScreenshot(String screenshotPath, ScreenshotFormat format) {

+

+		try {

+			BufferedImage bufferedImage = new Robot().createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit()

+				.getScreenSize()));

+			File temp = new File(screenshotPath);

+			temp.deleteOnExit();

+			ImageIO.write(bufferedImage, format.getType(), temp);

+			return temp.getAbsolutePath();

+		} catch (HeadlessException e) {

+			WorkspaceUtil.logException("Could not create screenshot.", e);

+		} catch (AWTException e) {

+			WorkspaceUtil.logException("Could not create screenshot.", e);

+		} catch (IOException e) {

+			WorkspaceUtil.logException("Could not create screenshot.", e);

+		}

+

+		return null;

+	}

+	

+	/**

+	 * Returns the screenshot path.

+	 * @param date

+	 * 			the date that will be part of the screenshot name

+	 * @param format

+	 * 			the format of the screenshot

+	 * @return the constructed path to the screenshot

+	 */

+	public static String getScreenshotPath(Date date, ScreenshotFormat format) {

+		String screenShotFilename = DEFAULT_SCREENSHOT_PREFIX + formatDate(date) + "." + format.getType();

+		return StringUtils.join(Arrays.asList(getScreenshotFolder(), screenShotFilename),

+			File.separatorChar);

+	}

+

+	

+	private static String getScreenshotFolder() {

+		File screenshotDir = new File(StringUtils.join(Arrays.asList(Configuration.getErrorLogDirectory(),

+			SCREENSHOT_FOLDER_NAME), File.separatorChar));

+		

+		if (!screenshotDir.exists()) {

+			screenshotDir.mkdir();

+		}

+		

+		return screenshotDir.getAbsolutePath();

+	}

+}

diff --git a/org.eclipse.emf.emfstore.ui.errorreporting/src/org/eclipse/emf/emfstore/ui/errorreporting/ExceptionLog.java b/org.eclipse.emf.emfstore.ui.errorreporting/src/org/eclipse/emf/emfstore/ui/errorreporting/ExceptionLog.java
new file mode 100644
index 0000000..0aa0bb3
--- /dev/null
+++ b/org.eclipse.emf.emfstore.ui.errorreporting/src/org/eclipse/emf/emfstore/ui/errorreporting/ExceptionLog.java
@@ -0,0 +1,57 @@
+/*******************************************************************************

+ * Copyright (c) 2008-2012 EclipseSource Muenchen GmbH.

+ * 

+ * 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:

+ ******************************************************************************/

+package org.eclipse.emf.emfstore.ui.errorreporting;

+

+import java.util.ArrayList;

+import java.util.List;

+

+/**

+ * Class for logging exceptions.

+ * 

+ * @author Maximilian Koegel

+ */

+public class ExceptionLog {

+

+	private List<Exception> exceptions;

+	private EmfStoreExceptionObserver exceptionObserver;

+

+	/**

+	 * Constructor.

+	 * 

+	 * @param exceptionObserver

+	 * 			the exception that is used to notify this class when to add exceptions

+	 */

+	public ExceptionLog(EmfStoreExceptionObserver exceptionObserver) {

+		this.exceptions = new ArrayList<Exception>();

+		this.exceptionObserver = exceptionObserver;

+		exceptionObserver.addLog(this);

+	}

+

+	/**

+	 * Adds and exception to the log.

+	 * 

+	 * @param exception

+	 * 			the exception to be added

+	 */

+	public void addException(Exception exception) {

+		exceptions.add(exception);

+	}

+

+	/**

+	 * Destroys the exception log.

+	 * 

+	 * @return the list of collected exceptions

+	 */

+	public List<Exception> destroy() {

+		exceptionObserver.removeLog(this);

+		return exceptions;

+	}

+}

diff --git a/org.eclipse.emf.emfstore.ui.errorreporting/src/org/eclipse/emf/emfstore/ui/errorreporting/ILoggable.java b/org.eclipse.emf.emfstore.ui.errorreporting/src/org/eclipse/emf/emfstore/ui/errorreporting/ILoggable.java
new file mode 100644
index 0000000..b7d8415
--- /dev/null
+++ b/org.eclipse.emf.emfstore.ui.errorreporting/src/org/eclipse/emf/emfstore/ui/errorreporting/ILoggable.java
@@ -0,0 +1,27 @@
+/*******************************************************************************

+ * Copyright (c) 2008-2012 EclipseSource Muenchen GmbH.

+ * 

+ * 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:

+ ******************************************************************************/

+package org.eclipse.emf.emfstore.ui.errorreporting;

+

+/**

+ * Interface for adding information to the error diagnosis and system information file that 

+ * is created via {@link ErrorReportingUtil#captureSysInfo(java.util.Date, String)}.

+ *  

+ * @author emueller

+ */

+public interface ILoggable {

+

+	/**

+	 * Returns the string to be logged.

+	 * 

+	 * @return the string to be logged

+	 */

+	String getLoggable();

+}

diff --git a/org.eclipse.emf.emfstore.ui.errorreporting/src/org/eclipse/emf/emfstore/ui/errorreporting/LogFilenameFilter.java b/org.eclipse.emf.emfstore.ui.errorreporting/src/org/eclipse/emf/emfstore/ui/errorreporting/LogFilenameFilter.java
new file mode 100644
index 0000000..fb447c7
--- /dev/null
+++ b/org.eclipse.emf.emfstore.ui.errorreporting/src/org/eclipse/emf/emfstore/ui/errorreporting/LogFilenameFilter.java
@@ -0,0 +1,27 @@
+/*******************************************************************************

+ * Copyright (c) 2008-2012 EclipseSource Muenchen GmbH.

+ * 

+ * 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:

+ ******************************************************************************/

+package org.eclipse.emf.emfstore.ui.errorreporting;

+

+import java.io.File;

+import java.io.FilenameFilter;

+

+/**

+ * Filter for log files.

+ */

+public class LogFilenameFilter implements FilenameFilter {

+	

+	/**

+	 * {@inheritDoc}

+	 */

+	public boolean accept(File file, String name) {

+		return name.toLowerCase().endsWith(".log");

+	}

+}
\ No newline at end of file
diff --git a/org.eclipse.emf.emfstore.ui.errorreporting/src/org/eclipse/emf/emfstore/ui/errorreporting/MailBugHandler.java b/org.eclipse.emf.emfstore.ui.errorreporting/src/org/eclipse/emf/emfstore/ui/errorreporting/MailBugHandler.java
new file mode 100644
index 0000000..5bdeff4
--- /dev/null
+++ b/org.eclipse.emf.emfstore.ui.errorreporting/src/org/eclipse/emf/emfstore/ui/errorreporting/MailBugHandler.java
@@ -0,0 +1,240 @@
+/*******************************************************************************

+ * Copyright (c) 2008-2012 EclipseSource Muenchen GmbH.

+ * 

+ * 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:

+ ******************************************************************************/

+package org.eclipse.emf.emfstore.ui.errorreporting;

+

+import java.io.File;

+import java.io.FileNotFoundException;

+import java.io.IOException;

+import java.lang.reflect.InvocationTargetException;

+import java.net.MalformedURLException;

+import java.net.URL;

+import java.util.Arrays;

+import java.util.Date;

+

+import org.apache.commons.lang.ArrayUtils;

+import org.apache.commons.lang.StringUtils;

+import org.eclipse.core.commands.AbstractHandler;

+import org.eclipse.core.commands.ExecutionEvent;

+import org.eclipse.core.commands.ExecutionException;

+import org.eclipse.core.runtime.IPath;

+import org.eclipse.core.runtime.IProgressMonitor;

+import org.eclipse.core.runtime.Platform;

+import org.eclipse.emf.emfstore.client.model.Configuration;

+import org.eclipse.emf.emfstore.client.model.util.WorkspaceUtil;

+import org.eclipse.jface.action.IAction;

+import org.eclipse.jface.dialogs.MessageDialog;

+import org.eclipse.jface.operation.IRunnableWithProgress;

+import org.eclipse.jface.viewers.ISelection;

+import org.eclipse.swt.widgets.Display;

+import org.eclipse.ui.IWorkbenchWindow;

+import org.eclipse.ui.IWorkbenchWindowActionDelegate;

+import org.eclipse.ui.PartInitException;

+import org.eclipse.ui.PlatformUI;

+import org.eclipse.ui.browser.IWebBrowser;

+import org.eclipse.ui.browser.IWorkbenchBrowserSupport;

+import org.eclipse.ui.progress.IProgressService;

+import org.eclipse.ui.statushandlers.StatusAdapter;

+

+import com.ibm.icu.text.MessageFormat;

+

+/**

+ * Handler for submitting a bug via mail.

+ * 

+ * @author emueller

+ */

+public class MailBugHandler extends AbstractHandler implements IWorkbenchWindowActionDelegate {

+	

+	private IWorkbenchWindow window;

+	private StatusAdapter statusAdapter;

+	

+	/**

+	 * Constructor.

+	 */

+	public MailBugHandler() {

+		this.window = null;

+		this.statusAdapter = null;

+	}

+	

+	/**

+	 * Constructor.

+	 * @param window

+	 * 			a window that is used to determine the shell

+	 * @param statusAdapter

+	 * 			a status adapter that may contain the most recent stack trace

+	 */

+	public MailBugHandler(IWorkbenchWindow window, StatusAdapter statusAdapter) {

+		this.window = window;

+		this.statusAdapter = statusAdapter;

+	}

+

+	private void archive(final Date currentDate, IProgressMonitor monitor, String[] paths)

+		throws FileNotFoundException {

+		monitor.beginTask("Creating error report...", paths.length);

+		try {

+			ZipHandle zipHandle = ZipHandle.openZipHandle(getZipPathname(currentDate));

+			

+			for (String path : paths) {

+				File file = new File(path);

+				

+				if (!file.exists()) {

+					continue;

+				}

+				

+				if (file.isDirectory()) {

+					zipHandle.addFile(StringUtils.EMPTY, path + "/");

+				} else {

+					zipHandle.addFile(StringUtils.EMPTY, path);

+				}

+				

+				monitor.worked(1);

+			}

+

+			zipHandle.close();	

+		} catch (IOException e) {

+			MessageDialog.openError(window.getShell(), "Error while creating zip",

+				MessageFormat.format("An error occurred while trying to archive the workspace folder {0}: {1}", 

+					Configuration.getErrorLogDirectory(), e.getMessage()));

+		}

+		

+		monitor.done();

+	}

+

+	private String getZipPathname(Date currentDate) {

+		String userHome = System.getProperty("user.home");

+		// TODO: where to put zip

+		return StringUtils.join(Arrays.asList(userHome, "Desktop", 

+			ZipHandle.ZIP_PREFIX + ErrorReportingUtil.formatDate(currentDate) + ".zip"), File.separatorChar);

+	}

+

+	/**

+	 * {@inheritDoc}

+	 */

+	public void dispose() {

+	}

+

+	/**

+	 * {@inheritDoc}

+	 */

+	public void init(IWorkbenchWindow window) {

+		this.window = window;

+	}

+

+	/**

+	 * {@inheritDoc}

+	 */

+	public void selectionChanged(IAction action, ISelection selection) {

+		

+	}

+

+	/**

+	 * Display an error message.

+	 */

+	private void openWebBrowserError(final String href, final Throwable t) {

+		String title = "Send Bug Report";

+		String msg = "Unable to open URL " + href + " exception: " + t.getLocalizedMessage();

+		MessageDialog.openError(window.getShell(), title, msg);

+	}

+

+	/**

+	 * {@inheritDoc}

+	 */

+	public Object execute(ExecutionEvent event) throws ExecutionException {

+		

+		final Date date = new Date();

+		boolean shouldCaptureErrorDiagnosis = openShouldCreateErrorReportDialog(date);

+

+		if (shouldCaptureErrorDiagnosis) {

+			IProgressService progressService = PlatformUI.getWorkbench().getProgressService();

+			try {

+				progressService.run(false, false, new IRunnableWithProgress() {

+					public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {

+						try {

+							String screenshotPath = ErrorReportingUtil.makeScreenshot(

+								ErrorReportingUtil.getScreenshotPath(date, ScreenshotFormat.JPG), ScreenshotFormat.JPG);

+							String sysInfoPath = ErrorReportingUtil.captureSysInfo(date, ErrorReportingUtil.getSysInfoPath(date), statusAdapter);

+							IPath logFolder = Platform.getLogFileLocation().removeLastSegments(1);

+							String[] logFiles = getLogFilePaths(logFolder);

+														

+							archive(date, monitor, (String[]) ArrayUtils.addAll(new String[] { screenshotPath, sysInfoPath, Configuration.getWorkspaceDirectory() },

+								logFiles));	

+						} catch (FileNotFoundException exception) {

+							WorkspaceUtil.logException("Could not capture error diagnosis information.", exception);

+						}

+					}

+

+				});

+			} catch (InvocationTargetException exception) {

+				WorkspaceUtil.logException("Could not capture error diagnosis information.", exception);

+			} catch (InterruptedException exception) {

+				WorkspaceUtil.logException("Could not capture error diagnosis information.", exception);

+			}

+		}

+

+		ErrorReportingUtil.copyLogToClipboard(PlatformUI.getWorkbench().getActiveWorkbenchWindow());

+

+		String url;

+		

+		if (shouldCaptureErrorDiagnosis) {

+			url = Platform.getResourceBundle((Activator.getDefault().getBundle())).getString("supportMailURL_errorDiagnosisCaptured");

+		} else {

+			url = Platform.getResourceBundle((Activator.getDefault().getBundle())).getString("supportMailURL");

+		}

+

+		IWorkbenchBrowserSupport support = PlatformUI.getWorkbench().getBrowserSupport();

+		

+		try {

+			IWebBrowser browser = support.getExternalBrowser();

+			browser.openURL(new URL(url));

+		} catch (MalformedURLException exception) {

+			openWebBrowserError(url, exception);

+		} catch (PartInitException exception) {

+			openWebBrowserError(url, exception);

+		}

+

+		return null;

+	}

+	

+	private String[] getLogFilePaths(IPath logFolder) {

+		String[] logFiles = new File(logFolder.toOSString()).list(new LogFilenameFilter());

+		

+		for (int i = 0; i < logFiles.length; i++) {

+			logFiles[i] = logFolder.toOSString() + File.separatorChar + logFiles[i];

+		}

+		

+		return logFiles;

+	}

+

+	private boolean openShouldCreateErrorReportDialog(final Date date) {

+		return MessageDialog.openQuestion(window == null ? Display.getDefault().getActiveShell() : window.getShell(),

+			"Error diagnosis information capture", MessageFormat.format("Would you like to capture error diagnosis information?\n"

+				+ "The data will be stored in a zip file on your desktop with the name \"{0}\".", 

+				ZipHandle.ZIP_PREFIX + ErrorReportingUtil.formatDate(date) + ".zip"));

+	}

+

+	/**

+	 * {@inheritDoc}

+	 */

+	public void run(IAction action) {

+		execute();

+	}

+	

+	/**

+	 * Executes the handler.

+	 */

+	public void execute() {

+		try {

+			execute(new ExecutionEvent());

+		} catch (ExecutionException e) {

+			WorkspaceUtil.logException(e.getMessage(), e);

+		}

+	}

+

+}
\ No newline at end of file
diff --git a/org.eclipse.emf.emfstore.ui.errorreporting/src/org/eclipse/emf/emfstore/ui/errorreporting/MailBugStatusAreaProvider.java b/org.eclipse.emf.emfstore.ui.errorreporting/src/org/eclipse/emf/emfstore/ui/errorreporting/MailBugStatusAreaProvider.java
new file mode 100644
index 0000000..4f91cbf
--- /dev/null
+++ b/org.eclipse.emf.emfstore.ui.errorreporting/src/org/eclipse/emf/emfstore/ui/errorreporting/MailBugStatusAreaProvider.java
@@ -0,0 +1,52 @@
+/*******************************************************************************

+ * Copyright (c) 2008-2012 EclipseSource Muenchen GmbH.

+ * 

+ * 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:

+ ******************************************************************************/

+package org.eclipse.emf.emfstore.ui.errorreporting;

+

+import org.eclipse.jface.dialogs.Dialog;

+import org.eclipse.swt.SWT;

+import org.eclipse.swt.events.SelectionAdapter;

+import org.eclipse.swt.events.SelectionEvent;

+import org.eclipse.swt.widgets.Composite;

+import org.eclipse.swt.widgets.Control;

+import org.eclipse.swt.widgets.Link;

+import org.eclipse.ui.IWorkbenchWindow;

+import org.eclipse.ui.PlatformUI;

+import org.eclipse.ui.statushandlers.AbstractStatusAreaProvider;

+import org.eclipse.ui.statushandlers.StatusAdapter;

+

+/**

+ * Status area provider for sending a bug report via mail. 

+ * 

+ * @author Maximilian Koegel

+ *

+ */

+public class MailBugStatusAreaProvider extends AbstractStatusAreaProvider {

+

+	/**

+	 * {@inheritDoc}

+	 */

+	public Control createSupportArea(final Composite parent, final StatusAdapter statusAdapter) {

+		Link link = new Link(parent, SWT.NONE);

+		IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();

+		final MailBugHandler bugHandler = new MailBugHandler(window, statusAdapter);

+		link.setText("Please <a>send us a bug report</a>. Clicking\nthe link will create a new mail with\nyour default mail program. Before\nsending the mail please follow the\ninstructions in the mail body.");

+		// TODo

+//		link.setToolTipText(bugHandler.getToolTipText());

+		link.addSelectionListener(new SelectionAdapter() {

+			public void widgetSelected(SelectionEvent e) {

+				bugHandler.execute();

+			}

+		});

+		Dialog.applyDialogFont(link);

+		return parent;

+	}

+

+}

diff --git a/org.eclipse.emf.emfstore.ui.errorreporting/src/org/eclipse/emf/emfstore/ui/errorreporting/ScreenshotFormat.java b/org.eclipse.emf.emfstore.ui.errorreporting/src/org/eclipse/emf/emfstore/ui/errorreporting/ScreenshotFormat.java
new file mode 100644
index 0000000..6128c2f
--- /dev/null
+++ b/org.eclipse.emf.emfstore.ui.errorreporting/src/org/eclipse/emf/emfstore/ui/errorreporting/ScreenshotFormat.java
@@ -0,0 +1,46 @@
+/*******************************************************************************

+ * Copyright (c) 2008-2012 EclipseSource Muenchen GmbH.

+ * 

+ * 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:

+ ******************************************************************************/

+package org.eclipse.emf.emfstore.ui.errorreporting;

+

+/**

+ * Represents the format of a screenshot.

+ * 

+ * @author emueller

+ *

+ */

+public enum ScreenshotFormat {

+	

+	/**

+	 * JPG format.

+	 */

+	JPG("jpg");

+	

+	private final String type;

+	

+	/**

+	 * Constructor.

+	 * 

+	 * @param type 

+	 * 			the format type 

+	 */

+	ScreenshotFormat(String type) {

+		this.type = type;

+	}

+	

+	/**

+	 * Returns the format type as a string.

+	 * @return the format type as a string

+	 */

+	public String getType() {

+		return type;

+	}

+

+}

diff --git a/org.eclipse.emf.emfstore.ui.errorreporting/src/org/eclipse/emf/emfstore/ui/errorreporting/ZipHandle.java b/org.eclipse.emf.emfstore.ui.errorreporting/src/org/eclipse/emf/emfstore/ui/errorreporting/ZipHandle.java
new file mode 100644
index 0000000..ace1901
--- /dev/null
+++ b/org.eclipse.emf.emfstore.ui.errorreporting/src/org/eclipse/emf/emfstore/ui/errorreporting/ZipHandle.java
@@ -0,0 +1,141 @@
+/*******************************************************************************

+ * Copyright (c) 2008-2012 EclipseSource Muenchen GmbH.

+ * 

+ * 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:

+ ******************************************************************************/

+package org.eclipse.emf.emfstore.ui.errorreporting;

+

+import java.io.BufferedOutputStream;

+import java.io.File;

+import java.io.FileInputStream;

+import java.io.FileNotFoundException;

+import java.io.FileOutputStream;

+import java.io.IOException;

+import java.util.zip.ZipEntry;

+import java.util.zip.ZipOutputStream;

+

+import org.apache.commons.io.IOUtils;

+

+/**

+ * A zip handle for creating zip files.

+ * 

+ * @author emueller

+ */

+public final class ZipHandle {

+

+	/**

+	 * The prefix that will be used as part of the zip file.

+	 */

+	public static final String ZIP_PREFIX = "EMFStoreErrorLog_";

+	

+	private final ZipOutputStream zipOutputStream;

+	private final FileOutputStream fileOutputStream;

+	private final BufferedOutputStream bufferedOutputStream;

+

+	private ZipHandle(FileOutputStream fileOutputStream, BufferedOutputStream bufferedOutputStream,

+		ZipOutputStream zipOutputStream) {

+		this.fileOutputStream = fileOutputStream;

+		this.bufferedOutputStream = bufferedOutputStream;

+		this.zipOutputStream = zipOutputStream;

+	}

+

+	/**

+	 * Adds a file to the zip.

+	 * 

+	 * @param base

+	 * 			the base name of the file being added

+	 * @param path

+	 * 			the actual path of file to be added to the zip

+	 * @throws IOException in case the file could not be added

+	 */

+	public void addFile(String base, String path) throws IOException {

+

+		if (path == null) {

+			return;

+		}

+

+		addFileToZip(zipOutputStream, path, base);

+	}

+

+	/**

+	 * Closes the handle.

+	 * 

+	 * @throws IOException in case anything goes wrong during the closing of the handle

+	 */

+	public void close() throws IOException {

+		if (zipOutputStream != null) {

+			zipOutputStream.finish();

+			zipOutputStream.close();

+		}

+

+		if (bufferedOutputStream != null) {

+			bufferedOutputStream.close();

+		}

+

+		if (fileOutputStream != null) {

+			fileOutputStream.close();

+		}

+	}

+

+	/**

+	 * Creates a zip entry for the path specified with a name built from the base passed in and the file/directory

+	 * name. If the path is a directory, a recursive call is made such that the full directory is added to the zip.

+	 * 

+	 * @param zipOutputStream 

+	 * 				the zip file's output stream

+	 * @param path 

+	 * 				the filesystem path of the file/directory being added

+	 * @param base 

+	 * 				the base prefix to for the name of the zip file entry

+	 * 

+	 * @throws IOException in case of an error during addition of the file to the zip

+	 */

+	private void addFileToZip(ZipOutputStream zipOutputStream, String path, String base) throws IOException {

+		File file = new File(path);

+		String entryName = base + file.getName();

+		ZipEntry zipEntry = new ZipEntry(entryName);

+

+

+		if (file.isFile()) {

+			zipOutputStream.putNextEntry(zipEntry);

+			FileInputStream fileInputStream = null;

+			try {

+				fileInputStream = new FileInputStream(file);

+				IOUtils.copy(fileInputStream, zipOutputStream);

+			} finally {

+			}

+		} else {

+			File[] children = file.listFiles();

+

+			if (children != null) {

+				for (File child : children) {

+					addFileToZip(zipOutputStream, child.getAbsolutePath(), entryName + "/");

+				}

+			}

+		}

+	}

+	

+	/**

+	 * Opens up a zip handle.

+	 * @param zipPath

+	 * 			the path of the zip file being created

+	 * @return the created zip handle

+	 * @throws FileNotFoundException in case intial zip file creation fails

+	 */

+	public static ZipHandle openZipHandle(String zipPath) throws FileNotFoundException {

+		FileOutputStream fileOutputStream = null;

+		BufferedOutputStream bufferedOutputStream = null;

+		ZipOutputStream zipOutputStream = null;

+

+		fileOutputStream = new FileOutputStream(new File(zipPath));

+		bufferedOutputStream = new BufferedOutputStream(fileOutputStream);

+		zipOutputStream = new ZipOutputStream(bufferedOutputStream);

+		ZipHandle zipHandle = new ZipHandle(fileOutputStream, bufferedOutputStream, zipOutputStream);

+		return zipHandle;

+	}

+}