feature[TW18768]: Update unit tests for asynchronous branch archiving

Change-Id: I9c57280bbc5930f7cc528c8b9a21007e8816cd88
Signed-off-by: Dominic Guss <Dominic.Guss@boeing.com>
diff --git a/plugins/org.eclipse.osee.ats.ide/src/org/eclipse/osee/ats/ide/branch/internal/AtsBranchServiceImpl.java b/plugins/org.eclipse.osee.ats.ide/src/org/eclipse/osee/ats/ide/branch/internal/AtsBranchServiceImpl.java
index 5caf33f..4ae302f 100644
--- a/plugins/org.eclipse.osee.ats.ide/src/org/eclipse/osee/ats/ide/branch/internal/AtsBranchServiceImpl.java
+++ b/plugins/org.eclipse.osee.ats.ide/src/org/eclipse/osee/ats/ide/branch/internal/AtsBranchServiceImpl.java
@@ -103,7 +103,7 @@
 
    @Override
    public void archiveBranch(BranchId branch) {
-      BranchManager.setArchiveState(branch, BranchArchivedState.ARCHIVED);
+      BranchManager.archiveUnArchiveBranch(branch, BranchArchivedState.ARCHIVED);
    }
 
    @Override
diff --git a/plugins/org.eclipse.osee.client.integration.tests/src/org/eclipse/osee/client/integration/tests/integration/skynet/core/BranchEventListenerAsync.java b/plugins/org.eclipse.osee.client.integration.tests/src/org/eclipse/osee/client/integration/tests/integration/skynet/core/BranchEventListenerAsync.java
new file mode 100644
index 0000000..925fa7a
--- /dev/null
+++ b/plugins/org.eclipse.osee.client.integration.tests/src/org/eclipse/osee/client/integration/tests/integration/skynet/core/BranchEventListenerAsync.java
@@ -0,0 +1,65 @@
+/*********************************************************************
+ * Copyright (c) 2021 Boeing
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Boeing - initial API and implementation
+ **********************************************************************/
+package org.eclipse.osee.client.integration.tests.integration.skynet.core;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.eclipse.osee.framework.jdk.core.type.Pair;
+import org.eclipse.osee.framework.skynet.core.event.filter.IEventFilter;
+import org.eclipse.osee.framework.skynet.core.event.listener.IBranchEventListener;
+import org.eclipse.osee.framework.skynet.core.event.model.BranchEvent;
+import org.eclipse.osee.framework.skynet.core.event.model.BranchEventType;
+import org.eclipse.osee.framework.skynet.core.event.model.Sender;
+
+/**
+ * @author Dominic Guss
+ */
+public class BranchEventListenerAsync implements IBranchEventListener {
+   private final List<Pair<Sender, BranchEvent>> eventPairs;
+   private static final long WAIT_TIME_MSEC = 1000L;
+
+   public BranchEventListenerAsync() {
+      eventPairs = new ArrayList<Pair<Sender, BranchEvent>>();
+   }
+
+   public synchronized void reset() {
+      eventPairs.clear();
+   }
+
+   @Override
+   public List<? extends IEventFilter> getEventFilters() {
+      return null;
+   }
+
+   @Override
+   public synchronized void handleBranchEvent(Sender sender, BranchEvent branchEvent) {
+      eventPairs.add(new Pair<Sender, BranchEvent>(sender, branchEvent));
+      notify();
+   }
+
+   public synchronized List<Pair<Sender, BranchEvent>> getResults(BranchEventType branchEventType) throws InterruptedException {
+      while (eventNull(branchEventType)) {
+         wait(WAIT_TIME_MSEC);
+      }
+      return eventPairs;
+   }
+
+   private synchronized boolean eventNull(BranchEventType eventType) {
+      for (Pair<Sender, BranchEvent> eventPair : eventPairs) {
+         if (eventPair.getSecond().getEventType().equals(eventType)) {
+            return false;
+         }
+      }
+      return true;
+   }
+}
diff --git a/plugins/org.eclipse.osee.client.integration.tests/src/org/eclipse/osee/client/integration/tests/integration/skynet/core/BranchEventTest.java b/plugins/org.eclipse.osee.client.integration.tests/src/org/eclipse/osee/client/integration/tests/integration/skynet/core/BranchEventTest.java
index 2b735de..9c33c43 100644
--- a/plugins/org.eclipse.osee.client.integration.tests/src/org/eclipse/osee/client/integration/tests/integration/skynet/core/BranchEventTest.java
+++ b/plugins/org.eclipse.osee.client.integration.tests/src/org/eclipse/osee/client/integration/tests/integration/skynet/core/BranchEventTest.java
@@ -71,6 +71,7 @@
    private BranchId topLevel;
 
    private BranchEventListener branchEventListener;
+   private BranchEventListenerAsync branchEventListenerAsync;
 
    @Before
    public void setup() {
@@ -78,6 +79,7 @@
       mainBranch = IOseeBranch.create(topLevelBranchName);
 
       branchEventListener = new BranchEventListener();
+      branchEventListenerAsync = new BranchEventListenerAsync();
    }
 
    @After
@@ -140,7 +142,7 @@
 
       Assert.assertNotNull(committedBranch);
       Assert.assertTrue(BranchManager.isArchived(committedBranch));
-      BranchManager.setArchiveState(committedBranch, BranchArchivedState.UNARCHIVED);
+      BranchManager.archiveUnArchiveBranch(committedBranch, BranchArchivedState.UNARCHIVED);
 
       verifyReceivedBranchStatesEvent(branchEventListener.getResults(0), BranchEventType.ArchiveStateUpdated,
          committedBranch);
@@ -197,15 +199,19 @@
       Assert.assertNotNull(workingBranch);
       Assert.assertNotSame(BranchState.DELETED, BranchManager.getState(workingBranch));
 
-      branchEventListener.reset();
+      OseeEventManager.addListener(branchEventListenerAsync);
+      branchEventListenerAsync.reset();
       Operations.executeWorkAndCheckStatus(new DeleteBranchOperation(workingBranch));
 
-      verifyReceivedBranchStatesEvent(branchEventListener.getResults(0), BranchEventType.StateUpdated, workingBranch);
-      verifyReceivedBranchStatesEvent(branchEventListener.getResults(1), BranchEventType.ArchiveStateUpdated,
-         workingBranch);
-      verifyReceivedBranchStatesEvent(branchEventListener.getResults(2), BranchEventType.Deleting, workingBranch);
-      verifyReceivedBranchStatesEvent(branchEventListener.getResults(3), BranchEventType.StateUpdated, workingBranch);
-      verifyReceivedBranchStatesEvent(branchEventListener.getResults(4), BranchEventType.Deleted, workingBranch);
+      verifyReceivedBranchStatesEvent(branchEventListenerAsync.getResults(BranchEventType.StateUpdated), workingBranch,
+         BranchEventType.StateUpdated);
+      verifyReceivedBranchStatesEvent(branchEventListenerAsync.getResults(BranchEventType.ArchiveStateUpdated),
+         workingBranch, BranchEventType.ArchiveStateUpdated);
+      verifyReceivedBranchStatesEvent(branchEventListenerAsync.getResults(BranchEventType.Deleting), workingBranch,
+         BranchEventType.Deleting);
+      verifyReceivedBranchStatesEvent(branchEventListenerAsync.getResults(BranchEventType.Deleted), workingBranch,
+         BranchEventType.Deleted);
+      OseeEventManager.removeListener(branchEventListenerAsync);
 
       Assert.assertEquals(BranchState.DELETED, BranchManager.getState(workingBranch));
    }
@@ -283,6 +289,39 @@
       }
    }
 
+   private void verifyReceivedBranchStatesEvent(List<Pair<Sender, BranchEvent>> eventPairs, BranchId expectedBranch, BranchEventType expectedEventType) {
+      Sender receivedSender = null;
+      BranchEvent receivedBranchEvent = null;
+
+      Assert.assertTrue(containsBranchEventType(eventPairs, expectedEventType));
+
+      for (Pair<Sender, BranchEvent> eventPair : eventPairs) {
+         receivedSender = eventPair.getFirst();
+         receivedBranchEvent = eventPair.getSecond();
+
+         if (receivedBranchEvent.getEventType().equals(expectedEventType)) {
+            if (isRemoteTest()) {
+               Assert.assertTrue(receivedSender.isRemote());
+            } else {
+               Assert.assertTrue(receivedSender.isLocal());
+            }
+            if (expectedBranch != null) {
+               Assert.assertEquals(expectedBranch, receivedBranchEvent.getSourceBranch());
+            }
+            break;
+         }
+      }
+   }
+
+   private boolean containsBranchEventType(List<Pair<Sender, BranchEvent>> eventPairs, BranchEventType eventType) {
+      for (Pair<Sender, BranchEvent> eventPair : eventPairs) {
+         if (eventPair.getSecond().getEventType().equals(eventType)) {
+            return true;
+         }
+      }
+      return false;
+   }
+
    protected boolean isRemoteTest() {
       return false;
    }
@@ -320,4 +359,4 @@
          return new Pair<>(senders[sequence], events[sequence]);
       }
    };
-}
\ No newline at end of file
+}
diff --git a/plugins/org.eclipse.osee.client.integration.tests/src/org/eclipse/osee/client/integration/tests/integration/skynet/core/BranchStateTest.java b/plugins/org.eclipse.osee.client.integration.tests/src/org/eclipse/osee/client/integration/tests/integration/skynet/core/BranchStateTest.java
index 69c11e7..3f66696 100644
--- a/plugins/org.eclipse.osee.client.integration.tests/src/org/eclipse/osee/client/integration/tests/integration/skynet/core/BranchStateTest.java
+++ b/plugins/org.eclipse.osee.client.integration.tests/src/org/eclipse/osee/client/integration/tests/integration/skynet/core/BranchStateTest.java
@@ -20,11 +20,12 @@
 import static org.junit.Assert.assertTrue;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.List;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.jobs.Job;
 import org.eclipse.osee.client.integration.tests.integration.skynet.core.utils.Asserts;
 import org.eclipse.osee.client.test.framework.OseeClientIntegrationRule;
+import org.eclipse.osee.client.test.framework.OseeHousekeepingRule;
 import org.eclipse.osee.client.test.framework.OseeLogMonitorRule;
 import org.eclipse.osee.framework.core.data.ArtifactId;
 import org.eclipse.osee.framework.core.data.BranchId;
@@ -37,20 +38,27 @@
 import org.eclipse.osee.framework.core.operation.IOperation;
 import org.eclipse.osee.framework.core.operation.Operations;
 import org.eclipse.osee.framework.jdk.core.type.OseeCoreException;
+import org.eclipse.osee.framework.jdk.core.type.Pair;
 import org.eclipse.osee.framework.skynet.core.OseeSystemArtifacts;
 import org.eclipse.osee.framework.skynet.core.artifact.Artifact;
 import org.eclipse.osee.framework.skynet.core.artifact.ArtifactTypeManager;
 import org.eclipse.osee.framework.skynet.core.artifact.BranchManager;
+import org.eclipse.osee.framework.skynet.core.artifact.DeleteBranchOperation;
 import org.eclipse.osee.framework.skynet.core.artifact.PurgeArtifacts;
 import org.eclipse.osee.framework.skynet.core.artifact.operation.FinishUpdateBranchOperation;
 import org.eclipse.osee.framework.skynet.core.artifact.operation.UpdateBranchOperation;
 import org.eclipse.osee.framework.skynet.core.artifact.search.ArtifactQuery;
 import org.eclipse.osee.framework.skynet.core.artifact.update.ConflictResolverOperation;
 import org.eclipse.osee.framework.skynet.core.conflict.ConflictManagerExternal;
+import org.eclipse.osee.framework.skynet.core.event.OseeEventManager;
+import org.eclipse.osee.framework.skynet.core.event.model.BranchEvent;
+import org.eclipse.osee.framework.skynet.core.event.model.BranchEventType;
+import org.eclipse.osee.framework.skynet.core.event.model.Sender;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.MethodRule;
 
 /**
  * @author Roberto E. Escobar
@@ -63,9 +71,27 @@
    @Rule
    public OseeLogMonitorRule monitorRule = new OseeLogMonitorRule();
 
+   @Rule
+   public MethodRule oseeHousekeepingRule = new OseeHousekeepingRule();
+
+   private BranchEventListenerAsync branchEventListenerAsync;
+
    @Before
    public void setUp() throws Exception {
       BranchManager.refreshBranches();
+      branchEventListenerAsync = new BranchEventListenerAsync();
+   }
+
+   @Test
+   public void testRegistration() throws Exception {
+      OseeEventManager.removeAllListeners();
+      Assert.assertEquals(0, OseeEventManager.getNumberOfListeners());
+
+      OseeEventManager.addListener(branchEventListenerAsync);
+      Assert.assertEquals(1, OseeEventManager.getNumberOfListeners());
+
+      OseeEventManager.removeListener(branchEventListenerAsync);
+      Assert.assertEquals(0, OseeEventManager.getNumberOfListeners());
    }
 
    @Test
@@ -107,25 +133,36 @@
 
    @Test
    public void testDeleteState() throws InterruptedException {
+      OseeEventManager.addListener(branchEventListenerAsync);
+
       String originalBranchName = "Deleted State Branch";
       IOseeBranch workingBranch = null;
+      boolean pending = OseeEventManager.getPreferences().isPendRunning();
       try {
+         OseeEventManager.getPreferences().setPendRunning(true);
+
          workingBranch = BranchManager.createWorkingBranch(SAW_Bld_1, originalBranchName);
          assertEquals(BranchState.CREATED, BranchManager.getState(workingBranch));
          assertTrue(BranchManager.isEditable(workingBranch));
 
-         Job job = BranchManager.deleteBranch(workingBranch);
-         job.join();
-         assertEquals(BranchState.DELETED, BranchManager.getState(workingBranch));
+         branchEventListenerAsync.reset();
+         Operations.executeWorkAndCheckStatus(new DeleteBranchOperation(workingBranch));
+
+         verifyReceivedBranchStatesEvent(branchEventListenerAsync.getResults(BranchEventType.ArchiveStateUpdated),
+            workingBranch, BranchEventType.ArchiveStateUpdated);
+
          assertTrue(BranchManager.isArchived(workingBranch));
          assertTrue(!BranchManager.isEditable(workingBranch));
          assertTrue(BranchManager.getState(workingBranch).isDeleted());
+         assertEquals(BranchState.DELETED, BranchManager.getState(workingBranch));
       } finally {
          if (workingBranch != null) {
             // needed to allow for archiving to occur
             Thread.sleep(5000);
             BranchManager.purgeBranch(workingBranch);
          }
+         OseeEventManager.getPreferences().setPendRunning(pending);
+         OseeEventManager.removeListener(branchEventListenerAsync);
       }
    }
 
@@ -410,4 +447,39 @@
          String.format("%s - moved by update on -", originalBranchName)));
    }
 
+   private boolean containsBranchEventType(List<Pair<Sender, BranchEvent>> eventPairs, BranchEventType eventType) {
+      for (Pair<Sender, BranchEvent> eventPair : eventPairs) {
+         if (eventPair.getSecond().getEventType().equals(eventType)) {
+            return true;
+         }
+      }
+      return false;
+   }
+
+   private void verifyReceivedBranchStatesEvent(List<Pair<Sender, BranchEvent>> eventPairs, BranchId expectedBranch, BranchEventType expectedEventType) {
+      Sender receivedSender = null;
+      BranchEvent receivedBranchEvent = null;
+
+      Assert.assertTrue(containsBranchEventType(eventPairs, expectedEventType));
+
+      for (Pair<Sender, BranchEvent> eventPair : eventPairs) {
+         receivedSender = eventPair.getFirst();
+         receivedBranchEvent = eventPair.getSecond();
+
+         if (receivedBranchEvent.getEventType().equals(expectedEventType)) {
+            if (isRemoteTest()) {
+               Assert.assertTrue(receivedSender.isRemote());
+            } else {
+               Assert.assertTrue(receivedSender.isLocal());
+            }
+            if (expectedBranch != null) {
+               Assert.assertEquals(expectedBranch, receivedBranchEvent.getSourceBranch());
+            }
+         }
+      }
+   }
+
+   protected boolean isRemoteTest() {
+      return false;
+   }
 }
diff --git a/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/enums/CoreUserGroups.java b/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/enums/CoreUserGroups.java
index 7ee7a42..e779c70 100644
--- a/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/enums/CoreUserGroups.java
+++ b/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/enums/CoreUserGroups.java
@@ -27,10 +27,10 @@
    public static final IUserGroupArtifactToken OseeAdmin = UserGroupArtifactToken.valueOf(52247L, "OseeAdmin");
    public static final IUserGroupArtifactToken OseeDeveloper =
       UserGroupArtifactToken.valueOf(464565465L, "OseeDeveloper");
+   public static final IUserGroupArtifactToken OseeSupport = UserGroupArtifactToken.valueOf(10865894L, "OseeSupport");
    public static IUserGroupArtifactToken AgileUser = UserGroupArtifactToken.valueOf(10635635L, "Agile User");
    public static IUserGroupArtifactToken EarnedValueUser =
       UserGroupArtifactToken.valueOf(10635662L, "Earner Value User");
    public static IUserGroupArtifactToken DefaultArtifactEditor =
       UserGroupArtifactToken.valueOf(10862351L, "Deault Artifact Editor");
-
 }
diff --git a/plugins/org.eclipse.osee.framework.jdk.core/src/org/eclipse/osee/framework/jdk/core/util/OseeProperties.java b/plugins/org.eclipse.osee.framework.jdk.core/src/org/eclipse/osee/framework/jdk/core/util/OseeProperties.java
index b37b6a9..5d5ecc3 100644
--- a/plugins/org.eclipse.osee.framework.jdk.core/src/org/eclipse/osee/framework/jdk/core/util/OseeProperties.java
+++ b/plugins/org.eclipse.osee.framework.jdk.core/src/org/eclipse/osee/framework/jdk/core/util/OseeProperties.java
@@ -232,4 +232,7 @@
       return Strings.isValid(System.getProperty(OSEE_DB));
    }
 
+   public static String getOseeDbName() {
+      return System.getProperty(OSEE_DB);
+   }
 }
diff --git a/plugins/org.eclipse.osee.framework.skynet.core/src/org/eclipse/osee/framework/skynet/core/artifact/ArchiveUnArchiveBranchJob.java b/plugins/org.eclipse.osee.framework.skynet.core/src/org/eclipse/osee/framework/skynet/core/artifact/ArchiveUnArchiveBranchJob.java
new file mode 100644
index 0000000..aeeff18
--- /dev/null
+++ b/plugins/org.eclipse.osee.framework.skynet.core/src/org/eclipse/osee/framework/skynet/core/artifact/ArchiveUnArchiveBranchJob.java
@@ -0,0 +1,71 @@
+/*********************************************************************
+ * Copyright (c) 2021 Boeing
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Boeing - initial API and implementation
+ **********************************************************************/
+package org.eclipse.osee.framework.skynet.core.artifact;
+
+import java.util.logging.Level;
+import javax.ws.rs.core.Response;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.osee.framework.core.data.BranchId;
+import org.eclipse.osee.framework.logging.OseeLog;
+import org.eclipse.osee.framework.skynet.core.internal.Activator;
+import org.eclipse.osee.framework.skynet.core.internal.ServiceUtil;
+import org.eclipse.osee.orcs.rest.model.BranchEndpoint;
+
+/**
+ * @author Dominic Guss
+ */
+public class ArchiveUnArchiveBranchJob extends Job {
+
+   private final BranchId branchId;
+   private final BranchEndpoint branchEndpoint;
+   private final ArchiveType archiveType;
+   private Response response;
+
+   public enum ArchiveType {
+      ARCHIVE,
+      UNARCHIVE;
+   }
+
+   public ArchiveUnArchiveBranchJob(String name, BranchId branchId, ArchiveType archiveType) {
+      super(name);
+      this.branchId = branchId;
+      this.archiveType = archiveType;
+      branchEndpoint = ServiceUtil.getOseeClient().getBranchEndpoint();
+   }
+
+   @Override
+   protected IStatus run(IProgressMonitor monitor) {
+      IStatus toReturn = Status.CANCEL_STATUS;
+      try {
+         if (archiveType == ArchiveType.ARCHIVE) {
+            response = branchEndpoint.archiveBranch(branchId);
+         } else {
+            response = branchEndpoint.unarchiveBranch(branchId);
+         }
+      } catch (Exception ex) {
+         OseeLog.log(Activator.class, Level.SEVERE, ex.getLocalizedMessage());
+         return toReturn;
+      }
+      if (response.getStatus() == javax.ws.rs.core.Response.Status.OK.getStatusCode()) {
+         toReturn = Status.OK_STATUS;
+      }
+      return toReturn;
+   }
+
+   public Response getResponse() {
+      return response;
+   }
+}
diff --git a/plugins/org.eclipse.osee.framework.skynet.core/src/org/eclipse/osee/framework/skynet/core/artifact/BranchManager.java b/plugins/org.eclipse.osee.framework.skynet.core/src/org/eclipse/osee/framework/skynet/core/artifact/BranchManager.java
index 44aad2b..5c0d991 100644
--- a/plugins/org.eclipse.osee.framework.skynet.core/src/org/eclipse/osee/framework/skynet/core/artifact/BranchManager.java
+++ b/plugins/org.eclipse.osee.framework.skynet.core/src/org/eclipse/osee/framework/skynet/core/artifact/BranchManager.java
@@ -27,7 +27,10 @@
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.IJobChangeEvent;
 import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.core.runtime.jobs.JobChangeAdapter;
 import org.eclipse.osee.framework.core.client.OseeClientProperties;
 import org.eclipse.osee.framework.core.data.ArtifactId;
 import org.eclipse.osee.framework.core.data.ArtifactToken;
@@ -333,23 +336,36 @@
       }
    }
 
-   public static void setArchiveState(BranchId branch, BranchArchivedState state) {
-      BranchEndpoint proxy = ServiceUtil.getOseeClient().getBranchEndpoint();
+   public static void archiveUnArchiveBranch(BranchId branch, BranchArchivedState state) {
+      ArchiveUnArchiveBranchJob archiveBranchJob;
+      boolean setArchived;
       if (state.isArchived()) {
-         Response response = proxy.archiveBranch(branch);
-         if (response.getStatus() == javax.ws.rs.core.Response.Status.OK.getStatusCode()) {
-            BranchManager.getBranch(branch).setArchived(true);
-            OseeEventManager.kickBranchEvent(BranchManager.class,
-               new BranchEvent(BranchEventType.ArchiveStateUpdated, branch));
-         }
+         archiveBranchJob = new ArchiveUnArchiveBranchJob("Archive Branch", BranchId.valueOf(branch.getId()),
+            ArchiveUnArchiveBranchJob.ArchiveType.ARCHIVE);
+         setArchived = true;
       } else {
-         Response response = proxy.unarchiveBranch(branch);
-         if (response.getStatus() == javax.ws.rs.core.Response.Status.OK.getStatusCode()) {
-            BranchManager.getBranch(branch).setArchived(false);
-            OseeEventManager.kickBranchEvent(BranchManager.class,
-               new BranchEvent(BranchEventType.ArchiveStateUpdated, branch));
-         }
+         archiveBranchJob = new ArchiveUnArchiveBranchJob("Unarchive Branch", BranchId.valueOf(branch.getId()),
+            ArchiveUnArchiveBranchJob.ArchiveType.UNARCHIVE);
+         setArchived = false;
       }
+      archiveBranchJob.addJobChangeListener(new JobChangeAdapter() {
+
+         @Override
+         public void done(IJobChangeEvent event) {
+            IStatus status = event.getResult();
+            if (status.equals(Status.OK_STATUS)) {
+               ArchiveUnArchiveBranchJob job = (ArchiveUnArchiveBranchJob) event.getJob();
+               Response response = job.getResponse();
+               if (response.getStatus() == javax.ws.rs.core.Response.Status.OK.getStatusCode()) {
+                  BranchManager.getBranch(branch).setArchived(setArchived);
+                  OseeEventManager.kickBranchEvent(this, new BranchEvent(BranchEventType.ArchiveStateUpdated, branch));
+               }
+            }
+         }
+      });
+      archiveBranchJob.setUser(true);
+      archiveBranchJob.setPriority(Job.LONG);
+      archiveBranchJob.schedule();
    }
 
    public static void setName(BranchId branch, String newBranchName) {
@@ -600,7 +616,6 @@
    public static void setAssociatedArtifactId(BranchId branch, ArtifactId artifactId) {
       OseeClient client = ServiceUtil.getOseeClient();
       BranchEndpoint proxy = client.getBranchEndpoint();
-
       Response response = proxy.associateBranchToArtifact(branch, artifactId);
       if (javax.ws.rs.core.Response.Status.OK.getStatusCode() == response.getStatus()) {
          getBranch(branch).setAssociatedArtifact(artifactId);
diff --git a/plugins/org.eclipse.osee.framework.skynet.core/src/org/eclipse/osee/framework/skynet/core/artifact/DeleteBranchOperation.java b/plugins/org.eclipse.osee.framework.skynet.core/src/org/eclipse/osee/framework/skynet/core/artifact/DeleteBranchOperation.java
index b7c278b..439145f 100644
--- a/plugins/org.eclipse.osee.framework.skynet.core/src/org/eclipse/osee/framework/skynet/core/artifact/DeleteBranchOperation.java
+++ b/plugins/org.eclipse.osee.framework.skynet.core/src/org/eclipse/osee/framework/skynet/core/artifact/DeleteBranchOperation.java
@@ -47,7 +47,7 @@
 
       try {
          BranchManager.setState(branch, BranchState.DELETE_IN_PROGRESS);
-         BranchManager.setArchiveState(branch, BranchArchivedState.ARCHIVED);
+         BranchManager.archiveUnArchiveBranch(branch, BranchArchivedState.ARCHIVED);
          OseeEventManager.kickBranchEvent(this, new BranchEvent(BranchEventType.Deleting, branch));
 
          BranchManager.setState(branch, BranchState.DELETED);
@@ -59,7 +59,7 @@
       } catch (Exception ex) {
          try {
             BranchManager.setState(branch, originalState);
-            BranchManager.setArchiveState(branch, BranchArchivedState.fromBoolean(originalArchivedState));
+            BranchManager.archiveUnArchiveBranch(branch, BranchArchivedState.fromBoolean(originalArchivedState));
          } catch (Exception ex2) {
             log(ex2);
          }
diff --git a/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/commandHandlers/branch/ArchiveBranchHandler.java b/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/commandHandlers/branch/ArchiveBranchHandler.java
index 6d26425..6f3ae6b 100644
--- a/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/commandHandlers/branch/ArchiveBranchHandler.java
+++ b/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/commandHandlers/branch/ArchiveBranchHandler.java
@@ -67,7 +67,7 @@
 
                for (BranchId branch : branches) {
                   BranchArchivedState state = BranchArchivedState.fromBoolean(!BranchManager.isArchived(branch));
-                  BranchManager.setArchiveState(branch, state);
+                  BranchManager.archiveUnArchiveBranch(branch, state);
                   OseeEventManager.kickBranchEvent(this, new BranchEvent(BranchEventType.Committed, branch));
                }
             }
diff --git a/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/util/PromptChangeUtil.java b/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/util/PromptChangeUtil.java
index 4e52794..fc85516 100644
--- a/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/util/PromptChangeUtil.java
+++ b/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/util/PromptChangeUtil.java
@@ -63,7 +63,7 @@
       if (result == 0) {
          BranchArchivedState state = ld.getSelection();
          for (TreeItem item : branches) {
-            BranchManager.setArchiveState((BranchId) item.getData(), state);
+            BranchManager.archiveUnArchiveBranch((BranchId) item.getData(), state);
          }
          return true;
       }
diff --git a/plugins/org.eclipse.osee.mail.api/src/org/eclipse/osee/mail/api/MailService.java b/plugins/org.eclipse.osee.mail.api/src/org/eclipse/osee/mail/api/MailService.java
index ef9633e..f453865 100644
--- a/plugins/org.eclipse.osee.mail.api/src/org/eclipse/osee/mail/api/MailService.java
+++ b/plugins/org.eclipse.osee.mail.api/src/org/eclipse/osee/mail/api/MailService.java
@@ -24,6 +24,10 @@
 
    MailStatus sendTestMessage();
 
+   String getAdminEmail();
+
+   String getReplyToEmail();
+
    Future<MailStatus> sendAsyncTestMessage();
 
    List<MailStatus> sendMessages(MailMessage... email);
diff --git a/plugins/org.eclipse.osee.mail/src/org/eclipse/osee/mail/internal/MailConfiguration.java b/plugins/org.eclipse.osee.mail/src/org/eclipse/osee/mail/internal/MailConfiguration.java
index 73d562c..2aa4ee7 100644
--- a/plugins/org.eclipse.osee.mail/src/org/eclipse/osee/mail/internal/MailConfiguration.java
+++ b/plugins/org.eclipse.osee.mail/src/org/eclipse/osee/mail/internal/MailConfiguration.java
@@ -17,6 +17,7 @@
 import static org.eclipse.osee.mail.internal.MailConstants.DEFAULT_MAIL_SERVER_HOST;
 import static org.eclipse.osee.mail.internal.MailConstants.DEFAULT_MAIL_SERVER_PASSWORD;
 import static org.eclipse.osee.mail.internal.MailConstants.DEFAULT_MAIL_SERVER_PORT;
+import static org.eclipse.osee.mail.internal.MailConstants.DEFAULT_MAIL_SERVER_REPLY_TO_EMAIL;
 import static org.eclipse.osee.mail.internal.MailConstants.DEFAULT_MAIL_SERVER_STATUS_WAIT_TIME_MILLIS;
 import static org.eclipse.osee.mail.internal.MailConstants.DEFAULT_MAIL_SERVER_TEST_EMAIL_BODY;
 import static org.eclipse.osee.mail.internal.MailConstants.DEFAULT_MAIL_SERVER_TEST_EMAIL_SUBJECT;
@@ -25,6 +26,7 @@
 import static org.eclipse.osee.mail.internal.MailConstants.MAIL_SERVER_HOST;
 import static org.eclipse.osee.mail.internal.MailConstants.MAIL_SERVER_PASSWORD;
 import static org.eclipse.osee.mail.internal.MailConstants.MAIL_SERVER_PORT;
+import static org.eclipse.osee.mail.internal.MailConstants.MAIL_SERVER_REPLY_TO_EMAIL;
 import static org.eclipse.osee.mail.internal.MailConstants.MAIL_SERVER_STATUS_WAIT_TIME_MILLIS;
 import static org.eclipse.osee.mail.internal.MailConstants.MAIL_SERVER_TEST_EMAIL_BODY;
 import static org.eclipse.osee.mail.internal.MailConstants.MAIL_SERVER_TEST_EMAIL_SUBJECT;
@@ -39,13 +41,13 @@
  *  host = "smtp.gmail.com;
  *  transport = "smpts";
  *  requireAuthentication = true;
- * 
+ *
  *  Yahoo Example:
  *  host = "smtp.mail.yahoo.com";
  *  transport = "smpts";
  *  requireAuthentication = true;
  * </pre>
- * 
+ *
  * @author Roberto E. Escobar
  */
 public class MailConfiguration {
@@ -56,6 +58,7 @@
    private int port;
    private String transport;
    private String adminEmail;
+   private String replyToEmail;
    private String testEmailSubject;
    private String testEmailBody;
    private long waitTimeInMillis;
@@ -92,6 +95,10 @@
       return adminEmail;
    }
 
+   public String getReplyToEmail() {
+      return replyToEmail;
+   }
+
    public String getTestEmailSubject() {
       return testEmailSubject;
    }
@@ -112,6 +119,7 @@
       data.port = this.port;
       data.transport = this.transport;
       data.adminEmail = this.adminEmail;
+      data.replyToEmail = this.replyToEmail;
       data.testEmailSubject = this.testEmailSubject;
       data.testEmailBody = this.testEmailBody;
       data.waitTimeInMillis = this.waitTimeInMillis;
@@ -142,6 +150,10 @@
       this.adminEmail = adminEmail;
    }
 
+   void setReplyToEmail(String replyToEmail) {
+      this.replyToEmail = replyToEmail;
+   }
+
    void setTestEmailSubject(String testEmailSubject) {
       this.testEmailSubject = testEmailSubject;
    }
@@ -156,7 +168,7 @@
 
    @Override
    public String toString() {
-      return "MailConfiguration [username=" + username + ", password=" + password + ", host=" + host + ", port=" + port + ", transport=" + transport + ", adminEmail=" + adminEmail + ", testEmailSubject=" + testEmailSubject + ", testEmailBody=" + testEmailBody + ", waitTimeInMillis=" + waitTimeInMillis + "]";
+      return "MailConfiguration [username=" + username + ", password=" + password + ", host=" + host + ", port=" + port + ", transport=" + transport + ", adminEmail=" + adminEmail + ", replyToEmail=" + replyToEmail + ", testEmailSubject=" + testEmailSubject + ", testEmailBody=" + testEmailBody + ", waitTimeInMillis=" + waitTimeInMillis + "]";
    }
 
    public static MailConfigurationBuilder newBuilder() {
@@ -186,6 +198,7 @@
          port(getInt(props, MAIL_SERVER_PORT, DEFAULT_MAIL_SERVER_PORT));
          transport(get(props, MAIL_SERVER_TRANSPORT, DEFAULT_MAIL_SERVER_TRANSPORT));
          adminEmail(get(props, MAIL_SERVER_ADMIN_EMAIL, DEFAULT_MAIL_SERVER_ADMIN_EMAIL));
+         replyToEmail(get(props, MAIL_SERVER_REPLY_TO_EMAIL, DEFAULT_MAIL_SERVER_REPLY_TO_EMAIL));
          testEmailSubject(get(props, MAIL_SERVER_TEST_EMAIL_SUBJECT, DEFAULT_MAIL_SERVER_TEST_EMAIL_SUBJECT));
          testEmailBody(get(props, MAIL_SERVER_TEST_EMAIL_BODY, DEFAULT_MAIL_SERVER_TEST_EMAIL_BODY));
          statusWaitTime(getLong(props, MAIL_SERVER_STATUS_WAIT_TIME_MILLIS, DEFAULT_MAIL_SERVER_STATUS_WAIT_TIME_MILLIS));
@@ -223,6 +236,11 @@
          return this;
       }
 
+      public MailConfigurationBuilder replyToEmail(String replyToEmail) {
+         config.setReplyToEmail(replyToEmail);
+         return this;
+      }
+
       public MailConfigurationBuilder testEmailSubject(String testMailSubject) {
          config.setTestEmailSubject(testMailSubject);
          return this;
@@ -257,5 +275,4 @@
          return toReturn;
       }
    }
-
 }
diff --git a/plugins/org.eclipse.osee.mail/src/org/eclipse/osee/mail/internal/MailConstants.java b/plugins/org.eclipse.osee.mail/src/org/eclipse/osee/mail/internal/MailConstants.java
index c86c8e9..800608f 100644
--- a/plugins/org.eclipse.osee.mail/src/org/eclipse/osee/mail/internal/MailConstants.java
+++ b/plugins/org.eclipse.osee.mail/src/org/eclipse/osee/mail/internal/MailConstants.java
@@ -34,6 +34,7 @@
    public static final String MAIL_SERVER_PORT = qualify("port");
    public static final String MAIL_SERVER_TRANSPORT = qualify("transport");
    public static final String MAIL_SERVER_ADMIN_EMAIL = qualify("admin.email");
+   public static final String MAIL_SERVER_REPLY_TO_EMAIL = qualify("reply.to.email");
    public static final String MAIL_SERVER_TEST_EMAIL_SUBJECT = qualify("test.email.subject");
    public static final String MAIL_SERVER_TEST_EMAIL_BODY = qualify("test.email.body");
    public static final String MAIL_SERVER_STATUS_WAIT_TIME_MILLIS = qualify("status.wait.time");
@@ -44,6 +45,7 @@
    public static final int DEFAULT_MAIL_SERVER_PORT = 25;
    public static final String DEFAULT_MAIL_SERVER_TRANSPORT = "smtp";
    public static final String DEFAULT_MAIL_SERVER_ADMIN_EMAIL = null;
+   public static final String DEFAULT_MAIL_SERVER_REPLY_TO_EMAIL = null;
    public static final String DEFAULT_MAIL_SERVER_TEST_EMAIL_SUBJECT = "Test Email";
    public static final String DEFAULT_MAIL_SERVER_TEST_EMAIL_BODY = "This is a test email sent from OSEE Mail Service";
    public static final long DEFAULT_MAIL_SERVER_STATUS_WAIT_TIME_MILLIS = 60L * 1000L;
diff --git a/plugins/org.eclipse.osee.mail/src/org/eclipse/osee/mail/internal/MailServiceImpl.java b/plugins/org.eclipse.osee.mail/src/org/eclipse/osee/mail/internal/MailServiceImpl.java
index 464458e..6022607 100644
--- a/plugins/org.eclipse.osee.mail/src/org/eclipse/osee/mail/internal/MailServiceImpl.java
+++ b/plugins/org.eclipse.osee.mail/src/org/eclipse/osee/mail/internal/MailServiceImpl.java
@@ -152,4 +152,14 @@
    private Callable<MailStatus> newSendCallable(MailMessage mail) {
       return new SendMailCallable(config, factory, mail);
    }
-}
\ No newline at end of file
+
+   @Override
+   public String getAdminEmail() {
+      return config.getAdminEmail();
+   }
+
+   @Override
+   public String getReplyToEmail() {
+      return config.getReplyToEmail();
+   }
+}
diff --git a/plugins/org.eclipse.osee.orcs.core/src/org/eclipse/osee/orcs/core/internal/access/UserGroupImpl.java b/plugins/org.eclipse.osee.orcs.core/src/org/eclipse/osee/orcs/core/internal/access/UserGroupImpl.java
index 242e80a..198b3c8 100644
--- a/plugins/org.eclipse.osee.orcs.core/src/org/eclipse/osee/orcs/core/internal/access/UserGroupImpl.java
+++ b/plugins/org.eclipse.osee.orcs.core/src/org/eclipse/osee/orcs/core/internal/access/UserGroupImpl.java
@@ -13,17 +13,21 @@
 
 package org.eclipse.osee.orcs.core.internal.access;
 
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.List;
 import org.eclipse.osee.framework.core.data.ArtifactToken;
 import org.eclipse.osee.framework.core.data.ArtifactTypeToken;
 import org.eclipse.osee.framework.core.data.BranchId;
 import org.eclipse.osee.framework.core.data.IRelationLink;
+import org.eclipse.osee.framework.core.data.IUserGroupArtifactToken;
+import org.eclipse.osee.framework.core.data.UserGroupArtifactToken;
 import org.eclipse.osee.framework.core.data.UserId;
 import org.eclipse.osee.framework.core.data.UserToken;
 import org.eclipse.osee.framework.core.enums.CoreArtifactTypes;
+import org.eclipse.osee.framework.core.enums.CoreAttributeTypes;
 import org.eclipse.osee.framework.core.enums.CoreRelationTypes;
 import org.eclipse.osee.framework.core.util.AbstractUserGroupImpl;
-import org.eclipse.osee.framework.jdk.core.util.Collections;
 import org.eclipse.osee.framework.jdk.core.util.Conditions;
 import org.eclipse.osee.orcs.data.ArtifactReadable;
 
@@ -91,11 +95,27 @@
    @Override
    public Collection<UserToken> getMembers() {
       checkGroupExists();
-      return Collections.castAll(getArtifact().getRelated(CoreRelationTypes.Users_User).getList());
+      List<UserToken> users = new ArrayList<UserToken>();
+      for (ArtifactReadable userArt : getArtifact().getRelated(CoreRelationTypes.Users_User).getList()) {
+         String name = userArt.getName();
+         String email = userArt.getSoleAttributeValue(CoreAttributeTypes.Email);
+         String userId = userArt.getSoleAttributeValue(CoreAttributeTypes.UserId);
+         boolean active = userArt.getSoleAttributeValue(CoreAttributeTypes.Active);
+         List<IUserGroupArtifactToken> roles = new ArrayList<IUserGroupArtifactToken>();
+         for (ArtifactReadable userGroupArt : userArt.getRelated(CoreRelationTypes.Users_Artifact).getList()) {
+            IUserGroupArtifactToken userGroup =
+               UserGroupArtifactToken.valueOf(userGroupArt.getId(), userGroupArt.getName());
+            roles.add(userGroup);
+         }
+         UserToken userToken = UserToken.create(userArt.getId(), name, email, userId, active,
+            roles.toArray(new IUserGroupArtifactToken[roles.size()]));
+         users.add(userToken);
+      }
+      return users;
    }
 
    @Override
    public BranchId getBranch() {
       return getArtifact().getBranch();
    }
-}
\ No newline at end of file
+}
diff --git a/plugins/org.eclipse.osee.orcs.rest.client/META-INF/MANIFEST.MF b/plugins/org.eclipse.osee.orcs.rest.client/META-INF/MANIFEST.MF
index 420dec2..f3781b2 100644
--- a/plugins/org.eclipse.osee.orcs.rest.client/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.osee.orcs.rest.client/META-INF/MANIFEST.MF
@@ -20,6 +20,7 @@
  org.eclipse.osee.framework.jdk.core.util,
  org.eclipse.osee.framework.server.ide.api,
  org.eclipse.osee.framework.server.ide.api.client,
+ org.eclipse.osee.mail.api,
  org.eclipse.osee.orcs.rest.model,
  org.eclipse.osee.orcs.rest.model.search.artifact
 Export-Package: org.eclipse.osee.orcs.rest.client
diff --git a/plugins/org.eclipse.osee.orcs.rest.client/src/org/eclipse/osee/orcs/rest/client/OseeClient.java b/plugins/org.eclipse.osee.orcs.rest.client/src/org/eclipse/osee/orcs/rest/client/OseeClient.java
index 12904fc..2eb0c88 100644
--- a/plugins/org.eclipse.osee.orcs.rest.client/src/org/eclipse/osee/orcs/rest/client/OseeClient.java
+++ b/plugins/org.eclipse.osee.orcs.rest.client/src/org/eclipse/osee/orcs/rest/client/OseeClient.java
@@ -23,6 +23,7 @@
 import org.eclipse.osee.framework.core.data.TransactionId;
 import org.eclipse.osee.framework.server.ide.api.SessionEndpoint;
 import org.eclipse.osee.framework.server.ide.api.client.ClientEndpoint;
+import org.eclipse.osee.mail.api.MailEndpoint;
 import org.eclipse.osee.orcs.rest.model.ApplicabilityEndpoint;
 import org.eclipse.osee.orcs.rest.model.ApplicabilityUiEndpoint;
 import org.eclipse.osee.orcs.rest.model.ArtifactEndpoint;
@@ -73,9 +74,10 @@
 
    DefineBranchEndpointApi getDefineBranchEndpoint();
 
+   MailEndpoint getMailEndpoint();
+
    SessionEndpoint getSessionEndpoint();
 
    @Deprecated
    String loadAttributeValue(Integer attrId, TransactionId transactionId, ArtifactToken artifact);
-
-}
\ No newline at end of file
+}
diff --git a/plugins/org.eclipse.osee.orcs.rest.client/src/org/eclipse/osee/orcs/rest/client/internal/OseeClientImpl.java b/plugins/org.eclipse.osee.orcs.rest.client/src/org/eclipse/osee/orcs/rest/client/internal/OseeClientImpl.java
index 392c75f..36098c3 100644
--- a/plugins/org.eclipse.osee.orcs.rest.client/src/org/eclipse/osee/orcs/rest/client/internal/OseeClientImpl.java
+++ b/plugins/org.eclipse.osee.orcs.rest.client/src/org/eclipse/osee/orcs/rest/client/internal/OseeClientImpl.java
@@ -30,6 +30,7 @@
 import org.eclipse.osee.framework.jdk.core.util.Conditions;
 import org.eclipse.osee.framework.server.ide.api.SessionEndpoint;
 import org.eclipse.osee.framework.server.ide.api.client.ClientEndpoint;
+import org.eclipse.osee.mail.api.MailEndpoint;
 import org.eclipse.osee.orcs.rest.client.OseeClient;
 import org.eclipse.osee.orcs.rest.client.QueryBuilder;
 import org.eclipse.osee.orcs.rest.client.internal.search.PredicateFactory;
@@ -180,6 +181,11 @@
    public DefineBranchEndpointApi getDefineBranchEndpoint() {
       return getDefineEndpoint(DefineBranchEndpointApi.class);
    }
+   
+   @Override
+   public MailEndpoint getMailEndpoint() {
+      return getOrcsEndpoint(MailEndpoint.class);
+   }
 
    private <T> T getOrcsBranchEndpoint(Class<T> clazz, BranchId branch) {
       return jaxRsApi().newProxy("orcs/branch/" + branch.getIdString(), clazz);
diff --git a/plugins/org.eclipse.osee.orcs.rest/META-INF/MANIFEST.MF b/plugins/org.eclipse.osee.orcs.rest/META-INF/MANIFEST.MF
index 5746bdf..f1fe5d6 100644
--- a/plugins/org.eclipse.osee.orcs.rest/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.osee.orcs.rest/META-INF/MANIFEST.MF
@@ -44,6 +44,7 @@
  org.eclipse.osee.jaxrs,
  org.eclipse.osee.jaxrs.mvc,
  org.eclipse.osee.jdbc,
+ org.eclipse.osee.mail.api,
  org.eclipse.osee.orcs,
  org.eclipse.osee.orcs.core.ds,
  org.eclipse.osee.orcs.data,
diff --git a/plugins/org.eclipse.osee.orcs.rest/OSGI-INF/orcs.support.email.service.xml b/plugins/org.eclipse.osee.orcs.rest/OSGI-INF/orcs.support.email.service.xml
new file mode 100644
index 0000000..5c29055
--- /dev/null
+++ b/plugins/org.eclipse.osee.orcs.rest/OSGI-INF/orcs.support.email.service.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" activate="start">
+   <implementation class="org.eclipse.osee.orcs.rest.internal.email.SupportEmailService"/>
+<reference bind="setMailService" cardinality="1..1" interface="org.eclipse.osee.mail.api.MailService" name="MailService" policy="static"/>
+<reference bind="setOrcsApi" cardinality="1..1" interface="org.eclipse.osee.orcs.OrcsApi" name="OrcsApi" policy="static"/>
+</scr:component>
diff --git a/plugins/org.eclipse.osee.orcs.rest/src/org/eclipse/osee/orcs/rest/internal/BranchEndpointImpl.java b/plugins/org.eclipse.osee.orcs.rest/src/org/eclipse/osee/orcs/rest/internal/BranchEndpointImpl.java
index 3e2dd7c..306a0cb 100644
--- a/plugins/org.eclipse.osee.orcs.rest/src/org/eclipse/osee/orcs/rest/internal/BranchEndpointImpl.java
+++ b/plugins/org.eclipse.osee.orcs.rest/src/org/eclipse/osee/orcs/rest/internal/BranchEndpointImpl.java
@@ -30,6 +30,7 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.Callable;
+import java.util.logging.Level;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.POST;
 import javax.ws.rs.Path;
@@ -87,6 +88,7 @@
 import org.eclipse.osee.orcs.data.CreateBranchData;
 import org.eclipse.osee.orcs.data.TransactionReadable;
 import org.eclipse.osee.orcs.rest.internal.branch.UpdateBranchOperation;
+import org.eclipse.osee.orcs.rest.internal.email.SupportEmailService;
 import org.eclipse.osee.orcs.rest.model.BranchCommitOptions;
 import org.eclipse.osee.orcs.rest.model.BranchEndpoint;
 import org.eclipse.osee.orcs.rest.model.BranchExportOptions;
@@ -110,6 +112,7 @@
    private final IResourceManager resourceManager;
    private final ActivityLog activityLog;
    private final OrcsBranch branchOps;
+   private final SupportEmailService supportEmailService;
 
    @Context
    private UriInfo uriInfo;
@@ -122,6 +125,7 @@
       this.resourceManager = resourceManager;
       this.activityLog = activityLog;
       this.branchOps = orcsApi.getBranchOps();
+      this.supportEmailService = new SupportEmailService();
    }
 
    public HttpHeaders getHeaders() {
@@ -413,11 +417,17 @@
    @Override
    public Response archiveBranch(BranchId branchId) {
       Branch branch = getBranchById(branchId);
-
       boolean modified = false;
       if (!branch.isArchived()) {
-         Callable<?> op = branchOps.archiveUnarchiveBranch(branch, ArchiveOperation.ARCHIVE);
-         executeCallable(op);
+         try {
+            Callable<?> op = branchOps.archiveUnarchiveBranch(branch, ArchiveOperation.ARCHIVE);
+            executeCallable(op);
+         } catch (Exception ex) {
+            supportEmailService.sendSupportEmail("Exception caught during archival of branch " + branchId.getIdString(),
+               ex.getLocalizedMessage());
+            OseeLog.log(ActivityLog.class, Level.SEVERE, ex);
+            return asResponse(modified);
+         }
          modified = true;
          try {
             activityLog.createEntry(BRANCH_OPERATION, ActivityLog.INITIAL_STATUS,
@@ -430,6 +440,32 @@
    }
 
    @Override
+   public Response unarchiveBranch(BranchId branchId) {
+      Branch branch = getBranchById(branchId);
+
+      boolean modified = false;
+      if (branch.isArchived()) {
+         try {
+            Callable<?> op = branchOps.archiveUnarchiveBranch(branch, ArchiveOperation.UNARCHIVE);
+            executeCallable(op);
+         } catch (Exception ex) {
+            supportEmailService.sendSupportEmail(
+               "Exception caught during unarchival of branch " + branchId.getIdString(), ex.getLocalizedMessage());
+            OseeLog.log(ActivityLog.class, Level.SEVERE, ex);
+            return asResponse(modified);
+         }
+         modified = true;
+         try {
+            activityLog.createEntry(BRANCH_OPERATION, ActivityLog.INITIAL_STATUS,
+               String.format("Branch Operation Unarchive Branch {branchId: %s}", branchId));
+         } catch (OseeCoreException ex) {
+            OseeLog.log(ActivityLog.class, OseeLevel.SEVERE_POPUP, ex);
+         }
+      }
+      return asResponse(modified);
+   }
+
+   @Override
    public Response writeTx(BranchId branch, NewTransaction data) {
       String comment = data.getComment();
 
@@ -725,25 +761,6 @@
    }
 
    @Override
-   public Response unarchiveBranch(BranchId branchId) {
-      Branch branch = getBranchById(branchId);
-
-      boolean modified = false;
-      if (branch.isArchived()) {
-         Callable<?> op = branchOps.archiveUnarchiveBranch(branch, ArchiveOperation.UNARCHIVE);
-         executeCallable(op);
-         modified = true;
-         try {
-            activityLog.createEntry(BRANCH_OPERATION, ActivityLog.INITIAL_STATUS,
-               String.format("Branch Operation Unarchive Branch {branchId: %s}", branchId));
-         } catch (OseeCoreException ex) {
-            OseeLog.log(ActivityLog.class, OseeLevel.SEVERE_POPUP, ex);
-         }
-      }
-      return asResponse(modified);
-   }
-
-   @Override
    public Response unCommitBranch(BranchId branch, BranchId destinationBranch) {
       throw new UnsupportedOperationException("Not yet implemented");
    }
@@ -924,4 +941,4 @@
       rel.setTypeId(chStmt.getString("rel_link_type_id"));
       return rel;
    }
-}
\ No newline at end of file
+}
diff --git a/plugins/org.eclipse.osee.orcs.rest/src/org/eclipse/osee/orcs/rest/internal/branch/UpdateBranchOperation.java b/plugins/org.eclipse.osee.orcs.rest/src/org/eclipse/osee/orcs/rest/internal/branch/UpdateBranchOperation.java
index 71e08ac..7f7977a 100644
--- a/plugins/org.eclipse.osee.orcs.rest/src/org/eclipse/osee/orcs/rest/internal/branch/UpdateBranchOperation.java
+++ b/plugins/org.eclipse.osee.orcs.rest/src/org/eclipse/osee/orcs/rest/internal/branch/UpdateBranchOperation.java
@@ -27,8 +27,6 @@
 public class UpdateBranchOperation {
    private final BranchId toBranchId;
    private final BranchId fromBranchId;
-   private final String toName;
-   private final String fromName;
    private final ArtifactId author;
    private final UpdateBranchData branchData;
    private final OrcsApi orcsApi;
@@ -38,8 +36,6 @@
       this.toBranchId = branchData.getToBranch();
       this.fromBranchId = branchData.getFromBranch();
       this.author = branchData.getAuthor();
-      this.toName = branchData.getToName();
-      this.fromName = branchData.getFromName();
       this.branchData = branchData;
    }
 
diff --git a/plugins/org.eclipse.osee.orcs.rest/src/org/eclipse/osee/orcs/rest/internal/email/SupportEmailService.java b/plugins/org.eclipse.osee.orcs.rest/src/org/eclipse/osee/orcs/rest/internal/email/SupportEmailService.java
new file mode 100644
index 0000000..f2b853f
--- /dev/null
+++ b/plugins/org.eclipse.osee.orcs.rest/src/org/eclipse/osee/orcs/rest/internal/email/SupportEmailService.java
@@ -0,0 +1,75 @@
+/*********************************************************************
+ * Copyright (c) 2021 Boeing
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Boeing - initial API and implementation
+ **********************************************************************/
+
+package org.eclipse.osee.orcs.rest.internal.email;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import org.eclipse.osee.framework.core.data.IUserGroup;
+import org.eclipse.osee.framework.core.data.UserToken;
+import org.eclipse.osee.framework.core.enums.CoreUserGroups;
+import org.eclipse.osee.framework.core.util.MailStatus;
+import org.eclipse.osee.framework.jdk.core.util.EmailUtil;
+import org.eclipse.osee.mail.api.MailMessage;
+import org.eclipse.osee.mail.api.MailMessage.MailMessageBuilder;
+import org.eclipse.osee.mail.api.MailService;
+import org.eclipse.osee.orcs.OrcsApi;
+
+/**
+ * @author Dominic Guss
+ */
+public class SupportEmailService {
+
+   private static MailService mailService;
+   private static OrcsApi orcsApi;
+
+   public SupportEmailService() {
+      // Default constructor required. Do nothing
+   }
+
+   public void setOrcsApi(OrcsApi orcsApi) {
+      SupportEmailService.orcsApi = orcsApi;
+   }
+
+   public void setMailService(MailService mailService) {
+      SupportEmailService.mailService = mailService;
+   }
+
+   public List<MailStatus> sendSupportEmail(String subject, String msg) {
+      List<String> recipients = new ArrayList<String>();
+      IUserGroup oseeSupportGroup = orcsApi.getUserGroupService().getUserGroup(CoreUserGroups.OseeSupport);
+      Collection<UserToken> members = oseeSupportGroup.getMembers();
+
+      String email;
+      for (UserToken token : members) {
+         email = token.getEmail();
+         if (EmailUtil.isEmailValid(email)) {
+            recipients.add(email);
+         }
+      }
+
+      List<MailStatus> status = null;
+      if (!recipients.isEmpty()) {
+         MailMessageBuilder builder = MailMessage.newBuilder();
+         builder.addText(msg);
+         builder.subject(subject);
+         builder.replyTo(mailService.getReplyToEmail());
+         builder.from(mailService.getAdminEmail());
+         builder.recipients(recipients);
+         MailMessage message = builder.build();
+         status = mailService.sendMessages(message);
+      }
+      return status;
+   }
+}