class ZTSAuthorizer implements Authorizer {

    @Override
    public boolean access(String op, String resource, Principal principal, String trustDomain) {
        
        // for consistent handling of all requests, we're going to convert
        // all incoming object values into lower case (e.g. domain, role,
        // policy, service, etc name)
        
        resource = resource.toLowerCase();
        if (trustDomain != null) {
            trustDomain = trustDomain.toLowerCase();
        }
        op = op.toLowerCase();
        
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("access:({}, {}, {}, {})", op, resource, principal, trustDomain);
        }
        
        // check to see if the authority is allowed to be processed in
        // authorization checks. If this value is false then the principal
        // must get a usertoken from ZMS first and the submit the request
        // with that token
        
        if (!AuthzHelper.authorityAuthorizationAllowed(principal)) {
            LOGGER.error("Authority is not allowed to support authorization checks");
            return false;
        }
        
        // retrieve our domain based on resource and action/trustDomain pair
        // we want to provider better error reporting to the users so if we get a
        // request where the domain is not found instead of just returning 403
        // forbidden (which is confusing since it assumes the user doesn't have
        // access as oppose to possible mistype of the domain name by the user)
        // we want to return 404 not found. The rest_core has special handling
        // for rest.ResourceExceptions so we'll throw that exception in this
        // special case of not found domains.
        
        String domainName = AuthzHelper.retrieveResourceDomain(resource, op, trustDomain);
        if (domainName == null) {
            throw new ResourceException(ResourceException.NOT_FOUND,
                    new ResourceError().code(ResourceException.NOT_FOUND).message("Domain not found"));
        }
        DataCache domain = dataStore.getDataCache(domainName);
        if (domain == null) {
            throw new ResourceException(ResourceException.NOT_FOUND,
                    new ResourceError().code(ResourceException.NOT_FOUND).message("Domain not found"));
        }
        
        AccessStatus accessStatus = evaluateAccess(domain, principal.getFullName(), op, resource, trustDomain);
        return accessStatus == AccessStatus.ALLOWED;
    }

    public  ZTSAuthorizer(final DataStore dataStore);

}