docs: public static final void getAnnotationsForSecurity(Method[] beanMethods,
                                                         ArrayList<String>[] rolesAllowed,
                                                         boolean[] denyAll,
                                                         boolean[] permitAll)
                      throws EJBConfigurationException
      {
          final boolean isTraceOn = TraceComponent.isAnyTracingEnabled();
          if (isTraceOn && tc.isEntryEnabled())
              Tr.entry(tc, "getAnnotationsForSecurity");
  
          // Check for security annotations @PermitAll, @DenyAll, and @RolesAllowed
          // The following rules apply:
          // 1. If a method has been defined in XML to permit all access or deny
          //    all access, then we do not need to look at annotations at all.
          // 2. Any role defined in XML will override any roles defined in
          //    annotations at either the class or method level.  So
          //    the values contained in the @RolesAllowed annotations will only
          //    be used for a method if no roles are yet defined for that method
          //    via XML.
          // 3. Roles defined within XML will remain in affect regardless of
          //    any annotations defined.
          //
          // Also, from the "Common Annotations for Java" Specification: JSR 250
          // 1. PermitAll, DenyAll and RolesAllowed annotations MUST NOT be applied
          //    on the same method or class.
          // 2. If PermitAll is applied at the class level and RolesAllowed or
          //    DenyAll are applied on methods of the same class, then the method
          //    level annotations take precedence over the class level annotation.
          // 3. If DenyAll is specified at the class level and PermitAll or
          //    RolesAllowed are specified on methods of the same class, then
          //    the method level annotation takes precedence over the class level
          //    annotation.
          // 4. If RolesAllowed is specified at the class level and PermitAll
          //    or DenyAll are specified on methods, then the method level annotation
          //    takes precedence over the class level annotation.
          //
          // Also: The RolesAllowed annotation can be specified on a class or on method(s).
          // Specifying it at a class level means that it applies to all the methods in
          // the class. Specifying it on a method means that it is applicable to that
          // method only. If applied at both the class and method level, the method value
          // overrides the class value.
          //
          for (int i = 0; i < beanMethods.length; i++)
          {
              RolesAllowed classRolesAllowed = null;
              RolesAllowed methRolesAllowed = null;
              DenyAll classDenyAll = null; // F743-21028
              DenyAll methDenyAll = null;
              PermitAll classPermitAll = null;
              PermitAll methPermitAll = null;
              Method beanMethod = beanMethods[i];
  
              if (beanMethod != null) {
  
                  if (isTraceOn && tc.isDebugEnabled()) {
                      Tr.debug(tc, "Processing method: " + beanMethod.getName());
                  }
                  // Is Security Policy information defined in XML?.
                  if ((denyAll[i]) || (permitAll[i]) || (rolesAllowed[i] != null)) {
                      if (isTraceOn && tc.isDebugEnabled())
                          Tr.debug(tc, "DenyAll, PermitAll, or Roles already set in XML.");
                      continue;
                  }
  
                  // Process DenyAll - can be either method or class level, but the
                  // class-level version can be overridden by @PermitAll or
                  // @RolesAllowed at the method-level, so only the method-level
                  // will be evaluated here.
                  methDenyAll = beanMethod.getAnnotation(DenyAll.class);
                  if (methDenyAll != null) {
                      if (isTraceOn && tc.isDebugEnabled())
                          Tr.debug(tc, "DenyAll annotation set: " + methDenyAll.toString());
                      denyAll[i] = true;
                  }
  
                  // PermitAll can be at either method or class level,
                  // but the class-level version can be overridden by @RolesAllowed
                  // at the method-level.  So this point we will only look for
                  // @PermitAll at the method-level.
                  methPermitAll = beanMethod.getAnnotation(PermitAll.class);
                  if (methPermitAll != null) {
                      if (isTraceOn && tc.isDebugEnabled()) {
                          Tr.debug(tc, "PermitAll annotation set: " + methPermitAll.toString());
                      }
                      if (methDenyAll != null) {
                          Tr.error(tc, "CONFLICTING_ANNOTATIONS_CONFIGURED_ON_METHOD_CNTR0150E",
                                   new Object[] { "@PermitAll", "@DenyAll", beanMethod.getName(), beanMethod.getDeclaringClass().getName() });
                          throw new EJBConfigurationException("@DenyAll and @PermitAll annotations are both set on class:  " +
                                                              beanMethod.getDeclaringClass().getName() +
                                                              " method: " + beanMethod.getName());
                      }
                      permitAll[i] = true;
                  }
  
                  // Check for @RolesAllowed at the method.
                  methRolesAllowed = beanMethod.getAnnotation(RolesAllowed.class);
                  if (methRolesAllowed != null)
                  {
                      if (isTraceOn && tc.isDebugEnabled())
                          Tr.debug(tc, "Method-level RolsAllowed annotation set. ");
  
                      if ((methDenyAll != null)) {
                          Tr.error(tc, "CONFLICTING_ANNOTATIONS_CONFIGURED_ON_METHOD_CNTR0150E",
                                   new Object[] { "@RolesAllowed", "@DenyAll", beanMethod.getName(), beanMethod.getDeclaringClass().getName() });
                          throw new EJBConfigurationException("@RolesAllowed and @DenyAll annotations are both set on class:  " +
                                                              beanMethod.getDeclaringClass().getName() + " method: " + beanMethod.getName());
                      } else if (methPermitAll != null) {
                          Tr.error(tc, "CONFLICTING_ANNOTATIONS_CONFIGURED_ON_METHOD_CNTR0150E",
                                   new Object[] { "RolesAllowed", "@PermitAll", beanMethod.getName(), beanMethod.getDeclaringClass().getName() });
                          throw new EJBConfigurationException("@RolesAllowed and @PermitAll annotations are both set on class:  " +
                                                              beanMethod.getDeclaringClass().getName() +
                                                              " method: " + beanMethod.getName());
                      }
  
                      rolesAllowed[i] = new ArrayList<String>();
                      for (String role : methRolesAllowed.value()) {
                          if (isTraceOn && tc.isDebugEnabled())
                              Tr.debug(tc, "Adding role: " + role);
  
                          // Duplicate roles are not allowed.
                          boolean roleAdded = rolesAllowed[i].add(role);
                          if (!roleAdded) {
                              Tr.error(tc, "DUPLICATE_ROLES_SPECIFIED_IN_METHOD_ANNOTATION_CNTR0151E",
                                       new Object[] { role, beanMethod.getName(), beanMethod.getDeclaringClass().getName() });
                              throw new EJBConfigurationException("Role: " + role + " is defined multiple times on the @RolesAllowed annotation for class: " +
                                                                  beanMethod.getDeclaringClass().getName() +
                                                                  " method: " + beanMethod.getName());
                          }
  
                      } // for (String role : methRolesAllowed.value())
                  } // if (methRolesAllowed != null)
  
                  // Get role values from class level.
                  // These are only valid if nothing has been set at the method level
                  // already.  We have to check these for each method because methods
                  // might be inherited and only the class annotations from the declaring
                  // class will be applicable for this particular method.
                  if ((methRolesAllowed == null) &&
                      (methDenyAll == null) &&
                      (methPermitAll == null))
                  {
                      classRolesAllowed = beanMethod.getDeclaringClass().getAnnotation(RolesAllowed.class);
                      classPermitAll = beanMethod.getDeclaringClass().getAnnotation(PermitAll.class);
                      classDenyAll = beanMethod.getDeclaringClass().getAnnotation(DenyAll.class); // F743-21028
  
                      // Must not be more than one of @DenyAll, @PermitAll or
                      // @RolesAllowed set at class level.                   F743-21028
                      String conflict1 = null, conflict2 = null;
                      if (classRolesAllowed != null)
                      {
                          if (classPermitAll != null)
                          {
                              conflict1 = "@RolesAllowed";
                              conflict2 = "@PermitAll";
                          }
                          else if (classDenyAll != null)
                          {
                              conflict1 = "@RolesAllowed";
                              conflict2 = "@DenyAll";
                          }
                      }
                      else if (classPermitAll != null && classDenyAll != null)
                      {
                          conflict1 = "@PermitAll";
                          conflict2 = "@DenyAll";
                      }
  
                      if (conflict1 != null)
                      {
                          Tr.error(tc, "CONFLICTING_ANNOTATIONS_CONFIGURED_ON_CLASS_CNTR0152E",
                                   new Object[] { conflict1, conflict2, beanMethod.getDeclaringClass().getName() });
                          throw new EJBConfigurationException(conflict1 + " and " + conflict2 +
                                                              " must not both be set on class level annotation" +
                                                              " of class: " +
                                                              beanMethod.getDeclaringClass().getName());
                      }
  
                      if (classRolesAllowed != null)
                      {
                          if (isTraceOn && tc.isDebugEnabled())
                              Tr.debug(tc, "Class RolesAllowed annotation set: ");
  
                          rolesAllowed[i] = new ArrayList<String>();
  
                          for (String role : classRolesAllowed.value()) {
                              boolean roleAdded = rolesAllowed[i].add(role);
                              // Duplicate Roles will not be allowed.
                              if (!roleAdded) {
                                  Tr.error(tc, "DUPLICATE_ROLES_SPECIFIED_IN_CLASS_ANNOTATION_CNTR0153E",
                                           new Object[] { role, beanMethod.getDeclaringClass().getName() });
                                  throw new EJBConfigurationException("Role: " + role + " is defined multiple times on the @RolesAllowed class level annotation of class: " +
                                                                      beanMethod.getDeclaringClass().getName());
                              }
  
                          } // for (String role : classRolesAllowed.value())
  
                      } //if ((methRolesAllowed == null) &&
  
                      if (classPermitAll != null) {
                          if (isTraceOn && tc.isDebugEnabled())
                              Tr.debug(tc, "Class PermitAll annotation set: ");
                          permitAll[i] = true;
                      }
  
                      else if (classDenyAll != null) // F743-21028
                      {
                          if (isTraceOn && tc.isDebugEnabled())
                              Tr.debug(tc, "Class DenyAll annotation set");
                          denyAll[i] = true;
                      }
  
                  } // if ((methRolesAllowed == null) &&
  
              } //if (beanMethod != null)
  
              if (isTraceOn && tc.isDebugEnabled())
              {
                  String methodName = "Unknown";
                  if (beanMethods[i] != null) {
                      methodName = beanMethods[i].getName();
                  }
                  Tr.debug(tc, methodName + " denyAll:  " + denyAll[i]);
                  Tr.debug(tc, methodName + " permitAll:  " + permitAll[i]);
                  if (rolesAllowed[i] == null) {
                      Tr.debug(tc, methodName + " roles:  null");
                  } else {
                      Tr.debug(tc, methodName + " roles:  " +
                                   Arrays.toString(rolesAllowed[i].toArray()));
                  }
              }
  
          } // for (int i = 0; i < beanMethods.length; i++)
  
          if (isTraceOn && tc.isEntryEnabled()) {
              Tr.exit(tc, "getAnnotationsForSecurity");
          }
  
      }