protected <T> Subject createSubject(final SudoAction<T> c) {
        Subject s = c.getSubject();
        
        if(s == null) {
            final Set<Object> credsPrivate = new LinkedHashSet<Object>();
            final Set<Object> credsPublic = new LinkedHashSet<Object>();
            final Set<Principal> principals = new LinkedHashSet<Principal>();
            
            if(c.getCallerPrincipal() != null) {
                principals.add(c.getCallerPrincipal());
            }

            if(c.getGroups() != null) {
                principals.addAll(Arrays.asList(c.getGroups()));
            }

            switch(c.getType()) {
                case USERNAME_PASSWORD: {
                    if(log.isLoggable(Level.FINE)) {
                        log.log(Level.FINE, "[SUDO] Request: {0} (username={1}, password=********, realm={2})",
                                new Object[]{c.getType().name(), c.getUsername(), c.getRealm()});
                    }

                    PasswordCredential pwd = new PasswordCredential(
                            c.getUsername(),
                            c.getPassword(),
                            c.getRealm());

                    credsPrivate.add(pwd);
                    break;
                }
                case CLIENT_CERT: {
                    if(log.isLoggable(Level.FINE)) {
                        log.log(Level.FINE, "[SUDO] Request: {0} (cert-chain-length={1}, alias={2}, realm={3})",
                                new Object[]{c.getType().name(), c.getCertChain().length, c.getAlias(), c.getRealm()});
                    }

                    X509CertificateCredential cert = new X509CertificateCredential(
                            c.getCertChain(),
                            c.getAlias(),
                            c.getRealm());

                    credsPrivate.add(cert);
                    break;
                }
                default:
                    throw new IllegalArgumentException(
                            "[SUDO] Illegal return value for SudoAction.getType() --> "
                            + c.getType());
            }

            s = new Subject(false, principals, credsPublic, credsPrivate);
        }
        
        return s;
    }