Index: branches/HiveProjectManagement/HeuristicLab.Clients.Access/3.3/HeuristicLab.Clients.Access-3.3.csproj
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Clients.Access/3.3/HeuristicLab.Clients.Access-3.3.csproj	(revision 15399)
+++ branches/HiveProjectManagement/HeuristicLab.Clients.Access/3.3/HeuristicLab.Clients.Access-3.3.csproj	(revision 15401)
@@ -106,4 +106,5 @@
     <Compile Include="ClientInformation.cs" />
     <Compile Include="ClientInformationUtils.cs" />
+    <Compile Include="HiveRoles.cs" />
     <Compile Include="Plugin.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
Index: branches/HiveProjectManagement/HeuristicLab.Clients.Access/3.3/HiveRoles.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Clients.Access/3.3/HiveRoles.cs	(revision 15401)
+++ branches/HiveProjectManagement/HeuristicLab.Clients.Access/3.3/HiveRoles.cs	(revision 15401)
@@ -0,0 +1,38 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+
+namespace HeuristicLab.Clients.Access {
+  public static class HiveRoles {
+    public const string Administrator = "Hive Administrator";
+    public const string User = "Hive User";
+    public const string Slave = "Hive Slave";
+
+    public static bool CheckAdminUserPermissions() {
+      return UserInformation.Instance.UserExists && UserInformation.Instance.User.Roles.Any(x => x.Name == Administrator);
+    }
+
+    public static bool CheckHiveUserPermissions() {
+      return UserInformation.Instance.UserExists && UserInformation.Instance.User.Roles.Any(x => x.Name == User);
+    }
+  }
+}
Index: branches/HiveProjectManagement/HeuristicLab.Clients.Common/3.3/HeuristicLab.Clients.Common-3.3.csproj
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Clients.Common/3.3/HeuristicLab.Clients.Common-3.3.csproj	(revision 15399)
+++ branches/HiveProjectManagement/HeuristicLab.Clients.Common/3.3/HeuristicLab.Clients.Common-3.3.csproj	(revision 15401)
@@ -139,4 +139,5 @@
       <DependentUpon>Settings.settings</DependentUpon>
     </Compile>
+    <Compile Include="SecurityExceptionUtil.cs" />
     <None Include="app.config" />
     <None Include="Properties\AssemblyInfo.cs.frame" />
Index: branches/HiveProjectManagement/HeuristicLab.Clients.Common/3.3/SecurityExceptionUtil.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Clients.Common/3.3/SecurityExceptionUtil.cs	(revision 15401)
+++ branches/HiveProjectManagement/HeuristicLab.Clients.Common/3.3/SecurityExceptionUtil.cs	(revision 15401)
@@ -0,0 +1,32 @@
+﻿using System;
+using System.ServiceModel.Security;
+using System.Threading.Tasks;
+using HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.Clients.Hive {
+  public class SecurityExceptionUtil {
+    public static void TryAndReportSecurityExceptions(Action action, Action finallyCallback = null) {
+      try {
+        action();
+      } catch (MessageSecurityException ex) {
+        ErrorHandling.ShowErrorDialog("There is something wrong with the applied security. Are your credentials correct?", ex);
+      } catch (SecurityAccessDeniedException ex) {
+        ErrorHandling.ShowErrorDialog("The security authorization request failed. Are you a Hive administrator?", ex);
+      } finally {
+        finallyCallback?.Invoke();
+      }
+    }
+
+    public static async Task TryAsyncAndReportSecurityExceptions(Action action, Action finallyCallback = null) {
+      try {
+        await Task.Run(action);
+      } catch (MessageSecurityException ex) {
+        ErrorHandling.ShowErrorDialog("There is something wrong with the applied security. Are your credentials correct?", ex);
+      } catch (SecurityAccessDeniedException ex) {
+        ErrorHandling.ShowErrorDialog("The security authorization request failed. Are you a Hive administrator?", ex);
+      } finally {
+        finallyCallback?.Invoke();
+      }
+    }
+  }
+}
Index: branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/HeuristicLab.Clients.Hive.Administrator-3.3.csproj
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/HeuristicLab.Clients.Hive.Administrator-3.3.csproj	(revision 15399)
+++ branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/HeuristicLab.Clients.Hive.Administrator-3.3.csproj	(revision 15401)
@@ -110,5 +110,4 @@
   </ItemGroup>
   <ItemGroup>
-    <Compile Include="HiveRoles.cs" />
     <Compile Include="Views\DowntimeTypeDialog.cs">
       <SubType>Form</SubType>
@@ -133,4 +132,16 @@
     </Compile>
     <Compile Include="MenuItems\AdministratorMenuItem.cs" />
+    <Compile Include="Views\ProjectsView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="Views\ProjectsView.Designer.cs">
+      <DependentUpon>ProjectsView.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Views\ProjectView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="Views\ProjectView.Designer.cs">
+      <DependentUpon>ProjectView.cs</DependentUpon>
+    </Compile>
     <Compile Include="Views\Recurrence.cs">
       <SubType>Form</SubType>
Index: branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/HiveRoles.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/HiveRoles.cs	(revision 15399)
+++ 	(revision )
@@ -1,35 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2016 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 HeuristicLab.Clients.Access;
-
-namespace HeuristicLab.Clients.Hive.Administrator {
-  public static class HiveRoles {
-    public const string Administrator = "Hive Administrator";
-    public const string User = "Hive User";
-    public const string Slave = "Hive Slave";
-
-    public static bool CheckAdminUserPermissions() {
-      return UserInformation.Instance.UserExists && UserInformation.Instance.User.Roles.Any(x => x.Name == HiveRoles.Administrator);
-    }
-  }
-}
Index: branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/MenuItems/AdministratorMenuItem.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/MenuItems/AdministratorMenuItem.cs	(revision 15399)
+++ branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/MenuItems/AdministratorMenuItem.cs	(revision 15401)
@@ -20,21 +20,43 @@
 #endregion
 
+using System;
 using System.Collections.Generic;
-using HeuristicLab.Clients.Hive;
+using System.Windows.Forms;
+using HeuristicLab.Clients.Access;
 using HeuristicLab.MainForm;
+using HeuristicLab.Optimizer;
 
-namespace HeuristicLab.Optimizer.MenuItems {
-  public class AdministratorMenuItem : HeuristicLab.MainForm.WindowsForms.MenuItem, IOptimizerUserInterfaceItemProvider {
+namespace HeuristicLab.Clients.Hive.Administrator {
+  public class AdministratorMenuItem : MainForm.WindowsForms.MenuItem, IOptimizerUserInterfaceItemProvider {
     public override string Name {
       get { return "&Administrator"; }
     }
+
     public override IEnumerable<string> Structure {
       get { return new string[] { "&Services", "&Hive" }; }
     }
+
     public override void Execute() {
-      MainFormManager.MainForm.ShowContent(HiveAdminClient.Instance);
+      if (HiveRoles.CheckAdminUserPermissions()) {
+        MainFormManager.MainForm.ShowContent(HiveAdminClient.Instance);
+      } else if (!UserInformation.Instance.UserExists) {
+        MessageBox.Show(
+          "Couldn't fetch user information from the server." + Environment.NewLine +
+          "Please verify that you have an existing user and that your user name and password is correct.",
+          "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Error);
+      } else {
+        MessageBox.Show(
+          "You do not seem to have the permissions to use the Hive Administrator." + Environment.NewLine +
+          "If that's not the case or you have any questions please write an email to support@heuristiclab.com",
+          "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Error);
+      }
     }
+
     public override int Position {
-      get { return 10000; }
+      get { return 8000; }
+    }
+
+    public override Keys ShortCutKeys {
+      get { return Keys.Control | Keys.Shift | Keys.H; }
     }
   }
Index: branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/HiveAdministratorView.Designer.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/HiveAdministratorView.Designer.cs	(revision 15399)
+++ branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/HiveAdministratorView.Designer.cs	(revision 15401)
@@ -30,16 +30,20 @@
       this.tabAdmin = new System.Windows.Forms.TabControl();
       this.tabSlaves = new System.Windows.Forms.TabPage();
+      this.resourcesView = new HeuristicLab.Clients.Hive.Administrator.Views.ResourcesView();
+      this.tabPage1 = new System.Windows.Forms.TabPage();
       this.imageListUsers = new System.Windows.Forms.ImageList(this.components);
-      this.resourcesView = new HeuristicLab.Clients.Hive.Administrator.Views.ResourcesView();
+      this.projectsView = new HeuristicLab.Clients.Hive.Administrator.Views.ProjectsView();
       this.tabAdmin.SuspendLayout();
       this.tabSlaves.SuspendLayout();
+      this.tabPage1.SuspendLayout();
       this.SuspendLayout();
       // 
       // tabAdmin
       // 
-      this.tabAdmin.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.tabAdmin.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.tabAdmin.Controls.Add(this.tabSlaves);
+      this.tabAdmin.Controls.Add(this.tabPage1);
       this.tabAdmin.Location = new System.Drawing.Point(3, 0);
       this.tabAdmin.Name = "tabAdmin";
@@ -59,15 +63,9 @@
       this.tabSlaves.UseVisualStyleBackColor = true;
       // 
-      // imageListUsers
-      // 
-      this.imageListUsers.ColorDepth = System.Windows.Forms.ColorDepth.Depth32Bit;
-      this.imageListUsers.ImageSize = new System.Drawing.Size(16, 16);
-      this.imageListUsers.TransparentColor = System.Drawing.Color.Transparent;
-      // 
       // resourcesView
       // 
-      this.resourcesView.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.resourcesView.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.resourcesView.Caption = "ResourcesView";
       this.resourcesView.Content = null;
@@ -78,13 +76,42 @@
       this.resourcesView.TabIndex = 0;
       // 
-      // HiveAdministrationView
+      // tabPage1
       // 
-      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      this.tabPage1.Controls.Add(this.projectsView);
+      this.tabPage1.Location = new System.Drawing.Point(4, 22);
+      this.tabPage1.Name = "tabPage1";
+      this.tabPage1.Size = new System.Drawing.Size(734, 520);
+      this.tabPage1.TabIndex = 4;
+      this.tabPage1.Text = "Projects";
+      this.tabPage1.UseVisualStyleBackColor = true;
+      // 
+      // imageListUsers
+      // 
+      this.imageListUsers.ColorDepth = System.Windows.Forms.ColorDepth.Depth32Bit;
+      this.imageListUsers.ImageSize = new System.Drawing.Size(16, 16);
+      this.imageListUsers.TransparentColor = System.Drawing.Color.Transparent;
+      // 
+      // projectsView
+      // 
+      this.projectsView.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.projectsView.Caption = "Resources View";
+      this.projectsView.Content = null;
+      this.projectsView.Location = new System.Drawing.Point(0, 0);
+      this.projectsView.Name = "projectsView";
+      this.projectsView.ReadOnly = false;
+      this.projectsView.Size = new System.Drawing.Size(734, 520);
+      this.projectsView.TabIndex = 0;
+      // 
+      // HiveAdministratorView
+      // 
       this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
       this.Controls.Add(this.tabAdmin);
-      this.Name = "HiveAdministrationView";
+      this.Name = "HiveAdministratorView";
       this.Size = new System.Drawing.Size(745, 546);
       this.tabAdmin.ResumeLayout(false);
       this.tabSlaves.ResumeLayout(false);
+      this.tabPage1.ResumeLayout(false);
       this.ResumeLayout(false);
 
@@ -96,5 +123,6 @@
     private System.Windows.Forms.ImageList imageListUsers;
     private System.Windows.Forms.TabPage tabSlaves;
-
+    private System.Windows.Forms.TabPage tabPage1;
+    private ProjectsView projectsView;
   }
 }
Index: branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectView.Designer.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectView.Designer.cs	(revision 15401)
+++ branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectView.Designer.cs	(revision 15401)
@@ -0,0 +1,224 @@
+﻿namespace HeuristicLab.Clients.Hive.Administrator.Views {
+  partial class ProjectView {
+    /// <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.nameLabel = new System.Windows.Forms.Label();
+      this.nameTextBox = new System.Windows.Forms.TextBox();
+      this.descriptionLabel = new System.Windows.Forms.Label();
+      this.descriptionTextBox = new System.Windows.Forms.TextBox();
+      this.ownerComboBox = new System.Windows.Forms.ComboBox();
+      this.ownerLabel = new System.Windows.Forms.Label();
+      this.createdLabel = new System.Windows.Forms.Label();
+      this.startDateTimePicker = new System.Windows.Forms.DateTimePicker();
+      this.startLabel = new System.Windows.Forms.Label();
+      this.endDateTimePicker = new System.Windows.Forms.DateTimePicker();
+      this.endLabel = new System.Windows.Forms.Label();
+      this.indefiniteCheckBox = new System.Windows.Forms.CheckBox();
+      this.createdTextBox = new System.Windows.Forms.TextBox();
+      this.refreshButton = new System.Windows.Forms.Button();
+      this.SuspendLayout();
+      // 
+      // nameLabel
+      // 
+      this.nameLabel.AutoSize = true;
+      this.nameLabel.Location = new System.Drawing.Point(3, 11);
+      this.nameLabel.Name = "nameLabel";
+      this.nameLabel.Size = new System.Drawing.Size(38, 13);
+      this.nameLabel.TabIndex = 0;
+      this.nameLabel.Text = "Name:";
+      // 
+      // nameTextBox
+      // 
+      this.nameTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.nameTextBox.Location = new System.Drawing.Point(72, 8);
+      this.nameTextBox.Name = "nameTextBox";
+      this.nameTextBox.Size = new System.Drawing.Size(464, 20);
+      this.nameTextBox.TabIndex = 1;
+      this.nameTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.nameTextBox_Validating);
+      // 
+      // descriptionLabel
+      // 
+      this.descriptionLabel.AutoSize = true;
+      this.descriptionLabel.Location = new System.Drawing.Point(3, 37);
+      this.descriptionLabel.Name = "descriptionLabel";
+      this.descriptionLabel.Size = new System.Drawing.Size(63, 13);
+      this.descriptionLabel.TabIndex = 2;
+      this.descriptionLabel.Text = "Description:";
+      // 
+      // descriptionTextBox
+      // 
+      this.descriptionTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.descriptionTextBox.Location = new System.Drawing.Point(72, 34);
+      this.descriptionTextBox.Multiline = true;
+      this.descriptionTextBox.Name = "descriptionTextBox";
+      this.descriptionTextBox.Size = new System.Drawing.Size(464, 98);
+      this.descriptionTextBox.TabIndex = 3;
+      this.descriptionTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.descriptionTextBox_Validating);
+      // 
+      // ownerComboBox
+      // 
+      this.ownerComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.ownerComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+      this.ownerComboBox.FormattingEnabled = true;
+      this.ownerComboBox.Location = new System.Drawing.Point(72, 138);
+      this.ownerComboBox.Name = "ownerComboBox";
+      this.ownerComboBox.Size = new System.Drawing.Size(434, 21);
+      this.ownerComboBox.TabIndex = 5;
+      this.ownerComboBox.SelectedIndexChanged += new System.EventHandler(this.ownerComboBox_SelectedIndexChanged);
+      // 
+      // ownerLabel
+      // 
+      this.ownerLabel.AutoSize = true;
+      this.ownerLabel.Location = new System.Drawing.Point(3, 141);
+      this.ownerLabel.Name = "ownerLabel";
+      this.ownerLabel.Size = new System.Drawing.Size(41, 13);
+      this.ownerLabel.TabIndex = 4;
+      this.ownerLabel.Text = "Owner:";
+      // 
+      // createdLabel
+      // 
+      this.createdLabel.AutoSize = true;
+      this.createdLabel.Location = new System.Drawing.Point(3, 171);
+      this.createdLabel.Name = "createdLabel";
+      this.createdLabel.Size = new System.Drawing.Size(47, 13);
+      this.createdLabel.TabIndex = 6;
+      this.createdLabel.Text = "Created:";
+      // 
+      // startDateTimePicker
+      // 
+      this.startDateTimePicker.CustomFormat = "ddd, dd.MM.yyyy, HH:mm:ss";
+      this.startDateTimePicker.Enabled = false;
+      this.startDateTimePicker.Format = System.Windows.Forms.DateTimePickerFormat.Custom;
+      this.startDateTimePicker.Location = new System.Drawing.Point(72, 190);
+      this.startDateTimePicker.Name = "startDateTimePicker";
+      this.startDateTimePicker.Size = new System.Drawing.Size(200, 20);
+      this.startDateTimePicker.TabIndex = 9;
+      this.startDateTimePicker.Validating += new System.ComponentModel.CancelEventHandler(this.startDateTimePicker_Validating);
+      // 
+      // startLabel
+      // 
+      this.startLabel.AutoSize = true;
+      this.startLabel.Location = new System.Drawing.Point(3, 197);
+      this.startLabel.Name = "startLabel";
+      this.startLabel.Size = new System.Drawing.Size(32, 13);
+      this.startLabel.TabIndex = 8;
+      this.startLabel.Text = "Start:";
+      // 
+      // endDateTimePicker
+      // 
+      this.endDateTimePicker.CustomFormat = "ddd, dd.MM.yyyy, HH:mm:ss";
+      this.endDateTimePicker.Enabled = false;
+      this.endDateTimePicker.Format = System.Windows.Forms.DateTimePickerFormat.Custom;
+      this.endDateTimePicker.Location = new System.Drawing.Point(72, 217);
+      this.endDateTimePicker.Name = "endDateTimePicker";
+      this.endDateTimePicker.Size = new System.Drawing.Size(200, 20);
+      this.endDateTimePicker.TabIndex = 11;
+      this.endDateTimePicker.Validating += new System.ComponentModel.CancelEventHandler(this.endDateTimePicker_Validating);
+      // 
+      // endLabel
+      // 
+      this.endLabel.AutoSize = true;
+      this.endLabel.Location = new System.Drawing.Point(3, 223);
+      this.endLabel.Name = "endLabel";
+      this.endLabel.Size = new System.Drawing.Size(29, 13);
+      this.endLabel.TabIndex = 10;
+      this.endLabel.Text = "End:";
+      // 
+      // indefiniteCheckBox
+      // 
+      this.indefiniteCheckBox.AutoSize = true;
+      this.indefiniteCheckBox.Location = new System.Drawing.Point(278, 219);
+      this.indefiniteCheckBox.Name = "indefiniteCheckBox";
+      this.indefiniteCheckBox.Size = new System.Drawing.Size(69, 17);
+      this.indefiniteCheckBox.TabIndex = 12;
+      this.indefiniteCheckBox.Text = "Indefinite";
+      this.indefiniteCheckBox.UseVisualStyleBackColor = true;
+      this.indefiniteCheckBox.CheckedChanged += new System.EventHandler(this.indefiniteCheckBox_CheckedChanged);
+      // 
+      // createdTextBox
+      // 
+      this.createdTextBox.Location = new System.Drawing.Point(72, 164);
+      this.createdTextBox.Name = "createdTextBox";
+      this.createdTextBox.ReadOnly = true;
+      this.createdTextBox.Size = new System.Drawing.Size(200, 20);
+      this.createdTextBox.TabIndex = 7;
+      // 
+      // refreshButton
+      // 
+      this.refreshButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+      this.refreshButton.Image = HeuristicLab.Common.Resources.VSImageLibrary.Refresh;
+      this.refreshButton.Location = new System.Drawing.Point(512, 136);
+      this.refreshButton.Name = "refreshButton";
+      this.refreshButton.Size = new System.Drawing.Size(24, 24);
+      this.refreshButton.TabIndex = 15;
+      this.refreshButton.UseVisualStyleBackColor = true;
+      this.refreshButton.Click += new System.EventHandler(this.refreshButton_Click);
+      // 
+      // ProjectView
+      // 
+      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.Controls.Add(this.refreshButton);
+      this.Controls.Add(this.createdTextBox);
+      this.Controls.Add(this.indefiniteCheckBox);
+      this.Controls.Add(this.endLabel);
+      this.Controls.Add(this.endDateTimePicker);
+      this.Controls.Add(this.startLabel);
+      this.Controls.Add(this.startDateTimePicker);
+      this.Controls.Add(this.createdLabel);
+      this.Controls.Add(this.ownerLabel);
+      this.Controls.Add(this.ownerComboBox);
+      this.Controls.Add(this.descriptionTextBox);
+      this.Controls.Add(this.descriptionLabel);
+      this.Controls.Add(this.nameTextBox);
+      this.Controls.Add(this.nameLabel);
+      this.Name = "ProjectView";
+      this.Size = new System.Drawing.Size(539, 246);
+      this.Load += new System.EventHandler(this.ProjectView_Load);
+      this.ResumeLayout(false);
+      this.PerformLayout();
+
+    }
+
+    #endregion
+
+    private System.Windows.Forms.Label nameLabel;
+    private System.Windows.Forms.TextBox nameTextBox;
+    private System.Windows.Forms.Label descriptionLabel;
+    private System.Windows.Forms.TextBox descriptionTextBox;
+    private System.Windows.Forms.ComboBox ownerComboBox;
+    private System.Windows.Forms.Label ownerLabel;
+    private System.Windows.Forms.Label createdLabel;
+    private System.Windows.Forms.DateTimePicker startDateTimePicker;
+    private System.Windows.Forms.Label startLabel;
+    private System.Windows.Forms.DateTimePicker endDateTimePicker;
+    private System.Windows.Forms.Label endLabel;
+    private System.Windows.Forms.CheckBox indefiniteCheckBox;
+    private System.Windows.Forms.TextBox createdTextBox;
+    private System.Windows.Forms.Button refreshButton;
+  }
+}
Index: branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectView.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectView.cs	(revision 15401)
+++ branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectView.cs	(revision 15401)
@@ -0,0 +1,195 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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.ComponentModel;
+using System.Linq;
+using System.Windows.Forms;
+using HeuristicLab.Clients.Access;
+using HeuristicLab.Core.Views;
+using HeuristicLab.MainForm;
+using Tasks = System.Threading.Tasks;
+
+namespace HeuristicLab.Clients.Hive.Administrator.Views {
+  [View("ProjectView")]
+  [Content(typeof(Project), IsDefaultView = true)]
+  public partial class ProjectView : ItemView {
+    private readonly object locker = new object();
+    private bool updatingUsers = false;
+
+    public new Project Content {
+      get { return (Project)base.Content; }
+      set { base.Content = value; }
+    }
+
+    public ProjectView() {
+      InitializeComponent();
+
+      AccessClient.Instance.Refreshing += AccessClient_Instance_Refreshing;
+      AccessClient.Instance.Refreshed += AccessClient_Instance_Refreshed;
+    }
+
+    protected override void OnClosing(FormClosingEventArgs e) {
+      AccessClient.Instance.Refreshed -= AccessClient_Instance_Refreshed;
+      AccessClient.Instance.Refreshing -= AccessClient_Instance_Refreshing;
+      base.OnClosing(e);
+    }
+
+    protected override void RegisterContentEvents() {
+      base.RegisterContentEvents();
+      Content.PropertyChanged += Content_PropertyChanged;
+    }
+
+    protected override void DeregisterContentEvents() {
+      Content.PropertyChanged -= Content_PropertyChanged;
+      base.DeregisterContentEvents();
+    }
+
+    private void Content_PropertyChanged(object sender, PropertyChangedEventArgs e) {
+      OnContentChanged();
+    }
+
+    protected override void OnContentChanged() {
+      base.OnContentChanged();
+      if (Content == null) {
+        nameTextBox.Clear();
+        descriptionTextBox.Clear();
+        ownerComboBox.DataSource = null;
+        ownerComboBox.SelectedItem = null;
+        createdTextBox.Clear();
+        startDateTimePicker.Value = DateTime.Now;
+        endDateTimePicker.Value = startDateTimePicker.Value;
+        indefiniteCheckBox.Checked = false;
+      } else {
+        nameTextBox.Text = Content.Name;
+        descriptionTextBox.Text = Content.Description;
+        ownerComboBox.DataSource = AccessClient.Instance.UsersAndGroups.OfType<LightweightUser>().ToList();
+        ownerComboBox.SelectedItem = AccessClient.Instance.UsersAndGroups.FirstOrDefault(x => x.Id == Content.OwnerUserId);
+        createdTextBox.Text = Content.DateCreated.ToString("ddd, dd.MM.yyyy, HH:mm:ss");
+        startDateTimePicker.Value = Content.StartDate;
+        if (indefiniteCheckBox.Checked = !Content.EndDate.HasValue) {
+          endDateTimePicker.Value = startDateTimePicker.Value;
+        } else {
+          endDateTimePicker.Value = Content.EndDate.Value;
+        }
+      }
+    }
+
+    protected override void SetEnabledStateOfControls() {
+      base.SetEnabledStateOfControls();
+      bool enabled = Content != null;
+      nameTextBox.Enabled = enabled;
+      descriptionTextBox.Enabled = enabled;
+      ownerComboBox.Enabled = enabled;
+      createdTextBox.Enabled = enabled;
+      startDateTimePicker.Enabled = enabled;
+      endDateTimePicker.Enabled = enabled && Content.EndDate.HasValue;
+      indefiniteCheckBox.Enabled = enabled;
+    }
+
+    private void AccessClient_Instance_Refreshing(object sender, EventArgs e) {
+      if (InvokeRequired) Invoke((Action<object, EventArgs>)AccessClient_Instance_Refreshing, sender, e);
+      else {
+        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
+        mainForm.AddOperationProgressToView(this, "Refreshing ...");
+        SetEnabledStateOfControls();
+      }
+    }
+
+    private void AccessClient_Instance_Refreshed(object sender, EventArgs e) {
+      if (InvokeRequired) Invoke((Action<object, EventArgs>)AccessClient_Instance_Refreshed, sender, e);
+      else {
+        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
+        mainForm.RemoveOperationProgressFromView(this);
+        SetEnabledStateOfControls();
+      }
+    }
+
+    private async void ProjectView_Load(object sender, EventArgs e) {
+      lock (locker) {
+        if (updatingUsers) return;
+        updatingUsers = true;
+      }
+      try {
+        await Tasks.Task.Run(() => UpdateUsers());
+      } finally {
+        updatingUsers = false;
+      }
+    }
+
+    private async void refreshButton_Click(object sender, EventArgs e) {
+      lock (locker) {
+        if (updatingUsers) return;
+        updatingUsers = true;
+      }
+      try {
+        await Tasks.Task.Run(() => UpdateUsers());
+      } finally {
+        updatingUsers = false;
+      }
+    }
+
+    private void UpdateUsers() {
+      ownerComboBox.DataSource = null;
+      AccessClient.Instance.Refresh();
+      if (Content != null) {
+        ownerComboBox.DataSource = AccessClient.Instance.UsersAndGroups.OfType<LightweightUser>().ToList();
+        ownerComboBox.SelectedItem = AccessClient.Instance.UsersAndGroups.FirstOrDefault(x => x.Id == Content.OwnerUserId);
+      }
+    }
+
+    private void nameTextBox_Validating(object sender, CancelEventArgs e) {
+      if (string.IsNullOrEmpty(nameTextBox.Text)) {
+        MessageBox.Show(
+          "Project must have a name.",
+          "HeuristicLab Hive Administrator",
+          MessageBoxButtons.OK,
+          MessageBoxIcon.Error);
+        e.Cancel = true;
+      } else Content.Name = nameTextBox.Text;
+    }
+
+    private void descriptionTextBox_Validating(object sender, CancelEventArgs e) {
+      Content.Description = descriptionTextBox.Text;
+    }
+
+    private void ownerComboBox_SelectedIndexChanged(object sender, EventArgs e) {
+      var selectedItem = (LightweightUser)ownerComboBox.SelectedItem;
+      Content.OwnerUserId = selectedItem != null ? selectedItem.Id : Guid.Empty;
+    }
+
+    private void startDateTimePicker_Validating(object sender, CancelEventArgs e) {
+      if (!Content.EndDate.HasValue || startDateTimePicker.Value > Content.EndDate)
+        endDateTimePicker.Value = startDateTimePicker.Value;
+      Content.StartDate = startDateTimePicker.Value;
+    }
+
+    private void endDateTimePicker_Validating(object sender, CancelEventArgs e) {
+      if (endDateTimePicker.Value < startDateTimePicker.Value)
+        endDateTimePicker.Value = startDateTimePicker.Value;
+      Content.EndDate = endDateTimePicker.Value;
+    }
+
+    private void indefiniteCheckBox_CheckedChanged(object sender, EventArgs e) {
+      Content.EndDate = indefiniteCheckBox.Checked ? (DateTime?)null : Content.StartDate;
+    }
+  }
+}
Index: branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectsView.Designer.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectsView.Designer.cs	(revision 15401)
+++ branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectsView.Designer.cs	(revision 15401)
@@ -0,0 +1,248 @@
+﻿namespace HeuristicLab.Clients.Hive.Administrator.Views {
+  partial class ProjectsView {
+    /// <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.components = new System.ComponentModel.Container();
+      this.splitContainer = new System.Windows.Forms.SplitContainer();
+      this.refreshButton = new System.Windows.Forms.Button();
+      this.saveProjectButton = new System.Windows.Forms.Button();
+      this.removeButton = new System.Windows.Forms.Button();
+      this.addButton = new System.Windows.Forms.Button();
+      this.projectsTreeView = new System.Windows.Forms.TreeView();
+      this.imageList = new System.Windows.Forms.ImageList(this.components);
+      this.tabControl = new System.Windows.Forms.TabControl();
+      this.detailsTabPage = new System.Windows.Forms.TabPage();
+      this.projectView = new HeuristicLab.Clients.Hive.Administrator.Views.ProjectView();
+      this.permissionsTabPage = new System.Windows.Forms.TabPage();
+      this.savePermissionsButton = new System.Windows.Forms.Button();
+      this.permissionsView = new HeuristicLab.Clients.Access.Views.RefreshableLightweightUserView();
+      ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit();
+      this.splitContainer.Panel1.SuspendLayout();
+      this.splitContainer.Panel2.SuspendLayout();
+      this.splitContainer.SuspendLayout();
+      this.tabControl.SuspendLayout();
+      this.detailsTabPage.SuspendLayout();
+      this.permissionsTabPage.SuspendLayout();
+      this.SuspendLayout();
+      // 
+      // splitContainer
+      // 
+      this.splitContainer.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.splitContainer.Location = new System.Drawing.Point(3, 3);
+      this.splitContainer.Name = "splitContainer";
+      // 
+      // splitContainer.Panel1
+      // 
+      this.splitContainer.Panel1.Controls.Add(this.refreshButton);
+      this.splitContainer.Panel1.Controls.Add(this.saveProjectButton);
+      this.splitContainer.Panel1.Controls.Add(this.removeButton);
+      this.splitContainer.Panel1.Controls.Add(this.addButton);
+      this.splitContainer.Panel1.Controls.Add(this.projectsTreeView);
+      // 
+      // splitContainer.Panel2
+      // 
+      this.splitContainer.Panel2.Controls.Add(this.tabControl);
+      this.splitContainer.Size = new System.Drawing.Size(847, 547);
+      this.splitContainer.SplitterDistance = 249;
+      this.splitContainer.TabIndex = 0;
+      // 
+      // refreshButton
+      // 
+      this.refreshButton.Image = HeuristicLab.Common.Resources.VSImageLibrary.Refresh;
+      this.refreshButton.Location = new System.Drawing.Point(3, 3);
+      this.refreshButton.Name = "refreshButton";
+      this.refreshButton.Size = new System.Drawing.Size(24, 24);
+      this.refreshButton.TabIndex = 14;
+      this.refreshButton.UseVisualStyleBackColor = true;
+      this.refreshButton.Click += new System.EventHandler(this.refreshButton_Click);
+      // 
+      // saveProjectButton
+      // 
+      this.saveProjectButton.Image = HeuristicLab.Common.Resources.VSImageLibrary.PublishToWeb;
+      this.saveProjectButton.Location = new System.Drawing.Point(93, 3);
+      this.saveProjectButton.Name = "saveProjectButton";
+      this.saveProjectButton.Size = new System.Drawing.Size(24, 24);
+      this.saveProjectButton.TabIndex = 12;
+      this.saveProjectButton.UseVisualStyleBackColor = true;
+      this.saveProjectButton.Click += new System.EventHandler(this.saveProjectButton_Click);
+      // 
+      // removeButton
+      // 
+      this.removeButton.Image = HeuristicLab.Common.Resources.VSImageLibrary.Remove;
+      this.removeButton.Location = new System.Drawing.Point(63, 3);
+      this.removeButton.Name = "removeButton";
+      this.removeButton.Size = new System.Drawing.Size(24, 24);
+      this.removeButton.TabIndex = 11;
+      this.removeButton.UseVisualStyleBackColor = true;
+      this.removeButton.Click += new System.EventHandler(this.removeButton_Click);
+      // 
+      // addButton
+      // 
+      this.addButton.Image = HeuristicLab.Common.Resources.VSImageLibrary.Add;
+      this.addButton.Location = new System.Drawing.Point(33, 3);
+      this.addButton.Name = "addButton";
+      this.addButton.Size = new System.Drawing.Size(24, 24);
+      this.addButton.TabIndex = 10;
+      this.addButton.UseVisualStyleBackColor = true;
+      this.addButton.Click += new System.EventHandler(this.addButton_Click);
+      // 
+      // projectsTreeView
+      // 
+      this.projectsTreeView.AllowDrop = true;
+      this.projectsTreeView.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.projectsTreeView.ImageIndex = 0;
+      this.projectsTreeView.ImageList = this.imageList;
+      this.projectsTreeView.Location = new System.Drawing.Point(3, 33);
+      this.projectsTreeView.Name = "projectsTreeView";
+      this.projectsTreeView.SelectedImageIndex = 0;
+      this.projectsTreeView.Size = new System.Drawing.Size(243, 511);
+      this.projectsTreeView.TabIndex = 9;
+      this.projectsTreeView.ItemDrag += new System.Windows.Forms.ItemDragEventHandler(this.projectsTreeView_ItemDrag);
+      this.projectsTreeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.projectsTreeView_AfterSelect);
+      this.projectsTreeView.DragDrop += new System.Windows.Forms.DragEventHandler(this.projectsTreeView_DragDrop);
+      this.projectsTreeView.DragEnter += new System.Windows.Forms.DragEventHandler(this.projectsTreeView_DragEnter);
+      this.projectsTreeView.DragOver += new System.Windows.Forms.DragEventHandler(this.projectsTreeView_DragOver);
+      this.projectsTreeView.QueryContinueDrag += new System.Windows.Forms.QueryContinueDragEventHandler(this.projectsTreeView_QueryContinueDrag);
+      // 
+      // imageList
+      // 
+      this.imageList.ColorDepth = System.Windows.Forms.ColorDepth.Depth8Bit;
+      this.imageList.ImageSize = new System.Drawing.Size(16, 16);
+      this.imageList.TransparentColor = System.Drawing.Color.Transparent;
+      // 
+      // tabControl
+      // 
+      this.tabControl.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.tabControl.Controls.Add(this.detailsTabPage);
+      this.tabControl.Controls.Add(this.permissionsTabPage);
+      this.tabControl.Location = new System.Drawing.Point(3, 3);
+      this.tabControl.Name = "tabControl";
+      this.tabControl.SelectedIndex = 0;
+      this.tabControl.Size = new System.Drawing.Size(585, 541);
+      this.tabControl.TabIndex = 0;
+      this.tabControl.SelectedIndexChanged += new System.EventHandler(this.tabControl_SelectedIndexChanged);
+      // 
+      // detailsTabPage
+      // 
+      this.detailsTabPage.Controls.Add(this.projectView);
+      this.detailsTabPage.Location = new System.Drawing.Point(4, 22);
+      this.detailsTabPage.Name = "detailsTabPage";
+      this.detailsTabPage.Padding = new System.Windows.Forms.Padding(3);
+      this.detailsTabPage.Size = new System.Drawing.Size(577, 515);
+      this.detailsTabPage.TabIndex = 0;
+      this.detailsTabPage.Text = "Details";
+      this.detailsTabPage.UseVisualStyleBackColor = true;
+      // 
+      // projectView
+      // 
+      this.projectView.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.projectView.Caption = "ProjectView";
+      this.projectView.Content = null;
+      this.projectView.Location = new System.Drawing.Point(6, 6);
+      this.projectView.Name = "projectView";
+      this.projectView.ReadOnly = false;
+      this.projectView.Size = new System.Drawing.Size(565, 503);
+      this.projectView.TabIndex = 0;
+      // 
+      // permissionsTabPage
+      // 
+      this.permissionsTabPage.Controls.Add(this.savePermissionsButton);
+      this.permissionsTabPage.Controls.Add(this.permissionsView);
+      this.permissionsTabPage.Location = new System.Drawing.Point(4, 22);
+      this.permissionsTabPage.Name = "permissionsTabPage";
+      this.permissionsTabPage.Padding = new System.Windows.Forms.Padding(3);
+      this.permissionsTabPage.Size = new System.Drawing.Size(577, 515);
+      this.permissionsTabPage.TabIndex = 1;
+      this.permissionsTabPage.Text = "Permissions";
+      this.permissionsTabPage.UseVisualStyleBackColor = true;
+      // 
+      // savePermissionsButton
+      // 
+      this.savePermissionsButton.Enabled = false;
+      this.savePermissionsButton.Image = HeuristicLab.Common.Resources.VSImageLibrary.PublishToWeb;
+      this.savePermissionsButton.Location = new System.Drawing.Point(39, 9);
+      this.savePermissionsButton.Name = "savePermissionsButton";
+      this.savePermissionsButton.Size = new System.Drawing.Size(24, 24);
+      this.savePermissionsButton.TabIndex = 2;
+      this.savePermissionsButton.UseVisualStyleBackColor = true;
+      this.savePermissionsButton.Click += new System.EventHandler(this.savePermissionsButton_Click);
+      // 
+      // permissionsView
+      // 
+      this.permissionsView.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.permissionsView.Caption = "RefreshableLightweightUser View";
+      this.permissionsView.Content = null;
+      this.permissionsView.FetchSelectedUsers = null;
+      this.permissionsView.Location = new System.Drawing.Point(6, 6);
+      this.permissionsView.Name = "permissionsView";
+      this.permissionsView.ReadOnly = false;
+      this.permissionsView.Size = new System.Drawing.Size(565, 503);
+      this.permissionsView.TabIndex = 0;
+      // 
+      // ProjectsView
+      // 
+      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.Controls.Add(this.splitContainer);
+      this.Name = "ProjectsView";
+      this.Size = new System.Drawing.Size(853, 553);
+      this.Load += new System.EventHandler(this.ProjectsView_Load);
+      this.splitContainer.Panel1.ResumeLayout(false);
+      this.splitContainer.Panel2.ResumeLayout(false);
+      ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).EndInit();
+      this.splitContainer.ResumeLayout(false);
+      this.tabControl.ResumeLayout(false);
+      this.detailsTabPage.ResumeLayout(false);
+      this.permissionsTabPage.ResumeLayout(false);
+      this.ResumeLayout(false);
+
+    }
+
+    #endregion
+
+    private System.Windows.Forms.SplitContainer splitContainer;
+    private System.Windows.Forms.Button refreshButton;
+    private System.Windows.Forms.Button saveProjectButton;
+    private System.Windows.Forms.Button removeButton;
+    private System.Windows.Forms.Button addButton;
+    private System.Windows.Forms.TreeView projectsTreeView;
+    private System.Windows.Forms.TabControl tabControl;
+    private System.Windows.Forms.TabPage detailsTabPage;
+    private System.Windows.Forms.TabPage permissionsTabPage;
+    private ProjectView projectView;
+    private System.Windows.Forms.ImageList imageList;
+    private Access.Views.RefreshableLightweightUserView permissionsView;
+    private System.Windows.Forms.Button savePermissionsButton;
+  }
+}
Index: branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectsView.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectsView.cs	(revision 15401)
+++ branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectsView.cs	(revision 15401)
@@ -0,0 +1,418 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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.ComponentModel;
+using System.Drawing;
+using System.Linq;
+using System.Windows.Forms;
+using HeuristicLab.Clients.Access;
+using HeuristicLab.Clients.Hive.Views;
+using HeuristicLab.Collections;
+using HeuristicLab.Common.Resources;
+using HeuristicLab.Core;
+using HeuristicLab.Core.Views;
+using HeuristicLab.MainForm;
+
+namespace HeuristicLab.Clients.Hive.Administrator.Views {
+  [View("Projects View")]
+  [Content(typeof(IItemList<Project>), false)]
+  public partial class ProjectsView : ItemView, IDisposable {
+    private const int greenFlagImageIndex = 0;
+    private const int redFlagImageIndex = 1;
+
+    private readonly object locker = new object();
+    private bool updatingProjects = false;
+    private bool removingProjects = false;
+    private bool savingProjects = false;
+
+    public new IItemList<Project> Content {
+      get { return (IItemList<Project>)base.Content; }
+      set { base.Content = value; }
+    }
+
+    public ProjectsView() {
+      InitializeComponent();
+
+      projectsTreeView.ImageList.Images.Add(VSImageLibrary.FlagGreen);
+      projectsTreeView.ImageList.Images.Add(VSImageLibrary.FlagRed);
+
+      HiveAdminClient.Instance.Refreshing += HiveAdminClient_Instance_Refreshing;
+      HiveAdminClient.Instance.Refreshed += HiveAdminClient_Instance_Refreshed;
+      AccessClient.Instance.Refreshing += AccessClient_Instance_Refreshing;
+      AccessClient.Instance.Refreshed += AccessClient_Instance_Refreshed;
+    }
+
+    #region Overrides
+    protected override void OnClosing(FormClosingEventArgs e) {
+      AccessClient.Instance.Refreshed -= AccessClient_Instance_Refreshed;
+      AccessClient.Instance.Refreshing -= AccessClient_Instance_Refreshing;
+      HiveAdminClient.Instance.Refreshed -= HiveAdminClient_Instance_Refreshed;
+      HiveAdminClient.Instance.Refreshing -= HiveAdminClient_Instance_Refreshing;
+      base.OnClosing(e);
+    }
+
+    protected override void RegisterContentEvents() {
+      base.RegisterContentEvents();
+      Content.ItemsAdded += Content_ItemsAdded;
+      Content.ItemsRemoved += Content_ItemsRemoved;
+    }
+
+    protected override void DeregisterContentEvents() {
+      Content.ItemsRemoved -= Content_ItemsRemoved;
+      Content.ItemsAdded -= Content_ItemsAdded;
+      base.DeregisterContentEvents();
+    }
+
+    protected override void OnContentChanged() {
+      base.OnContentChanged();
+      if (Content == null) {
+        projectsTreeView.Nodes.Clear();
+        projectView.Content = null;
+        permissionsView.Content = null;
+        permissionsView.FetchSelectedUsers = null;
+      } else {
+        var top = BuildProjectTree(Content);
+        projectView.Content = top;
+        permissionsView.Content = AccessClient.Instance;
+      }
+    }
+
+    protected override void SetEnabledStateOfControls() {
+      base.SetEnabledStateOfControls();
+      bool enabled = Content != null;
+      addButton.Enabled = enabled;
+      removeButton.Enabled = enabled;
+      saveProjectButton.Enabled = enabled;
+      savePermissionsButton.Enabled = enabled && permissionsView.FetchSelectedUsers != null;
+      permissionsView.Enabled = enabled && permissionsView.FetchSelectedUsers != null;
+    }
+    #endregion
+
+    #region Event Handlers
+    private void Content_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<Project>> e) {
+      OnContentChanged();
+    }
+
+    private void Content_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<Project>> e) {
+      OnContentChanged();
+    }
+
+    private void ProjectViewContent_PropertyChanged(object sender, PropertyChangedEventArgs e) {
+      OnContentChanged();
+    }
+
+    private void HiveAdminClient_Instance_Refreshing(object sender, EventArgs e) {
+      if (InvokeRequired) Invoke((Action<object, EventArgs>)HiveAdminClient_Instance_Refreshing, sender, e);
+      else {
+        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
+        mainForm.AddOperationProgressToView(this, "Refreshing ...");
+        SetEnabledStateOfControls();
+      }
+    }
+
+    private void HiveAdminClient_Instance_Refreshed(object sender, EventArgs e) {
+      if (InvokeRequired) Invoke((Action<object, EventArgs>)HiveAdminClient_Instance_Refreshed, sender, e);
+      else {
+        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
+        mainForm.RemoveOperationProgressFromView(this);
+        SetEnabledStateOfControls();
+      }
+    }
+
+    private void AccessClient_Instance_Refreshing(object sender, EventArgs e) {
+      if (InvokeRequired) Invoke((Action<object, EventArgs>)AccessClient_Instance_Refreshing, sender, e);
+      else {
+        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
+        mainForm.AddOperationProgressToView(this, "Refreshing ...");
+        SetEnabledStateOfControls();
+      }
+    }
+
+    private void AccessClient_Instance_Refreshed(object sender, EventArgs e) {
+      if (InvokeRequired) Invoke((Action<object, EventArgs>)AccessClient_Instance_Refreshed, sender, e);
+      else {
+        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
+        mainForm.RemoveOperationProgressFromView(this);
+        SetEnabledStateOfControls();
+      }
+    }
+
+    private async void ProjectsView_Load(object sender, EventArgs e) {
+      lock (locker) {
+        if (updatingProjects) return;
+        updatingProjects = true;
+      }
+
+      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
+        action: () => UpdateProjects(),
+        finallyCallback: () => updatingProjects = false);
+    }
+
+    private async void refreshButton_Click(object sender, EventArgs e) {
+      lock (locker) {
+        if (updatingProjects) return;
+        updatingProjects = true;
+      }
+
+      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
+        action: () => UpdateProjects(),
+        finallyCallback: () => updatingProjects = false);
+    }
+
+    private void addButton_Click(object sender, EventArgs e) {
+      var project = new Project {
+        Name = "New Project",
+        OwnerUserId = UserInformation.Instance.User.Id
+      };
+      Content.Add(project);
+    }
+
+    private async void removeButton_Click(object sender, EventArgs e) {
+      lock (locker) {
+        if (removingProjects) return;
+        removingProjects = true;
+      }
+
+      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
+        action: () => RemoveProject(),
+        finallyCallback: () => removingProjects = false);
+    }
+
+    private async void saveProjectButton_Click(object sender, EventArgs e) {
+      lock (locker) {
+        if (savingProjects) return;
+        savingProjects = true;
+      }
+
+      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
+        action: () => {
+          var projectsToSave = Content.Where(x => x.Id == Guid.Empty || x.Modified);
+          foreach (var project in projectsToSave)
+            project.Store();
+        },
+        finallyCallback: () => savingProjects = false);
+    }
+
+    private async void projectsTreeView_AfterSelect(object sender, TreeViewEventArgs e) {
+      var selectedProject = (Project)e.Node.Tag;
+
+      if (projectView.Content != null)
+        projectView.Content.PropertyChanged -= ProjectViewContent_PropertyChanged;
+
+      projectView.Content = selectedProject;
+
+      selectedProject.PropertyChanged += ProjectViewContent_PropertyChanged;
+
+      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
+        action: () => UpdatePermissions());
+    }
+
+    private void projectsTreeView_DragDrop(object sender, DragEventArgs e) {
+      var sourceNode = (TreeNode)e.Data.GetData(typeof(TreeNode));
+      if (sourceNode == null) return;
+
+      var treeView = (TreeView)sender;
+      if (sourceNode.TreeView != treeView) return;
+
+      var targetPoint = treeView.PointToClient(new Point(e.X, e.Y));
+      var targetNode = treeView.GetNodeAt(targetPoint);
+
+      if (sourceNode == targetNode) return;
+
+      if (sourceNode.Parent == null)
+        treeView.Nodes.Remove(sourceNode);
+      else {
+        sourceNode.Parent.Nodes.Remove(sourceNode);
+        ((Project)sourceNode.Tag).ParentProjectId = null;
+      }
+
+      if (targetNode == null) {
+        treeView.Nodes.Add(sourceNode);
+      } else {
+        targetNode.Nodes.Add(sourceNode);
+        ((Project)sourceNode.Tag).ParentProjectId = ((Project)targetNode.Tag).Id;
+      }
+    }
+
+    private void projectsTreeView_ItemDrag(object sender, ItemDragEventArgs e) {
+      var sourceNode = (TreeNode)e.Item;
+      if (IsAuthorized((Project)sourceNode.Tag))
+        DoDragDrop(sourceNode, DragDropEffects.All);
+    }
+
+    private void projectsTreeView_DragEnter(object sender, DragEventArgs e) {
+      e.Effect = DragDropEffects.Move;
+    }
+
+    private void projectsTreeView_DragOver(object sender, DragEventArgs e) {
+      e.Effect = DragDropEffects.Move;
+    }
+
+    private void projectsTreeView_QueryContinueDrag(object sender, QueryContinueDragEventArgs e) {
+      e.Action = DragAction.Continue;
+    }
+
+    private void tabControl_SelectedIndexChanged(object sender, EventArgs e) {
+      if (tabControl.SelectedIndex == 1) {
+        UpdatePermissions();
+      }
+    }
+
+    private async void savePermissionsButton_Click(object sender, EventArgs e) {
+      var project = (Project)projectsTreeView.SelectedNode.Tag;
+
+      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
+        action: () => HiveServiceLocator.Instance.CallHiveService(s => {
+          s.GrantProjectPermissions(project.Id, permissionsView.GetAddedUsers().Select(x => x.Id).ToList());
+          s.RevokeProjectPermissions(project.Id, permissionsView.GetDeletedUsers().Select(x => x.Id).ToList());
+        }));
+    }
+    #endregion
+
+    #region Helpers
+    private Project BuildProjectTree(IEnumerable<Project> projects) {
+      projectsTreeView.Nodes.Clear();
+      if (!projects.Any()) return null;
+
+      var mainProjects = new HashSet<Project>(projects.Where(x => x.ParentProjectId == null));
+      var subProbjects = new HashSet<Project>(projects.Except(mainProjects));
+
+      var stack = new Stack<Project>(mainProjects.OrderByDescending(x => x.Name));
+      var top = stack.Peek();
+
+      TreeNode currentNode = null;
+      Project currentProject = null;
+
+      while (stack.Any()) {
+        var newProject = stack.Pop();
+        var newNode = new TreeNode(newProject.Name) { Tag = newProject };
+
+        while (currentNode != null && newProject.ParentProjectId != currentProject.Id) {
+          currentNode = currentNode.Parent;
+          currentProject = currentNode == null ? null : (Project)currentNode.Tag;
+        }
+
+        if (currentNode == null) {
+          projectsTreeView.Nodes.Add(newNode);
+          newNode.ImageIndex = greenFlagImageIndex;
+        } else {
+          currentNode.Nodes.Add(newNode);
+          newNode.ImageIndex = redFlagImageIndex;
+        }
+
+        newNode.SelectedImageIndex = newNode.ImageIndex;
+
+        var childProjects = subProbjects.Where(x => x.ParentProjectId == newProject.Id);
+        if (childProjects.Any()) {
+          foreach (var project in childProjects.OrderByDescending(x => x.Name)) {
+            subProbjects.Remove(project);
+            stack.Push(project);
+          }
+          currentNode = newNode;
+          currentProject = newProject;
+        }
+      }
+
+      projectsTreeView.ExpandAll();
+
+      return top;
+    }
+
+    private void UpdateProjects() {
+      try {
+
+      } catch (AnonymousUserException) {
+        ShowHiveInformationDialog();
+      }
+      HiveAdminClient.Instance.Refresh();
+      Content = HiveAdminClient.Instance.Projects;
+    }
+
+    private void RemoveProject() {
+      var selectedNode = projectsTreeView.SelectedNode;
+      if (selectedNode == null || selectedNode.Tag == null) return;
+
+      var project = (Project)selectedNode.Tag;
+      var result = MessageBox.Show(
+        "Do you really want to delete " + project.Name + "?",
+        "HeuristicLab Hive Administrator",
+        MessageBoxButtons.YesNo,
+        MessageBoxIcon.Question);
+
+      if (result == DialogResult.Yes) {
+        if (Content.Any(x => x.ParentProjectId == project.Id)) {
+          MessageBox.Show(
+            "Only empty projects can be deleted.",
+            "HeuristicLab Hive Administrator",
+            MessageBoxButtons.OK,
+            MessageBoxIcon.Error);
+        } else {
+          Content.Remove(project);
+          HiveAdminClient.Delete(project);
+        }
+      }
+    }
+
+    private void UpdatePermissions() {
+      var selectedNode = projectsTreeView.SelectedNode;
+      var project = (Project)selectedNode?.Tag;
+
+      if (IsAuthorized(project)) {
+        permissionsView.FetchSelectedUsers = () =>
+          HiveServiceLocator.Instance.CallHiveService(s => s.GetProjectPermissions(project.Id))
+                                            .Select(x => x.GrantedUserId)
+                                            .ToList();
+
+        savePermissionsButton.Enabled = true;
+
+        if (!tabControl.TabPages.Contains(permissionsTabPage))
+          tabControl.TabPages.Add(permissionsTabPage);
+
+        if (tabControl.SelectedIndex == 1 && permissionsView.Content != null && permissionsView.FetchSelectedUsers != null)
+          permissionsView.ManualRefresh();
+      } else {
+        permissionsView.FetchSelectedUsers = null;
+        savePermissionsButton.Enabled = false;
+
+        if (tabControl.TabPages.Contains(permissionsTabPage))
+          tabControl.TabPages.Remove(permissionsTabPage);
+      }
+    }
+
+    private bool IsAuthorized(Project project) {
+      return project != null
+          && UserInformation.Instance.UserExists
+          && (project.OwnerUserId == UserInformation.Instance.User.Id || HiveRoles.CheckAdminUserPermissions());
+    }
+
+    private void ShowHiveInformationDialog() {
+      if (InvokeRequired) Invoke((Action)ShowHiveInformationDialog);
+      else {
+        using (HiveInformationDialog dialog = new HiveInformationDialog()) {
+          dialog.ShowDialog(this);
+        }
+      }
+    }
+    #endregion
+  }
+}
Index: branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ResourcesView.Designer.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ResourcesView.Designer.cs	(revision 15399)
+++ branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ResourcesView.Designer.cs	(revision 15401)
@@ -37,9 +37,9 @@
         components.Dispose();
       }
-      HiveAdminClient.Instance.Refreshing -= new EventHandler(Instance_Refreshing);
-      HiveAdminClient.Instance.Refreshed -= new EventHandler(Instance_Refreshed);
-
-      Access.AccessClient.Instance.Refreshing -= new EventHandler(AccessClient_Refreshing);
-      Access.AccessClient.Instance.Refreshed -= new EventHandler(AccessClient_Refreshed);
+      HiveAdminClient.Instance.Refreshing -= new EventHandler(HiveAdminClient_Instance_Refreshing);
+      HiveAdminClient.Instance.Refreshed -= new EventHandler(HiveAdminClient_Instance_Refreshed);
+
+      Access.AccessClient.Instance.Refreshing -= new EventHandler(AccessClient_Instance_Refreshing);
+      Access.AccessClient.Instance.Refreshed -= new EventHandler(AccessClient_Instance_Refreshed);
       base.Dispose(disposing);
     }
@@ -53,12 +53,11 @@
     private void InitializeComponent() {
       this.components = new System.ComponentModel.Container();
+      System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ResourcesView));
       this.imageListSlaveGroups = new System.Windows.Forms.ImageList(this.components);
       this.splitSlaves = new System.Windows.Forms.SplitContainer();
       this.btnRefresh = new System.Windows.Forms.Button();
-      this.progressBar = new System.Windows.Forms.ProgressBar();
       this.btnSave = new System.Windows.Forms.Button();
       this.btnRemoveGroup = new System.Windows.Forms.Button();
       this.btnAddGroup = new System.Windows.Forms.Button();
-      this.btnPermissionsSave = new System.Windows.Forms.Button();
       this.treeSlaveGroup = new System.Windows.Forms.TreeView();
       this.tabSlaveGroup = new System.Windows.Forms.TabControl();
@@ -68,6 +67,4 @@
       this.scheduleView = new HeuristicLab.Clients.Hive.Administrator.Views.ScheduleView();
       this.toolTip = new System.Windows.Forms.ToolTip(this.components);
-      this.tabPermissions = new System.Windows.Forms.TabPage();
-      this.permissionView = new HeuristicLab.Clients.Access.Views.RefreshableLightweightUserView();
       ((System.ComponentModel.ISupportInitialize)(this.splitSlaves)).BeginInit();
       this.splitSlaves.Panel1.SuspendLayout();
@@ -77,5 +74,4 @@
       this.tabDetails.SuspendLayout();
       this.tabSchedule.SuspendLayout();
-      this.tabPermissions.SuspendLayout();
       this.SuspendLayout();
       // 
@@ -88,6 +84,6 @@
       // splitSlaves
       // 
-      this.splitSlaves.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
-            | System.Windows.Forms.AnchorStyles.Left)
+      this.splitSlaves.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.splitSlaves.Location = new System.Drawing.Point(3, 3);
@@ -97,5 +93,4 @@
       // 
       this.splitSlaves.Panel1.Controls.Add(this.btnRefresh);
-      this.splitSlaves.Panel1.Controls.Add(this.progressBar);
       this.splitSlaves.Panel1.Controls.Add(this.btnSave);
       this.splitSlaves.Panel1.Controls.Add(this.btnRemoveGroup);
@@ -121,12 +116,4 @@
       this.btnRefresh.Click += new System.EventHandler(this.btnRefresh_Click);
       // 
-      // progressBar
-      // 
-      this.progressBar.Location = new System.Drawing.Point(123, 4);
-      this.progressBar.Name = "progressBar";
-      this.progressBar.Size = new System.Drawing.Size(123, 23);
-      this.progressBar.Style = System.Windows.Forms.ProgressBarStyle.Continuous;
-      this.progressBar.TabIndex = 7;
-      // 
       // btnSave
       // 
@@ -165,6 +152,6 @@
       // 
       this.treeSlaveGroup.AllowDrop = true;
-      this.treeSlaveGroup.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
-            | System.Windows.Forms.AnchorStyles.Left)
+      this.treeSlaveGroup.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.treeSlaveGroup.ImageIndex = 0;
@@ -184,10 +171,9 @@
       // tabSlaveGroup
       // 
-      this.tabSlaveGroup.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
-            | System.Windows.Forms.AnchorStyles.Left)
+      this.tabSlaveGroup.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.tabSlaveGroup.Controls.Add(this.tabDetails);
       this.tabSlaveGroup.Controls.Add(this.tabSchedule);
-      this.tabSlaveGroup.Controls.Add(this.tabPermissions);
       this.tabSlaveGroup.Location = new System.Drawing.Point(3, 3);
       this.tabSlaveGroup.Name = "tabSlaveGroup";
@@ -210,6 +196,6 @@
       // slaveView
       // 
-      this.slaveView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
-            | System.Windows.Forms.AnchorStyles.Left)
+      this.slaveView.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.slaveView.Caption = "SlaveView";
@@ -234,6 +220,6 @@
       // scheduleView
       // 
-      this.scheduleView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
-            | System.Windows.Forms.AnchorStyles.Left)
+      this.scheduleView.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.scheduleView.Caption = "ScheduleView";
@@ -244,42 +230,4 @@
       this.scheduleView.Size = new System.Drawing.Size(565, 503);
       this.scheduleView.TabIndex = 0;
-      // 
-      // tabPermissions
-      // 
-      this.tabPermissions.Controls.Add(this.btnPermissionsSave);
-      this.tabPermissions.Controls.Add(this.permissionView);
-      this.tabPermissions.Location = new System.Drawing.Point(4, 22);
-      this.tabPermissions.Name = "tabPermissions";
-      this.tabPermissions.Padding = new System.Windows.Forms.Padding(3);
-      this.tabPermissions.Size = new System.Drawing.Size(577, 515);
-      this.tabPermissions.TabIndex = 2;
-      this.tabPermissions.Text = "Permissions";
-      this.tabPermissions.UseVisualStyleBackColor = true;
-      // 
-      // btnPermissionsSave
-      // 
-      this.btnPermissionsSave.Enabled = false;
-      this.btnPermissionsSave.Image = HeuristicLab.Common.Resources.VSImageLibrary.PublishToWeb;
-      this.btnPermissionsSave.Location = new System.Drawing.Point(39, 9);
-      this.btnPermissionsSave.Name = "btnPermissionsSave";
-      this.btnPermissionsSave.Size = new System.Drawing.Size(24, 24);
-      this.btnPermissionsSave.TabIndex = 1;
-      this.toolTip.SetToolTip(this.btnPermissionsSave, "Store slave and group sharing permissions on the server");
-      this.btnPermissionsSave.UseVisualStyleBackColor = true;
-      this.btnPermissionsSave.Click += new System.EventHandler(this.btnPermissionsSave_Click);
-      // 
-      // permissionView
-      // 
-      this.permissionView.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.permissionView.Caption = "RefreshableLightweightUser View";
-      this.permissionView.Content = null;
-      this.permissionView.FetchSelectedUsers = null;
-      this.permissionView.Location = new System.Drawing.Point(6, 6);
-      this.permissionView.Name = "permissionView";
-      this.permissionView.ReadOnly = false;
-      this.permissionView.Size = new System.Drawing.Size(565, 503);
-      this.permissionView.TabIndex = 0;
       // 
       // ResourcesView
@@ -297,5 +245,4 @@
       this.tabDetails.ResumeLayout(false);
       this.tabSchedule.ResumeLayout(false);
-      this.tabPermissions.ResumeLayout(false);
       this.ResumeLayout(false);
 
@@ -315,10 +262,6 @@
     private ScheduleView scheduleView;
     private System.Windows.Forms.Button btnSave;
-    private System.Windows.Forms.ProgressBar progressBar;
     private System.Windows.Forms.Button btnRefresh;
     private System.Windows.Forms.ToolTip toolTip;
-    private System.Windows.Forms.TabPage tabPermissions;
-    private Access.Views.RefreshableLightweightUserView permissionView;
-    private System.Windows.Forms.Button btnPermissionsSave;
   }
 }
Index: branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ResourcesView.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ResourcesView.cs	(revision 15399)
+++ branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ResourcesView.cs	(revision 15401)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2017 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -21,17 +21,14 @@
 
 using System;
-using System.Collections.Generic;
+using System.ComponentModel;
 using System.Drawing;
 using System.Linq;
-using System.ServiceModel.Security;
-using System.Threading;
-using System.Threading.Tasks;
 using System.Windows.Forms;
 using HeuristicLab.Clients.Access;
 using HeuristicLab.Clients.Hive.Views;
+using HeuristicLab.Common.Resources;
 using HeuristicLab.Core;
 using HeuristicLab.Core.Views;
 using HeuristicLab.MainForm;
-using TS = System.Threading.Tasks;
 
 namespace HeuristicLab.Clients.Hive.Administrator.Views {
@@ -39,4 +36,14 @@
   [Content(typeof(IItemList<Resource>), false)]
   public partial class ResourcesView : ItemView, IDisposable {
+    private const string UngroupedGroupName = "UNGROUPED";
+    private const int slaveImageIndex = 0;
+    private const int slaveGroupImageIndex = 1;
+
+    private readonly Color ownedResourceColor = Color.LightGreen;
+    private readonly object locker = new object();
+    private bool updatingResources = false;
+    private bool removingResources = false;
+    private bool savingResources = false;
+
     public new IItemList<Resource> Content {
       get { return (IItemList<Resource>)base.Content; }
@@ -44,82 +51,36 @@
     }
 
-    public const string UngroupedGroupName = "UNGROUPED";
-    private const int slaveImageIndex = 0;
-    private const int slaveGroupImageIndex = 1;
-    private readonly Color ownedResourceColor = Color.LightGreen;
-    private TS.Task progressTask;
-    private bool stopProgressTask;
-    private bool currentlyAuthorized;
-
-
     public ResourcesView() {
       InitializeComponent();
-      treeSlaveGroup.ImageList.Images.Add(HeuristicLab.Common.Resources.VSImageLibrary.MonitorLarge);
-      treeSlaveGroup.ImageList.Images.Add(HeuristicLab.Common.Resources.VSImageLibrary.NetworkCenterLarge);
-
-      HiveAdminClient.Instance.Refreshing += new EventHandler(Instance_Refreshing);
-      HiveAdminClient.Instance.Refreshed += new EventHandler(Instance_Refreshed);
-
-      Access.AccessClient.Instance.Refreshing += new EventHandler(AccessClient_Refreshing);
-      Access.AccessClient.Instance.Refreshed += new EventHandler(AccessClient_Refreshed);
-    }
-
-    private void UpdateProgress() {
-      while (!stopProgressTask) {
-        int diff = (progressBar.Maximum - progressBar.Minimum) / 10;
-
-        if (progressBar.InvokeRequired) {
-          progressBar.Invoke(new Action(delegate() { progressBar.Value = (progressBar.Value + diff) % progressBar.Maximum; }));
-        } else {
-          progressBar.Value = (progressBar.Value + diff) % progressBar.Maximum;
-        }
-
-        //ok, this is not very clever...
-        Thread.Sleep(500);
-      }
-      if (progressBar.InvokeRequired) {
-        progressBar.Invoke(new Action(delegate() { progressBar.Value = progressBar.Minimum; }));
-      } else {
-        progressBar.Value = progressBar.Minimum;
-      }
-    }
-
-    void Instance_Refreshing(object sender, EventArgs e) {
-      stopProgressTask = false;
-      progressTask = new TS.Task(UpdateProgress);
-      progressTask.Start();
-      SetEnabledStateOfControls();
-    }
-
-    void Instance_Refreshed(object sender, EventArgs e) {
-      stopProgressTask = true;
-      SetEnabledStateOfControls();
-    }
-
-    void AccessClient_Refreshing(object sender, EventArgs e) {
-      stopProgressTask = false;
-      progressTask = new TS.Task(UpdateProgress);
-      progressTask.Start();
-      SetEnabledStateOfControls();
-      btnPermissionsSave.Enabled = false;
-    }
-
-    void AccessClient_Refreshed(object sender, EventArgs e) {
-      stopProgressTask = true;
-      SetEnabledStateOfControls();
-    }
-
-    #region Register Content Events
-    protected override void DeregisterContentEvents() {
-      Content.ItemsAdded -= new Collections.CollectionItemsChangedEventHandler<Collections.IndexedItem<Resource>>(Content_ItemsAdded);
-      Content.ItemsRemoved -= new Collections.CollectionItemsChangedEventHandler<Collections.IndexedItem<Resource>>(Content_ItemsRemoved);
-      base.DeregisterContentEvents();
-    }
+
+      treeSlaveGroup.ImageList.Images.Add(VSImageLibrary.MonitorLarge);
+      treeSlaveGroup.ImageList.Images.Add(VSImageLibrary.NetworkCenterLarge);
+
+      HiveAdminClient.Instance.Refreshing += HiveAdminClient_Instance_Refreshing;
+      HiveAdminClient.Instance.Refreshed += HiveAdminClient_Instance_Refreshed;
+      AccessClient.Instance.Refreshing += AccessClient_Instance_Refreshing;
+      AccessClient.Instance.Refreshed += AccessClient_Instance_Refreshed;
+    }
+
+    #region Overrides
+    protected override void OnClosing(FormClosingEventArgs e) {
+      AccessClient.Instance.Refreshed -= AccessClient_Instance_Refreshed;
+      AccessClient.Instance.Refreshing -= AccessClient_Instance_Refreshing;
+      HiveAdminClient.Instance.Refreshed -= HiveAdminClient_Instance_Refreshed;
+      HiveAdminClient.Instance.Refreshing -= HiveAdminClient_Instance_Refreshing;
+      base.OnClosing(e);
+    }
+
     protected override void RegisterContentEvents() {
       base.RegisterContentEvents();
-      Content.ItemsAdded += new Collections.CollectionItemsChangedEventHandler<Collections.IndexedItem<Resource>>(Content_ItemsAdded);
-      Content.ItemsRemoved += new Collections.CollectionItemsChangedEventHandler<Collections.IndexedItem<Resource>>(Content_ItemsRemoved);
-    }
-    #endregion
+      Content.ItemsAdded += Content_ItemsAdded;
+      Content.ItemsRemoved += Content_ItemsRemoved;
+    }
+
+    protected override void DeregisterContentEvents() {
+      Content.ItemsRemoved -= Content_ItemsRemoved;
+      Content.ItemsAdded -= Content_ItemsAdded;
+      base.DeregisterContentEvents();
+    }
 
     protected override void OnContentChanged() {
@@ -128,9 +89,6 @@
         slaveView.Content = null;
         scheduleView.Content = null;
-        permissionView.Content = null;
-        permissionView.FetchSelectedUsers = null;
         treeSlaveGroup.Nodes.Clear();
       } else {
-        permissionView.Content = Access.AccessClient.Instance;
         treeSlaveGroup.Nodes.Clear();
 
@@ -145,5 +103,5 @@
         ungrp.Tag = newGroup;
 
-        foreach (Resource g in Content) {
+        foreach (Resource g in Content.OrderBy(x => x.Name)) {
           if (g.GetType() == typeof(SlaveGroup)) {
             //root node
@@ -175,89 +133,24 @@
     }
 
-    private void BuildSlaveGroupTree(Resource g, TreeNode tn) {
-      foreach (Resource r in Content.Where(s => s.ParentResourceId != null && s.ParentResourceId == g.Id)) {
-        TreeNode stn = new TreeNode(r.Name);
-        if (r is Slave) {
-          stn.ImageIndex = slaveImageIndex;
-        } else if (r is SlaveGroup) {
-          stn.ImageIndex = slaveGroupImageIndex;
-        }
-        stn.SelectedImageIndex = stn.ImageIndex;
-        stn.Tag = r;
-        if (r.OwnerUserId == Access.UserInformation.Instance.User.Id) stn.BackColor = ownedResourceColor;
-        tn.Nodes.Add(stn);
-
-        BuildSlaveGroupTree(r, stn);
-      }
-    }
-
     protected override void SetEnabledStateOfControls() {
       base.SetEnabledStateOfControls();
-      if (Content == null) {
-        btnAddGroup.Enabled = false;
-        btnRemoveGroup.Enabled = false;
-        btnSave.Enabled = false;
-        btnPermissionsSave.Enabled = false;
-        permissionView.Enabled = false;
-        scheduleView.SetEnabledStateOfSchedule(false);
-        btnPermissionsSave.Enabled = false;
-        permissionView.Enabled = false;
-      } else {
-        btnAddGroup.Enabled = true;
-        btnRemoveGroup.Enabled = true;
-        btnSave.Enabled = true;
-        scheduleView.SetEnabledStateOfSchedule(IsAuthorized(slaveView.Content));
-        btnPermissionsSave.Enabled = permissionView.FetchSelectedUsers != null;
-        permissionView.Enabled = permissionView.FetchSelectedUsers != null;
-      }
-    }
-
-    private bool IsAuthorized(Resource resource) {
-      return resource != null
-          && resource.Name != UngroupedGroupName
-          && resource.Id != Guid.Empty
-          && UserInformation.Instance.UserExists
-          && (resource.OwnerUserId == UserInformation.Instance.User.Id || HiveRoles.CheckAdminUserPermissions());
-    }
-
-    private void treeSlaveGroup_AfterSelect(object sender, TreeViewEventArgs e) {
-      if (e.Action != TreeViewAction.Unknown) {
-        Resource selectedResource = ((Resource)e.Node.Tag);
-        currentlyAuthorized = IsAuthorized(selectedResource);
-        if (currentlyAuthorized) {
-          permissionView.FetchSelectedUsers = new Func<List<Guid>>(() => {
-            return HiveServiceLocator.Instance.CallHiveService<List<ResourcePermission>>(service => {
-              return service.GetResourcePermissions(selectedResource.Id);
-            }).Select(x => x.GrantedUserId).ToList();
-          });
-          if (!tabSlaveGroup.TabPages.Contains(tabPermissions)) tabSlaveGroup.TabPages.Add(tabPermissions);
-        } else {
-          permissionView.FetchSelectedUsers = null;
-          btnPermissionsSave.Enabled = false;
-          if (selectedResource.Id == Guid.Empty) {
-            if (!tabSlaveGroup.TabPages.Contains(tabPermissions)) tabSlaveGroup.TabPages.Add(tabPermissions);
-          } else tabSlaveGroup.TabPages.Remove(tabPermissions);
-        }
-
-        if (slaveView.Content != null && slaveView.Content is SlaveGroup) {
-          slaveView.Content.PropertyChanged -= new System.ComponentModel.PropertyChangedEventHandler(SlaveViewContent_PropertyChanged);
-        }
-
-        slaveView.Content = selectedResource;
-        HiveAdminClient.Instance.DowntimeForResourceId = selectedResource.Id;
-
-        if (selectedResource is SlaveGroup) {
-          slaveView.Content.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(SlaveViewContent_PropertyChanged);
-        }
-
-        if (tabSlaveGroup.SelectedIndex == 1) {
-          UpdateScheduleAsync();
-        } else if (tabSlaveGroup.SelectedIndex == 2) {
-          UpdatePermissionsAsync();
-        }
-      }
-    }
-
-    void SlaveViewContent_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) {
+      bool enabled = Content != null;
+      btnAddGroup.Enabled = enabled;
+      btnRemoveGroup.Enabled = enabled;
+      btnSave.Enabled = enabled;
+      scheduleView.SetEnabledStateOfSchedule(enabled && IsAuthorized(slaveView.Content));
+    }
+    #endregion
+
+    #region Event Handlers
+    private void Content_ItemsAdded(object sender, Collections.CollectionItemsChangedEventArgs<Collections.IndexedItem<Resource>> e) {
+      OnContentChanged();
+    }
+
+    private void Content_ItemsRemoved(object sender, Collections.CollectionItemsChangedEventArgs<Collections.IndexedItem<Resource>> e) {
+      OnContentChanged();
+    }
+
+    private void SlaveViewContent_PropertyChanged(object sender, PropertyChangedEventArgs e) {
       OnContentChanged();
       if (e.PropertyName == "HbInterval") {
@@ -266,59 +159,109 @@
     }
 
-    private void UpdateChildHbIntervall(Resource resource) {
-      foreach (Resource r in Content.Where(x => x.ParentResourceId == resource.Id)) {
-        r.HbInterval = resource.HbInterval;
-        if (r is SlaveGroup) {
-          UpdateChildHbIntervall(r);
-        }
-      }
+    private void HiveAdminClient_Instance_Refreshing(object sender, EventArgs e) {
+      if (InvokeRequired) Invoke((Action<object, EventArgs>)HiveAdminClient_Instance_Refreshing, sender, e);
+      else {
+        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
+        mainForm.AddOperationProgressToView(this, "Refreshing ...");
+        SetEnabledStateOfControls();
+      }
+    }
+
+    private void HiveAdminClient_Instance_Refreshed(object sender, EventArgs e) {
+      if (InvokeRequired) Invoke((Action<object, EventArgs>)HiveAdminClient_Instance_Refreshed, sender, e);
+      else {
+        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
+        mainForm.RemoveOperationProgressFromView(this);
+        SetEnabledStateOfControls();
+      }
+    }
+
+    private void AccessClient_Instance_Refreshing(object sender, EventArgs e) {
+      if (InvokeRequired) Invoke((Action<object, EventArgs>)AccessClient_Instance_Refreshing, sender, e);
+      else {
+        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
+        mainForm.AddOperationProgressToView(this, "Refreshing ...");
+        SetEnabledStateOfControls();
+      }
+    }
+
+    private void AccessClient_Instance_Refreshed(object sender, EventArgs e) {
+      if (InvokeRequired) Invoke((Action<object, EventArgs>)AccessClient_Instance_Refreshed, sender, e);
+      else {
+        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
+        mainForm.RemoveOperationProgressFromView(this);
+        SetEnabledStateOfControls();
+      }
+    }
+
+    private async void ResourcesView_Load(object sender, EventArgs e) {
+      lock (locker) {
+        if (updatingResources) return;
+        updatingResources = true;
+      }
+
+      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
+        action: () => UpdateResources(),
+        finallyCallback: () => updatingResources = false);
+    }
+
+    private async void btnRefresh_Click(object sender, EventArgs e) {
+      lock (locker) {
+        if (updatingResources) return;
+        updatingResources = true;
+      }
+
+      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
+        action: () => UpdateResources(),
+        finallyCallback: () => updatingResources = false);
     }
 
     private void btnAddGroup_Click(object sender, EventArgs e) {
-      SlaveGroup newGroup = new SlaveGroup();
-      newGroup.Name = "New Group";
-      newGroup.OwnerUserId = UserInformation.Instance.User.Id;
-      Content.Add(newGroup);
-    }
-
-    void Content_ItemsRemoved(object sender, Collections.CollectionItemsChangedEventArgs<Collections.IndexedItem<Resource>> e) {
-      OnContentChanged();
-    }
-
-    void Content_ItemsAdded(object sender, Collections.CollectionItemsChangedEventArgs<Collections.IndexedItem<Resource>> e) {
-      OnContentChanged();
-    }
-
-    private void btnRemoveGroup_Click(object sender, EventArgs e) {
-      if (treeSlaveGroup.SelectedNode != null && treeSlaveGroup.SelectedNode.Tag != null) {
-        Resource res = (Resource)treeSlaveGroup.SelectedNode.Tag;
-
-        DialogResult diagRes = MessageBox.Show("Do you really want to delete " + res.Name + "?", "HeuristicLab Hive Administrator", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
-        if (diagRes == DialogResult.Yes) {
-          if (res is Slave) {
-            Content.Remove(res);
-            HiveAdminClient.Delete(res);
-          } else if (res is SlaveGroup) {
-            //only delete empty groups
-            if (Content.Where(s => s.ParentResourceId == res.Id).Count() < 1) {
-              Content.Remove(res);
-              HiveAdminClient.Delete(res);
-            } else {
-              MessageBox.Show("Only empty groups can be deleted.", "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Error);
-            }
-          }
-        }
-      }
-    }
-
-    private void btnSave_Click(object sender, EventArgs e) {
-      foreach (Resource res in Content) {
-        if (res is SlaveGroup && res.Id == Guid.Empty) {
-          SlaveGroup slaveGroup = (SlaveGroup)res;
-          slaveGroup.Store();
-        } else if (res.Id != Guid.Empty && res.Modified) {
-          res.Store();
-        }
-      }
+      var group = new SlaveGroup {
+        Name = "New Group",
+        OwnerUserId = UserInformation.Instance.User.Id
+      };
+      Content.Add(group);
+    }
+
+    private async void btnRemoveGroup_Click(object sender, EventArgs e) {
+      lock (locker) {
+        if (removingResources) return;
+        removingResources = true;
+      }
+
+      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
+        action: () => RemoveResource(),
+        finallyCallback: () => removingResources = false);
+    }
+
+    private async void btnSave_Click(object sender, EventArgs e) {
+      lock (locker) {
+        if (savingResources) return;
+        savingResources = true;
+      }
+
+      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
+        action: () => {
+          var resourcesToSave = Content.Where(x => x.Id == Guid.Empty || x.Modified);
+          foreach (var resource in resourcesToSave)
+            resource.Store();
+        },
+        finallyCallback: () => savingResources = false);
+    }
+
+    private async void treeSlaveGroup_AfterSelect(object sender, TreeViewEventArgs e) {
+      var selectedResource = (Resource)e.Node.Tag;
+
+      if (slaveView.Content != null && slaveView.Content is SlaveGroup)
+        slaveView.Content.PropertyChanged -= SlaveViewContent_PropertyChanged;
+
+      slaveView.Content = selectedResource;
+
+      if (selectedResource is SlaveGroup)
+        slaveView.Content.PropertyChanged += SlaveViewContent_PropertyChanged;
+
+      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
+        action: () => UpdateSchedule());
     }
 
@@ -386,16 +329,4 @@
     }
 
-    private bool CheckParentsEqualsMovedNode(TreeNode dest, TreeNode movedNode) {
-      TreeNode tmp = dest;
-
-      while (tmp != null) {
-        if (tmp == movedNode) {
-          return true;
-        }
-        tmp = tmp.Parent;
-      }
-      return false;
-    }
-
     private void treeSlaveGroup_ItemDrag(object sender, ItemDragEventArgs e) {
       TreeNode sourceNode = (TreeNode)e.Item;
@@ -416,17 +347,64 @@
     }
 
-    void ResetView() {
-      if (this.InvokeRequired) {
-        Invoke(new Action(ResetView));
-      } else {
+    private void tabSlaveGroup_SelectedIndexChanged(object sender, EventArgs e) {
+      if (tabSlaveGroup.SelectedIndex == 1) {
+        UpdateSchedule();
+      }
+    }
+    #endregion
+
+    #region Helpers
+    private void BuildSlaveGroupTree(Resource g, TreeNode tn) {
+      foreach (Resource r in Content.Where(s => s.ParentResourceId != null && s.ParentResourceId == g.Id).OrderBy(x => x.Name)) {
+        TreeNode stn = new TreeNode(r.Name);
+        if (r is Slave) {
+          stn.ImageIndex = slaveImageIndex;
+        } else if (r is SlaveGroup) {
+          stn.ImageIndex = slaveGroupImageIndex;
+        }
+        stn.SelectedImageIndex = stn.ImageIndex;
+        stn.Tag = r;
+        if (r.OwnerUserId == Access.UserInformation.Instance.User.Id) stn.BackColor = ownedResourceColor;
+        tn.Nodes.Add(stn);
+
+        BuildSlaveGroupTree(r, stn);
+      }
+    }
+
+    private void UpdateChildHbIntervall(Resource resource) {
+      foreach (Resource r in Content.Where(x => x.ParentResourceId == resource.Id)) {
+        r.HbInterval = resource.HbInterval;
+        if (r is SlaveGroup) {
+          UpdateChildHbIntervall(r);
+        }
+      }
+    }
+
+    private bool CheckParentsEqualsMovedNode(TreeNode dest, TreeNode movedNode) {
+      TreeNode tmp = dest;
+
+      while (tmp != null) {
+        if (tmp == movedNode) {
+          return true;
+        }
+        tmp = tmp.Parent;
+      }
+      return false;
+    }
+
+    private void ResetView() {
+      if (InvokeRequired) Invoke((Action)ResetView);
+      else {
         treeSlaveGroup.Nodes.Clear();
 
         if (slaveView.Content != null && slaveView.Content is SlaveGroup) {
-          slaveView.Content.PropertyChanged -= new System.ComponentModel.PropertyChangedEventHandler(SlaveViewContent_PropertyChanged);
-        }
+          slaveView.Content.PropertyChanged -= SlaveViewContent_PropertyChanged;
+        }
+
         slaveView.Content = null;
         if (scheduleView.Content != null) {
           scheduleView.Content.Clear();
         }
+
         HiveAdminClient.Instance.ResetDowntime();
       }
@@ -434,34 +412,76 @@
 
     private void UpdateResources() {
-      ResetView();
-
       try {
-        if (!Access.UserInformation.Instance.UserExists) {
-          //do a refresh just in case that the user has changed his usr and pwd in between
-          Access.UserInformation.Instance.Refresh();
-        }
+        ResetView();
         HiveAdminClient.Instance.Refresh();
         Content = HiveAdminClient.Instance.Resources;
-      }
-      catch (MessageSecurityException) {
-        ShowMessageSecurityException();
-      }
-      catch (AnonymousUserException) {
+      } catch (AnonymousUserException) {
         ShowHiveInformationDialog();
       }
     }
 
-    private void ShowMessageSecurityException() {
-      if (this.InvokeRequired) {
-        Invoke(new Action(ShowMessageSecurityException));
+    private void RemoveResource() {
+      var selectedNode = treeSlaveGroup.SelectedNode;
+      if (selectedNode == null || selectedNode.Tag == null) return;
+
+      var resource = (Resource)selectedNode.Tag;
+      var result = MessageBox.Show(
+        "Do you really want to delete " + resource.Name + "?",
+        "HeuristicLab Hive Administrator",
+        MessageBoxButtons.YesNo,
+        MessageBoxIcon.Question);
+
+      if (result == DialogResult.Yes) {
+        if (resource is Slave) {
+          Content.Remove(resource);
+          HiveAdminClient.Delete(resource);
+        } else if (resource is SlaveGroup) {
+          if (Content.Any(x => x.ParentResourceId == resource.Id)) {
+            MessageBox.Show(
+              "Only empty resources can be deleted.",
+              "HeuristicLab Hive Administrator",
+              MessageBoxButtons.OK,
+              MessageBoxIcon.Error);
+          } else {
+            Content.Remove(resource);
+            HiveAdminClient.Delete(resource);
+          }
+        }
+      }
+    }
+
+    private void UpdateSchedule() {
+      var selectedNode = treeSlaveGroup.SelectedNode;
+      var resource = (Resource)selectedNode?.Tag;
+
+      if (IsAuthorized(resource)) {
+        if (!tabSlaveGroup.TabPages.Contains(tabSchedule))
+          tabSlaveGroup.TabPages.Add(tabSchedule);
+
+        if (tabSlaveGroup.SelectedIndex == 1) {
+          HiveAdminClient.Instance.DowntimeForResourceId = resource.Id;
+          HiveAdminClient.Instance.RefreshCalendar();
+          scheduleView.Invoke((Action)(() => {
+            scheduleView.Content = HiveAdminClient.Instance.Downtimes;
+            SetEnabledStateOfControls();
+          }));
+        }
       } else {
-        MessageBox.Show("A Message Security error has occured. This normally means that your user name or password is wrong.", "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Error);
-      }
+        if (tabSlaveGroup.TabPages.Contains(tabSchedule))
+          tabSlaveGroup.TabPages.Remove(tabSchedule);
+      }
+    }
+
+    private bool IsAuthorized(Resource resource) {
+      return resource != null
+          && resource.Name != UngroupedGroupName
+          && resource.Id != Guid.Empty
+          && UserInformation.Instance.UserExists
+          && (resource.OwnerUserId == UserInformation.Instance.User.Id || HiveRoles.CheckAdminUserPermissions());
     }
 
     private void ShowHiveInformationDialog() {
-      if (this.InvokeRequired) {
-        Invoke(new Action(ShowHiveInformationDialog));
-      } else {
+      if (InvokeRequired) Invoke((Action)ShowHiveInformationDialog);
+      else {
         using (HiveInformationDialog dialog = new HiveInformationDialog()) {
           dialog.ShowDialog(this);
@@ -469,65 +489,5 @@
       }
     }
-
-    private void UpdateResourcesAsync() {
-      TS.Task.Factory.StartNew(UpdateResources).ContinueWith((t) => {
-        DisplayError(t.Exception);
-      }, TaskContinuationOptions.OnlyOnFaulted);
-    }
-
-    private void UpdateSchedule() {
-      HiveAdminClient.Instance.RefreshCalendar();
-      scheduleView.Invoke(new Action(() => {
-        scheduleView.Content = HiveAdminClient.Instance.Downtimes;
-        SetEnabledStateOfControls();
-      }));
-    }
-
-    private void UpdateScheduleAsync() {
-      TS.Task.Factory.StartNew(UpdateSchedule).ContinueWith((t) => {
-        DisplayError(t.Exception);
-      }, TaskContinuationOptions.OnlyOnFaulted);
-    }
-
-    private void UpdatePermissions() {
-      if (permissionView.Content != null && permissionView.FetchSelectedUsers != null)
-        permissionView.Invoke(new Action(() => permissionView.ManualRefresh()));
-    }
-
-    private void UpdatePermissionsAsync() {
-      TS.Task.Factory.StartNew(UpdatePermissions).ContinueWith((t) => {
-        DisplayError(t.Exception);
-      }, TaskContinuationOptions.OnlyOnFaulted);
-    }
-
-
-    private void DisplayError(Exception ex) {
-      MessageBox.Show(string.Format("An error occured while updating: {0} {1}", Environment.NewLine, ex.Message), "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Error);
-    }
-
-    private void tabSlaveGroup_SelectedIndexChanged(object sender, EventArgs e) {
-      if (tabSlaveGroup.SelectedIndex == 1) {
-        UpdateScheduleAsync();
-      } else if (tabSlaveGroup.SelectedIndex == 2) {
-        UpdatePermissionsAsync();
-      }
-    }
-
-    private void btnRefresh_Click(object sender, EventArgs e) {
-      UpdateResourcesAsync();
-    }
-
-    private void ResourcesView_Load(object sender, EventArgs e) {
-      UpdateResourcesAsync();
-    }
-
-    private void btnPermissionsSave_Click(object sender, EventArgs e) {
-      SetEnabledStateOfControls();
-      HiveServiceLocator.Instance.CallHiveService(service => {
-        service.GrantResourcePermissions(((Resource)treeSlaveGroup.SelectedNode.Tag).Id, permissionView.GetAddedUsers().Select(x => x.Id).ToList());
-        service.RevokeResourcePermissions(((Resource)treeSlaveGroup.SelectedNode.Tag).Id, permissionView.GetDeletedUsers().Select(x => x.Id).ToList());
-      });
-      SetEnabledStateOfControls();
-    }
+    #endregion
   }
 }
Index: branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/HeuristicLab.Clients.Hive.JobManager-3.3.csproj
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/HeuristicLab.Clients.Hive.JobManager-3.3.csproj	(revision 15399)
+++ branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/HeuristicLab.Clients.Hive.JobManager-3.3.csproj	(revision 15401)
@@ -159,4 +159,9 @@
   </ItemGroup>
   <ItemGroup>
+    <ProjectReference Include="..\..\HeuristicLab.Clients.Access\3.3\HeuristicLab.Clients.Access-3.3.csproj">
+      <Project>{494f87f4-0f25-4d33-a382-10cdb2174d48}</Project>
+      <Name>HeuristicLab.Clients.Access-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
     <ProjectReference Include="..\..\HeuristicLab.Clients.Hive.Views\3.3\HeuristicLab.Clients.Hive.Views-3.3.csproj">
       <Project>{E1D6C801-892A-406A-B606-F158E36DD3C3}</Project>
Index: branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/MenuItems/JobManagerMenuItem.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/MenuItems/JobManagerMenuItem.cs	(revision 15399)
+++ branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/MenuItems/JobManagerMenuItem.cs	(revision 15401)
@@ -20,23 +20,41 @@
 #endregion
 
+using System;
 using System.Collections.Generic;
 using System.Windows.Forms;
+using HeuristicLab.Clients.Access;
 using HeuristicLab.MainForm;
 using HeuristicLab.Optimizer;
 
 namespace HeuristicLab.Clients.Hive.JobManager {
-  public class JobManagerMenuItem : HeuristicLab.MainForm.WindowsForms.MenuItem, IOptimizerUserInterfaceItemProvider {
+  public class JobManagerMenuItem : MainForm.WindowsForms.MenuItem, IOptimizerUserInterfaceItemProvider {
     public override string Name {
       get { return "&Job Manager"; }
     }
+
     public override IEnumerable<string> Structure {
       get { return new string[] { "&Services", "&Hive" }; }
     }
+
     public override void Execute() {
-      MainFormManager.MainForm.ShowContent(HiveClient.Instance);
+      if (HiveRoles.CheckHiveUserPermissions()) {
+        MainFormManager.MainForm.ShowContent(HiveClient.Instance);
+      } else if (!UserInformation.Instance.UserExists) {
+        MessageBox.Show(
+          "Couldn't fetch user information from the server." + Environment.NewLine +
+          "Please verify that you have an existing user and that your user name and password is correct.",
+          "HeuristicLab Hive Job Manager", MessageBoxButtons.OK, MessageBoxIcon.Error);
+      } else {
+        MessageBox.Show(
+          "You do not seem to have the permissions to use the Hive Job Manager." + Environment.NewLine +
+          "If that's not the case or you have any questions please write an email to support@heuristiclab.com",
+          "HeuristicLab Hive Job Manager", MessageBoxButtons.OK, MessageBoxIcon.Error);
+      }
     }
+
     public override int Position {
       get { return 10000; }
     }
+
     public override Keys ShortCutKeys {
       get { return Keys.Control | Keys.H; }
Index: branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelector.Designer.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelector.Designer.cs	(revision 15399)
+++ branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelector.Designer.cs	(revision 15401)
@@ -21,5 +21,5 @@
 
 namespace HeuristicLab.Clients.Hive.JobManager.Views {
-  partial class HiveResourceSelector {
+  partial class HiveProjectSelector {
     /// <summary> 
     /// Required designer variable.
@@ -46,5 +46,4 @@
     private void InitializeComponent() {
       this.components = new System.ComponentModel.Container();
-      System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(HiveResourceSelector));
       this.resourcesGroupBox = new System.Windows.Forms.GroupBox();
       this.splitContainer = new System.Windows.Forms.SplitContainer();
@@ -71,5 +70,5 @@
       this.resourcesGroupBox.TabIndex = 0;
       this.resourcesGroupBox.TabStop = false;
-      this.resourcesGroupBox.Text = "Available Resources";
+      this.resourcesGroupBox.Text = "Available Projects";
       // 
       // splitContainer
@@ -95,6 +94,6 @@
       // resourcesTreeView
       // 
-      this.resourcesTreeView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
-            | System.Windows.Forms.AnchorStyles.Left)
+      this.resourcesTreeView.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.resourcesTreeView.CheckBoxes = true;
@@ -128,5 +127,5 @@
       // searchTextBox
       // 
-      this.searchTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+      this.searchTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
             | System.Windows.Forms.AnchorStyles.Right)));
       this.searchTextBox.Location = new System.Drawing.Point(29, 3);
@@ -139,6 +138,6 @@
       // descriptionTextBox
       // 
-      this.descriptionTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
-            | System.Windows.Forms.AnchorStyles.Left)
+      this.descriptionTextBox.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.descriptionTextBox.Font = new System.Drawing.Font("Courier New", 8.25F);
@@ -154,5 +153,4 @@
       // HiveResourceSelector
       // 
-      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
       this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
       this.Controls.Add(this.resourcesGroupBox);
Index: branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelector.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelector.cs	(revision 15399)
+++ branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelector.cs	(revision 15401)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2017 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -24,7 +24,5 @@
 using System.Drawing;
 using System.Linq;
-using System.Text;
 using System.Windows.Forms;
-using HeuristicLab.Clients.Hive.JobManager.ExtensionMethods;
 using HeuristicLab.Core;
 using HeuristicLab.Core.Views;
@@ -33,40 +31,44 @@
 
 namespace HeuristicLab.Clients.Hive.JobManager.Views {
-  [View("Hive Resource Selector View")]
-  [Content(typeof(IItemList<Resource>), true)]
-  public partial class HiveResourceSelector : ItemView, IDisposable {
-    private const int slaveImageIndex = 0;
-    private const int slaveGroupImageIndex = 1;
+  [View("Hive Project Selector View")]
+  [Content(typeof(IItemList<Project>), true)]
+  public partial class HiveProjectSelector : ItemView, IDisposable {
+    private const int greenFlagImageIndex = 0;
+    private const int redFlagImageIndex = 1;
     private string currentSearchString;
     private ISet<TreeNode> mainTreeNodes;
     private ISet<TreeNode> filteredTreeNodes;
     private ISet<TreeNode> nodeStore;
-    
-    private ISet<Resource> selectedResources;
-    public ISet<Resource> SelectedResources {
+
+    private ISet<Project> selectedResources;
+    public ISet<Project> SelectedResources {
       get { return selectedResources; }
       set { selectedResources = value; }
     }
 
-    public new IItemList<Resource> Content {
-      get { return (IItemList<Resource>)base.Content; }
+    public Project SelectedProject {
+      get { return (Project)resourcesTreeView.SelectedNode.Tag; }
+    }
+
+    public new IItemList<Project> Content {
+      get { return (IItemList<Project>)base.Content; }
       set { base.Content = value; }
     }
 
-    public HiveResourceSelector() {
+    public HiveProjectSelector() {
       InitializeComponent();
       mainTreeNodes = new HashSet<TreeNode>();
       filteredTreeNodes = new HashSet<TreeNode>();
       nodeStore = new HashSet<TreeNode>();
-      selectedResources = new HashSet<Resource>();
-      imageList.Images.Add(HeuristicLab.Common.Resources.VSImageLibrary.MonitorLarge);
-      imageList.Images.Add(HeuristicLab.Common.Resources.VSImageLibrary.NetworkCenterLarge);
-    }
-  
+      selectedResources = new HashSet<Project>();
+      imageList.Images.Add(HeuristicLab.Common.Resources.VSImageLibrary.FlagGreen);
+      imageList.Images.Add(HeuristicLab.Common.Resources.VSImageLibrary.FlagRed);
+    }
+
     public void StartProgressView() {
       if (InvokeRequired) {
         Invoke(new Action(StartProgressView));
       } else {
-        var message = "Downloading resources. Please be patient.";
+        var message = "Downloading projects. Please be patient.";
         MainFormManager.GetMainForm<HeuristicLab.MainForm.WindowsForms.MainForm>().AddOperationProgressToView(this, message);
       }
@@ -85,5 +87,5 @@
 
       if (Content != null) {
-        selectedResources = new HashSet<Resource>(Content.Where(x => selectedResources.Any(y => x.Id == y.Id)));
+        selectedResources = new HashSet<Project>(Content.Where(x => selectedResources.Any(y => x.Id == y.Id)));
         UpdateMainTree();
         ExtractStatistics();
@@ -98,19 +100,17 @@
       mainTreeNodes.Clear();
 
-      foreach (Resource g in Content) {
-        if (g.GetType() == typeof(SlaveGroup)) {
-          //root node
-          if (g.ParentResourceId == null) {
-            TreeNode tn = new TreeNode();
-            tn.ImageIndex = slaveGroupImageIndex;
-            tn.SelectedImageIndex = tn.ImageIndex;
-
-            tn.Tag = g;
-            tn.Text = g.Name;
-            tn.Checked = selectedResources.Any(x => x.Id == g.Id);
-
-            BuildMainTree(tn);
-            mainTreeNodes.Add(tn);
-          }
+      foreach (Project g in Content.OrderBy(x => x.Name)) {
+        //root node
+        if (g.ParentProjectId == null) {
+          TreeNode tn = new TreeNode();
+          tn.ImageIndex = greenFlagImageIndex;
+          tn.SelectedImageIndex = tn.ImageIndex;
+
+          tn.Tag = g;
+          tn.Text = g.Name;
+          tn.Checked = selectedResources.Any(x => x.Id == g.Id);
+
+          BuildMainTree(tn);
+          mainTreeNodes.Add(tn);
         }
       }
@@ -119,8 +119,7 @@
 
     private void BuildMainTree(TreeNode tn) {
-      foreach (Resource r in Content.Where(s => s.ParentResourceId != null && s.ParentResourceId == ((Resource)tn.Tag).Id)) {
+      foreach (Project r in Content.Where(s => s.ParentProjectId != null && s.ParentProjectId == ((Project)tn.Tag).Id).OrderBy(x => x.Name)) {
         TreeNode stn = new TreeNode(r.Name);
-        if (r is Slave) stn.ImageIndex = slaveImageIndex;
-        else if (r is SlaveGroup) stn.ImageIndex = slaveGroupImageIndex;
+        stn.ImageIndex = redFlagImageIndex;
         stn.SelectedImageIndex = stn.ImageIndex;
         stn.Tag = r;
@@ -139,5 +138,5 @@
       foreach (TreeNode n in mainTreeNodes) {
         n.BackColor = SystemColors.Window;
-        if (currentSearchString == null || ((Resource)n.Tag).Name.ToLower().Contains(currentSearchString)) {
+        if (currentSearchString == null || ((Project)n.Tag).Name.ToLower().Contains(currentSearchString)) {
           n.BackColor = string.IsNullOrEmpty(currentSearchString) ? SystemColors.Window : Color.LightBlue;
           filteredTreeNodes.Add(n);
@@ -162,5 +161,5 @@
 
       foreach (TreeNode node in filteredTreeNodes) {
-        var clone = nodeStore.SingleOrDefault(x => ((Resource)x.Tag).Id == ((Resource)node.Tag).Id);
+        var clone = nodeStore.SingleOrDefault(x => ((Project)x.Tag).Id == ((Project)node.Tag).Id);
         if (clone == null) {
           clone = (TreeNode)node.Clone();
@@ -169,6 +168,6 @@
         }
         foreach (TreeNode child in node.Nodes)
-          if (filteredTreeNodes.Any(x => ((Resource)x.Tag).Id == ((Resource)child.Tag).Id)) {
-            var childClone = nodeStore.SingleOrDefault(x => ((Resource)x.Tag).Id == ((Resource)child.Tag).Id);
+          if (filteredTreeNodes.Any(x => ((Project)x.Tag).Id == ((Project)child.Tag).Id)) {
+            var childClone = nodeStore.SingleOrDefault(x => ((Project)x.Tag).Id == ((Project)child.Tag).Id);
             if (childClone == null) {
               childClone = (TreeNode)child.Clone();
@@ -179,5 +178,5 @@
           }
       }
-      resourcesTreeView.Nodes.AddRange(nodeStore.Where(x => ((Resource)x.Tag).ParentResourceId == null).ToArray());
+      resourcesTreeView.Nodes.AddRange(nodeStore.Where(x => ((Project)x.Tag).ParentProjectId == null).ToArray());
       if (string.IsNullOrEmpty(currentSearchString)) ExpandSlaveGroupNodes();
       else resourcesTreeView.ExpandAll();
@@ -187,14 +186,14 @@
     #region Events
     private void resourcesTreeView_AfterCheck(object sender, TreeViewEventArgs e) {
-      if (e.Action != TreeViewAction.Unknown) {
-        if (e.Node.Checked) {
-          IncludeChildNodes(mainTreeNodes.SingleOrDefault(x => ((Resource)x.Tag).Id == ((Resource)e.Node.Tag).Id));
-          IncludeParentNodes(mainTreeNodes.SingleOrDefault(x => ((Resource)x.Tag).Id == ((Resource)e.Node.Tag).Id));
-        } else {
-          ExcludeChildNodes(mainTreeNodes.SingleOrDefault(x => ((Resource)x.Tag).Id == ((Resource)e.Node.Tag).Id));
-          ExcludeParentNodes(mainTreeNodes.SingleOrDefault(x => ((Resource)x.Tag).Id == ((Resource)e.Node.Tag).Id));
-        }
-        ExtractStatistics();
-      }
+      //if (e.Action != TreeViewAction.Unknown) {
+      //  if (e.Node.Checked) {
+      //    IncludeChildNodes(mainTreeNodes.SingleOrDefault(x => ((Project)x.Tag).Id == ((Project)e.Node.Tag).Id));
+      //    IncludeParentNodes(mainTreeNodes.SingleOrDefault(x => ((Project)x.Tag).Id == ((Project)e.Node.Tag).Id));
+      //  } else {
+      //    ExcludeChildNodes(mainTreeNodes.SingleOrDefault(x => ((Project)x.Tag).Id == ((Project)e.Node.Tag).Id));
+      //    ExcludeParentNodes(mainTreeNodes.SingleOrDefault(x => ((Project)x.Tag).Id == ((Project)e.Node.Tag).Id));
+      //  }
+      //  ExtractStatistics();
+      //}
     }
 
@@ -212,50 +211,4 @@
 
     #region Helpers
-    private void IncludeChildNodes(TreeNode node) {
-      if (node != null) {
-        node.Checked = true;
-        selectedResources.Add((Resource)node.Tag);
-        AdjustNodeCheckedState(node);
-        foreach (TreeNode n in node.Nodes) IncludeChildNodes(n);
-      }
-    }
-
-    private void IncludeParentNodes(TreeNode node) {
-      if (node != null && node.Parent != null) {
-        TreeNode parent = node.Parent;
-        if (parent.Nodes.OfType<TreeNode>().All(x => x.Checked)) {
-          parent.Checked = true;
-          selectedResources.Add((Resource)parent.Tag);
-          AdjustNodeCheckedState(parent);
-          IncludeParentNodes(parent);
-        }
-      }
-    }
-
-    private void ExcludeChildNodes(TreeNode node) {
-      if (node != null) {
-        node.Checked = false;
-        selectedResources.Remove((Resource)node.Tag);
-        AdjustNodeCheckedState(node);
-        foreach (TreeNode n in node.Nodes) ExcludeChildNodes(n);
-      }
-    }
-
-    private void ExcludeParentNodes(TreeNode node) {
-      if (node != null) {
-        node.Checked = false;
-        selectedResources.Remove((Resource)node.Tag);
-        AdjustNodeCheckedState(node);
-        ExcludeParentNodes(node.Parent);
-      }
-    }
-
-    private void AdjustNodeCheckedState(TreeNode node) {
-      var filterdNode = filteredTreeNodes.SingleOrDefault(x => ((Resource)x.Tag).Id == ((Resource)node.Tag).Id);
-      var storedNode = nodeStore.SingleOrDefault(x => ((Resource)x.Tag).Id == ((Resource)node.Tag).Id);
-      if (filterdNode != null) filterdNode.Checked = node.Checked;
-      if (storedNode != null) storedNode.Checked = node.Checked;
-    }
-
     private void ExpandSlaveGroupNodes() {
       foreach (TreeNode n in nodeStore.Where(x => x.Tag is SlaveGroup)) {
@@ -267,61 +220,61 @@
 
     private void ExtractStatistics(TreeNode treeNode = null) {
-      StringBuilder sb = new StringBuilder();
-      Resource resource = treeNode == null ? null : treeNode.Tag as Resource;
-      ISet<Resource> resources = treeNode == null ? selectedResources : new HashSet<Resource>(treeNode.DescendantNodes().Select(x => x.Tag as Resource)); ;
-      IEnumerable<SlaveGroup> slaveGroups = resources.OfType<SlaveGroup>();
-      IEnumerable<Slave> slaves = resources.OfType<Slave>();
-      int cpuSpeed = 0, cores = 0, freeCores = 0, memory = 0, freeMemory = 0;
-      string contextString = treeNode == null ? "Selected" : "Included";
-
-      if (resources.Any() || resource != null) {
-        foreach (Slave s in slaves) {
-          cpuSpeed += s.CpuSpeed.GetValueOrDefault();
-          cores += s.Cores.GetValueOrDefault();
-          freeCores += s.FreeCores.GetValueOrDefault();
-          memory += s.Memory.GetValueOrDefault();
-          freeMemory += s.FreeMemory.GetValueOrDefault();
-        }
-        if (resource != null) {
-          if (resource is SlaveGroup) sb.Append("Slave group: ");
-          else if (resource is Slave) {
-            sb.Append("Slave: ");
-            if (!resources.Any()) {
-              Slave s = resource as Slave;
-              cpuSpeed = s.CpuSpeed.GetValueOrDefault();
-              cores = s.Cores.GetValueOrDefault();
-              freeCores = s.FreeCores.GetValueOrDefault();
-              memory = s.Memory.GetValueOrDefault();
-              freeMemory = s.FreeMemory.GetValueOrDefault();
-            }
-          }
-          sb.AppendLine(string.Format("{0}", resource.Name));
-        }
-        if (resource == null || resource is SlaveGroup) {
-          if (resources.Any()) {
-            sb.AppendFormat("{0} slave groups ({1}): ", contextString, slaveGroups.Count());
-            foreach (SlaveGroup sg in slaveGroups) sb.AppendFormat("{0}; ", sg.Name);
-            sb.AppendLine();
-            sb.AppendFormat("{0} slaves ({1}): ", contextString, slaves.Count());
-            foreach (Slave s in slaves) sb.AppendFormat("{0}; ", s.Name);
-            sb.AppendLine();
-          } else {
-            sb.Append("The selection does not inlcude any further resources.");
-          }
-        }
-        sb.AppendLine();
-        sb.AppendLine(string.Format("CPU speed: {0} MHz", cpuSpeed));
-        if (resources.Any()) sb.AppendLine(string.Format("Avg. CPU speed: {0:0.00} MHz", (double)cpuSpeed / resources.Count()));
-        sb.AppendLine(string.Format("Cores: {0}", cores));
-        sb.AppendLine(string.Format("Free cores: {0}", freeCores));
-        if (resources.Any()) sb.AppendLine(string.Format("Avg. free cores: {0:0.00}", (double)freeCores / resources.Count()));
-        sb.AppendLine(string.Format("Memory: {0} MB", memory));
-        sb.AppendFormat("Free memory: {0} MB", freeMemory);
-        if (resources.Any()) sb.Append(string.Format("{0}Avg. free memory: {1:0.00} MB", Environment.NewLine, (double)freeMemory / resources.Count()));
-      } else {
-        sb.Append("No resources selected.");
-      }
-
-      descriptionTextBox.Text = sb.ToString();
+      //StringBuilder sb = new StringBuilder();
+      //Resource resource = treeNode == null ? null : treeNode.Tag as Resource;
+      //ISet<Resource> resources = treeNode == null ? selectedResources : new HashSet<Resource>(treeNode.DescendantNodes().Select(x => x.Tag as Resource)); ;
+      //IEnumerable<SlaveGroup> slaveGroups = resources.OfType<SlaveGroup>();
+      //IEnumerable<Slave> slaves = resources.OfType<Slave>();
+      //int cpuSpeed = 0, cores = 0, freeCores = 0, memory = 0, freeMemory = 0;
+      //string contextString = treeNode == null ? "Selected" : "Included";
+
+      //if (resources.Any() || resource != null) {
+      //  foreach (Slave s in slaves) {
+      //    cpuSpeed += s.CpuSpeed.GetValueOrDefault();
+      //    cores += s.Cores.GetValueOrDefault();
+      //    freeCores += s.FreeCores.GetValueOrDefault();
+      //    memory += s.Memory.GetValueOrDefault();
+      //    freeMemory += s.FreeMemory.GetValueOrDefault();
+      //  }
+      //  if (resource != null) {
+      //    if (resource is SlaveGroup) sb.Append("Slave group: ");
+      //    else if (resource is Slave) {
+      //      sb.Append("Slave: ");
+      //      if (!resources.Any()) {
+      //        Slave s = resource as Slave;
+      //        cpuSpeed = s.CpuSpeed.GetValueOrDefault();
+      //        cores = s.Cores.GetValueOrDefault();
+      //        freeCores = s.FreeCores.GetValueOrDefault();
+      //        memory = s.Memory.GetValueOrDefault();
+      //        freeMemory = s.FreeMemory.GetValueOrDefault();
+      //      }
+      //    }
+      //    sb.AppendLine(string.Format("{0}", resource.Name));
+      //  }
+      //  if (resource == null || resource is SlaveGroup) {
+      //    if (resources.Any()) {
+      //      sb.AppendFormat("{0} slave groups ({1}): ", contextString, slaveGroups.Count());
+      //      foreach (SlaveGroup sg in slaveGroups) sb.AppendFormat("{0}; ", sg.Name);
+      //      sb.AppendLine();
+      //      sb.AppendFormat("{0} slaves ({1}): ", contextString, slaves.Count());
+      //      foreach (Slave s in slaves) sb.AppendFormat("{0}; ", s.Name);
+      //      sb.AppendLine();
+      //    } else {
+      //      sb.Append("The selection does not inlcude any further resources.");
+      //    }
+      //  }
+      //  sb.AppendLine();
+      //  sb.AppendLine(string.Format("CPU speed: {0} MHz", cpuSpeed));
+      //  if (resources.Any()) sb.AppendLine(string.Format("Avg. CPU speed: {0:0.00} MHz", (double)cpuSpeed / resources.Count()));
+      //  sb.AppendLine(string.Format("Cores: {0}", cores));
+      //  sb.AppendLine(string.Format("Free cores: {0}", freeCores));
+      //  if (resources.Any()) sb.AppendLine(string.Format("Avg. free cores: {0:0.00}", (double)freeCores / resources.Count()));
+      //  sb.AppendLine(string.Format("Memory: {0} MB", memory));
+      //  sb.AppendFormat("Free memory: {0} MB", freeMemory);
+      //  if (resources.Any()) sb.Append(string.Format("{0}Avg. free memory: {1:0.00} MB", Environment.NewLine, (double)freeMemory / resources.Count()));
+      //} else {
+      //  sb.Append("No resources selected.");
+      //}
+
+      //descriptionTextBox.Text = sb.ToString();
     }
     #endregion
Index: branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelectorDialog.Designer.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelectorDialog.Designer.cs	(revision 15399)
+++ branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelectorDialog.Designer.cs	(revision 15401)
@@ -45,9 +45,8 @@
     /// </summary>
     private void InitializeComponent() {
-      System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(HiveResourceSelectorDialog));
       this.okButton = new System.Windows.Forms.Button();
       this.cancelButton = new System.Windows.Forms.Button();
       this.refreshButton = new System.Windows.Forms.Button();
-      this.hiveResourceSelector = new HeuristicLab.Clients.Hive.JobManager.Views.HiveResourceSelector();
+      this.hiveResourceSelector = new HeuristicLab.Clients.Hive.JobManager.Views.HiveProjectSelector();
       this.SuspendLayout();
       // 
@@ -87,6 +86,6 @@
       // hiveResourceSelector
       // 
-      this.hiveResourceSelector.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
-            | System.Windows.Forms.AnchorStyles.Left)
+      this.hiveResourceSelector.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.hiveResourceSelector.Caption = "View";
@@ -101,5 +100,4 @@
       // 
       this.AcceptButton = this.okButton;
-      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
       this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
       this.CancelButton = this.cancelButton;
@@ -115,5 +113,5 @@
       this.ShowInTaskbar = false;
       this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
-      this.Text = "Select Resources";
+      this.Text = "Select Project";
       this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.HiveResourceSelectorDialog_FormClosing);
       this.Load += new System.EventHandler(this.HiveResourceSelectorDialog_Load);
@@ -126,5 +124,5 @@
     protected System.Windows.Forms.Button okButton;
     protected System.Windows.Forms.Button cancelButton;
-    protected HiveResourceSelector hiveResourceSelector;
+    protected HiveProjectSelector hiveResourceSelector;
     protected System.Windows.Forms.Button refreshButton;
   }
Index: branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelectorDialog.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelectorDialog.cs	(revision 15399)
+++ branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelectorDialog.cs	(revision 15401)
@@ -31,5 +31,6 @@
     }
 
-    public ISet<Resource> GetSelectedResources() { return hiveResourceSelector.SelectedResources; }
+    public ISet<Project> GetSelectedResources() { return hiveResourceSelector.SelectedResources; }
+    public Project SelectedProject { get { return hiveResourceSelector.SelectedProject; } }
 
     private void HiveResourceSelectorDialog_Load(object sender, System.EventArgs e) {
@@ -43,5 +44,5 @@
 
     void Instance_Refreshed(object sender, System.EventArgs e) {
-      hiveResourceSelector.Content = HiveAdminClient.Instance.Resources;
+      hiveResourceSelector.Content = HiveAdminClient.Instance.Projects;
     }
 
Index: branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/Views/RefreshableHiveJobView.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/Views/RefreshableHiveJobView.cs	(revision 15399)
+++ branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/Views/RefreshableHiveJobView.cs	(revision 15401)
@@ -130,5 +130,5 @@
           nameTextBox.Text = Content.Job.Name;
           executionTimeTextBox.Text = Content.ExecutionTime.ToString();
-          resourceNamesTextBox.Text = Content.Job.ResourceNames;
+          //resourceNamesTextBox.Text = Content.Job.ResourceNames;
           refreshAutomaticallyCheckBox.Checked = Content.RefreshAutomatically;
           logView.Content = Content.Log;
@@ -337,11 +337,15 @@
       if (hiveResourceSelectorDialog.ShowDialog(this) == DialogResult.OK) {
         StringBuilder sb = new StringBuilder();
-        foreach (Resource resource in hiveResourceSelectorDialog.GetSelectedResources()) {
-          sb.Append(resource.Name);
-          sb.Append(";");
-        }
-        resourceNamesTextBox.Text = sb.ToString();
-        if (Content.Job.ResourceNames != resourceNamesTextBox.Text)
-          Content.Job.ResourceNames = resourceNamesTextBox.Text;
+        //foreach (Project resource in hiveResourceSelectorDialog.GetSelectedResources()) {
+        //  sb.Append(resource.Name);
+        //  sb.Append(";");
+        //}
+        //resourceNamesTextBox.Text = sb.ToString();
+        //if (Content.Job.ResourceNames != resourceNamesTextBox.Text)
+        //  Content.Job.ResourceNames = resourceNamesTextBox.Text;
+        var selectedProject = hiveResourceSelectorDialog.SelectedProject;
+        resourceNamesTextBox.Text = selectedProject.Name;
+        if (Content.Job.ProjectId != selectedProject.Id)
+          Content.Job.ProjectId = selectedProject.Id;
       }
     }
@@ -404,6 +408,6 @@
 
     private void resourceNamesTextBox_Validated(object sender, EventArgs e) {
-      if (!SuppressEvents && Content.Job != null && Content.Job.ResourceNames != resourceNamesTextBox.Text)
-        Content.Job.ResourceNames = resourceNamesTextBox.Text;
+      //if (!SuppressEvents && Content.Job != null && Content.Job.ResourceNames != resourceNamesTextBox.Text)
+      //  Content.Job.ResourceNames = resourceNamesTextBox.Text;
     }
 
Index: branches/HiveProjectManagement/HeuristicLab.Clients.Hive/3.3/HeuristicLab.Clients.Hive-3.3.csproj
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Clients.Hive/3.3/HeuristicLab.Clients.Hive-3.3.csproj	(revision 15399)
+++ branches/HiveProjectManagement/HeuristicLab.Clients.Hive/3.3/HeuristicLab.Clients.Hive-3.3.csproj	(revision 15401)
@@ -125,4 +125,5 @@
     <Compile Include="HiveAdminClient.cs" />
     <Compile Include="HiveClient.cs" />
+    <Compile Include="ServiceClients\Project.cs" />
     <Compile Include="ServiceClients\UserPriority.cs" />
     <Compile Include="ServiceClients\ResourcePermission.cs" />
Index: branches/HiveProjectManagement/HeuristicLab.Clients.Hive/3.3/HiveAdminClient.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Clients.Hive/3.3/HiveAdminClient.cs	(revision 15399)
+++ branches/HiveProjectManagement/HeuristicLab.Clients.Hive/3.3/HiveAdminClient.cs	(revision 15401)
@@ -57,4 +57,9 @@
     }
 
+    private IItemList<Project> projects;
+    public IItemList<Project> Projects {
+      get { return projects; }
+    }
+
     #region Events
     public event EventHandler Refreshing;
@@ -78,8 +83,10 @@
       try {
         resources = new ItemList<Resource>();
+        projects = new ItemList<Project>();
 
         HiveServiceLocator.Instance.CallHiveService(service => {
           service.GetSlaveGroups().ForEach(g => resources.Add(g));
           service.GetSlaves().ForEach(s => resources.Add(s));
+          service.GetProjects().ForEach(p => projects.Add(p));
         });
       }
@@ -127,4 +134,7 @@
           item.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddDowntime((Downtime)item));
         }
+        if (item is Project) {
+          item.Id = HiveServiceLocator.Instance.CallHiveService(s => s.AddProject((Project)item));
+        }
       } else {
         if (item is SlaveGroup) {
@@ -136,4 +146,7 @@
         if (item is Downtime) {
           HiveServiceLocator.Instance.CallHiveService((s) => s.UpdateDowntime((Downtime)item));
+        }
+        if (item is Project) {
+          HiveServiceLocator.Instance.CallHiveService((s) => s.UpdateProject((Project)item));
         }
       }
@@ -149,4 +162,6 @@
       } else if (item is Downtime) {
         HiveServiceLocator.Instance.CallHiveService((s) => s.DeleteDowntime(item.Id));
+      } else if (item is Project) {
+        HiveServiceLocator.Instance.CallHiveService((s) => s.DeleteProject(item.Id));
       }
     }
Index: branches/HiveProjectManagement/HeuristicLab.Clients.Hive/3.3/HiveClient.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Clients.Hive/3.3/HiveClient.cs	(revision 15399)
+++ branches/HiveProjectManagement/HeuristicLab.Clients.Hive/3.3/HiveClient.cs	(revision 15401)
@@ -140,7 +140,12 @@
           HiveServiceLocator.Instance.CallHiveService((s) => s.GrantPermission(hep.JobId, hep.GrantedUserId, hep.Permission));
         }
+        if (item is Project) {
+          HiveServiceLocator.Instance.CallHiveService(s => s.AddProject((Project)item));
+        }
       } else {
         if (item is Job)
           HiveServiceLocator.Instance.CallHiveService(s => s.UpdateJob((Job)item));
+        if (item is Project)
+          HiveServiceLocator.Instance.CallHiveService(s => s.UpdateProject((Project)item));
       }
     }
@@ -250,5 +255,5 @@
         refreshableJob.IsProgressing = true;
         refreshableJob.Progress.Start("Connecting to server...");
-        IEnumerable<string> resourceNames = ToResourceNameList(refreshableJob.Job.ResourceNames);
+        IEnumerable<string> resourceNames = ToResourceNameList("");
         var resourceIds = new List<Guid>();
         foreach (var resourceName in resourceNames) {
@@ -372,5 +377,5 @@
               hiveTask.Task.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddChildTask(parentHiveTask.Task.Id, hiveTask.Task, taskData));
             } else {
-              hiveTask.Task.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddTask(hiveTask.Task, taskData, groups.ToList()));
+              hiveTask.Task.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddTask(hiveTask.Task, taskData));
             }
           }
Index: branches/HiveProjectManagement/HeuristicLab.Clients.Hive/3.3/ServiceClients/HiveServiceClient.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Clients.Hive/3.3/ServiceClients/HiveServiceClient.cs	(revision 15399)
+++ branches/HiveProjectManagement/HeuristicLab.Clients.Hive/3.3/ServiceClients/HiveServiceClient.cs	(revision 15401)
@@ -26,7 +26,8 @@
     [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.Project))]
     [System.Runtime.Serialization.KnownTypeAttribute(typeof(HeuristicLab.Clients.Hive.JobPermission))]
     [System.Runtime.Serialization.KnownTypeAttribute(typeof(HeuristicLab.Clients.Hive.PluginData))]
-    [System.Runtime.Serialization.KnownTypeAttribute(typeof(HeuristicLab.Clients.Hive.ResourcePermission))]
+    [System.Runtime.Serialization.KnownTypeAttribute(typeof(HeuristicLab.Clients.Hive.ProjectPermission))]
     [System.Runtime.Serialization.KnownTypeAttribute(typeof(HeuristicLab.Clients.Hive.Downtime))]
     [System.Runtime.Serialization.KnownTypeAttribute(typeof(HeuristicLab.Clients.Hive.UserPriority))]
@@ -211,4 +212,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.Project))]
     public partial class NamedHiveItem : HeuristicLab.Clients.Hive.HiveItem
     {
@@ -284,5 +286,5 @@
         
         [System.Runtime.Serialization.OptionalFieldAttribute()]
-        private string ResourceNamesField;
+        private System.Guid ProjectIdField;
         
         [System.Runtime.Serialization.DataMemberAttribute()]
@@ -406,16 +408,16 @@
         
         [System.Runtime.Serialization.DataMemberAttribute()]
-        public string ResourceNames
-        {
-            get
-            {
-                return this.ResourceNamesField;
-            }
-            set
-            {
-                if ((object.ReferenceEquals(this.ResourceNamesField, value) != true))
-                {
-                    this.ResourceNamesField = value;
-                    this.RaisePropertyChanged("ResourceNames");
+        public System.Guid ProjectId
+        {
+            get
+            {
+                return this.ProjectIdField;
+            }
+            set
+            {
+                if ((this.ProjectIdField.Equals(value) != true))
+                {
+                    this.ProjectIdField = value;
+                    this.RaisePropertyChanged("ProjectId");
                 }
             }
@@ -839,4 +841,112 @@
     [System.Diagnostics.DebuggerStepThroughAttribute()]
     [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
+    [System.Runtime.Serialization.DataContractAttribute(Name="Project", Namespace="http://schemas.datacontract.org/2004/07/HeuristicLab.Services.Hive.DataTransfer")]
+    [System.SerializableAttribute()]
+    public partial class Project : HeuristicLab.Clients.Hive.NamedHiveItem
+    {
+        
+        [System.Runtime.Serialization.OptionalFieldAttribute()]
+        private System.DateTime DateCreatedField;
+        
+        [System.Runtime.Serialization.OptionalFieldAttribute()]
+        private System.Nullable<System.DateTime> EndDateField;
+        
+        [System.Runtime.Serialization.OptionalFieldAttribute()]
+        private System.Guid OwnerUserIdField;
+        
+        [System.Runtime.Serialization.OptionalFieldAttribute()]
+        private System.Nullable<System.Guid> ParentProjectIdField;
+        
+        [System.Runtime.Serialization.OptionalFieldAttribute()]
+        private System.DateTime StartDateField;
+        
+        [System.Runtime.Serialization.DataMemberAttribute()]
+        public System.DateTime DateCreated
+        {
+            get
+            {
+                return this.DateCreatedField;
+            }
+            set
+            {
+                if ((this.DateCreatedField.Equals(value) != true))
+                {
+                    this.DateCreatedField = value;
+                    this.RaisePropertyChanged("DateCreated");
+                }
+            }
+        }
+        
+        [System.Runtime.Serialization.DataMemberAttribute()]
+        public System.Nullable<System.DateTime> EndDate
+        {
+            get
+            {
+                return this.EndDateField;
+            }
+            set
+            {
+                if ((this.EndDateField.Equals(value) != true))
+                {
+                    this.EndDateField = value;
+                    this.RaisePropertyChanged("EndDate");
+                }
+            }
+        }
+        
+        [System.Runtime.Serialization.DataMemberAttribute()]
+        public System.Guid OwnerUserId
+        {
+            get
+            {
+                return this.OwnerUserIdField;
+            }
+            set
+            {
+                if ((this.OwnerUserIdField.Equals(value) != true))
+                {
+                    this.OwnerUserIdField = value;
+                    this.RaisePropertyChanged("OwnerUserId");
+                }
+            }
+        }
+        
+        [System.Runtime.Serialization.DataMemberAttribute()]
+        public System.Nullable<System.Guid> ParentProjectId
+        {
+            get
+            {
+                return this.ParentProjectIdField;
+            }
+            set
+            {
+                if ((this.ParentProjectIdField.Equals(value) != true))
+                {
+                    this.ParentProjectIdField = value;
+                    this.RaisePropertyChanged("ParentProjectId");
+                }
+            }
+        }
+        
+        [System.Runtime.Serialization.DataMemberAttribute()]
+        public System.DateTime StartDate
+        {
+            get
+            {
+                return this.StartDateField;
+            }
+            set
+            {
+                if ((this.StartDateField.Equals(value) != true))
+                {
+                    this.StartDateField = value;
+                    this.RaisePropertyChanged("StartDate");
+                }
+            }
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
     [System.Runtime.Serialization.DataContractAttribute(Name="JobPermission", Namespace="http://schemas.datacontract.org/2004/07/HeuristicLab.Services.Hive.DataTransfer")]
     [System.SerializableAttribute()]
@@ -995,7 +1105,7 @@
     [System.Diagnostics.DebuggerStepThroughAttribute()]
     [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
-    [System.Runtime.Serialization.DataContractAttribute(Name="ResourcePermission", Namespace="http://schemas.datacontract.org/2004/07/HeuristicLab.Services.Hive.DataTransfer")]
+    [System.Runtime.Serialization.DataContractAttribute(Name="ProjectPermission", Namespace="http://schemas.datacontract.org/2004/07/HeuristicLab.Services.Hive.DataTransfer")]
     [System.SerializableAttribute()]
-    public partial class ResourcePermission : HeuristicLab.Clients.Hive.HiveItem
+    public partial class ProjectPermission : HeuristicLab.Clients.Hive.HiveItem
     {
         
@@ -1007,5 +1117,5 @@
         
         [System.Runtime.Serialization.OptionalFieldAttribute()]
-        private System.Guid ResourceIdField;
+        private System.Guid ProjectIdField;
         
         [System.Runtime.Serialization.DataMemberAttribute()]
@@ -1044,16 +1154,16 @@
         
         [System.Runtime.Serialization.DataMemberAttribute()]
-        public System.Guid ResourceId
-        {
-            get
-            {
-                return this.ResourceIdField;
-            }
-            set
-            {
-                if ((this.ResourceIdField.Equals(value) != true))
-                {
-                    this.ResourceIdField = value;
-                    this.RaisePropertyChanged("ResourceId");
+        public System.Guid ProjectId
+        {
+            get
+            {
+                return this.ProjectIdField;
+            }
+            set
+            {
+                if ((this.ProjectIdField.Equals(value) != true))
+                {
+                    this.ProjectIdField = value;
+                    this.RaisePropertyChanged("ProjectId");
                 }
             }
@@ -2100,5 +2210,5 @@
         
         [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/AddTask", ReplyAction="http://tempuri.org/IHiveService/AddTaskResponse")]
-        System.Guid AddTask(HeuristicLab.Clients.Hive.Task task, HeuristicLab.Clients.Hive.TaskData taskData, System.Collections.Generic.List<System.Guid> resourceIds);
+        System.Guid AddTask(HeuristicLab.Clients.Hive.Task task, HeuristicLab.Clients.Hive.TaskData taskData);
         
         [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/AddChildTask", ReplyAction="http://tempuri.org/IHiveService/AddChildTaskResponse")]
@@ -2184,12 +2294,27 @@
         System.Collections.Generic.List<HeuristicLab.Clients.Hive.PluginData> GetPluginDatas(System.Collections.Generic.List<System.Guid> pluginIds);
         
-        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GrantResourcePermissions", ReplyAction="http://tempuri.org/IHiveService/GrantResourcePermissionsResponse")]
-        void GrantResourcePermissions(System.Guid resourceId, System.Collections.Generic.List<System.Guid> grantedUserIds);
-        
-        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/RevokeResourcePermissions", ReplyAction="http://tempuri.org/IHiveService/RevokeResourcePermissionsResponse")]
-        void RevokeResourcePermissions(System.Guid resourceId, System.Collections.Generic.List<System.Guid> grantedUserIds);
-        
-        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GetResourcePermissions", ReplyAction="http://tempuri.org/IHiveService/GetResourcePermissionsResponse")]
-        System.Collections.Generic.List<HeuristicLab.Clients.Hive.ResourcePermission> GetResourcePermissions(System.Guid resourceId);
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/AddProject", ReplyAction="http://tempuri.org/IHiveService/AddProjectResponse")]
+        System.Guid AddProject(HeuristicLab.Clients.Hive.Project projectDto);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/UpdateProject", ReplyAction="http://tempuri.org/IHiveService/UpdateProjectResponse")]
+        void UpdateProject(HeuristicLab.Clients.Hive.Project projectDto);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/DeleteProject", ReplyAction="http://tempuri.org/IHiveService/DeleteProjectResponse")]
+        void DeleteProject(System.Guid projectId);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GetProject", ReplyAction="http://tempuri.org/IHiveService/GetProjectResponse")]
+        HeuristicLab.Clients.Hive.Project GetProject(System.Guid projectId);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GetProjects", ReplyAction="http://tempuri.org/IHiveService/GetProjectsResponse")]
+        System.Collections.Generic.List<HeuristicLab.Clients.Hive.Project> GetProjects();
+        
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GrantProjectPermissions", ReplyAction="http://tempuri.org/IHiveService/GrantProjectPermissionsResponse")]
+        void GrantProjectPermissions(System.Guid projectId, System.Collections.Generic.List<System.Guid> grantedUserIds);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/RevokeProjectPermissions", ReplyAction="http://tempuri.org/IHiveService/RevokeProjectPermissionsResponse")]
+        void RevokeProjectPermissions(System.Guid projectId, System.Collections.Generic.List<System.Guid> grantedUserIds);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GetProjectPermissions", ReplyAction="http://tempuri.org/IHiveService/GetProjectPermissionsResponse")]
+        System.Collections.Generic.List<HeuristicLab.Clients.Hive.ProjectPermission> GetProjectPermissions(System.Guid projectId);
         
         [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/AddSlave", ReplyAction="http://tempuri.org/IHiveService/AddSlaveResponse")]
@@ -2291,7 +2416,7 @@
         }
         
-        public System.Guid AddTask(HeuristicLab.Clients.Hive.Task task, HeuristicLab.Clients.Hive.TaskData taskData, System.Collections.Generic.List<System.Guid> resourceIds)
-        {
-            return base.Channel.AddTask(task, taskData, resourceIds);
+        public System.Guid AddTask(HeuristicLab.Clients.Hive.Task task, HeuristicLab.Clients.Hive.TaskData taskData)
+        {
+            return base.Channel.AddTask(task, taskData);
         }
         
@@ -2431,17 +2556,42 @@
         }
         
-        public void GrantResourcePermissions(System.Guid resourceId, System.Collections.Generic.List<System.Guid> grantedUserIds)
-        {
-            base.Channel.GrantResourcePermissions(resourceId, grantedUserIds);
-        }
-        
-        public void RevokeResourcePermissions(System.Guid resourceId, System.Collections.Generic.List<System.Guid> grantedUserIds)
-        {
-            base.Channel.RevokeResourcePermissions(resourceId, grantedUserIds);
-        }
-        
-        public System.Collections.Generic.List<HeuristicLab.Clients.Hive.ResourcePermission> GetResourcePermissions(System.Guid resourceId)
-        {
-            return base.Channel.GetResourcePermissions(resourceId);
+        public System.Guid AddProject(HeuristicLab.Clients.Hive.Project projectDto)
+        {
+            return base.Channel.AddProject(projectDto);
+        }
+        
+        public void UpdateProject(HeuristicLab.Clients.Hive.Project projectDto)
+        {
+            base.Channel.UpdateProject(projectDto);
+        }
+        
+        public void DeleteProject(System.Guid projectId)
+        {
+            base.Channel.DeleteProject(projectId);
+        }
+        
+        public HeuristicLab.Clients.Hive.Project GetProject(System.Guid projectId)
+        {
+            return base.Channel.GetProject(projectId);
+        }
+        
+        public System.Collections.Generic.List<HeuristicLab.Clients.Hive.Project> GetProjects()
+        {
+            return base.Channel.GetProjects();
+        }
+        
+        public void GrantProjectPermissions(System.Guid projectId, System.Collections.Generic.List<System.Guid> grantedUserIds)
+        {
+            base.Channel.GrantProjectPermissions(projectId, grantedUserIds);
+        }
+        
+        public void RevokeProjectPermissions(System.Guid projectId, System.Collections.Generic.List<System.Guid> grantedUserIds)
+        {
+            base.Channel.RevokeProjectPermissions(projectId, grantedUserIds);
+        }
+        
+        public System.Collections.Generic.List<HeuristicLab.Clients.Hive.ProjectPermission> GetProjectPermissions(System.Guid projectId)
+        {
+            return base.Channel.GetProjectPermissions(projectId);
         }
         
Index: branches/HiveProjectManagement/HeuristicLab.Clients.Hive/3.3/ServiceClients/Job.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Clients.Hive/3.3/ServiceClients/Job.cs	(revision 15399)
+++ branches/HiveProjectManagement/HeuristicLab.Clients.Hive/3.3/ServiceClients/Job.cs	(revision 15401)
@@ -29,5 +29,5 @@
     #region Constructors and Cloning
     public Job() {
-      ResourceNames = "HEAL";
+      ProjectId = Guid.Empty;
       DateCreated = DateTime.Now;
       Permission = Permission.Full;
@@ -38,5 +38,5 @@
       this.OwnerUserId = original.OwnerUserId;
       this.DateCreated = original.DateCreated;
-      this.ResourceNames = original.ResourceNames;
+      this.ProjectId = original.ProjectId;
       this.Name = original.Name;
       this.Description = original.Description;
Index: branches/HiveProjectManagement/HeuristicLab.Clients.Hive/3.3/ServiceClients/Project.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Clients.Hive/3.3/ServiceClients/Project.cs	(revision 15401)
+++ branches/HiveProjectManagement/HeuristicLab.Clients.Hive/3.3/ServiceClients/Project.cs	(revision 15401)
@@ -0,0 +1,42 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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 HeuristicLab.Common;
+
+namespace HeuristicLab.Clients.Hive {
+  public partial class Project : IDeepCloneable, IContent {
+    public Project() {
+      Description = string.Empty;
+      DateCreated = DateTime.Now;
+      StartDate = DateCreated;
+      EndDate = DateCreated.AddMonths(3);
+    }
+
+    protected Project(Project original, Cloner cloner) : base(original, cloner) {
+      ParentProjectId = original.ParentProjectId;
+      DateCreated = original.DateCreated;
+      OwnerUserId = original.OwnerUserId;
+      StartDate = original.StartDate;
+      EndDate = original.EndDate;
+    }
+  }
+}
Index: branches/HiveProjectManagement/HeuristicLab.Clients.Hive/3.3/ServiceClients/ResourcePermission.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Clients.Hive/3.3/ServiceClients/ResourcePermission.cs	(revision 15399)
+++ branches/HiveProjectManagement/HeuristicLab.Clients.Hive/3.3/ServiceClients/ResourcePermission.cs	(revision 15401)
@@ -24,5 +24,5 @@
 
 namespace HeuristicLab.Clients.Hive {
-  public partial class ResourcePermission : IDeepCloneable, IContent {
+  public partial class ProjectPermission : IDeepCloneable, IContent {
 
     private string grantedUserName;
@@ -41,5 +41,5 @@
     }
 
-    public ResourcePermission() { }
+    public ProjectPermission() { }
 
     protected override void OnPropertyChanged(PropertyChangedEventArgs e) {
@@ -50,13 +50,13 @@
     }
 
-    protected ResourcePermission(ResourcePermission original, Cloner cloner)
+    protected ProjectPermission(ProjectPermission original, Cloner cloner)
       : base(original, cloner) {
       this.GrantedByUserId = original.GrantedByUserId;
       this.GrantedUserId = original.GrantedUserId;
-      this.ResourceId = original.ResourceId;
+      this.ProjectId = original.ProjectId;
     }
 
     public override IDeepCloneable Clone(Cloner cloner) {
-      return new ResourcePermission(this, cloner);
+      return new ProjectPermission(this, cloner);
     }
 
Index: branches/HiveProjectManagement/HeuristicLab.Optimizer/3.3/MenuItems/UsernamePasswordMenuItem.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Optimizer/3.3/MenuItems/UsernamePasswordMenuItem.cs	(revision 15399)
+++ branches/HiveProjectManagement/HeuristicLab.Optimizer/3.3/MenuItems/UsernamePasswordMenuItem.cs	(revision 15401)
@@ -22,4 +22,5 @@
 using System.Collections.Generic;
 using System.Windows.Forms;
+using HeuristicLab.Clients.Access;
 using HeuristicLab.Clients.Common;
 using HeuristicLab.MainForm;
@@ -43,4 +44,5 @@
       using (PasswordDialog dialog = new PasswordDialog()) {
         dialog.ShowDialog((IWin32Window)MainFormManager.MainForm);
+        UserInformation.Instance.Refresh();
       }
     }
