Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.4/HeuristicLab.Clients.Hive.ExperimentManager-3.4.csproj
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.4/HeuristicLab.Clients.Hive.ExperimentManager-3.4.csproj	(revision 6458)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.4/HeuristicLab.Clients.Hive.ExperimentManager-3.4.csproj	(revision 6463)
@@ -102,4 +102,5 @@
   </PropertyGroup>
   <ItemGroup>
+    <Reference Include="HeuristicLab.Clients.Hive.ExperimentManager-3.4, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL" />
     <Reference Include="HeuristicLab.Collections-3.3">
       <HintPath>C:\Program Files\HeuristicLab 3.3\HeuristicLab.Collections-3.3.dll</HintPath>
@@ -151,4 +152,23 @@
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="Views\HiveExperimentManagerView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="Views\HiveExperimentManagerView.Designer.cs">
+      <DependentUpon>HiveExperimentManagerView.cs</DependentUpon>
+    </Compile>
+    <Compile Include="MenuItems\ExperimentManagerMenuItem.cs" />
+    <Compile Include="Views\HiveExperimentPermissionListView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="Views\HiveExperimentPermissionListView.Designer.cs">
+      <DependentUpon>HiveExperimentPermissionListView.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Views\HiveExperimentPermissionView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="Views\HiveExperimentPermissionView.Designer.cs">
+      <DependentUpon>HiveExperimentPermissionView.cs</DependentUpon>
+    </Compile>
     <Compile Include="Views\RefreshableHiveExperimentListView.cs">
       <SubType>UserControl</SubType>
@@ -157,11 +177,4 @@
       <DependentUpon>RefreshableHiveExperimentListView.cs</DependentUpon>
     </Compile>
-    <Compile Include="Views\HiveExperimentManagerView.cs">
-      <SubType>UserControl</SubType>
-    </Compile>
-    <Compile Include="Views\HiveExperimentManagerView.Designer.cs">
-      <DependentUpon>HiveExperimentManagerView.cs</DependentUpon>
-    </Compile>
-    <Compile Include="MenuItems\ExperimentManagerMenuItem.cs" />
     <Compile Include="Views\RefreshableHiveExperimentView.cs">
       <SubType>UserControl</SubType>
@@ -200,4 +213,7 @@
       <DependentUpon>HiveExperimentManagerView.cs</DependentUpon>
       <SubType>Designer</SubType>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Views\HiveExperimentPermissionView.resx">
+      <DependentUpon>HiveExperimentPermissionView.cs</DependentUpon>
     </EmbeddedResource>
     <EmbeddedResource Include="Views\RefreshableHiveExperimentView.resx">
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.4/Views/HiveExperimentPermissionListView.Designer.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.4/Views/HiveExperimentPermissionListView.Designer.cs	(revision 6463)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.4/Views/HiveExperimentPermissionListView.Designer.cs	(revision 6463)
@@ -0,0 +1,32 @@
+﻿namespace HeuristicLab.Clients.Hive.ExperimentManager.Views {
+  partial class HiveExperimentPermissionListView {
+    /// <summary> 
+    /// Required designer variable.
+    /// </summary>
+    private System.ComponentModel.IContainer components = null;
+
+    /// <summary> 
+    /// Clean up any resources being used.
+    /// </summary>
+    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+    protected override void Dispose(bool disposing) {
+      if (disposing && (components != null)) {
+        components.Dispose();
+      }
+      base.Dispose(disposing);
+    }
+
+    #region Component Designer generated code
+
+    /// <summary> 
+    /// Required method for Designer support - do not modify 
+    /// the contents of this method with the code editor.
+    /// </summary>
+    private void InitializeComponent() {
+      components = new System.ComponentModel.Container();
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+    }
+
+    #endregion
+  }
+}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.4/Views/HiveExperimentPermissionListView.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.4/Views/HiveExperimentPermissionListView.cs	(revision 6463)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.4/Views/HiveExperimentPermissionListView.cs	(revision 6463)
@@ -0,0 +1,46 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Windows.Forms;
+using HeuristicLab.Core.Views;
+using HeuristicLab.MainForm;
+
+namespace HeuristicLab.Clients.Hive.ExperimentManager.Views {
+  [View("HiveExperimentPermissionList View")]
+  [Content(typeof(HiveItemCollection<HiveExperimentPermission>), false)]
+  public partial class HiveExperimentPermissionListView : ItemCollectionView<HiveExperimentPermission> {
+
+    private Guid hiveExperimentId;
+    public Guid HiveExperimentId {
+      get { return hiveExperimentId; }
+      set { hiveExperimentId = value; }
+    }    
+
+    public HiveExperimentPermissionListView() {
+      InitializeComponent();
+    }
+
+    protected override HiveExperimentPermission CreateItem() {
+      return new HiveExperimentPermission() { HiveExperimentId = this.hiveExperimentId };
+    }
+  }
+}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.4/Views/HiveExperimentPermissionView.Designer.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.4/Views/HiveExperimentPermissionView.Designer.cs	(revision 6463)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.4/Views/HiveExperimentPermissionView.Designer.cs	(revision 6463)
@@ -0,0 +1,102 @@
+﻿namespace HeuristicLab.Clients.Hive.ExperimentManager.Views {
+  partial class HiveExperimentPermissionView {
+    /// <summary> 
+    /// Required designer variable.
+    /// </summary>
+    private System.ComponentModel.IContainer components = null;
+
+    /// <summary> 
+    /// Clean up any resources being used.
+    /// </summary>
+    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+    protected override void Dispose(bool disposing) {
+      if (disposing && (components != null)) {
+        components.Dispose();
+      }
+      base.Dispose(disposing);
+    }
+
+    #region Component Designer generated code
+
+    /// <summary> 
+    /// Required method for Designer support - do not modify 
+    /// the contents of this method with the code editor.
+    /// </summary>
+    private void InitializeComponent() {
+      this.usernameLabel = new System.Windows.Forms.Label();
+      this.permissionLabel = new System.Windows.Forms.Label();
+      this.usernameTextBox = new System.Windows.Forms.TextBox();
+      this.permissionComboBox = new System.Windows.Forms.ComboBox();
+      this.SuspendLayout();
+      // 
+      // storeButton
+      // 
+      this.toolTip.SetToolTip(this.storeButton, "Store Data");
+      // 
+      // usernameLabel
+      // 
+      this.usernameLabel.AutoSize = true;
+      this.usernameLabel.Location = new System.Drawing.Point(3, 27);
+      this.usernameLabel.Name = "usernameLabel";
+      this.usernameLabel.Size = new System.Drawing.Size(58, 13);
+      this.usernameLabel.TabIndex = 1;
+      this.usernameLabel.Text = "Username:";
+      // 
+      // permissionLabel
+      // 
+      this.permissionLabel.AutoSize = true;
+      this.permissionLabel.Location = new System.Drawing.Point(4, 57);
+      this.permissionLabel.Name = "permissionLabel";
+      this.permissionLabel.Size = new System.Drawing.Size(57, 13);
+      this.permissionLabel.TabIndex = 2;
+      this.permissionLabel.Text = "Permission";
+      // 
+      // usernameTextBox
+      // 
+      this.usernameTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.usernameTextBox.Location = new System.Drawing.Point(67, 28);
+      this.usernameTextBox.Name = "usernameTextBox";
+      this.usernameTextBox.Size = new System.Drawing.Size(284, 20);
+      this.usernameTextBox.TabIndex = 3;
+      this.usernameTextBox.Validated += new System.EventHandler(this.usernameTextBox_Validated);
+      // 
+      // permissionComboBox
+      // 
+      this.permissionComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.permissionComboBox.FormattingEnabled = true;
+      this.permissionComboBox.Location = new System.Drawing.Point(67, 54);
+      this.permissionComboBox.Name = "permissionComboBox";
+      this.permissionComboBox.Size = new System.Drawing.Size(284, 21);
+      this.permissionComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+      this.permissionComboBox.TabIndex = 4;
+      this.permissionComboBox.Validated += new System.EventHandler(this.permissionComboBox_Validated);
+      // 
+      // HiveExperimentPermissionView
+      // 
+      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.Controls.Add(this.usernameLabel);
+      this.Controls.Add(this.permissionComboBox);
+      this.Controls.Add(this.permissionLabel);
+      this.Controls.Add(this.usernameTextBox);
+      this.Name = "HiveExperimentPermissionView";
+      this.Controls.SetChildIndex(this.usernameTextBox, 0);
+      this.Controls.SetChildIndex(this.permissionLabel, 0);
+      this.Controls.SetChildIndex(this.permissionComboBox, 0);
+      this.Controls.SetChildIndex(this.usernameLabel, 0);
+      this.Controls.SetChildIndex(this.storeButton, 0);
+      this.ResumeLayout(false);
+      this.PerformLayout();
+
+    }
+
+    #endregion
+
+    private System.Windows.Forms.Label usernameLabel;
+    private System.Windows.Forms.Label permissionLabel;
+    private System.Windows.Forms.TextBox usernameTextBox;
+    private System.Windows.Forms.ComboBox permissionComboBox;
+  }
+}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.4/Views/HiveExperimentPermissionView.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.4/Views/HiveExperimentPermissionView.cs	(revision 6463)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.4/Views/HiveExperimentPermissionView.cs	(revision 6463)
@@ -0,0 +1,73 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Clients.Hive.Views;
+using HeuristicLab.MainForm;
+
+namespace HeuristicLab.Clients.Hive.ExperimentManager.Views {
+  [View("HiveExperimentPermission View")]
+  [Content(typeof(HiveExperimentPermission), true)]
+  public partial class HiveExperimentPermissionView : HiveItemView {
+    public new HiveExperimentPermission Content {
+      get { return (HiveExperimentPermission)base.Content; }
+      set { base.Content = value; }
+    }
+
+    public HiveExperimentPermissionView() {
+      InitializeComponent();
+      permissionComboBox.Items.Add(Permission.ReadOnly);
+      permissionComboBox.Items.Add(Permission.Full);
+      permissionComboBox.SelectedItem = Permission.ReadOnly;
+    }
+
+    protected override void OnContentChanged() {
+      base.OnContentChanged();
+      if (Content == null) {
+        usernameTextBox.Text = string.Empty;
+        permissionComboBox.SelectedIndex = 0;
+      } else {
+        usernameTextBox.Text = Content.GrantedUserName;
+        permissionComboBox.SelectedValue = Content.Permission;
+      }
+    }
+
+    protected override void SetEnabledStateOfControls() {
+      base.SetEnabledStateOfControls();
+      if (Content == null) {
+        usernameTextBox.Enabled = false;
+        permissionComboBox.Enabled = false;
+      } else {
+        usernameTextBox.Enabled = true;
+        permissionComboBox.Enabled = true;
+      }
+    }
+
+    #region Child Control Events
+    private void usernameTextBox_Validated(object sender, System.EventArgs e) {
+      Content.GrantedUserName = usernameTextBox.Text;
+    }
+
+    private void permissionComboBox_Validated(object sender, System.EventArgs e) {
+      Content.Permission = (Permission)permissionComboBox.SelectedItem;
+    }
+    #endregion
+  }
+}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.4/Views/HiveExperimentPermissionView.resx
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.4/Views/HiveExperimentPermissionView.resx	(revision 6463)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.4/Views/HiveExperimentPermissionView.resx	(revision 6463)
@@ -0,0 +1,126 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+  <metadata name="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+</root>
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.4/Views/RefreshableHiveExperimentView.Designer.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.4/Views/RefreshableHiveExperimentView.Designer.cs	(revision 6458)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.4/Views/RefreshableHiveExperimentView.Designer.cs	(revision 6463)
@@ -54,4 +54,6 @@
       this.stateTabPage = new System.Windows.Forms.TabPage();
       this.stateLogViewHost = new HeuristicLab.MainForm.WindowsForms.ViewHost();
+      this.sharingTabPage = new System.Windows.Forms.TabPage();
+      this.hiveExperimentPermissionListView = new HeuristicLab.Clients.Hive.ExperimentManager.Views.HiveExperimentPermissionListView();
       this.logTabPage = new System.Windows.Forms.TabPage();
       this.logView = new HeuristicLab.Core.Views.LogView();
@@ -77,7 +79,9 @@
       this.calculatingLabel = new System.Windows.Forms.Label();
       this.jobsLabel = new System.Windows.Forms.Label();
+      this.refreshPermissionsButton = new System.Windows.Forms.Button();
       this.tabControl.SuspendLayout();
       this.jobsTabPage.SuspendLayout();
       this.stateTabPage.SuspendLayout();
+      this.sharingTabPage.SuspendLayout();
       this.logTabPage.SuspendLayout();
       this.infoGroupBox.SuspendLayout();
@@ -91,4 +95,5 @@
       this.tabControl.Controls.Add(this.jobsTabPage);
       this.tabControl.Controls.Add(this.stateTabPage);
+      this.tabControl.Controls.Add(this.sharingTabPage);
       this.tabControl.Controls.Add(this.logTabPage);
       this.tabControl.Location = new System.Drawing.Point(0, 78);
@@ -132,5 +137,5 @@
       this.stateTabPage.Size = new System.Drawing.Size(709, 426);
       this.stateTabPage.TabIndex = 6;
-      this.stateTabPage.Text = "State";
+      this.stateTabPage.Text = "States";
       this.stateTabPage.UseVisualStyleBackColor = true;
       // 
@@ -149,4 +154,28 @@
       this.stateLogViewHost.ViewType = null;
       // 
+      // sharingTabPage
+      // 
+      this.sharingTabPage.Controls.Add(this.refreshPermissionsButton);
+      this.sharingTabPage.Controls.Add(this.hiveExperimentPermissionListView);
+      this.sharingTabPage.Location = new System.Drawing.Point(4, 22);
+      this.sharingTabPage.Name = "sharingTabPage";
+      this.sharingTabPage.Size = new System.Drawing.Size(709, 426);
+      this.sharingTabPage.TabIndex = 7;
+      this.sharingTabPage.Text = "Sharing";
+      this.sharingTabPage.UseVisualStyleBackColor = true;
+      // 
+      // hiveExperimentPermissionListView
+      // 
+      this.hiveExperimentPermissionListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+                  | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.hiveExperimentPermissionListView.Caption = "HiveExperimentPermissionList View";
+      this.hiveExperimentPermissionListView.Content = null;
+      this.hiveExperimentPermissionListView.Location = new System.Drawing.Point(3, 33);
+      this.hiveExperimentPermissionListView.Name = "hiveExperimentPermissionListView";
+      this.hiveExperimentPermissionListView.ReadOnly = false;
+      this.hiveExperimentPermissionListView.Size = new System.Drawing.Size(703, 390);
+      this.hiveExperimentPermissionListView.TabIndex = 0;
+      // 
       // logTabPage
       // 
@@ -167,5 +196,5 @@
       this.logView.Name = "logView";
       this.logView.ReadOnly = false;
-      this.logView.Size = new System.Drawing.Size(813, 494);
+      this.logView.Size = new System.Drawing.Size(709, 426);
       this.logView.TabIndex = 0;
       // 
@@ -381,4 +410,15 @@
       this.jobsLabel.TabIndex = 0;
       this.jobsLabel.Text = "Jobs:";
+      // 
+      // refreshPermissionsButton
+      // 
+      this.refreshPermissionsButton.Image = ((System.Drawing.Image)(resources.GetObject("refreshPermissionsButton.Image")));
+      this.refreshPermissionsButton.Location = new System.Drawing.Point(3, 3);
+      this.refreshPermissionsButton.Name = "refreshPermissionsButton";
+      this.refreshPermissionsButton.Size = new System.Drawing.Size(24, 24);
+      this.refreshPermissionsButton.TabIndex = 23;
+      this.toolTip.SetToolTip(this.refreshPermissionsButton, "Refresh Data");
+      this.refreshPermissionsButton.UseVisualStyleBackColor = true;
+      this.refreshPermissionsButton.Click += new System.EventHandler(this.refreshPermissionsButton_Click);
       // 
       // RefreshableHiveExperimentView
@@ -406,4 +446,5 @@
       this.jobsTabPage.ResumeLayout(false);
       this.stateTabPage.ResumeLayout(false);
+      this.sharingTabPage.ResumeLayout(false);
       this.logTabPage.ResumeLayout(false);
       this.infoGroupBox.ResumeLayout(false);
@@ -443,4 +484,7 @@
     private System.Windows.Forms.TabPage stateTabPage;
     private ViewHost stateLogViewHost;
+    private System.Windows.Forms.TabPage sharingTabPage;
+    private HiveExperimentPermissionListView hiveExperimentPermissionListView;
+    private System.Windows.Forms.Button refreshPermissionsButton;
 
   }
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.4/Views/RefreshableHiveExperimentView.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.4/Views/RefreshableHiveExperimentView.cs	(revision 6458)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.4/Views/RefreshableHiveExperimentView.cs	(revision 6463)
@@ -21,4 +21,5 @@
 
 using System;
+using System.ComponentModel;
 using System.Linq;
 using System.Threading;
@@ -79,5 +80,7 @@
       Content.HiveExperiment.HiveJobsChanged += new EventHandler(Content_HiveJobChanged);
       Content.HiveExperiment.IsProgressingChanged += new EventHandler(Content_IsProgressingChanged);
-    }
+      Content.HiveExperiment.PropertyChanged += new PropertyChangedEventHandler(HiveExperiment_PropertyChanged);
+    }
+    
     private void DeregisterHiveExperimentEvents() {
       Content.HiveExperiment.ExecutionStateChanged -= new EventHandler(Content_ExecutionStateChanged);
@@ -85,15 +88,16 @@
       Content.HiveExperiment.HiveJobsChanged -= new EventHandler(Content_HiveJobChanged);
       Content.HiveExperiment.IsProgressingChanged -= new EventHandler(Content_IsProgressingChanged);
+      Content.HiveExperiment.PropertyChanged -= new PropertyChangedEventHandler(HiveExperiment_PropertyChanged);
     }
 
     private void RegisterHiveJobEvents() {
-      Content.HiveExperiment.HiveJobs.ItemsAdded += new Collections.CollectionItemsChangedEventHandler<HiveJob>(HiveJobs_ItemsAdded_Removed_Reset);
-      Content.HiveExperiment.HiveJobs.ItemsRemoved += new Collections.CollectionItemsChangedEventHandler<HiveJob>(HiveJobs_ItemsAdded_Removed_Reset);
-      Content.HiveExperiment.HiveJobs.CollectionReset += new Collections.CollectionItemsChangedEventHandler<HiveJob>(HiveJobs_ItemsAdded_Removed_Reset);
+      Content.HiveExperiment.HiveJobs.ItemsAdded += new CollectionItemsChangedEventHandler<HiveJob>(HiveJobs_ItemsAdded_Removed_Reset);
+      Content.HiveExperiment.HiveJobs.ItemsRemoved += new CollectionItemsChangedEventHandler<HiveJob>(HiveJobs_ItemsAdded_Removed_Reset);
+      Content.HiveExperiment.HiveJobs.CollectionReset += new CollectionItemsChangedEventHandler<HiveJob>(HiveJobs_ItemsAdded_Removed_Reset);
     }
     private void DeregisterHiveJobEvents() {
-      Content.HiveExperiment.HiveJobs.ItemsAdded -= new Collections.CollectionItemsChangedEventHandler<HiveJob>(HiveJobs_ItemsAdded_Removed_Reset);
-      Content.HiveExperiment.HiveJobs.ItemsRemoved -= new Collections.CollectionItemsChangedEventHandler<HiveJob>(HiveJobs_ItemsAdded_Removed_Reset);
-      Content.HiveExperiment.HiveJobs.CollectionReset -= new Collections.CollectionItemsChangedEventHandler<HiveJob>(HiveJobs_ItemsAdded_Removed_Reset);
+      Content.HiveExperiment.HiveJobs.ItemsAdded -= new CollectionItemsChangedEventHandler<HiveJob>(HiveJobs_ItemsAdded_Removed_Reset);
+      Content.HiveExperiment.HiveJobs.ItemsRemoved -= new CollectionItemsChangedEventHandler<HiveJob>(HiveJobs_ItemsAdded_Removed_Reset);
+      Content.HiveExperiment.HiveJobs.CollectionReset -= new CollectionItemsChangedEventHandler<HiveJob>(HiveJobs_ItemsAdded_Removed_Reset);
     }
 
@@ -116,4 +120,5 @@
         logView.Content = Content.Log;
       }
+      hiveExperimentPermissionListView.Content = null; // has to be filled by refresh button
       Content_JobStatisticsChanged(this, EventArgs.Empty);
       Content_HiveExperimentChanged(this, EventArgs.Empty);
@@ -121,4 +126,5 @@
       Content_IsProgressingChanged(this, EventArgs.Empty);
       Content_StateLogListChanged(this, EventArgs.Empty);
+      HiveExperiment_PropertyChanged(this, new PropertyChangedEventArgs("Id"));
       SetEnabledStateOfControls();
     }
@@ -277,4 +283,8 @@
       }
     }
+
+    private void HiveExperiment_PropertyChanged(object sender, PropertyChangedEventArgs e) {
+      if(this.Content != null && e.PropertyName == "Id") this.hiveExperimentPermissionListView.HiveExperimentId = this.Content.HiveExperiment.Id;
+    }
     #endregion
 
@@ -320,4 +330,10 @@
       }, null);
     }
+
+    private void refreshPermissionsButton_Click(object sender, EventArgs e) {
+      hiveExperimentPermissionListView.Content = HiveClient.GetHiveExperimentPermissions(this.Content.HiveExperiment.Id);
+    }
+
+
     #endregion
 
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.4/Views/RefreshableHiveExperimentView.resx
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.4/Views/RefreshableHiveExperimentView.resx	(revision 6458)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.4/Views/RefreshableHiveExperimentView.resx	(revision 6463)
@@ -119,54 +119,5 @@
   </resheader>
   <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
-  <data name="startButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
-    <value>
-        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
-        YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAAK/wAA
-        Cv8BNGKaggAAALBJREFUOE9j+P//PwMlGKvmsv3ZbsQaitWAhBkR/4k1BKcBlmX6RBmC1YCoKUH/N9xa
-        /J8YQ7AaEDzBG2Q7UYZgNcCnyxlsAAhHLQrA6xKsBjg2W/zP2BAL1mzbrP9fp1jhv0QaN4hWQ48drAaY
-        1+ihaOZPYMGqGWQYVgP0SpXhNuPTjNMAlXwpsLMJacZpgHSGIFGacRogksyJ089EBSK20MaVNyjKiTi9
-        QGxOBKkDACT9xOni1RbMAAAAAElFTkSuQmCC
-</value>
-  </data>
-  <metadata name="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
-    <value>17, 17</value>
-  </metadata>
-  <data name="stopButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
-    <value>
-        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
-        YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAAK/wAA
-        Cv8BNGKaggAAAWtJREFUOE/Nkz9IAmEYxl0KGqKtMVpaIiEoipYIgnByCSGhSQiCNBqCMiqwsr8clChF
-        YmYSSikeWEbZH2qwEhKhwhAXjQwKEbw0zyue7nO7hgtyqOEbf7/ne5+XVwJAUsorCSbB/0xAeT+xSBcw
-        685B52QwYU9jdOMFw+ZnDK0+YtCUyHzvSzACge/jH7hLcAg8FHB4w8IbZOEKsLD4s5AqdnheWLpAQJKj
-        TxyCUa4IOi/yWPPlsOJlMGePoU6+JS4g376NczgKsdg+y8PIg3pnBmPWV6ipMGq61sUFZOarCAf3JZ98
-        8I75XQKnoDEmoRg5RXW7QVxACvOHWdhO8lim36C1ptFvSEI5E4NsYA9VLUviAtK255qFcT+LSXsKahMP
-        66OQa0Po7HOholEvLiCr2jxmMG2LQEOFoBw/55M96FA50NpjRlmDTlxA9tym8qGpl0Z9twO1Mktx7srm
-        BZRLp34W/Oao/v4WvgBcI/R+TmAaZAAAAABJRU5ErkJggg==
-</value>
-  </data>
-  <data name="resetButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
-    <value>
-        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
-        YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAAK/wAA
-        Cv8BNGKaggAAAX9JREFUOE9j+P//PwMlmCLNIIupa0Dv5r//Ybht7bf/jSs+/69d/P5/xbxX/0tmP/9f
-        MP3x/9JZj4EWI7yN4oKuDb/+bzr57f/KQ1/+L9jz6f/lBz//965997956RuwIXnTX/zXDV2F2wCQrSsO
-        fvk/b9en/7ee/AIp/N+w5M3/0rkv/+dMff4/qffZf1W/RbgNADl5zo5P/x++/AHWDAIls1/+z5ry/H9C
-        79P/Ya2P/8u5zcJtAMi/Nx99hmtGZhy7/Oa/V+3D/2J2k3AbAPJn87I3/09deQnXG9355H9g0yMw36H0
-        /n9+s27cBoBCuhxoSM605/93HrkL1hTQ8Oi/W9UDMNss7+5/ToNW3AaAoikb6N9EoH/D2x7/n7Puwn/X
-        ivv/bYrvgQ3Qy7j1n1WnEbcBoDiO63n6P7Tl0X+fuof/ncrv/7cuvPffJPsO2AD1JCIMsEza9h+EjWM2
-        /NcKXv5fwWMuOOB4TTr/s+k24XcB0BKSkzbJGtAtodgAAJMl+qgyDSjjAAAAAElFTkSuQmCC
-</value>
-  </data>
-  <data name="pauseButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
-    <value>
-        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
-        YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAAK/wAA
-        Cv8BNGKaggAAAL5JREFUOE9j+P//PwMlmCLNIIsHoQG9m//+79rw63/e1EefQE5E56OHF4YXQJqvPvzz
-        Xzd0FVDtfwZ0PkED2tZ++3/r6e//qn6LwAag8wka0Lji8//LD3//l3ObBTYAnU/QgNrF7/+fuP77v5jd
-        JLAB6HyCBlTMe/V/94Wf//nNusEGoPMJGlAy+/n/9Sd//uc0aAUbgM4naEDB9Mf/F+z5/J9VpxFsADqf
-        oAGg+GfTbYIbgM4naACpGWvg8wIAkX3yJyVePz4AAAAASUVORK5CYII=
-</value>
-  </data>
-  <data name="refreshButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+  <data name="refreshPermissionsButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
     <value>
         iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAACH
@@ -229,4 +180,114 @@
 </value>
   </data>
+  <metadata name="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+  <data name="startButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+        YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAAK/wAA
+        Cv8BNGKaggAAALBJREFUOE9j+P//PwMlGKvmsv3ZbsQaitWAhBkR/4k1BKcBlmX6RBmC1YCoKUH/N9xa
+        /J8YQ7AaEDzBG2Q7UYZgNcCnyxlsAAhHLQrA6xKsBjg2W/zP2BAL1mzbrP9fp1jhv0QaN4hWQ48drAaY
+        1+ihaOZPYMGqGWQYVgP0SpXhNuPTjNMAlXwpsLMJacZpgHSGIFGacRogksyJ089EBSK20MaVNyjKiTi9
+        QGxOBKkDACT9xOni1RbMAAAAAElFTkSuQmCC
+</value>
+  </data>
+  <data name="stopButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+        YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAAK/wAA
+        Cv8BNGKaggAAAWtJREFUOE/Nkz9IAmEYxl0KGqKtMVpaIiEoipYIgnByCSGhSQiCNBqCMiqwsr8clChF
+        YmYSSikeWEbZH2qwEhKhwhAXjQwKEbw0zyue7nO7hgtyqOEbf7/ne5+XVwJAUsorCSbB/0xAeT+xSBcw
+        685B52QwYU9jdOMFw+ZnDK0+YtCUyHzvSzACge/jH7hLcAg8FHB4w8IbZOEKsLD4s5AqdnheWLpAQJKj
+        TxyCUa4IOi/yWPPlsOJlMGePoU6+JS4g376NczgKsdg+y8PIg3pnBmPWV6ipMGq61sUFZOarCAf3JZ98
+        8I75XQKnoDEmoRg5RXW7QVxACvOHWdhO8lim36C1ptFvSEI5E4NsYA9VLUviAtK255qFcT+LSXsKahMP
+        66OQa0Po7HOholEvLiCr2jxmMG2LQEOFoBw/55M96FA50NpjRlmDTlxA9tym8qGpl0Z9twO1Mktx7srm
+        BZRLp34W/Oao/v4WvgBcI/R+TmAaZAAAAABJRU5ErkJggg==
+</value>
+  </data>
+  <data name="resetButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+        YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAAK/wAA
+        Cv8BNGKaggAAAX9JREFUOE9j+P//PwMlmCLNIIupa0Dv5r//Ybht7bf/jSs+/69d/P5/xbxX/0tmP/9f
+        MP3x/9JZj4EWI7yN4oKuDb/+bzr57f/KQ1/+L9jz6f/lBz//965997956RuwIXnTX/zXDV2F2wCQrSsO
+        fvk/b9en/7ee/AIp/N+w5M3/0rkv/+dMff4/qffZf1W/RbgNADl5zo5P/x++/AHWDAIls1/+z5ry/H9C
+        79P/Ya2P/8u5zcJtAMi/Nx99hmtGZhy7/Oa/V+3D/2J2k3AbAPJn87I3/09deQnXG9355H9g0yMw36H0
+        /n9+s27cBoBCuhxoSM605/93HrkL1hTQ8Oi/W9UDMNss7+5/ToNW3AaAoikb6N9EoH/D2x7/n7Puwn/X
+        ivv/bYrvgQ3Qy7j1n1WnEbcBoDiO63n6P7Tl0X+fuof/ncrv/7cuvPffJPsO2AD1JCIMsEza9h+EjWM2
+        /NcKXv5fwWMuOOB4TTr/s+k24XcB0BKSkzbJGtAtodgAAJMl+qgyDSjjAAAAAElFTkSuQmCC
+</value>
+  </data>
+  <data name="pauseButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+        YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAAK/wAA
+        Cv8BNGKaggAAAL5JREFUOE9j+P//PwMlmCLNIIsHoQG9m//+79rw63/e1EefQE5E56OHF4YXQJqvPvzz
+        Xzd0FVDtfwZ0PkED2tZ++3/r6e//qn6LwAag8wka0Lji8//LD3//l3ObBTYAnU/QgNrF7/+fuP77v5jd
+        JLAB6HyCBlTMe/V/94Wf//nNusEGoPMJGlAy+/n/9Sd//uc0aAUbgM4naEDB9Mf/F+z5/J9VpxFsADqf
+        oAGg+GfTbYIbgM4naACpGWvg8wIAkX3yJyVePz4AAAAASUVORK5CYII=
+</value>
+  </data>
+  <data name="refreshButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAACH
+        DwAAjA8AAP1SAACBQAAAfXkAAOmLAAA85QAAGcxzPIV3AAAKOWlDQ1BQaG90b3Nob3AgSUNDIHByb2Zp
+        bGUAAEjHnZZ3VFTXFofPvXd6oc0wAlKG3rvAANJ7k15FYZgZYCgDDjM0sSGiAhFFRJoiSFDEgNFQJFZE
+        sRAUVLAHJAgoMRhFVCxvRtaLrqy89/Ly++Osb+2z97n77L3PWhcAkqcvl5cGSwGQyhPwgzyc6RGRUXTs
+        AIABHmCAKQBMVka6X7B7CBDJy82FniFyAl8EAfB6WLwCcNPQM4BOB/+fpFnpfIHomAARm7M5GSwRF4g4
+        JUuQLrbPipgalyxmGCVmvihBEcuJOWGRDT77LLKjmNmpPLaIxTmns1PZYu4V8bZMIUfEiK+ICzO5nCwR
+        3xKxRoowlSviN+LYVA4zAwAUSWwXcFiJIjYRMYkfEuQi4uUA4EgJX3HcVyzgZAvEl3JJS8/hcxMSBXQd
+        li7d1NqaQffkZKVwBALDACYrmcln013SUtOZvBwAFu/8WTLi2tJFRbY0tba0NDQzMv2qUP91829K3NtF
+        ehn4uWcQrf+L7a/80hoAYMyJarPziy2uCoDOLQDI3fti0zgAgKSobx3Xv7oPTTwviQJBuo2xcVZWlhGX
+        wzISF/QP/U+Hv6GvvmckPu6P8tBdOfFMYYqALq4bKy0lTcinZ6QzWRy64Z+H+B8H/nUeBkGceA6fwxNF
+        hImmjMtLELWbx+YKuGk8Opf3n5r4D8P+pMW5FonS+BFQY4yA1HUqQH7tBygKESDR+8Vd/6NvvvgwIH55
+        4SqTi3P/7zf9Z8Gl4iWDm/A5ziUohM4S8jMX98TPEqABAUgCKpAHykAd6ABDYAasgC1wBG7AG/iDEBAJ
+        VgMWSASpgA+yQB7YBApBMdgJ9oBqUAcaQTNoBcdBJzgFzoNL4Bq4AW6D+2AUTIBnYBa8BgsQBGEhMkSB
+        5CEVSBPSh8wgBmQPuUG+UBAUCcVCCRAPEkJ50GaoGCqDqqF6qBn6HjoJnYeuQIPQXWgMmoZ+h97BCEyC
+        qbASrAUbwwzYCfaBQ+BVcAK8Bs6FC+AdcCXcAB+FO+Dz8DX4NjwKP4PnEIAQERqiihgiDMQF8UeikHiE
+        j6xHipAKpAFpRbqRPuQmMorMIG9RGBQFRUcZomxRnqhQFAu1BrUeVYKqRh1GdaB6UTdRY6hZ1Ec0Ga2I
+        1kfboL3QEegEdBa6EF2BbkK3oy+ib6Mn0K8xGAwNo42xwnhiIjFJmLWYEsw+TBvmHGYQM46Zw2Kx8lh9
+        rB3WH8vECrCF2CrsUexZ7BB2AvsGR8Sp4Mxw7rgoHA+Xj6vAHcGdwQ3hJnELeCm8Jt4G749n43PwpfhG
+        fDf+On4Cv0CQJmgT7AghhCTCJkIloZVwkfCA8JJIJKoRrYmBRC5xI7GSeIx4mThGfEuSIemRXEjRJCFp
+        B+kQ6RzpLuklmUzWIjuSo8gC8g5yM/kC+RH5jQRFwkjCS4ItsUGiRqJDYkjiuSReUlPSSXK1ZK5kheQJ
+        yeuSM1J4KS0pFymm1HqpGqmTUiNSc9IUaVNpf+lU6RLpI9JXpKdksDJaMm4ybJkCmYMyF2TGKQhFneJC
+        YVE2UxopFykTVAxVm+pFTaIWU7+jDlBnZWVkl8mGyWbL1sielh2lITQtmhcthVZKO04bpr1borTEaQln
+        yfYlrUuGlszLLZVzlOPIFcm1yd2WeydPl3eTT5bfJd8p/1ABpaCnEKiQpbBf4aLCzFLqUtulrKVFS48v
+        vacIK+opBimuVTyo2K84p6Ss5KGUrlSldEFpRpmm7KicpFyufEZ5WoWiYq/CVSlXOavylC5Ld6Kn0Cvp
+        vfRZVUVVT1Whar3qgOqCmrZaqFq+WpvaQ3WCOkM9Xr1cvUd9VkNFw08jT6NF454mXpOhmai5V7NPc15L
+        Wytca6tWp9aUtpy2l3audov2Ax2yjoPOGp0GnVu6GF2GbrLuPt0berCehV6iXo3edX1Y31Kfq79Pf9AA
+        bWBtwDNoMBgxJBk6GWYathiOGdGMfI3yjTqNnhtrGEcZ7zLuM/5oYmGSYtJoct9UxtTbNN+02/R3Mz0z
+        llmN2S1zsrm7+QbzLvMXy/SXcZbtX3bHgmLhZ7HVosfig6WVJd+y1XLaSsMq1qrWaoRBZQQwShiXrdHW
+        ztYbrE9Zv7WxtBHYHLf5zdbQNtn2iO3Ucu3lnOWNy8ft1OyYdvV2o/Z0+1j7A/ajDqoOTIcGh8eO6o5s
+        xybHSSddpySno07PnU2c+c7tzvMuNi7rXM65Iq4erkWuA24ybqFu1W6P3NXcE9xb3Gc9LDzWepzzRHv6
+        eO7yHPFS8mJ5NXvNelt5r/Pu9SH5BPtU+zz21fPl+3b7wX7efrv9HqzQXMFb0ekP/L38d/s/DNAOWBPw
+        YyAmMCCwJvBJkGlQXlBfMCU4JvhI8OsQ55DSkPuhOqHC0J4wybDosOaw+XDX8LLw0QjjiHUR1yIVIrmR
+        XVHYqLCopqi5lW4r96yciLaILoweXqW9KnvVldUKq1NWn46RjGHGnIhFx4bHHol9z/RnNjDn4rziauNm
+        WS6svaxnbEd2OXuaY8cp40zG28WXxU8l2CXsTphOdEisSJzhunCruS+SPJPqkuaT/ZMPJX9KCU9pS8Wl
+        xqae5Mnwknm9acpp2WmD6frphemja2zW7Fkzy/fhN2VAGasyugRU0c9Uv1BHuEU4lmmfWZP5Jiss60S2
+        dDYvuz9HL2d7zmSue+63a1FrWWt78lTzNuWNrXNaV78eWh+3vmeD+oaCDRMbPTYe3kTYlLzpp3yT/LL8
+        V5vDN3cXKBVsLBjf4rGlpVCikF84stV2a9021DbutoHt5turtn8sYhddLTYprih+X8IqufqN6TeV33za
+        Eb9joNSydP9OzE7ezuFdDrsOl0mX5ZaN7/bb3VFOLy8qf7UnZs+VimUVdXsJe4V7Ryt9K7uqNKp2Vr2v
+        Tqy+XeNc01arWLu9dn4fe9/Qfsf9rXVKdcV17w5wD9yp96jvaNBqqDiIOZh58EljWGPft4xvm5sUmoqb
+        PhziHRo9HHS4t9mqufmI4pHSFrhF2DJ9NProje9cv+tqNWytb6O1FR8Dx4THnn4f+/3wcZ/jPScYJ1p/
+        0Pyhtp3SXtQBdeR0zHYmdo52RXYNnvQ+2dNt293+o9GPh06pnqo5LXu69AzhTMGZT2dzz86dSz83cz7h
+        /HhPTM/9CxEXbvUG9g5c9Ll4+ZL7pQt9Tn1nL9tdPnXF5srJq4yrndcsr3X0W/S3/2TxU/uA5UDHdavr
+        XTesb3QPLh88M+QwdP6m681Lt7xuXbu94vbgcOjwnZHokdE77DtTd1PuvriXeW/h/sYH6AdFD6UeVjxS
+        fNTws+7PbaOWo6fHXMf6Hwc/vj/OGn/2S8Yv7ycKnpCfVEyqTDZPmU2dmnafvvF05dOJZ+nPFmYKf5X+
+        tfa5zvMffnP8rX82YnbiBf/Fp99LXsq/PPRq2aueuYC5R69TXy/MF72Rf3P4LeNt37vwd5MLWe+x7ys/
+        6H7o/ujz8cGn1E+f/gUDmPP8usTo0wAAAAlwSFlzAAALDAAACwwBP0AiyAAAABl0RVh0U29mdHdhcmUA
+        UGFpbnQuTkVUIHYzLjUuNUmK/OAAAAJiSURBVDhPnZNtSFNRHMbdzAgV/DC0bL4R5rSNEjOjiJkhUfpB
+        Aikog74ERV+iIipymgvXbFZrW1NrFoQhQUr2phQxcK0XGWx+2JhGdrfWNmduM1N3r9vTPcNF0vVLFx4O
+        h3Of33nO+f9PUtLSRwcHkunQEJ8OGzOZGXMq8/NjJqsMZuZ9NhMyrqKnX/HIr/Peu5KE55+RmR3JM419
+        QLtRg/rHR1HVVQvprX243C+HjXKE6LD5iMqoBycg4usR9I++RN3zBsgmFFC4NLjiUKHJ0YYTn86h8k4N
+        rBN2lNzcxg1weMaDxHx14gZq+w4hq2kD1sk34pjxVBzU7LgehxQoxdyAC0+b0WA6ie3qPWgf1GLU5cSY
+        l0JOiyieKqFseSE34IDhMKSd+9FneQFmMSamF2Np/sA0bG7nMoigMZ8bUNFZhfNPZMRcyopHMzFer2UA
+        +QoJchXFIDsTc8ZFITdgi3YnRr7Y4Jv8kUJu2eMN5Li/+1O+eSfXeHyB1eycT7l9a52fKW4AuyOWtJcd
+        kyN0bJfb4+fNR6L8uYUo7xer2blommxYyQ0oM1Ris34Him+XBwvaJGFhqwgd5odYoKMCkoiFVHcM30eJ
+        doUybjVIoXTp4iUrVJXCQtnJccAmyCUprNQYah7VY31jEXeCTbqKPwACEanLYflqZztwHF2mnnhXklIe
+        f3CaG8DGRtG1smU1J6aEkZiFMhHuve3lBuS1ivHM+hpCtnH+NiUaiJgVQxoEQsxuzregf9MN9qLwzmHB
+        pd4W1OoOIv1sFtLPZKFaXQftYDemwkyqZ4rmr/ga/2fhN/0cpIchJAs6AAAAAElFTkSuQmCC
+</value>
+  </data>
   <metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>25</value>
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/HeuristicLab.Clients.Hive-3.4.csproj
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/HeuristicLab.Clients.Hive-3.4.csproj	(revision 6458)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/HeuristicLab.Clients.Hive-3.4.csproj	(revision 6463)
@@ -115,4 +115,5 @@
     <Compile Include="Jobs\ItemJob.cs" />
     <Compile Include="RefreshableHiveExperiment.cs" />
+    <Compile Include="ServiceClients\HiveExperimentPermission.cs" />
     <Compile Include="StateLogList.cs" />
     <Compile Include="StateLogListList.cs" />
@@ -156,5 +157,4 @@
     <Compile Include="ServiceClients\NamedHiveItem.cs" />
     <Compile Include="ServiceClients\Heartbeat.cs" />
-    <Compile Include="ServiceClients\HiveExperimentPermission.cs" />
     <Compile Include="ServiceClients\HiveItem.cs" />
     <Compile Include="ServiceClients\JobData.cs" />
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/HiveClient.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/HiveClient.cs	(revision 6458)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/HiveClient.cs	(revision 6463)
@@ -110,4 +110,12 @@
           HiveClient.Instance.UploadExperiment((RefreshableHiveExperiment)item, cancellationToken);
         }
+        if (item is HiveExperimentPermission) {
+          var hep = (HiveExperimentPermission)item;
+          hep.GrantedUserId = ServiceLocator.Instance.CallHiveService((s) => s.GetUserIdByUsername(hep.GrantedUserName));
+          if (hep.GrantedUserId == Guid.Empty) {
+            throw new ArgumentException(string.Format("The user {0} was not found.", hep.GrantedUserName));
+          }
+          ServiceLocator.Instance.CallHiveService((s) => s.GrantPermission(hep.HiveExperimentId, hep.GrantedUserId, hep.Permission));
+        }
       } else {
         if (item is HiveExperiment)
@@ -138,4 +146,8 @@
       if (item is RefreshableHiveExperiment)
         ServiceLocator.Instance.CallHiveService(s => s.DeleteHiveExperiment(item.Id));
+      if (item is HiveExperimentPermission) {
+        var hep = (HiveExperimentPermission)item;
+        ServiceLocator.Instance.CallHiveService(s => s.RevokePermission(hep.HiveExperimentId, hep.GrantedUserId));
+      }
       item.Id = Guid.Empty;
     }
@@ -241,5 +253,10 @@
           .ContinueWith((x) => refreshableHiveExperiment.Log.LogException(x.Exception), TaskContinuationOptions.OnlyOnFaulted));
         }
-        Task.WaitAll(tasks.ToArray());
+        try {
+          Task.WaitAll(tasks.ToArray());
+        }
+        catch (AggregateException ae) {
+          if (!ae.InnerExceptions.All(e => e is TaskCanceledException)) throw ae; // for some reason the WaitAll throws a AggregateException containg a TaskCanceledException. i don't know where it comes from, however the tasks all finish properly, so for now just ignore it
+        }
       }
       finally {
@@ -281,4 +298,5 @@
     private void UploadJobWithChildren(IProgress progress, HiveJob hiveJob, HiveJob parentHiveJob, IEnumerable<Guid> groups, int[] jobCount, int totalJobCount, Guid configPluginId, Guid hiveExperimentId, ILog log, bool isPrivileged, CancellationToken cancellationToken) {
       jobUploadSemaphore.WaitOne();
+      bool semaphoreReleased = false;
       try {
         cancellationToken.ThrowIfCancellationRequested();
@@ -337,8 +355,14 @@
           .ContinueWith((x) => log.LogException(x.Exception), TaskContinuationOptions.OnlyOnFaulted));
         }
-        Task.WaitAll(tasks.ToArray());
+        jobUploadSemaphore.Release(); semaphoreReleased = true; // the semaphore has to be release before waitall!
+        try {
+          Task.WaitAll(tasks.ToArray());
+        }
+        catch (AggregateException ae) {
+          if (!ae.InnerExceptions.All(e => e is TaskCanceledException)) throw ae; // for some reason the WaitAll throws a AggregateException containg a TaskCanceledException. i don't know where it comes from, however the tasks all finish properly, so for now just ignore it
+        }
       }
       finally {
-        jobUploadSemaphore.Release();
+        if(!semaphoreReleased) jobUploadSemaphore.Release();
       }
     }
@@ -441,4 +465,14 @@
       }
     }
+
+    public static HiveItemCollection<HiveExperimentPermission> GetHiveExperimentPermissions(Guid hiveExperimentId) {
+      return ServiceLocator.Instance.CallHiveService((service) => {
+        IEnumerable<HiveExperimentPermission> heps = service.GetHiveExperimentPermissions(hiveExperimentId);
+        foreach (var hep in heps) {
+          hep.GrantedUserName = service.GetUsernameByUserId(hep.GrantedUserId);
+        }
+        return new HiveItemCollection<HiveExperimentPermission>(heps);
+      });
+    }
   }
 }
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/ServiceClients/HiveExperimentPermission.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/ServiceClients/HiveExperimentPermission.cs	(revision 6458)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/ServiceClients/HiveExperimentPermission.cs	(revision 6463)
@@ -20,22 +20,40 @@
 #endregion
 
+using System.ComponentModel;
 using HeuristicLab.Common;
 
 namespace HeuristicLab.Clients.Hive {
-
   public partial class HiveExperimentPermission : IDeepCloneable, IContent {
 
-    public HiveExperimentPermission() { }
-
-    protected HiveExperimentPermission(HiveExperimentPermission original, Cloner cloner) {
-      cloner.RegisterClonedObject(original, this);
+    private string grantedUserName;
+    public string GrantedUserName {
+      get { return grantedUserName; }
+      set { grantedUserName = value; OnPropertyChanged(new PropertyChangedEventArgs("GrantedUserName")); }
     }
 
-    public object Clone() {
-      return Clone(new Cloner());
+    #region Constructors and Cloning
+    public HiveExperimentPermission() {
+      this.Permission = Hive.Permission.ReadOnly;
+      this.PropertyChanged += new PropertyChangedEventHandler(HiveExperimentPermission_PropertyChanged);
     }
 
-    public IDeepCloneable Clone(Cloner cloner) {
+    protected HiveExperimentPermission(HiveExperimentPermission original, Cloner cloner)
+      : base(original, cloner) {
+      this.GrantedByUserId = original.GrantedByUserId;
+      this.GrantedUserId = original.GrantedUserId;
+      this.HiveExperimentId = original.HiveExperimentId;
+      this.Permission = original.Permission;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
       return new HiveExperimentPermission(this, cloner);
+    }
+    #endregion
+
+    private void HiveExperimentPermission_PropertyChanged(object sender, PropertyChangedEventArgs e) {
+      OnToStringChanged();
+    }
+
+    public override string ToString() {
+      return string.Format("{0}: {1}", GrantedUserName, Permission.ToString());
     }
   }
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/ServiceClients/HiveServiceClient.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/ServiceClients/HiveServiceClient.cs	(revision 6458)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/ServiceClients/HiveServiceClient.cs	(revision 6463)
@@ -214,4 +214,5 @@
     [System.Runtime.Serialization.KnownTypeAttribute(typeof(HeuristicLab.Clients.Hive.SlaveGroup))]
     [System.Runtime.Serialization.KnownTypeAttribute(typeof(HeuristicLab.Clients.Hive.Plugin))]
+    [System.Runtime.Serialization.KnownTypeAttribute(typeof(HeuristicLab.Clients.Hive.HiveExperimentPermission))]
     [System.Runtime.Serialization.KnownTypeAttribute(typeof(HeuristicLab.Clients.Hive.PluginData))]
     [System.Runtime.Serialization.KnownTypeAttribute(typeof(HeuristicLab.Clients.Hive.LightweightJob))]
@@ -606,4 +607,7 @@
         
         [System.Runtime.Serialization.OptionalFieldAttribute()]
+        private HeuristicLab.Clients.Hive.Permission PermissionField;
+        
+        [System.Runtime.Serialization.OptionalFieldAttribute()]
         private string ResourceNamesField;
         
@@ -706,4 +710,21 @@
                     this.OwnerUserIdField = value;
                     this.RaisePropertyChanged("OwnerUserId");
+                }
+            }
+        }
+        
+        [System.Runtime.Serialization.DataMemberAttribute()]
+        public HeuristicLab.Clients.Hive.Permission Permission
+        {
+            get
+            {
+                return this.PermissionField;
+            }
+            set
+            {
+                if ((this.PermissionField.Equals(value) != true))
+                {
+                    this.PermissionField = value;
+                    this.RaisePropertyChanged("Permission");
                 }
             }
@@ -1088,4 +1109,93 @@
     [System.Diagnostics.DebuggerStepThroughAttribute()]
     [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
+    [System.Runtime.Serialization.DataContractAttribute(Name="HiveExperimentPermission", Namespace="http://schemas.datacontract.org/2004/07/HeuristicLab.Services.Hive.Common.DataTra" +
+        "nsfer")]
+    [System.SerializableAttribute()]
+    public partial class HiveExperimentPermission : HeuristicLab.Clients.Hive.HiveItem
+    {
+        
+        [System.Runtime.Serialization.OptionalFieldAttribute()]
+        private System.Guid GrantedByUserIdField;
+        
+        [System.Runtime.Serialization.OptionalFieldAttribute()]
+        private System.Guid GrantedUserIdField;
+        
+        [System.Runtime.Serialization.OptionalFieldAttribute()]
+        private System.Guid HiveExperimentIdField;
+        
+        [System.Runtime.Serialization.OptionalFieldAttribute()]
+        private HeuristicLab.Clients.Hive.Permission PermissionField;
+        
+        [System.Runtime.Serialization.DataMemberAttribute()]
+        public System.Guid GrantedByUserId
+        {
+            get
+            {
+                return this.GrantedByUserIdField;
+            }
+            set
+            {
+                if ((this.GrantedByUserIdField.Equals(value) != true))
+                {
+                    this.GrantedByUserIdField = value;
+                    this.RaisePropertyChanged("GrantedByUserId");
+                }
+            }
+        }
+        
+        [System.Runtime.Serialization.DataMemberAttribute()]
+        public System.Guid GrantedUserId
+        {
+            get
+            {
+                return this.GrantedUserIdField;
+            }
+            set
+            {
+                if ((this.GrantedUserIdField.Equals(value) != true))
+                {
+                    this.GrantedUserIdField = value;
+                    this.RaisePropertyChanged("GrantedUserId");
+                }
+            }
+        }
+        
+        [System.Runtime.Serialization.DataMemberAttribute()]
+        public System.Guid HiveExperimentId
+        {
+            get
+            {
+                return this.HiveExperimentIdField;
+            }
+            set
+            {
+                if ((this.HiveExperimentIdField.Equals(value) != true))
+                {
+                    this.HiveExperimentIdField = value;
+                    this.RaisePropertyChanged("HiveExperimentId");
+                }
+            }
+        }
+        
+        [System.Runtime.Serialization.DataMemberAttribute()]
+        public HeuristicLab.Clients.Hive.Permission Permission
+        {
+            get
+            {
+                return this.PermissionField;
+            }
+            set
+            {
+                if ((this.PermissionField.Equals(value) != true))
+                {
+                    this.PermissionField = value;
+                    this.RaisePropertyChanged("Permission");
+                }
+            }
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
     [System.Runtime.Serialization.DataContractAttribute(Name="PluginData", Namespace="http://schemas.datacontract.org/2004/07/HeuristicLab.Services.Hive.Common.DataTra" +
         "nsfer")]
@@ -1330,4 +1440,20 @@
         [System.Runtime.Serialization.EnumMemberAttribute()]
         Failed = 7,
+    }
+    
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
+    [System.Runtime.Serialization.DataContractAttribute(Name="Permission", Namespace="http://schemas.datacontract.org/2004/07/HeuristicLab.Services.Hive.Common.DataTra" +
+        "nsfer")]
+    public enum Permission : int
+    {
+        
+        [System.Runtime.Serialization.EnumMemberAttribute()]
+        NotAllowed = 0,
+        
+        [System.Runtime.Serialization.EnumMemberAttribute()]
+        ReadOnly = 1,
+        
+        [System.Runtime.Serialization.EnumMemberAttribute()]
+        Full = 2,
     }
     
@@ -1783,4 +1909,13 @@
     {
         
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/DeleteSlave", ReplyAction="http://tempuri.org/IHiveService/DeleteSlaveResponse")]
+        void DeleteSlave(System.Guid slaveId);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/DeleteSlaveGroup", ReplyAction="http://tempuri.org/IHiveService/DeleteSlaveGroupResponse")]
+        void DeleteSlaveGroup(System.Guid slaveGroupId);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/AddResourceToGroup", ReplyAction="http://tempuri.org/IHiveService/AddResourceToGroupResponse")]
+        void AddResourceToGroup(System.Guid slaveGroupId, System.Guid resourceId);
+        
         [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/RemoveResourceFromGroup", ReplyAction="http://tempuri.org/IHiveService/RemoveResourceFromGroupResponse")]
         void RemoveResourceFromGroup(System.Guid slaveGroupId, System.Guid resourceId);
@@ -1807,4 +1942,10 @@
         System.Collections.Generic.List<HeuristicLab.Clients.Hive.Downtime> GetDowntimesForResource(System.Guid resourceId);
         
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GetUsernameByUserId", ReplyAction="http://tempuri.org/IHiveService/GetUsernameByUserIdResponse")]
+        string GetUsernameByUserId(System.Guid userId);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GetUserIdByUsername", ReplyAction="http://tempuri.org/IHiveService/GetUserIdByUsernameResponse")]
+        System.Guid GetUserIdByUsername(string username);
+        
         [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/AddJob", ReplyAction="http://tempuri.org/IHiveService/AddJobResponse")]
         System.Guid AddJob(HeuristicLab.Clients.Hive.Job job, HeuristicLab.Clients.Hive.JobData jobData, System.Collections.Generic.List<System.Guid> resourceIds);
@@ -1872,4 +2013,13 @@
         [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/DeleteHiveExperiment", ReplyAction="http://tempuri.org/IHiveService/DeleteHiveExperimentResponse")]
         void DeleteHiveExperiment(System.Guid hiveExperimentId);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GrantPermission", ReplyAction="http://tempuri.org/IHiveService/GrantPermissionResponse")]
+        void GrantPermission(System.Guid hiveExperimentId, System.Guid grantedUserId, HeuristicLab.Clients.Hive.Permission permission);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/RevokePermission", ReplyAction="http://tempuri.org/IHiveService/RevokePermissionResponse")]
+        void RevokePermission(System.Guid hiveExperimentId, System.Guid grantedUserId);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GetHiveExperimentPermissions", ReplyAction="http://tempuri.org/IHiveService/GetHiveExperimentPermissionsResponse")]
+        System.Collections.Generic.List<HeuristicLab.Clients.Hive.HiveExperimentPermission> GetHiveExperimentPermissions(System.Guid hiveExperimentId);
         
         [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/Hello", ReplyAction="http://tempuri.org/IHiveService/HelloResponse")]
@@ -1924,13 +2074,4 @@
         [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/UpdateSlaveGroup", ReplyAction="http://tempuri.org/IHiveService/UpdateSlaveGroupResponse")]
         void UpdateSlaveGroup(HeuristicLab.Clients.Hive.SlaveGroup slaveGroup);
-        
-        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/DeleteSlave", ReplyAction="http://tempuri.org/IHiveService/DeleteSlaveResponse")]
-        void DeleteSlave(System.Guid slaveId);
-        
-        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/DeleteSlaveGroup", ReplyAction="http://tempuri.org/IHiveService/DeleteSlaveGroupResponse")]
-        void DeleteSlaveGroup(System.Guid slaveGroupId);
-        
-        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/AddResourceToGroup", ReplyAction="http://tempuri.org/IHiveService/AddResourceToGroupResponse")]
-        void AddResourceToGroup(System.Guid slaveGroupId, System.Guid resourceId);
     }
     
@@ -1969,4 +2110,19 @@
         }
         
+        public void DeleteSlave(System.Guid slaveId)
+        {
+            base.Channel.DeleteSlave(slaveId);
+        }
+        
+        public void DeleteSlaveGroup(System.Guid slaveGroupId)
+        {
+            base.Channel.DeleteSlaveGroup(slaveGroupId);
+        }
+        
+        public void AddResourceToGroup(System.Guid slaveGroupId, System.Guid resourceId)
+        {
+            base.Channel.AddResourceToGroup(slaveGroupId, resourceId);
+        }
+        
         public void RemoveResourceFromGroup(System.Guid slaveGroupId, System.Guid resourceId)
         {
@@ -2009,4 +2165,14 @@
         }
         
+        public string GetUsernameByUserId(System.Guid userId)
+        {
+            return base.Channel.GetUsernameByUserId(userId);
+        }
+        
+        public System.Guid GetUserIdByUsername(string username)
+        {
+            return base.Channel.GetUserIdByUsername(username);
+        }
+        
         public System.Guid AddJob(HeuristicLab.Clients.Hive.Job job, HeuristicLab.Clients.Hive.JobData jobData, System.Collections.Generic.List<System.Guid> resourceIds)
         {
@@ -2119,4 +2285,19 @@
         }
         
+        public void GrantPermission(System.Guid hiveExperimentId, System.Guid grantedUserId, HeuristicLab.Clients.Hive.Permission permission)
+        {
+            base.Channel.GrantPermission(hiveExperimentId, grantedUserId, permission);
+        }
+        
+        public void RevokePermission(System.Guid hiveExperimentId, System.Guid grantedUserId)
+        {
+            base.Channel.RevokePermission(hiveExperimentId, grantedUserId);
+        }
+        
+        public System.Collections.Generic.List<HeuristicLab.Clients.Hive.HiveExperimentPermission> GetHiveExperimentPermissions(System.Guid hiveExperimentId)
+        {
+            return base.Channel.GetHiveExperimentPermissions(hiveExperimentId);
+        }
+        
         public void Hello(HeuristicLab.Clients.Hive.Slave slave)
         {
@@ -2203,19 +2384,4 @@
             base.Channel.UpdateSlaveGroup(slaveGroup);
         }
-        
-        public void DeleteSlave(System.Guid slaveId)
-        {
-            base.Channel.DeleteSlave(slaveId);
-        }
-        
-        public void DeleteSlaveGroup(System.Guid slaveGroupId)
-        {
-            base.Channel.DeleteSlaveGroup(slaveGroupId);
-        }
-        
-        public void AddResourceToGroup(System.Guid slaveGroupId, System.Guid resourceId)
-        {
-            base.Channel.AddResourceToGroup(slaveGroupId, resourceId);
-        }
     }
 }
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Common/3.4/DataTransfer/HiveExperimentPermission.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Common/3.4/DataTransfer/HiveExperimentPermission.cs	(revision 6458)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Common/3.4/DataTransfer/HiveExperimentPermission.cs	(revision 6463)
@@ -26,5 +26,6 @@
   [DataContract]
   [Serializable]
-  public class HiveExperimentPermission {
+  public class HiveExperimentPermission : HiveItem {
+    // info: this class is derived from HiveItem to simplify handling on the client side, altough it does not have a Id.
     [DataMember]
     public Guid HiveExperimentId { get; set; }
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Common/3.4/DataTransfer/Permission.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Common/3.4/DataTransfer/Permission.cs	(revision 6458)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Common/3.4/DataTransfer/Permission.cs	(revision 6463)
@@ -30,10 +30,5 @@
     /// User can only download and view experiments
     /// </summary>
-    ReadOnly,
-
-    /// <summary>
-    /// User can also  experiments
-    /// </summary>
-    Write,
+    Read,
 
     /// <summary>
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Common/3.4/ServiceContracts/IHiveService.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Common/3.4/ServiceContracts/IHiveService.cs	(revision 6458)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Common/3.4/ServiceContracts/IHiveService.cs	(revision 6463)
@@ -111,6 +111,12 @@
 
     #region HiveExperimentPermission Methods
+    [OperationContract]
     void GrantPermission(Guid hiveExperimentId, Guid grantedUserId, Permission permission);
+
+    [OperationContract]
     void RevokePermission(Guid hiveExperimentId, Guid grantedUserId);
+
+    [OperationContract]
+    IEnumerable<HiveExperimentPermission> GetHiveExperimentPermissions(Guid hiveExperimentId);
     #endregion
 
@@ -205,4 +211,11 @@
     #endregion
 
+    #region User Methods
+    [OperationContract]
+    string GetUsernameByUserId(Guid userId);
+
+    [OperationContract]
+    Guid GetUserIdByUsername(string username);
+    #endregion
   }
 }
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Tests/DaoTests.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Tests/DaoTests.cs	(revision 6458)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Tests/DaoTests.cs	(revision 6463)
@@ -235,5 +235,5 @@
       perm.GrantedByUserId = he.OwnerUserId;
       perm.GrantedUserId = Guid.NewGuid();
-      perm.Permission = Permission.Write;
+      perm.Permission = Permission.Full;
       dao.AddHiveExperimentPermission(perm);
 
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Tests/HeuristicLab.Services.Hive-3.4.Tests.csproj
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Tests/HeuristicLab.Services.Hive-3.4.Tests.csproj	(revision 6458)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Tests/HeuristicLab.Services.Hive-3.4.Tests.csproj	(revision 6463)
@@ -72,4 +72,5 @@
   <ItemGroup>
     <Compile Include="Mocks\MockAuthenticationManager.cs" />
+    <Compile Include="Mocks\MockUserManager.cs" />
     <Compile Include="ServiceTests.cs" />
     <Compile Include="Mocks\MockAuthorizationManager.cs" />
@@ -108,4 +109,5 @@
     <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
     <Reference Include="System" />
+    <Reference Include="System.Configuration" />
     <Reference Include="System.Data" />
     <Reference Include="System.Data.DataSetExtensions" />
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Tests/Mocks/MockAuthorizationManager.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Tests/Mocks/MockAuthorizationManager.cs	(revision 6458)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Tests/Mocks/MockAuthorizationManager.cs	(revision 6463)
@@ -24,24 +24,14 @@
 namespace HeuristicLab.Services.Hive.Tests.Mocks {
   public class MockAuthorizationManager : IAuthorizationManager {
-    public static Guid MockUserId1 = new Guid("6C7911A1-46EA-4E51-97DF-5582653AAFCE");
-    public static Guid MockUserId2 = new Guid("897660EB-C90F-4054-988C-D39D530A0A02");
-    public static Guid MockUserId3 = new Guid("9F7B4EA8-A38D-4BC2-802F-E148AC7A6A87");
-
-    private Guid userId = MockUserId1;
-
-    public Guid UserId {
-      get { return userId; }
+    public void Authorize(Guid userId) {
+      // ok.
     }
 
-    public void AuthorizeJobs(params Guid[] jobId) {
-      // o.k.
+    public void AuthorizeForJob(Guid jobId, Common.DataTransfer.Permission requiredPermission) {
+      // ok.
     }
 
-    public void Authorize(Guid userId) {
-      // o.k.
-    }
-    
-    internal void SetUserId(Guid id) {
-      this.userId = id;
+    public void AuthorizeForExperiment(Guid experimentId, Common.DataTransfer.Permission requiredPermission) {
+      // ok.
     }
   }
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Tests/Mocks/MockServiceLocator.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Tests/Mocks/MockServiceLocator.cs	(revision 6458)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Tests/Mocks/MockServiceLocator.cs	(revision 6463)
@@ -20,7 +20,7 @@
 #endregion
 
+using System;
 using HeuristicLab.Services.Hive.DataAccess;
 using HeuristicLab.Services.Hive.Tests.Mocks;
-using System;
 
 namespace HeuristicLab.Services.Hive.Tests {
@@ -36,7 +36,7 @@
     }
 
-    private MockAuthorizationManager mockAuthorizationManager = new MockAuthorizationManager();
+    //private MockAuthorizationManager mockAuthorizationManager = new MockAuthorizationManager();
     public IAuthorizationManager AuthorizationManager {
-      get { return mockAuthorizationManager; }
+      get { return defaultServiceLocator.AuthorizationManager; }
     }
 
@@ -51,5 +51,8 @@
       get { return defaultServiceLocator.TransactionManager; }
     }
-
+    private MockUserManager mockUserManager = new MockUserManager();
+    public IUserManager UserManager {
+      get { return mockUserManager; }
+    }
     public HeartbeatManager HeartbeatManager {
       get { return defaultServiceLocator.HeartbeatManager; }
@@ -57,8 +60,7 @@
 
     #region Special mocking methods
-    public void SetCurrentUser(Guid id) {
-      mockAuthorizationManager.SetUserId(id);
+    public void SetCurrentUserId(Guid userId) {
+      mockUserManager.SetUserId(userId);
     }
-
     #endregion
   }
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Tests/Mocks/MockUserManager.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Tests/Mocks/MockUserManager.cs	(revision 6463)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Tests/Mocks/MockUserManager.cs	(revision 6463)
@@ -0,0 +1,33 @@
+﻿using System;
+using System.Web.Security;
+
+namespace HeuristicLab.Services.Hive.Tests.Mocks {
+  public class MockUserManager : IUserManager {
+    public static Guid MockUserId1 = new Guid("6C7911A1-46EA-4E51-97DF-5582653AAFCE");
+    public static Guid MockUserId2 = new Guid("897660EB-C90F-4054-988C-D39D530A0A02");
+    public static Guid MockUserId3 = new Guid("9F7B4EA8-A38D-4BC2-802F-E148AC7A6A87");
+
+    private Guid currentUserId = MockUserId1;
+    public Guid CurrentUserId {
+      get { return currentUserId; }
+    }
+
+    public MembershipUser CurrentUser {
+      get { return null; /* todo */ }
+    }
+    
+    public MembershipUser GetUserByName(string username) {
+      return null; // todo
+    }
+
+    public MembershipUser GetUserById(Guid userId) {
+      return null; // todo
+    }
+
+    public void SetUserId(Guid userId) {
+      this.currentUserId = userId;
+    }
+  }
+}
+
+
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Tests/ServiceTests.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Tests/ServiceTests.cs	(revision 6458)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Tests/ServiceTests.cs	(revision 6463)
@@ -303,5 +303,5 @@
     public void TestHiveExperimentPermissions() {
       var service = GetLocalService();
-      mockServiceLocator.SetCurrentUser(MockAuthorizationManager.MockUserId1);
+      mockServiceLocator.SetCurrentUserId(MockUserManager.MockUserId1);
 
       // create hive experiment
@@ -311,13 +311,19 @@
       var e1loaded = service.GetHiveExperiment(e1.Id);
       Assert.AreEqual(Permission.Full, e1loaded.Permission);
-
+      var allExp = service.GetHiveExperiments();
+      Assert.AreEqual(1, allExp.Count(x => x.Id == e1.Id));
+      
       // change to user2
-      mockServiceLocator.SetCurrentUser(MockAuthorizationManager.MockUserId2);
-      e1loaded = service.GetHiveExperiment(e1.Id);
-      Assert.AreEqual(null, e1loaded); // no access
+      mockServiceLocator.SetCurrentUserId(MockUserManager.MockUserId2);
+      try {
+        e1loaded = service.GetHiveExperiment(e1.Id);
+        Assert.Fail("Access should not be possible");
+      } catch { /* ok, cool */ }
+      allExp = service.GetHiveExperiments();
+      Assert.AreEqual(0, allExp.Count(x => x.Id == e1.Id));
 
       // user2 should not be able to grant permissions
       try {
-        service.GrantPermission(e1.Id, MockAuthorizationManager.MockUserId2, Permission.ReadOnly);
+        service.GrantPermission(e1.Id, MockUserManager.MockUserId2, Permission.Read);
         Assert.Fail("Should not be possible to grant permission due to missing permission for User2");
       }
@@ -325,15 +331,17 @@
 
       // switch back to user1 (owner) and grant user2 permissions
-      mockServiceLocator.SetCurrentUser(MockAuthorizationManager.MockUserId1);
-      service.GrantPermission(e1.Id, MockAuthorizationManager.MockUserId2, Permission.ReadOnly);
+      mockServiceLocator.SetCurrentUserId(MockUserManager.MockUserId1);
+      service.GrantPermission(e1.Id, MockUserManager.MockUserId2, Permission.Read);
 
       // back to user2
-      mockServiceLocator.SetCurrentUser(MockAuthorizationManager.MockUserId2);
+      mockServiceLocator.SetCurrentUserId(MockUserManager.MockUserId2);
       e1loaded = service.GetHiveExperiment(e1.Id);
-      Assert.AreEqual(Permission.ReadOnly, e1loaded.Permission);
+      Assert.AreEqual(Permission.Read, e1loaded.Permission);
+      allExp = service.GetHiveExperiments();
+      Assert.AreEqual(1, allExp.Count(x => x.Id == e1.Id));
 
       // user2 should still not be able to grant permissions
       try {
-        service.GrantPermission(e1.Id, MockAuthorizationManager.MockUserId2, Permission.ReadOnly);
+        service.GrantPermission(e1.Id, MockUserManager.MockUserId2, Permission.Read);
         Assert.Fail("Should not be possible to grant permission due to missing permission for User2");
       }
@@ -341,24 +349,33 @@
 
       // back to user1
-      mockServiceLocator.SetCurrentUser(MockAuthorizationManager.MockUserId1);
-      service.GrantPermission(e1.Id, MockAuthorizationManager.MockUserId2, Permission.Full);
+      mockServiceLocator.SetCurrentUserId(MockUserManager.MockUserId1);
+      service.GrantPermission(e1.Id, MockUserManager.MockUserId2, Permission.Full);
 
       // back to user2
-      mockServiceLocator.SetCurrentUser(MockAuthorizationManager.MockUserId2);
+      mockServiceLocator.SetCurrentUserId(MockUserManager.MockUserId2);
       e1loaded = service.GetHiveExperiment(e1.Id);
       Assert.AreEqual(Permission.Full, e1loaded.Permission);
-
+      allExp = service.GetHiveExperiments();
+      Assert.AreEqual(1, allExp.Count(x => x.Id == e1.Id));
+      
       // grant rights to user3, now this should be possible due to full permissions
-      service.GrantPermission(e1.Id, MockAuthorizationManager.MockUserId3, Permission.ReadOnly);
+      service.GrantPermission(e1.Id, MockUserManager.MockUserId3, Permission.Read);
 
       // back to user1 and revoke rights for user2
-      mockServiceLocator.SetCurrentUser(MockAuthorizationManager.MockUserId1);
-      service.RevokePermission(e1.Id, MockAuthorizationManager.MockUserId2);
+      mockServiceLocator.SetCurrentUserId(MockUserManager.MockUserId1);
+      service.RevokePermission(e1.Id, MockUserManager.MockUserId2);
 
       // back to user2
-      mockServiceLocator.SetCurrentUser(MockAuthorizationManager.MockUserId2);
-      e1loaded = service.GetHiveExperiment(e1.Id);
-      Assert.AreEqual(null, e1loaded); // no access
-
+      mockServiceLocator.SetCurrentUserId(MockUserManager.MockUserId2);
+      try {
+        e1loaded = service.GetHiveExperiment(e1.Id);
+        Assert.Fail("Access should not be possible");
+      }
+      catch { /* ok, cool */ }
+      allExp = service.GetHiveExperiments();
+      Assert.AreEqual(0, allExp.Count(x => x.Id == e1.Id));
+
+      // back to user1
+      mockServiceLocator.SetCurrentUserId(MockUserManager.MockUserId1);
       service.DeleteHiveExperiment(e1.Id);
     }
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Web/Hive-3.4/Web.config
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Web/Hive-3.4/Web.config	(revision 6458)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Web/Hive-3.4/Web.config	(revision 6463)
@@ -1,114 +1,112 @@
 <?xml version="1.0"?>
 <configuration>
-	<configSections>
-		<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
-			<section name="HeuristicLab.Services.Hive.DataAccess.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false"/>
-			<section name="HeuristicLab.Services.Hive.Common.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false"/>
-		</sectionGroup>
-	</configSections>
-	<appSettings>
-  <add key="ChartImageHandler" value="storage=file;timeout=20;dir=c:\TempImageFiles\;" />
- </appSettings>
- <applicationSettings>
-		<HeuristicLab.Services.Hive.DataAccess.Settings>
-			<!-- Timeout for long running database command (storing or loading jobData) -->
-			<setting name="LongRunningDatabaseCommandTimeout" serializeAs="String">
-				<value>00:05:33</value>
-			</setting>
-		</HeuristicLab.Services.Hive.DataAccess.Settings>
-		<HeuristicLab.Services.Hive.Common.Settings>
-			<!-- If a slave does not send a heartbeat for this time, it is set offline which means all of its jobs are rescheduled -->
-			<setting name="SlaveHeartbeatTimeout" serializeAs="String">
-				<value>00:01:00</value>
-			</setting>
-			<!-- When a job is in state `Calculating` this is the maximum time it does not have to send heartbeats, otherwise its rescheduled -->
-			<setting name="CalculatingJobHeartbeatTimeout" serializeAs="String">
-				<value>00:05:30</value>
-			</setting>
-			<!-- When a job is in state `Transferring` this is the maximum time it does not have to send heartbeats, otherwise its rescheduled -->
-			<setting name="TransferringJobHeartbeatTimeout" serializeAs="String">
-				<value>00:05:30</value>
-			</setting>
-		</HeuristicLab.Services.Hive.Common.Settings>
-	</applicationSettings>
-	<connectionStrings>
-		<add name="HeuristicLab.Authentication" connectionString="data source=localhost;Integrated Security=SSPI;Initial Catalog=HeuristicLab.Authentication"/>
-	</connectionStrings>
-	<system.web>
-		<httpHandlers>
-   <add path="ChartImg.axd" verb="GET,HEAD,POST" type="System.Web.UI.DataVisualization.Charting.ChartHttpHandler, System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
-    validate="false" />
-  </httpHandlers>
-  <compilation debug="true" targetFramework="4.0">
-			<assemblies>
-				<add assembly="System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/></assemblies></compilation>
-		<membership>
-			<providers>
-				<clear/>
-				<add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="HeuristicLab.Authentication" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="HeuristicLab.Authentication"/>
-			</providers>
-		</membership>
-		<roleManager enabled="true">
-			<providers>
-				<clear/>
-				<add name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="HeuristicLab.Authentication" applicationName="HeuristicLab.Authentication"/>
-			</providers>
-		</roleManager>
-		<pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID">
-   <controls>
-    <add tagPrefix="asp" namespace="System.Web.UI.DataVisualization.Charting"
-     assembly="System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
-   </controls>
-  </pages>
-		<httpRuntime maxRequestLength="1048576"/>
-	</system.web>
-	<system.serviceModel>
-		<diagnostics>
-			<messageLogging logEntireMessage="true" logMalformedMessages="true" logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="true" maxMessagesToLog="3000"/>
-		</diagnostics>
-		<bindings>
-			<wsHttpBinding>
-				<binding name="WSHttpBinding_IHiveService" receiveTimeout="00:10:00" sendTimeout="00:10:00" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647">
-					<readerQuotas maxStringContentLength="2147483647" maxArrayLength="2147483647"/>
-					<security mode="Message">
-						<transport clientCredentialType="Certificate"/>
-						<message clientCredentialType="UserName"/>
-					</security>
-				</binding>
-			</wsHttpBinding>
-		</bindings>
-		<behaviors>
-			<serviceBehaviors>
-				<behavior name="ServiceBehaviour_IHiveService">
-					<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
-					<serviceMetadata httpGetEnabled="true" httpsGetEnabled="false"/>
-					<!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
-					<serviceDebug httpHelpPageEnabled="true" includeExceptionDetailInFaults="true"/>
-					<serviceAuthorization principalPermissionMode="UseAspNetRoles" roleProviderName="AspNetSqlRoleProvider"/>
-					<serviceCredentials>
-						<serviceCertificate findValue="localhost" x509FindType="FindBySubjectName"/>
-						<userNameAuthentication userNamePasswordValidationMode="MembershipProvider" membershipProviderName="AspNetSqlMembershipProvider"/>
-					</serviceCredentials>
-					<serviceSecurityAudit auditLogLocation="Application" suppressAuditFailure="false" messageAuthenticationAuditLevel="SuccessOrFailure"/>
-					<serviceThrottling maxConcurrentCalls="100"/>
-					<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
-				</behavior>
-			</serviceBehaviors>
-		</behaviors>
-		<services>
-			<service behaviorConfiguration="ServiceBehaviour_IHiveService" name="HeuristicLab.Services.Hive.HiveService">
-				<endpoint address="mex" binding="mexHttpBinding" bindingConfiguration="" name="MexEndpoint" contract="IMetadataExchange"/>
-				<endpoint binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IHiveService" name="WSHttpBinding_IHiveService" contract="HeuristicLab.Services.Hive.Common.ServiceContracts.IHiveService"/>
-			</service>
-		</services>
-		<serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
-	</system.serviceModel>
-	<system.webServer>
-  <directoryBrowse enabled="true" />
-  <handlers>
-   <remove name="ChartImageHandler" />
-   <add name="ChartImageHandler" preCondition="integratedMode" verb="GET,HEAD,POST"
-    path="ChartImg.axd" type="System.Web.UI.DataVisualization.Charting.ChartHttpHandler, System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
-  </handlers>
- </system.webServer>
+  <configSections>
+    <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+      <section name="HeuristicLab.Services.Hive.DataAccess.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false"/>
+      <section name="HeuristicLab.Services.Hive.Common.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false"/>
+    </sectionGroup>
+  </configSections>
+  <appSettings>
+    <add key="ChartImageHandler" value="storage=file;timeout=20;dir=c:\TempImageFiles\;" />
+  </appSettings>
+  <applicationSettings>
+    <HeuristicLab.Services.Hive.DataAccess.Settings>
+      <!-- Timeout for long running database command (storing or loading jobData) -->
+      <setting name="LongRunningDatabaseCommandTimeout" serializeAs="String">
+        <value>00:05:33</value>
+      </setting>
+    </HeuristicLab.Services.Hive.DataAccess.Settings>
+    <HeuristicLab.Services.Hive.Common.Settings>
+      <!-- If a slave does not send a heartbeat for this time, it is set offline which means all of its jobs are rescheduled -->
+      <setting name="SlaveHeartbeatTimeout" serializeAs="String">
+        <value>00:01:00</value>
+      </setting>
+      <!-- When a job is in state `Calculating` this is the maximum time it does not have to send heartbeats, otherwise its rescheduled -->
+      <setting name="CalculatingJobHeartbeatTimeout" serializeAs="String">
+        <value>00:05:30</value>
+      </setting>
+      <!-- When a job is in state `Transferring` this is the maximum time it does not have to send heartbeats, otherwise its rescheduled -->
+      <setting name="TransferringJobHeartbeatTimeout" serializeAs="String">
+        <value>00:05:30</value>
+      </setting>
+    </HeuristicLab.Services.Hive.Common.Settings>
+  </applicationSettings>
+  <connectionStrings>
+    <add name="HeuristicLab.Authentication" connectionString="data source=localhost;Integrated Security=SSPI;Initial Catalog=HeuristicLab.Authentication"/>
+  </connectionStrings>
+  <system.web>
+    <compilation debug="true" targetFramework="4.0">
+      <assemblies>
+        <add assembly="System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
+      </assemblies>
+    </compilation>
+    <membership>
+      <providers>
+        <clear/>
+        <add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="HeuristicLab.Authentication" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="HeuristicLab.Authentication"/>
+      </providers>
+    </membership>
+    <roleManager enabled="true">
+      <providers>
+        <clear/>
+        <add name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="HeuristicLab.Authentication" applicationName="HeuristicLab.Authentication"/>
+      </providers>
+    </roleManager>
+    <pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID">
+      <controls>
+        <add tagPrefix="asp" namespace="System.Web.UI.DataVisualization.Charting"
+         assembly="System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
+      </controls>
+    </pages>
+    <httpRuntime maxRequestLength="1048576"/>
+  </system.web>
+  <system.serviceModel>
+    <diagnostics>
+      <messageLogging logEntireMessage="true" logMalformedMessages="true" logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="true" maxMessagesToLog="3000"/>
+    </diagnostics>
+    <bindings>
+      <wsHttpBinding>
+        <binding name="WSHttpBinding_IHiveService" receiveTimeout="00:10:00" sendTimeout="00:10:00" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647">
+          <readerQuotas maxStringContentLength="2147483647" maxArrayLength="2147483647"/>
+          <security mode="Message">
+            <transport clientCredentialType="Certificate"/>
+            <message clientCredentialType="UserName"/>
+          </security>
+        </binding>
+      </wsHttpBinding>
+    </bindings>
+    <behaviors>
+      <serviceBehaviors>
+        <behavior name="ServiceBehaviour_IHiveService">
+          <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
+          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="false"/>
+          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
+          <serviceDebug httpHelpPageEnabled="true" includeExceptionDetailInFaults="true"/>
+          <serviceAuthorization principalPermissionMode="UseAspNetRoles" roleProviderName="AspNetSqlRoleProvider"/>
+          <serviceCredentials>
+            <serviceCertificate findValue="localhost" x509FindType="FindBySubjectName"/>
+            <userNameAuthentication userNamePasswordValidationMode="MembershipProvider" membershipProviderName="AspNetSqlMembershipProvider"/>
+          </serviceCredentials>
+          <serviceSecurityAudit auditLogLocation="Application" suppressAuditFailure="false" messageAuthenticationAuditLevel="SuccessOrFailure"/>
+          <serviceThrottling maxConcurrentCalls="100"/>
+          <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
+        </behavior>
+      </serviceBehaviors>
+    </behaviors>
+    <services>
+      <service behaviorConfiguration="ServiceBehaviour_IHiveService" name="HeuristicLab.Services.Hive.HiveService">
+        <endpoint address="mex" binding="mexHttpBinding" bindingConfiguration="" name="MexEndpoint" contract="IMetadataExchange"/>
+        <endpoint binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IHiveService" name="WSHttpBinding_IHiveService" contract="HeuristicLab.Services.Hive.Common.ServiceContracts.IHiveService"/>
+      </service>
+    </services>
+    <serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
+  </system.serviceModel>
+  <system.webServer>
+    <directoryBrowse enabled="true" />
+    <handlers>
+      <remove name="ChartImageHandler" />
+      <add name="ChartImageHandler" preCondition="integratedMode" verb="GET,HEAD,POST"
+       path="ChartImg.axd" type="System.Web.UI.DataVisualization.Charting.ChartHttpHandler, System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
+    </handlers>
+  </system.webServer>  
 </configuration>
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/AuthenticationManager.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/AuthenticationManager.cs	(revision 6458)
+++ 	(revision )
@@ -1,46 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System.Linq;
-using System.Security.Authentication;
-using System.Web.Security;
-
-namespace HeuristicLab.Services.Hive {
-  public class AuthenticationManager : HeuristicLab.Services.Hive.IAuthenticationManager {
-    public bool IsInRole(string role) {
-      return Roles.IsUserInRole(role);
-    }
-    public bool IsInAnyRole(params string[] roles) {
-      return roles.Any(x => Roles.IsUserInRole(x));
-    }
-    public bool IsInAllRoles(params string[] roles) {
-      return roles.All(x => Roles.IsUserInRole(x));
-    }
-    public void AuthenticateForAnyRole(params string[] roles) {
-      if (!IsInAnyRole(roles))
-        throw new AuthenticationException("Could not authenticate user for any role required.");
-    }
-    public void AuthenticateForAllRoles(params string[] roles) {
-      if (!IsInAllRoles(roles))
-        throw new AuthenticationException("Could not authenticate user for all roles required.");
-    }
-  }
-}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/AuthorizationManager.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/AuthorizationManager.cs	(revision 6458)
+++ 	(revision )
@@ -1,41 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System;
-using System.Security;
-using System.Web.Security;
-
-namespace HeuristicLab.Services.Hive {
-  public class AuthorizationManager : IAuthorizationManager {
-    private MembershipUser Identity {
-      get { return Membership.GetUser(); }
-    }
-
-    public Guid UserId {
-      get { return (Guid)Identity.ProviderUserKey; }
-    }
-
-    public void Authorize(Guid userId) {
-      if (userId != this.UserId)
-        throw new SecurityException("User '" + Identity.UserName + "' is not authorized to access object");
-    }
-  }
-}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/HeartbeatManager.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/HeartbeatManager.cs	(revision 6458)
+++ 	(revision )
@@ -1,148 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using HeuristicLab.Services.Hive.Common;
-using HeuristicLab.Services.Hive.Common.DataTransfer;
-
-namespace HeuristicLab.Services.Hive {
-  public class HeartbeatManager {
-    private DataAccess.IHiveDao dao {
-      get { return ServiceLocator.Instance.HiveDao; }
-    }
-    private IAuthorizationManager auth {
-      get { return ServiceLocator.Instance.AuthorizationManager; }
-    }
-
-    /// <summary>
-    /// This method will be called every time a slave sends a heartbeat (-> very often; concurrency is important!)
-    /// </summary>
-    /// <returns>a list of actions the slave should do</returns>
-    public List<MessageContainer> ProcessHeartbeat(Heartbeat heartbeat) {
-      List<MessageContainer> actions = new List<MessageContainer>();
-      Slave slave = dao.GetSlave(heartbeat.SlaveId);
-      if (slave == null) {
-        actions.Add(new MessageContainer(MessageContainer.MessageType.SayHello));
-      } else {
-        // update slave data
-        slave.FreeCores = heartbeat.FreeCores;
-        slave.FreeMemory = heartbeat.FreeMemory;
-        slave.CpuUtilization = heartbeat.CpuUtilization;
-        slave.IsAllowedToCalculate = SlaveIsAllowedToCalculate(slave.Id);
-        slave.SlaveState = (heartbeat.JobProgress != null && heartbeat.JobProgress.Count > 0) ? SlaveState.Calculating : SlaveState.Idle;
-        slave.LastHeartbeat = DateTime.Now;
-        dao.UpdateSlave(slave);
-
-        // update job data
-        actions.AddRange(UpdateJobs(heartbeat, slave.IsAllowedToCalculate));
-
-        // assign new job
-        if (heartbeat.AssignJob && slave.IsAllowedToCalculate && heartbeat.FreeCores > 0) {
-          var availableJobs = dao.GetWaitingJobs(slave, 1);
-          if (availableJobs.Count() > 0) {
-            var job = availableJobs.First();
-            if (AssignJob(slave, job))
-              actions.Add(new MessageContainer(MessageContainer.MessageType.CalculateJob, job.Id));
-          }
-        }
-      }
-      return actions;
-    }
-
-    // returns true if assignment was successful
-    private bool AssignJob(Slave slave, Job job) {
-      // load job again and check if it is still available (this is an attempt to reduce the race condition which causes multiple heartbeats to get the same job assigned)
-      if (dao.GetJob(job.Id).State != JobState.Waiting) return false;
-
-      job = dao.UpdateJobState(job.Id, JobState.Transferring, slave.Id, null, null);
-
-      // from now on the job has some time to send the next heartbeat (ApplicationConstants.TransferringJobHeartbeatTimeout)
-      job.LastHeartbeat = DateTime.Now;
-      dao.UpdateJob(job);
-      return true;
-    }
-
-    /// <summary>
-    /// Update the progress of each job
-    /// Checks if all the jobs sent by heartbeat are supposed to be calculated by this slave
-    /// </summary>
-    private IEnumerable<MessageContainer> UpdateJobs(Heartbeat heartbeat, bool IsAllowedToCalculate) {
-      List<MessageContainer> actions = new List<MessageContainer>();
-
-      if (heartbeat.JobProgress == null)
-        return actions;
-
-      if (!IsAllowedToCalculate) {
-        actions.Add(new MessageContainer(MessageContainer.MessageType.PauseAll));
-      } else {
-        // process the jobProgresses
-        foreach (var jobProgress in heartbeat.JobProgress) {
-          Job curJob = dao.GetJob(jobProgress.Key);
-          if (curJob == null) {
-            // job does not exist in db
-            actions.Add(new MessageContainer(MessageContainer.MessageType.AbortJob, jobProgress.Key));
-            LogFactory.GetLogger(this.GetType().Namespace).Log("Job does not exist in DB: " + jobProgress.Key);
-          } else {
-            if (curJob.CurrentStateLog.SlaveId == Guid.Empty || curJob.CurrentStateLog.SlaveId != heartbeat.SlaveId) {
-              // assigned slave does not match heartbeat
-              actions.Add(new MessageContainer(MessageContainer.MessageType.AbortJob, curJob.Id));
-              LogFactory.GetLogger(this.GetType().Namespace).Log("The slave " + heartbeat.SlaveId + " is not supposed to calculate Job: " + curJob);
-            } else if (!JobIsAllowedToBeCalculatedBySlave(heartbeat.SlaveId, curJob)) {
-              // assigned resources ids of job do not match with slaveId (and parent resourceGroupIds); this might happen when slave is moved to different group
-              actions.Add(new MessageContainer(MessageContainer.MessageType.PauseJob, curJob.Id));
-            } else {
-              // save job execution time
-              curJob.ExecutionTime = jobProgress.Value;
-              curJob.LastHeartbeat = DateTime.Now;
-
-              switch (curJob.Command) {
-                case Command.Stop:
-                  actions.Add(new MessageContainer(MessageContainer.MessageType.StopJob, curJob.Id));
-                  break;
-                case Command.Pause:
-                  actions.Add(new MessageContainer(MessageContainer.MessageType.PauseJob, curJob.Id));
-                  break;
-                case Command.Abort:
-                  actions.Add(new MessageContainer(MessageContainer.MessageType.AbortJob, curJob.Id));
-                  break;
-              }
-              dao.UpdateJob(curJob);
-            }
-          }
-        }
-      }
-      return actions;
-    }
-
-    private bool JobIsAllowedToBeCalculatedBySlave(Guid slaveId, Job curJob) {
-      var assignedResourceIds = dao.GetAssignedResources(curJob.Id).Select(x => x.Id);
-      var slaveResourceIds = dao.GetParentResources(slaveId).Select(x => x.Id);
-      return assignedResourceIds.Any(x => slaveResourceIds.Contains(x));
-    }
-
-    private bool SlaveIsAllowedToCalculate(Guid slaveId) {
-      // the slave may only calculate if there is no downtime right now. this needs to be checked for every parent resource also
-      return dao.GetParentResources(slaveId).All(r => dao.GetDowntimes(x => x.ResourceId == r.Id && (DateTime.Now >= x.StartDate) && (DateTime.Now <= x.EndDate)).Count() == 0);
-    }
-  }
-}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/HeuristicLab.Services.Hive-3.4.csproj
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/HeuristicLab.Services.Hive-3.4.csproj	(revision 6458)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/HeuristicLab.Services.Hive-3.4.csproj	(revision 6463)
@@ -103,14 +103,16 @@
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="Interfaces\IUserManager.cs" />
+    <Compile Include="Manager\UserManager.cs" />
     <None Include="HeuristicLabServicesHivePlugin.cs.frame" />
     <None Include="Properties\AssemblyInfo.cs.frame" />
-    <Compile Include="AuthenticationManager.cs" />
-    <Compile Include="HeartbeatManager.cs" />
+    <Compile Include="Manager\AuthenticationManager.cs" />
+    <Compile Include="Manager\HeartbeatManager.cs" />
     <Compile Include="Interfaces\IAuthenticationManager.cs" />
     <Compile Include="Interfaces\ILifecycleManager.cs" />
     <Compile Include="Interfaces\IServiceLocator.cs" />
-    <Compile Include="AuthorizationManager.cs" />
+    <Compile Include="Manager\AuthorizationManager.cs" />
     <Compile Include="HeuristicLabServicesHivePlugin.cs" />
-    <Compile Include="LifecycleManager.cs" />
+    <Compile Include="Manager\LifecycleManager.cs" />
     <Compile Include="HiveRoles.cs" />
     <Compile Include="HiveService.cs" />
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/HiveService.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/HiveService.cs	(revision 6458)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/HiveService.cs	(revision 6463)
@@ -51,4 +51,7 @@
       get { return ServiceLocator.Instance.LifecycleManager; }
     }
+    private IUserManager userManager {
+      get { return ServiceLocator.Instance.UserManager; }
+    }
     private HeartbeatManager heartbeatManager {
       get { return ServiceLocator.Instance.HeartbeatManager; }
@@ -66,5 +69,5 @@
         }
         dao.AddJobData(jobData);
-        dao.UpdateJobState(job.Id, JobState.Waiting, null, author.UserId, null);
+        dao.UpdateJobState(job.Id, JobState.Waiting, null, userManager.CurrentUserId, null);
         return jobData.JobId;
       }, false, true);
@@ -81,4 +84,5 @@
     public Job GetJob(Guid jobId) {
       authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
+      author.AuthorizeForJob(jobId, Permission.Read);
       return dao.GetJob(jobId);
     }
@@ -86,19 +90,29 @@
     public IEnumerable<Job> GetJobs() {
       authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      return dao.GetJobs(x => true);
+      var jobs = dao.GetJobs(x => true);
+      foreach (var job in jobs)
+        author.AuthorizeForJob(job.Id, Permission.Read);
+      return jobs;
     }
 
     public IEnumerable<LightweightJob> GetLightweightJobs(IEnumerable<Guid> jobIds) {
       authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      return dao.GetJobs(x => jobIds.Contains(x.JobId)).Select(x => new LightweightJob(x)).ToArray();
+      var jobs = dao.GetJobs(x => jobIds.Contains(x.JobId)).Select(x => new LightweightJob(x)).ToArray();
+      foreach (var job in jobs)
+        author.AuthorizeForJob(job.Id, Permission.Read);
+      return jobs;
     }
 
     public IEnumerable<LightweightJob> GetLightweightChildJobs(Guid? parentJobId, bool recursive, bool includeParent) {
       authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      return GetChildJobs(parentJobId, recursive, includeParent).Select(x => new LightweightJob(x)).ToArray();
+      var jobs = GetChildJobs(parentJobId, recursive, includeParent).Select(x => new LightweightJob(x)).ToArray();
+      foreach (var job in jobs)
+        author.AuthorizeForJob(job.Id, Permission.Read);
+      return jobs;
     }
 
     public IEnumerable<LightweightJob> GetLightweightExperimentJobs(Guid experimentId) {
       authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      author.AuthorizeForExperiment(experimentId, Permission.Read);
       return dao.GetJobs(x => x.HiveExperimentId == experimentId).Select(x => new LightweightJob(x)).ToArray();
     }
@@ -106,4 +120,5 @@
     public JobData GetJobData(Guid jobId) {
       authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
+      author.AuthorizeForJob(jobId, Permission.Read);
       return dao.GetJobData(jobId);
     }
@@ -111,4 +126,5 @@
     public void UpdateJob(Job job) {
       authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
+      author.AuthorizeForJob(job.Id, Permission.Full);
       trans.UseTransaction(() => {
         dao.UpdateJob(job);
@@ -118,4 +134,6 @@
     public void UpdateJobData(Job job, JobData jobData) {
       authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
+      author.AuthorizeForJob(job.Id, Permission.Full);
+      author.AuthorizeForJob(jobData.JobId, Permission.Full);
       //trans.UseTransaction(() => { // cneumuel: try without transaction
       jobData.LastUpdate = DateTime.Now;
@@ -127,4 +145,5 @@
     public void DeleteJob(Guid jobId) {
       authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
+      author.AuthorizeForJob(jobId, Permission.Full);
       trans.UseTransaction(() => {
         dao.DeleteJob(jobId);
@@ -134,4 +153,5 @@
     public void DeleteChildJobs(Guid parentJobId) {
       authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
+      author.AuthorizeForJob(parentJobId, Permission.Full);
       trans.UseTransaction(() => {
         var jobs = GetChildJobs(parentJobId, true, false);
@@ -145,4 +165,5 @@
     public Job UpdateJobState(Guid jobId, JobState jobState, Guid? slaveId, Guid? userId, string exception) {
       authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
+      author.AuthorizeForJob(jobId, Permission.Full);
       return trans.UseTransaction(() => {
         Job job = dao.UpdateJobState(jobId, jobState, slaveId, userId, exception);
@@ -166,5 +187,8 @@
     public IEnumerable<Job> GetJobsByResourceId(Guid resourceId) {
       authen.AuthenticateForAnyRole(HiveRoles.Administrator);
-      return trans.UseTransaction(() => dao.GetJobsByResourceId(resourceId));
+      var jobs = trans.UseTransaction(() => dao.GetJobsByResourceId(resourceId));
+      foreach(var job in jobs)
+        author.AuthorizeForJob(job.Id, Permission.Read);
+      return jobs;
     }
     #endregion
@@ -173,4 +197,5 @@
     public void StopJob(Guid jobId) {
       authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
+      author.AuthorizeForJob(jobId, Permission.Full);
       trans.UseTransaction(() => {
         var job = dao.GetJob(jobId);
@@ -188,4 +213,5 @@
     public void PauseJob(Guid jobId) {
       authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
+      author.AuthorizeForJob(jobId, Permission.Full);
       trans.UseTransaction(() => {
         var job = dao.GetJob(jobId);
@@ -201,6 +227,7 @@
     public void RestartJob(Guid jobId) {
       authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
-      trans.UseTransaction(() => {
-        Job job = dao.UpdateJobState(jobId, JobState.Waiting, null, author.UserId, string.Empty);
+      author.AuthorizeForJob(jobId, Permission.Full);
+      trans.UseTransaction(() => {
+        Job job = dao.UpdateJobState(jobId, JobState.Waiting, null, userManager.CurrentUserId, string.Empty);
         job.Command = null;
         dao.UpdateJob(job);
@@ -212,9 +239,10 @@
     public HiveExperiment GetHiveExperiment(Guid id) {
       authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      author.AuthorizeForExperiment(id, Permission.Read);
       var hiveExperiment = dao.GetHiveExperiments(x =>
             x.HiveExperimentId == id
-            && (x.OwnerUserId == author.UserId || x.HiveExperimentPermissions.Count(hep => hep.Permission != Permission.NotAllowed && hep.GrantedUserId == author.UserId) > 0)
+            && (x.OwnerUserId == userManager.CurrentUserId || x.HiveExperimentPermissions.Count(hep => hep.Permission != Permission.NotAllowed && hep.GrantedUserId == userManager.CurrentUserId) > 0)
           ).FirstOrDefault();
-      if (hiveExperiment != null) hiveExperiment.Permission = dao.GetPermissionForExperiment(hiveExperiment.Id, author.UserId);
+      if (hiveExperiment != null) hiveExperiment.Permission = dao.GetPermissionForExperiment(hiveExperiment.Id, userManager.CurrentUserId);
       return hiveExperiment;
     }
@@ -222,7 +250,9 @@
     public IEnumerable<HiveExperiment> GetHiveExperiments() {
       authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      var hiveExperiments = dao.GetHiveExperiments(x => x.OwnerUserId == author.UserId || x.HiveExperimentPermissions.Count(hep => hep.Permission != Permission.NotAllowed && hep.GrantedUserId == author.UserId) > 0);
-      foreach (var he in hiveExperiments)
-        he.Permission = dao.GetPermissionForExperiment(he.Id, author.UserId);
+      var hiveExperiments = dao.GetHiveExperiments(x => x.OwnerUserId == userManager.CurrentUserId || x.HiveExperimentPermissions.Count(hep => hep.Permission != Permission.NotAllowed && hep.GrantedUserId == userManager.CurrentUserId) > 0);
+      foreach (var he in hiveExperiments) {
+        author.AuthorizeForExperiment(he.Id, Permission.Read);
+        he.Permission = dao.GetPermissionForExperiment(he.Id, userManager.CurrentUserId);
+      }
       return hiveExperiments;
     }
@@ -231,6 +261,6 @@
       authen.AuthenticateForAnyRole(HiveRoles.Administrator);
       var hiveExperiments = dao.GetHiveExperiments(x => true);
-      foreach (var he in hiveExperiments)
-        he.Permission = dao.GetPermissionForExperiment(he.Id, author.UserId);
+      foreach (var he in hiveExperiments) // no authorization here, since this method is admin-only! (admin is allowed to read all jobs)
+        he.Permission = dao.GetPermissionForExperiment(he.Id, userManager.CurrentUserId);
       return hiveExperiments;
     }
@@ -239,5 +269,5 @@
       authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
       return trans.UseTransaction(() => {
-        hiveExperimentDto.OwnerUserId = author.UserId;
+        hiveExperimentDto.OwnerUserId = userManager.CurrentUserId;
         hiveExperimentDto.DateCreated = DateTime.Now;
         return dao.AddHiveExperiment(hiveExperimentDto);
@@ -247,4 +277,5 @@
     public void UpdateHiveExperiment(HiveExperiment hiveExperimentDto) {
       authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      author.AuthorizeForExperiment(hiveExperimentDto.Id, Permission.Full);
       trans.UseTransaction(() => {
         dao.UpdateHiveExperiment(hiveExperimentDto);
@@ -254,4 +285,5 @@
     public void DeleteHiveExperiment(Guid hiveExperimentId) {
       authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      author.AuthorizeForExperiment(hiveExperimentId, Permission.Full);
       trans.UseTransaction(() => {
         HiveExperiment he = dao.GetHiveExperiment(hiveExperimentId);
@@ -267,7 +299,7 @@
         HiveExperiment he = dao.GetHiveExperiment(hiveExperimentId);
         if (he == null) throw new FaultException<FaultReason>(new FaultReason("Could not find hiveExperiment with id " + hiveExperimentId));
-        Permission perm = dao.GetPermissionForExperiment(he.Id, author.UserId);
+        Permission perm = dao.GetPermissionForExperiment(he.Id, userManager.CurrentUserId);
         if (perm != Permission.Full) throw new FaultException<FaultReason>(new FaultReason("Not allowed to grant permissions for this experiment"));
-        dao.SetHiveExperimentPermission(hiveExperimentId, author.UserId, grantedUserId, permission);
+        dao.SetHiveExperimentPermission(hiveExperimentId, userManager.CurrentUserId, grantedUserId, permission);
       });
     }
@@ -278,7 +310,15 @@
         HiveExperiment he = dao.GetHiveExperiment(hiveExperimentId);
         if (he == null) throw new FaultException<FaultReason>(new FaultReason("Could not find hiveExperiment with id " + hiveExperimentId));
-        Permission perm = dao.GetPermissionForExperiment(he.Id, author.UserId);
+        Permission perm = dao.GetPermissionForExperiment(he.Id, userManager.CurrentUserId);
         if (perm != Permission.Full) throw new FaultException<FaultReason>(new FaultReason("Not allowed to grant permissions for this experiment"));
-        dao.SetHiveExperimentPermission(hiveExperimentId, author.UserId, grantedUserId, Permission.NotAllowed);
+        dao.SetHiveExperimentPermission(hiveExperimentId, userManager.CurrentUserId, grantedUserId, Permission.NotAllowed);
+      });
+    }
+    public IEnumerable<HiveExperimentPermission> GetHiveExperimentPermissions(Guid hiveExperimentId) {
+      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      return trans.UseTransaction(() => {
+        Permission currentUserPermission = dao.GetPermissionForExperiment(hiveExperimentId, userManager.CurrentUserId);
+        if (currentUserPermission != Permission.Full) throw new FaultException<FaultReason>(new FaultReason("Not allowed to list permissions for this experiment"));
+        return dao.GetHiveExperimentPermissions(x => x.HiveExperimentId == hiveExperimentId);
       });
     }
@@ -341,5 +381,5 @@
       authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
       return trans.UseTransaction(() => {
-        plugin.UserId = author.UserId;
+        plugin.UserId = userManager.CurrentUserId;
         plugin.DateCreated = DateTime.Now;
 
@@ -369,4 +409,6 @@
     }
 
+    // note: this is a possible security problem, since a client is able to download all plugins, which may contain proprietary code (which can be disassembled)
+    //       change so that only with GetPluginByHash it is possible to download plugins
     public IEnumerable<Plugin> GetPlugins() {
       authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
@@ -376,6 +418,5 @@
     public IEnumerable<PluginData> GetPluginDatas(List<Guid> pluginIds) {
       authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
-      List<PluginData> pluginDatas = new List<PluginData>();
-
+      var pluginDatas = new List<PluginData>();
       return trans.UseTransaction(() => {
         foreach (Guid guid in pluginIds) {
@@ -394,35 +435,35 @@
     #region Slave Methods
     public Guid AddSlave(Slave slave) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      authen.AuthenticateForAnyRole(HiveRoles.Administrator);
       return trans.UseTransaction(() => dao.AddSlave(slave));
     }
 
     public Guid AddSlaveGroup(SlaveGroup slaveGroup) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      authen.AuthenticateForAnyRole(HiveRoles.Administrator);
       return trans.UseTransaction(() => dao.AddSlaveGroup(slaveGroup));
     }
 
     public Slave GetSlave(Guid slaveId) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      authen.AuthenticateForAnyRole(HiveRoles.Administrator);
       return dao.GetSlave(slaveId);
     }
 
     public SlaveGroup GetSlaveGroup(Guid slaveGroupId) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      authen.AuthenticateForAnyRole(HiveRoles.Administrator);
       return dao.GetSlaveGroup(slaveGroupId);
     }
 
     public IEnumerable<Slave> GetSlaves() {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      authen.AuthenticateForAnyRole(HiveRoles.Administrator);
       return dao.GetSlaves(x => true);
     }
 
     public IEnumerable<SlaveGroup> GetSlaveGroups() {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      authen.AuthenticateForAnyRole(HiveRoles.Administrator);
       return dao.GetSlaveGroups(x => true);
     }
 
     public void UpdateSlave(Slave slave) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      authen.AuthenticateForAnyRole(HiveRoles.Administrator);
       trans.UseTransaction(() => {
         dao.UpdateSlave(slave);
@@ -431,5 +472,5 @@
 
     public void UpdateSlaveGroup(SlaveGroup slaveGroup) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      authen.AuthenticateForAnyRole(HiveRoles.Administrator);
       trans.UseTransaction(() => {
         dao.UpdateSlaveGroup(slaveGroup);
@@ -438,5 +479,5 @@
 
     public void DeleteSlave(Guid slaveId) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      authen.AuthenticateForAnyRole(HiveRoles.Administrator);
       trans.UseTransaction(() => {
         dao.DeleteSlave(slaveId);
@@ -445,5 +486,5 @@
 
     public void DeleteSlaveGroup(Guid slaveGroupId) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      authen.AuthenticateForAnyRole(HiveRoles.Administrator);
       trans.UseTransaction(() => {
         dao.DeleteSlaveGroup(slaveGroupId);
@@ -452,5 +493,5 @@
 
     public void AddResourceToGroup(Guid slaveGroupId, Guid resourceId) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      authen.AuthenticateForAnyRole(HiveRoles.Administrator);
       trans.UseTransaction(() => {
         var resource = dao.GetResource(resourceId);
@@ -461,5 +502,5 @@
 
     public void RemoveResourceFromGroup(Guid slaveGroupId, Guid resourceId) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      authen.AuthenticateForAnyRole(HiveRoles.Administrator);
       trans.UseTransaction(() => {
         var resource = dao.GetResource(resourceId);
@@ -470,5 +511,5 @@
 
     public Guid GetResourceId(string resourceName) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      authen.AuthenticateForAnyRole(HiveRoles.Administrator);
       return trans.UseTransaction(() => {
         var resource = dao.GetResources(x => x.Name == resourceName).FirstOrDefault();
@@ -482,4 +523,5 @@
 
     public void TriggerLifecycle(bool force) {
+      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Slave);
       // use a serializable transaction here to ensure not two threads execute this simultaniously (mutex-lock would not work since IIS may use multiple AppDomains)
       trans.UseTransaction(() => {
@@ -519,4 +561,21 @@
     #endregion
 
+    #region User Methods
+    public string GetUsernameByUserId(Guid userId) {
+      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      var user = ServiceLocator.Instance.UserManager.GetUserById(userId);
+      if (user != null)
+        return user.UserName;
+      else
+        return null;
+    }
+
+    public Guid GetUserIdByUsername(string username) {
+      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      var user = ServiceLocator.Instance.UserManager.GetUserByName(username);
+      return user != null ? (Guid)user.ProviderUserKey : Guid.Empty;
+    }
+    #endregion
+
     #region Helper Methods
     private IEnumerable<Job> GetChildJobs(Guid? parentJobId, bool recursive, bool includeParent) {
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/Interfaces/IAuthorizationManager.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/Interfaces/IAuthorizationManager.cs	(revision 6458)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/Interfaces/IAuthorizationManager.cs	(revision 6463)
@@ -21,15 +21,15 @@
 
 using System;
+using HeuristicLab.Services.Hive.Common.DataTransfer;
 namespace HeuristicLab.Services.Hive {
   public interface IAuthorizationManager {
-    /// <summary>
-    /// Returns the UserId of the currently authenticated user
-    /// </summary>
-    Guid UserId { get; }
-
     /// <summary>
     /// Compares the current UserId with the given userId and takes appropriate actions if the mismatch
     /// </summary>
     void Authorize(Guid userId);
+
+    void AuthorizeForJob(Guid jobId, Permission requiredPermission);
+
+    void AuthorizeForExperiment(Guid experimentId, Permission requiredPermission);
   }
 }
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/Interfaces/IServiceLocator.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/Interfaces/IServiceLocator.cs	(revision 6458)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/Interfaces/IServiceLocator.cs	(revision 6463)
@@ -29,4 +29,5 @@
     ILifecycleManager LifecycleManager { get; }
     ITransactionManager TransactionManager { get; }
+    IUserManager UserManager { get; }
     HeartbeatManager HeartbeatManager { get; }
   }
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/Interfaces/IUserManager.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/Interfaces/IUserManager.cs	(revision 6463)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/Interfaces/IUserManager.cs	(revision 6463)
@@ -0,0 +1,32 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Web.Security;
+
+namespace HeuristicLab.Services.Hive {
+  public interface IUserManager {
+    MembershipUser CurrentUser { get; }
+    Guid CurrentUserId { get; }
+    MembershipUser GetUserByName(string username);
+    MembershipUser GetUserById(Guid userId);
+  }
+}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/LifecycleManager.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/LifecycleManager.cs	(revision 6458)
+++ 	(revision )
@@ -1,118 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using HeuristicLab.Services.Hive.Common;
-using HeuristicLab.Services.Hive.Common.DataTransfer;
-
-namespace HeuristicLab.Services.Hive {
-  /// <summary>
-  /// This class offers methods for cleaning up offline slaves and jobs
-  /// </summary>
-  public class LifecycleManager : ILifecycleManager {
-    private DataAccess.IHiveDao dao {
-      get { return ServiceLocator.Instance.HiveDao; }
-    }
-    private IAuthorizationManager auth {
-      get { return ServiceLocator.Instance.AuthorizationManager; }
-    }
-    private ILogger log {
-      get { return LogFactory.GetLogger(this.GetType().Namespace); }
-    }
-
-    public void Cleanup() {
-      log.Log("LifecycleManager.Cleanup()");
-      SetTimeoutSlavesOffline();
-      SetTimeoutJobsWaiting();
-      FinishParentJobs();
-      UpdateStatistics();
-    }
-
-    private void UpdateStatistics() {
-      var slaves = dao.GetSlaves(x => x.SlaveState == SlaveState.Calculating || x.SlaveState == SlaveState.Idle);
-
-      var stats = new Statistics();
-      stats.TimeStamp = DateTime.Now;
-      var slaveStats = new List<SlaveStatistics>();
-      foreach (var slave in slaves) {
-        slaveStats.Add(new SlaveStatistics() {
-          SlaveId = slave.Id,
-          Cores = slave.Cores.HasValue ? slave.Cores.Value : 0,
-          FreeCores = slave.FreeCores.HasValue ? slave.FreeCores.Value : 0,
-          Memory = slave.Memory.HasValue ? slave.Memory.Value : 0,
-          FreeMemory = slave.FreeMemory.HasValue ? slave.FreeMemory.Value : 0,
-          CpuUtilization = slave.CpuUtilization
-        });
-      }
-      stats.SlaveStatistics = slaveStats;
-      stats.UserStatistics = dao.GetUserStatistics();
-      dao.AddStatistics(stats);
-    }
-
-    /// <summary>
-    /// Searches for slaves which are timed out, puts them and their jobs offline
-    /// </summary>
-    private void SetTimeoutSlavesOffline() {
-      var slaves = dao.GetSlaves(x => x.SlaveState != SlaveState.Offline);
-      foreach (Slave slave in slaves) {
-        if (!slave.LastHeartbeat.HasValue || (DateTime.Now - slave.LastHeartbeat.Value) > Settings.Default.SlaveHeartbeatTimeout) {
-          slave.SlaveState = SlaveState.Offline;
-          SetJobsWaiting(slave.Id);
-          dao.UpdateSlave(slave);
-        }
-      }
-    }
-
-    /// <summary>
-    /// Looks for parent jobs which have FinishWhenChildJobsFinished and set their state to finished
-    /// </summary>
-    private void FinishParentJobs() {
-      var parentJobsToFinish = dao.GetParentJobs(dao.GetResources(x => true).Select(x => x.Id), 0, true);
-      foreach (var job in parentJobsToFinish) {
-        dao.UpdateJobState(job.Id, JobState.Finished, null, null, string.Empty);
-      }
-    }
-
-    private void SetJobsWaiting(Guid slaveId) {
-      var jobs = dao.GetJobs(x => x.State == JobState.Calculating).Where(x => x.StateLog.Last().SlaveId == slaveId);
-      foreach (var j in jobs) {
-        Job job = dao.UpdateJobState(j.Id, JobState.Waiting, slaveId, null, "Slave timed out.");
-        job.Command = null;
-        dao.UpdateJob(job);
-      }
-    }
-
-    /// <summary>
-    /// Looks for jobs which have not sent heartbeats for some time and reschedules them for calculation
-    /// </summary>
-    private void SetTimeoutJobsWaiting() {
-      var jobs = dao.GetJobs(x => (x.State == JobState.Calculating && (DateTime.Now - x.LastHeartbeat) > Settings.Default.CalculatingJobHeartbeatTimeout)
-                               || (x.State == JobState.Transferring && (DateTime.Now - x.LastHeartbeat) > Settings.Default.TransferringJobHeartbeatTimeout));
-      foreach (var j in jobs) {
-        Job job = dao.UpdateJobState(j.Id, JobState.Waiting, null, null, "Slave timed out.");
-        job.Command = null;
-        dao.UpdateJob(job);
-      }
-    }
-  }
-}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/Manager/AuthenticationManager.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/Manager/AuthenticationManager.cs	(revision 6463)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/Manager/AuthenticationManager.cs	(revision 6463)
@@ -0,0 +1,46 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Linq;
+using System.Security.Authentication;
+using System.Web.Security;
+
+namespace HeuristicLab.Services.Hive {
+  public class AuthenticationManager : HeuristicLab.Services.Hive.IAuthenticationManager {
+    public bool IsInRole(string role) {
+      return Roles.IsUserInRole(role);
+    }
+    public bool IsInAnyRole(params string[] roles) {
+      return roles.Any(x => Roles.IsUserInRole(x));
+    }
+    public bool IsInAllRoles(params string[] roles) {
+      return roles.All(x => Roles.IsUserInRole(x));
+    }
+    public void AuthenticateForAnyRole(params string[] roles) {
+      if (!IsInAnyRole(roles))
+        throw new AuthenticationException("Could not authenticate user for any role required.");
+    }
+    public void AuthenticateForAllRoles(params string[] roles) {
+      if (!IsInAllRoles(roles))
+        throw new AuthenticationException("Could not authenticate user for all roles required.");
+    }
+  }
+}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/Manager/AuthorizationManager.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/Manager/AuthorizationManager.cs	(revision 6463)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/Manager/AuthorizationManager.cs	(revision 6463)
@@ -0,0 +1,47 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Security;
+using HeuristicLab.Services.Hive.Common.DataTransfer;
+
+namespace HeuristicLab.Services.Hive {
+  public class AuthorizationManager : IAuthorizationManager {
+    public void Authorize(Guid userId) {
+      if (userId != ServiceLocator.Instance.UserManager.CurrentUserId)
+        throw new SecurityException("Current user is not authorized to access object");
+    }
+
+    public void AuthorizeForJob(Guid jobId, Permission requiredPermission) {
+      if (ServiceLocator.Instance.AuthenticationManager.IsInRole(HiveRoles.Slave)) return; // slave-users can access all jobs
+
+      Permission permission = ServiceLocator.Instance.HiveDao.GetPermissionForJob(jobId, ServiceLocator.Instance.UserManager.CurrentUserId);
+      if (permission == Permission.NotAllowed || (permission != requiredPermission && requiredPermission == Permission.Full))
+        throw new SecurityException("Current user is not authorized to access job");
+    }
+
+    public void AuthorizeForExperiment(Guid experimentId, Permission requiredPermission) {
+      Permission permission = ServiceLocator.Instance.HiveDao.GetPermissionForExperiment(experimentId, ServiceLocator.Instance.UserManager.CurrentUserId);
+      if (permission == Permission.NotAllowed || (permission != requiredPermission && requiredPermission == Permission.Full)) 
+        throw new SecurityException("Current user is not authorized to access experiment");
+    }
+  }
+}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/Manager/HeartbeatManager.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/Manager/HeartbeatManager.cs	(revision 6463)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/Manager/HeartbeatManager.cs	(revision 6463)
@@ -0,0 +1,148 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Services.Hive.Common;
+using HeuristicLab.Services.Hive.Common.DataTransfer;
+
+namespace HeuristicLab.Services.Hive {
+  public class HeartbeatManager {
+    private DataAccess.IHiveDao dao {
+      get { return ServiceLocator.Instance.HiveDao; }
+    }
+    private IAuthorizationManager auth {
+      get { return ServiceLocator.Instance.AuthorizationManager; }
+    }
+
+    /// <summary>
+    /// This method will be called every time a slave sends a heartbeat (-> very often; concurrency is important!)
+    /// </summary>
+    /// <returns>a list of actions the slave should do</returns>
+    public List<MessageContainer> ProcessHeartbeat(Heartbeat heartbeat) {
+      List<MessageContainer> actions = new List<MessageContainer>();
+      Slave slave = dao.GetSlave(heartbeat.SlaveId);
+      if (slave == null) {
+        actions.Add(new MessageContainer(MessageContainer.MessageType.SayHello));
+      } else {
+        // update slave data
+        slave.FreeCores = heartbeat.FreeCores;
+        slave.FreeMemory = heartbeat.FreeMemory;
+        slave.CpuUtilization = heartbeat.CpuUtilization;
+        slave.IsAllowedToCalculate = SlaveIsAllowedToCalculate(slave.Id);
+        slave.SlaveState = (heartbeat.JobProgress != null && heartbeat.JobProgress.Count > 0) ? SlaveState.Calculating : SlaveState.Idle;
+        slave.LastHeartbeat = DateTime.Now;
+        dao.UpdateSlave(slave);
+
+        // update job data
+        actions.AddRange(UpdateJobs(heartbeat, slave.IsAllowedToCalculate));
+
+        // assign new job
+        if (heartbeat.AssignJob && slave.IsAllowedToCalculate && heartbeat.FreeCores > 0) {
+          var availableJobs = dao.GetWaitingJobs(slave, 1);
+          if (availableJobs.Count() > 0) {
+            var job = availableJobs.First();
+            if (AssignJob(slave, job))
+              actions.Add(new MessageContainer(MessageContainer.MessageType.CalculateJob, job.Id));
+          }
+        }
+      }
+      return actions;
+    }
+
+    // returns true if assignment was successful
+    private bool AssignJob(Slave slave, Job job) {
+      // load job again and check if it is still available (this is an attempt to reduce the race condition which causes multiple heartbeats to get the same job assigned)
+      if (dao.GetJob(job.Id).State != JobState.Waiting) return false;
+
+      job = dao.UpdateJobState(job.Id, JobState.Transferring, slave.Id, null, null);
+
+      // from now on the job has some time to send the next heartbeat (ApplicationConstants.TransferringJobHeartbeatTimeout)
+      job.LastHeartbeat = DateTime.Now;
+      dao.UpdateJob(job);
+      return true;
+    }
+
+    /// <summary>
+    /// Update the progress of each job
+    /// Checks if all the jobs sent by heartbeat are supposed to be calculated by this slave
+    /// </summary>
+    private IEnumerable<MessageContainer> UpdateJobs(Heartbeat heartbeat, bool IsAllowedToCalculate) {
+      List<MessageContainer> actions = new List<MessageContainer>();
+
+      if (heartbeat.JobProgress == null)
+        return actions;
+
+      if (!IsAllowedToCalculate) {
+        actions.Add(new MessageContainer(MessageContainer.MessageType.PauseAll));
+      } else {
+        // process the jobProgresses
+        foreach (var jobProgress in heartbeat.JobProgress) {
+          Job curJob = dao.GetJob(jobProgress.Key);
+          if (curJob == null) {
+            // job does not exist in db
+            actions.Add(new MessageContainer(MessageContainer.MessageType.AbortJob, jobProgress.Key));
+            LogFactory.GetLogger(this.GetType().Namespace).Log("Job does not exist in DB: " + jobProgress.Key);
+          } else {
+            if (curJob.CurrentStateLog.SlaveId == Guid.Empty || curJob.CurrentStateLog.SlaveId != heartbeat.SlaveId) {
+              // assigned slave does not match heartbeat
+              actions.Add(new MessageContainer(MessageContainer.MessageType.AbortJob, curJob.Id));
+              LogFactory.GetLogger(this.GetType().Namespace).Log("The slave " + heartbeat.SlaveId + " is not supposed to calculate Job: " + curJob);
+            } else if (!JobIsAllowedToBeCalculatedBySlave(heartbeat.SlaveId, curJob)) {
+              // assigned resources ids of job do not match with slaveId (and parent resourceGroupIds); this might happen when slave is moved to different group
+              actions.Add(new MessageContainer(MessageContainer.MessageType.PauseJob, curJob.Id));
+            } else {
+              // save job execution time
+              curJob.ExecutionTime = jobProgress.Value;
+              curJob.LastHeartbeat = DateTime.Now;
+
+              switch (curJob.Command) {
+                case Command.Stop:
+                  actions.Add(new MessageContainer(MessageContainer.MessageType.StopJob, curJob.Id));
+                  break;
+                case Command.Pause:
+                  actions.Add(new MessageContainer(MessageContainer.MessageType.PauseJob, curJob.Id));
+                  break;
+                case Command.Abort:
+                  actions.Add(new MessageContainer(MessageContainer.MessageType.AbortJob, curJob.Id));
+                  break;
+              }
+              dao.UpdateJob(curJob);
+            }
+          }
+        }
+      }
+      return actions;
+    }
+
+    private bool JobIsAllowedToBeCalculatedBySlave(Guid slaveId, Job curJob) {
+      var assignedResourceIds = dao.GetAssignedResources(curJob.Id).Select(x => x.Id);
+      var slaveResourceIds = dao.GetParentResources(slaveId).Select(x => x.Id);
+      return assignedResourceIds.Any(x => slaveResourceIds.Contains(x));
+    }
+
+    private bool SlaveIsAllowedToCalculate(Guid slaveId) {
+      // the slave may only calculate if there is no downtime right now. this needs to be checked for every parent resource also
+      return dao.GetParentResources(slaveId).All(r => dao.GetDowntimes(x => x.ResourceId == r.Id && (DateTime.Now >= x.StartDate) && (DateTime.Now <= x.EndDate)).Count() == 0);
+    }
+  }
+}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/Manager/LifecycleManager.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/Manager/LifecycleManager.cs	(revision 6463)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/Manager/LifecycleManager.cs	(revision 6463)
@@ -0,0 +1,118 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Services.Hive.Common;
+using HeuristicLab.Services.Hive.Common.DataTransfer;
+
+namespace HeuristicLab.Services.Hive {
+  /// <summary>
+  /// This class offers methods for cleaning up offline slaves and jobs
+  /// </summary>
+  public class LifecycleManager : ILifecycleManager {
+    private DataAccess.IHiveDao dao {
+      get { return ServiceLocator.Instance.HiveDao; }
+    }
+    private IAuthorizationManager auth {
+      get { return ServiceLocator.Instance.AuthorizationManager; }
+    }
+    private ILogger log {
+      get { return LogFactory.GetLogger(this.GetType().Namespace); }
+    }
+
+    public void Cleanup() {
+      log.Log("LifecycleManager.Cleanup()");
+      SetTimeoutSlavesOffline();
+      SetTimeoutJobsWaiting();
+      FinishParentJobs();
+      UpdateStatistics();
+    }
+
+    private void UpdateStatistics() {
+      var slaves = dao.GetSlaves(x => x.SlaveState == SlaveState.Calculating || x.SlaveState == SlaveState.Idle);
+
+      var stats = new Statistics();
+      stats.TimeStamp = DateTime.Now;
+      var slaveStats = new List<SlaveStatistics>();
+      foreach (var slave in slaves) {
+        slaveStats.Add(new SlaveStatistics() {
+          SlaveId = slave.Id,
+          Cores = slave.Cores.HasValue ? slave.Cores.Value : 0,
+          FreeCores = slave.FreeCores.HasValue ? slave.FreeCores.Value : 0,
+          Memory = slave.Memory.HasValue ? slave.Memory.Value : 0,
+          FreeMemory = slave.FreeMemory.HasValue ? slave.FreeMemory.Value : 0,
+          CpuUtilization = slave.CpuUtilization
+        });
+      }
+      stats.SlaveStatistics = slaveStats;
+      stats.UserStatistics = dao.GetUserStatistics();
+      dao.AddStatistics(stats);
+    }
+
+    /// <summary>
+    /// Searches for slaves which are timed out, puts them and their jobs offline
+    /// </summary>
+    private void SetTimeoutSlavesOffline() {
+      var slaves = dao.GetSlaves(x => x.SlaveState != SlaveState.Offline);
+      foreach (Slave slave in slaves) {
+        if (!slave.LastHeartbeat.HasValue || (DateTime.Now - slave.LastHeartbeat.Value) > Settings.Default.SlaveHeartbeatTimeout) {
+          slave.SlaveState = SlaveState.Offline;
+          SetJobsWaiting(slave.Id);
+          dao.UpdateSlave(slave);
+        }
+      }
+    }
+
+    /// <summary>
+    /// Looks for parent jobs which have FinishWhenChildJobsFinished and set their state to finished
+    /// </summary>
+    private void FinishParentJobs() {
+      var parentJobsToFinish = dao.GetParentJobs(dao.GetResources(x => true).Select(x => x.Id), 0, true);
+      foreach (var job in parentJobsToFinish) {
+        dao.UpdateJobState(job.Id, JobState.Finished, null, null, string.Empty);
+      }
+    }
+
+    private void SetJobsWaiting(Guid slaveId) {
+      var jobs = dao.GetJobs(x => x.State == JobState.Calculating).Where(x => x.StateLog.Last().SlaveId == slaveId);
+      foreach (var j in jobs) {
+        Job job = dao.UpdateJobState(j.Id, JobState.Waiting, slaveId, null, "Slave timed out.");
+        job.Command = null;
+        dao.UpdateJob(job);
+      }
+    }
+
+    /// <summary>
+    /// Looks for jobs which have not sent heartbeats for some time and reschedules them for calculation
+    /// </summary>
+    private void SetTimeoutJobsWaiting() {
+      var jobs = dao.GetJobs(x => (x.State == JobState.Calculating && (DateTime.Now - x.LastHeartbeat) > Settings.Default.CalculatingJobHeartbeatTimeout)
+                               || (x.State == JobState.Transferring && (DateTime.Now - x.LastHeartbeat) > Settings.Default.TransferringJobHeartbeatTimeout));
+      foreach (var j in jobs) {
+        Job job = dao.UpdateJobState(j.Id, JobState.Waiting, null, null, "Slave timed out.");
+        job.Command = null;
+        dao.UpdateJob(job);
+      }
+    }
+  }
+}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/Manager/UserManager.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/Manager/UserManager.cs	(revision 6463)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/Manager/UserManager.cs	(revision 6463)
@@ -0,0 +1,22 @@
+﻿using System;
+using System.Web.Security;
+
+namespace HeuristicLab.Services.Hive {
+  public class UserManager : IUserManager {
+    public MembershipUser CurrentUser {
+      get { return Membership.GetUser(); }
+    }
+
+    public Guid CurrentUserId {
+      get { return (Guid)CurrentUser.ProviderUserKey; }
+    }
+
+    public MembershipUser GetUserByName(string username) {
+      return Membership.GetUser(username);
+    }
+
+    public MembershipUser GetUserById(Guid userId) {
+      return Membership.GetUser(userId);
+    }
+  }
+}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/ServiceLocator.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/ServiceLocator.cs	(revision 6458)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/ServiceLocator.cs	(revision 6463)
@@ -74,4 +74,12 @@
     }
 
+    private IUserManager userManager;
+    public IUserManager UserManager {
+      get {
+        if (userManager == null) userManager = new UserManager();
+        return userManager;
+      }
+    }
+
     private HeartbeatManager heartbeatManager;
     public HeartbeatManager HeartbeatManager {
