docs: protected BeanO doActivation(EJBThreadData threadData, ContainerTx tx, BeanId beanId,
                                   boolean takeInvocationRef)
                      throws RemoteException
      {
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
              Tr.entry(tc, "doActivation",
                       new Object[] { tx, beanId,
                                     new Boolean(takeInvocationRef) });
          }
  
          BeanO bean = null;
          Throwable exception = null;
          MasterKey key = new MasterKey(beanId);
          boolean activate = false;
          boolean pushedCallbackBeanO = false;
  
          try {
  
              synchronized (locks.getLock(key)) {
  
                  if ((bean = (BeanO) cache.find(key)) == null)
                  {
                      if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
                          Tr.debug(tc, "Bean not in cache");
  
                      bean = beanId.getHome().createBeanO(threadData, tx, beanId); // d630940
                      pushedCallbackBeanO = true;
                      cache.insert(key, bean);
                      bean.ivCacheKey = key; // d199233
                      activate = true;
                  }
                  else
                  {
                      if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
                          Tr.debug(tc, "Found bean in cache");
  
                      // Set the found BeanO as the 'Callback' BeanO, as this is the
                      // BeanO that is becoming the active beanO for the thread.
                      // This will allow methods called by customer code (like Timer
                      // methods) to determine the state of the BeanO that is making
                      // the call.                                              d168509
                      threadData.pushCallbackBeanO(bean); // d630940
                      pushedCallbackBeanO = true;
                  }
              }
  
              boolean pin = false;
  
              if (activate) {
                  bean.activate(beanId, tx); // d114677
              }
  
              pin = bean.enlist(tx); // d114677
  
              if (takeInvocationRef && pin) {
                  // We need to take an additional reference
                  cache.pin(key);
              } else if (!takeInvocationRef && !pin) {
                  // Need to drop reference taken by find or insert
                  cache.unpin(key);
              }
  
          } catch (RemoteException e) {
  
              FFDCFilter.processException(e, CLASS_NAME + ".doActivation", "123", this);
              exception = e;
              throw e;
  
          } catch (RuntimeException e) {
  
              FFDCFilter.processException(e, CLASS_NAME + ".doActivation", "129", this);
              exception = e;
              throw e;
  
          } finally {
  
              if (exception != null) {
                  if (TraceComponent.isAnyTracingEnabled() && tc.isEventEnabled())
                      Tr.event(tc, "doActivation: exception raised", exception);
              }
  
              if (exception != null && bean != null)
              {
                  if (pushedCallbackBeanO)
                  {
                      threadData.popCallbackBeanO();
                  }
  
                  bean.destroy();
  
                  if (activate) {
                      // Synchronize to insure that a temp pin obtained by getBean
                      // doesn't cause the remove to fail due to too many pins. PQ53065
                      synchronized (locks.getLock(key)) {
                          cache.remove(key, true);
                          bean.ivCacheKey = null; // d199233
                      }
                  }
              }
  
              if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
                  Tr.exit(tc, "doActivation", bean);
          }
  
          return bean;
      }