public boolean keep()

in core/src/main/java/jenkins/security/stapler/TypedFilter.java [191:269]


    public boolean keep(@NonNull Function function) {

        if (function.getAnnotation(StaplerNotDispatchable.class) != null) {
            // explicitly marked as an invalid getter
            return false;
        }

        if (function.getAnnotation(StaplerDispatchable.class) != null) {
            // explicitly marked as a valid getter
            return true;
        }

        String signature = function.getSignature();

        // check whitelist
        ExtensionList<RoutingDecisionProvider> decision = ExtensionList.lookup(RoutingDecisionProvider.class);
        if (decision.size() > 0) {
            for (RoutingDecisionProvider provider : decision) {
                RoutingDecisionProvider.Decision methodDecision = provider.decide(signature);
                if (methodDecision == RoutingDecisionProvider.Decision.ACCEPTED) {
                    LOGGER.log(Level.CONFIG, "Function {0} is acceptable because it is whitelisted by {1}", new Object[]{signature, provider});
                    return true;
                }
                if (methodDecision == RoutingDecisionProvider.Decision.REJECTED) {
                    LOGGER.log(Level.CONFIG, "Function {0} is not acceptable because it is blacklisted by {1}", new Object[]{signature, provider});
                    return false;
                }
                
                Class<?> type = function.getReturnType();
                if (type != null) {
                    String typeSignature = "class " + type.getCanonicalName();
                    RoutingDecisionProvider.Decision returnTypeDecision = provider.decide(typeSignature);
                    if (returnTypeDecision == RoutingDecisionProvider.Decision.ACCEPTED) {
                        LOGGER.log(Level.CONFIG, "Function {0} is acceptable because its type is whitelisted by {1}", new Object[]{signature, provider});
                        return true;
                    }
                    if (returnTypeDecision == RoutingDecisionProvider.Decision.REJECTED) {
                        LOGGER.log(Level.CONFIG, "Function {0} is not acceptable because its type is blacklisted by {1}", new Object[]{signature, provider});
                        return false;
                    }
                }
            }
        }

        if (PROHIBIT_STATIC_ACCESS && function.isStatic()) {
            // unless whitelisted or marked as routable, reject static methods
            return false;
        }

        if (function.getName().equals("getDynamic")) {
            Class[] parameterTypes = function.getParameterTypes();
            if (parameterTypes.length > 0 && parameterTypes[0] == String.class) {
                // While this is more general than what Stapler can invoke on these types,
                // The above is the only criterion for Stapler to attempt dispatch.
                // Therefore prohibit this as a regular getter.
                return false;
            }
        }

        if (function.getName().equals("getStaplerFallback") && function.getParameterTypes().length == 0) {
            // A parameter-less #getStaplerFallback() implements special fallback behavior for the
            // StaplerFallback interface. We do not check for the presence of the interface on the current
            // class, or the return type, as that could change since the implementing component was last built.
            return false;
        }

        if (function.getName().equals("getTarget") && function.getParameterTypes().length == 0) {
            // A parameter-less #getTarget() implements special redirection behavior for the
            // StaplerProxy interface. We do not check for the presence of the interface on the current
            // class, or the return type, as that could change since the implementing component was last built.
            return false;
        }

        Class<?> returnType = function.getReturnType();

        boolean isOk = isClassAcceptable(returnType);
        LOGGER.log(Level.FINE, "Function analyzed: {0} => {1}", new Object[]{signature, isOk});
        return isOk;
    }