/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at * docs/licenses/cddl.txt * or http://www.opensource.org/licenses/cddl1.php. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at * docs/licenses/cddl.txt. If applicable, * add the following below this CDDL HEADER, with the fields enclosed * by brackets "[]" replaced with your own identifying information: * Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * * Portions Copyright 2011-2023 Ping Identity Corporation */ package com.unboundid.directory.sdk.examples.groovy; import java.util.Arrays; import java.util.List; import com.unboundid.directory.sdk.examples.ExampleHelloServlet; import com.unboundid.directory.sdk.http.config.HTTPServletExtensionConfig; import com.unboundid.directory.sdk.http.scripting.ScriptedHTTPServletExtension; import com.unboundid.directory.sdk.http.types.HTTPServerContext; import com.unboundid.ldap.sdk.LDAPException; import com.unboundid.ldap.sdk.ResultCode; import com.unboundid.util.args.ArgumentException; import com.unboundid.util.args.ArgumentParser; import com.unboundid.util.args.StringArgument; /** * This class provides a simple example of a scripted HTTP servlet extension * which will create a simple "Hello, World!" servlet. It has two configuration * arguments: * <UL> * <LI>name -- The name to display in the servlet's hello message. If this is * not provided, then a default value of "World" will be used.</LI> * <LI>path -- The path that should be used to invoke the servlet. If this is * not provided, then a default value of "/hello" will be used.</LI> * </UL> */ public final class ExampleScriptedHTTPServletExtension extends ScriptedHTTPServletExtension { /** * The name of the argument that will be used to specify the name that should * be used in the greeting. */ private static final String ARG_NAME_NAME = "name"; /** * The name of the argument that will be used to specify the path that will be * used to access the servlet. */ private static final String ARG_NAME_PATH = "path"; // The servlet that has been created. private volatile ExampleHelloServlet servlet; // The path that will be used for the servlet. private volatile String path; /** * Creates a new instance of this HTTP servlet extension. All HTTP servlet * extension implementations must include a default constructor, but any * initialization should generally be done in the {@code createServlet} * method. */ public ExampleScriptedHTTPServletExtension() { servlet = null; path = null; } /** * Updates the provided argument parser to define any configuration arguments * which may be used by this HTTP servlet extension. The argument parser * may also be updated to define relationships between arguments (e.g., to * specify required, exclusive, or dependent argument sets). * * @param parser The argument parser to be updated with the configuration * arguments which may be used by this HTTP servlet * extension. * * @throws ArgumentException If a problem is encountered while updating the * provided argument parser. */ @Override() public void defineConfigArguments(final ArgumentParser parser) throws ArgumentException { // Add an argument that allows you to specify the name to use in the // greeting. Character shortIdentifier = null; String longIdentifier = ARG_NAME_NAME; boolean required = false; int maxOccurrences = 1; String placeholder = "{name}"; String description = "The name to use in the greeting."; String defaultValue = "World"; parser.addArgument(new StringArgument(shortIdentifier, longIdentifier, required, maxOccurrences, placeholder, description, defaultValue)); // Add an argument that allows you to specify the request path. shortIdentifier = null; longIdentifier = ARG_NAME_PATH; required = false; maxOccurrences = 1; placeholder = "{path}"; description = "The path to use to access the servlet. Note that " + "changes to this argument will only take effect if the associated " + "HTTP connection handler (or the entire server) is stopped and " + "re-started."; defaultValue = "/hello"; parser.addArgument(new StringArgument(shortIdentifier, longIdentifier, required, maxOccurrences, placeholder, description, defaultValue)); } /** * Creates an HTTP servlet extension using the provided information. * * @param serverContext A handle to the server context for the server in * which this extension is running. * @param config The general configuration for this HTTP servlet * extension. * @param parser The argument parser which has been initialized from * the configuration for this HTTP servlet extension. * * @return The HTTP servlet that has been created. * * @throws LDAPException If a problem is encountered while attempting to * create the HTTP servlet. */ @Override() public ExampleHelloServlet createServlet( final HTTPServerContext serverContext, final HTTPServletExtensionConfig config, final ArgumentParser parser) throws LDAPException { // Get the new greeting name. final StringArgument nameArg = (StringArgument) parser.getNamedArgument(ARG_NAME_NAME); // Get the servlet path. final StringArgument pathArg = (StringArgument) parser.getNamedArgument(ARG_NAME_PATH); path = pathArg.getValue(); servlet = new ExampleHelloServlet(nameArg.getValue()); return servlet; } /** * Retrieves a list of the request paths for which the associated servlet * should be invoked. This method will be called after the * {@link #createServlet} method has been used to create the servlet instance. * * @return A list of the request paths for which the associated servlet * should be invoked. */ @Override() public List<String> getServletPaths() { return Arrays.asList(path); } /** * Indicates whether the configuration contained in the provided argument * parser represents a valid configuration for this extension. * * @param config The general configuration for this HTTP * servlet extension. * @param parser The argument parser which has been initialized * with the proposed configuration. * @param unacceptableReasons A list that can be updated with reasons that * the proposed configuration is not acceptable. * * @return {@code true} if the proposed configuration is acceptable, or * {@code false} if not. */ @Override() public boolean isConfigurationAcceptable( final HTTPServletExtensionConfig config, final ArgumentParser parser, final List<String> unacceptableReasons) { // No special validation is required. return true; } /** * Attempts to apply the configuration contained in the provided argument * parser. * * @param config The general configuration for this HTTP * servlet extension. * @param parser The argument parser which has been * initialized with the new configuration. * @param adminActionsRequired A list that can be updated with information * about any administrative actions that may be * required before one or more of the * configuration changes will be applied. * @param messages A list that can be updated with information * about the result of applying the new * configuration. * * @return A result code that provides information about the result of * attempting to apply the configuration change. */ @Override() public ResultCode applyConfiguration(final HTTPServletExtensionConfig config, final ArgumentParser parser, final List<String> adminActionsRequired, final List<String> messages) { // We only need to validate changes made after the servlet has been created. // If the servlet hasn't yet been created, then we don't need to do // anything. if (servlet == null) { return ResultCode.SUCCESS; } // Get the new greeting name. final StringArgument nameArg = (StringArgument) parser.getNamedArgument(ARG_NAME_NAME); servlet.setName(nameArg.getValue()); // The path will not change dynamically. If a different path was given, // then report that as a required administrative action. final StringArgument pathArg = (StringArgument) parser.getNamedArgument(ARG_NAME_PATH); if (! path.equals(pathArg.getValue())) { adminActionsRequired.add("Changes to the servlet path will not take " + "effect until the HTTP connection handler (or entire server) is " + "restarted."); } return ResultCode.SUCCESS; } }