All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.juneau.rest.debug.DebugEnablement Maven / Gradle / Ivy

// ***************************************************************************************************************************
// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
// * with the License.  You may obtain a copy of the License at                                                              *
// *                                                                                                                         *
// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
// *                                                                                                                         *
// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
// * specific language governing permissions and limitations under the License.                                              *
// ***************************************************************************************************************************
package org.apache.juneau.rest.debug;

import static org.apache.juneau.Enablement.*;
import static org.apache.juneau.collections.JsonMap.*;
import static org.apache.juneau.internal.ObjectUtils.*;
import java.lang.reflect.Method;
import java.util.function.*;

import jakarta.servlet.http.*;

import org.apache.juneau.*;
import org.apache.juneau.cp.*;
import org.apache.juneau.http.response.*;
import org.apache.juneau.rest.*;
import org.apache.juneau.rest.annotation.*;
import org.apache.juneau.utils.*;

/**
 * Interface used for selectively turning on debug per request.
 *
 * 
See Also:
*/ public abstract class DebugEnablement { //----------------------------------------------------------------------------------------------------------------- // Static //----------------------------------------------------------------------------------------------------------------- /** * Represents no DebugEnablement. */ public abstract class Void extends DebugEnablement { Void(BeanStore beanStore) { super(beanStore); } } /** * Static creator. * * @param beanStore The bean store to use for creating beans. * @return A new builder for this object. */ public static Builder create(BeanStore beanStore) { return new Builder(beanStore); } //----------------------------------------------------------------------------------------------------------------- // Builder //----------------------------------------------------------------------------------------------------------------- /** * Builder class. */ public static class Builder { ReflectionMap.Builder mapBuilder; Enablement defaultEnablement = NEVER; Predicate conditional; BeanCreator creator; /** * Constructor. * * @param beanStore The bean store to use for creating beans. */ protected Builder(BeanStore beanStore) { mapBuilder = ReflectionMap.create(Enablement.class); defaultEnablement = NEVER; conditional = x -> "true".equalsIgnoreCase(x.getHeader("Debug")); creator = beanStore.createBean(DebugEnablement.class).type(BasicDebugEnablement.class).builder(Builder.class, this); } /** * Creates a new {@link DebugEnablement} object from this builder. *s *

* Instantiates an instance of the {@link #type(Class) implementation class} or * else {@link BasicDebugEnablement} if implementation class was not specified. * * @return A new {@link DebugEnablement} object. */ public DebugEnablement build() { try { return creator.run(); } catch (Exception e) { throw new InternalServerError(e); } } /** * Specifies a subclass of {@link DebugEnablement} to create when the {@link #build()} method is called. * * @param value The new value for this setting. * @return This object. */ public Builder type(Class value) { creator.type(value == null ? BasicDebugEnablement.class : value); return this; } /** * Specifies an already-instantiated bean for the {@link #build()} method to return. * * @param value The setting value. * @return This object. */ public Builder impl(DebugEnablement value) { creator.impl(value); return this; } /** * Enables or disables debug on the specified classes and/or methods. * *

* Allows you to target specified debug enablement on specified classes and/or methods. * * @param enablement * The debug enablement setting to set on the specified classes/methods. *
Can be any of the following: *

    *
  • {@link Enablement#ALWAYS ALWAYS} - Debug is always enabled. *
  • {@link Enablement#NEVER NEVER} - Debug is always disabled. *
  • {@link Enablement#CONDITIONAL CONDITIONAL} - Debug is enabled when the {@link #conditional(Predicate)} conditional predicate test} passes. *
* @param keys * The mapping keys. *
Can be any of the following: *
    *
  • Full class name (e.g. "com.foo.MyClass"). *
  • Simple class name (e.g. "MyClass"). *
  • All classes (e.g. "*"). *
  • Full method name (e.g. "com.foo.MyClass.myMethod"). *
  • Simple method name (e.g. "MyClass.myMethod"). *
  • A comma-delimited list of anything on this list. *
* @return This object. */ public Builder enable(Enablement enablement, String...keys) { for (String k : keys) mapBuilder.append(k, enablement); return this; } /** * Enables or disables debug on the specified classes. * *

* Identical to {@link #enable(Enablement, String...)} but allows you to specify specific classes. * * @param enablement * The debug enablement setting to set on the specified classes/methods. *
Can be any of the following: *

    *
  • {@link Enablement#ALWAYS ALWAYS} - Debug is always enabled. *
  • {@link Enablement#NEVER NEVER} - Debug is always disabled. *
  • {@link Enablement#CONDITIONAL CONDITIONAL} - Debug is enabled when the {@link #conditional(Predicate)} conditional predicate test} passes. *
* @param classes * The classes to set the debug enablement setting on. * @return This object. */ public Builder enable(Enablement enablement, Class...classes) { for (Class c : classes) mapBuilder.append(c.getName(), enablement); return this; } /** * Specifies the default debug enablement setting if not overridden per class/method. * *

* The default value for this setting is {@link Enablement#NEVER NEVER}. * * @param value The default debug enablement setting if not overridden per class/method. * @return This object. */ public Builder defaultEnable(Enablement value) { defaultEnablement = value; return this; } /** * Specifies the predicate to use for conditional debug enablement. * *

* Specifies the predicate to use to determine whether debug is enabled when the resolved enablement value * is {@link Enablement#CONDITIONAL CONDITIONAL}. * *

* The default value for this setting is (x)->"true".equalsIgnoreCase(x.getHeader("Debug")). * * @param value The predicate. * @return This object. */ public Builder conditional(Predicate value) { conditional = value; return this; } } //----------------------------------------------------------------------------------------------------------------- // Instance //----------------------------------------------------------------------------------------------------------------- private final Enablement defaultEnablement; private final ReflectionMap enablementMap; private final Predicate conditionalPredicate; /** * Constructor. *

* Subclasses typically override the {@link #init(BeanStore)} method when using this constructor. * * @param beanStore The bean store containing injectable beans for this enablement. */ public DebugEnablement(BeanStore beanStore) { Builder builder = init(beanStore); this.defaultEnablement = firstNonNull(builder.defaultEnablement, NEVER); this.enablementMap = builder.mapBuilder.build(); this.conditionalPredicate = firstNonNull(builder.conditional, x -> "true".equalsIgnoreCase(x.getHeader("Debug"))); } /** * Constructor. * * @param builder The builder for this enablement. */ public DebugEnablement(Builder builder) { this.defaultEnablement = firstNonNull(builder.defaultEnablement, NEVER); this.enablementMap = builder.mapBuilder.build(); this.conditionalPredicate = firstNonNull(builder.conditional, x -> "true".equalsIgnoreCase(x.getHeader("Debug"))); } /** * Initializer. *

* Subclasses should override this method to make modifications to the builder used to create this logger. * * @param beanStore The bean store containing injectable beans for this logger. * @return A new builder object. */ protected Builder init(BeanStore beanStore) { return new Builder(beanStore); } /** * Returns true if debug is enabled on the specified class and request. * *

* This enables debug mode on requests once the matched class is found and before the * Java method is found. * * @param context The context of the {@link Rest}-annotated class. * @param req The HTTP request. * @return true if debug is enabled on the specified method and request. */ public boolean isDebug(RestContext context, HttpServletRequest req) { Class c = context.getResourceClass(); Enablement e = enablementMap.find(c).orElse(defaultEnablement); return e == ALWAYS || (e == CONDITIONAL && isConditionallyEnabled(req)); } /** * Returns true if debug is enabled on the specified method and request. * *

* This enables debug mode after the Java method is found and allows you to enable * debug on individual Java methods instead of the entire class. * * @param context The context of the {@link RestOp}-annotated method. * @param req The HTTP request. * @return true if debug is enabled on the specified method and request. */ public boolean isDebug(RestOpContext context, HttpServletRequest req) { Method m = context.getJavaMethod(); Enablement e = enablementMap.find(m).orElse(enablementMap.find(m.getDeclaringClass()).orElse(defaultEnablement)); return e == ALWAYS || (e == CONDITIONAL && isConditionallyEnabled(req)); } /** * Returns true if debugging is conditionally enabled on the specified request. * *

* This method only gets called when the enablement value resolves to {@link Enablement#CONDITIONAL CONDITIONAL}. * *

* Subclasses can override this method to provide their own implementation. * The default implementation is provided by {@link DebugEnablement.Builder#conditional(Predicate)} * which has a default predicate of x -> "true".equalsIgnoreCase(x.getHeader("Debug"). * * @param req The incoming HTTP request. * @return true if debugging is conditionally enabled on the specified request. */ protected boolean isConditionallyEnabled(HttpServletRequest req) { return conditionalPredicate.test(req); } @Override /* Object */ public String toString() { return filteredMap() .append("defaultEnablement", defaultEnablement) .append("enablementMap", enablementMap) .append("conditionalPredicate", conditionalPredicate) .asString(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy