001/*
002 * Copyright 2012-2018 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.boot.web.servlet;
018
019import java.util.LinkedHashMap;
020import java.util.Map;
021
022import javax.servlet.Registration;
023import javax.servlet.ServletContext;
024
025import org.apache.commons.logging.Log;
026import org.apache.commons.logging.LogFactory;
027
028import org.springframework.core.Conventions;
029import org.springframework.util.Assert;
030import org.springframework.util.StringUtils;
031
032/**
033 * Base class for Servlet 3.0+ {@link javax.servlet.Registration.Dynamic dynamic} based
034 * registration beans.
035 *
036 * @param <D> the dynamic registration result
037 * @author Phillip Webb
038 * @since 2.0.0
039 */
040public abstract class DynamicRegistrationBean<D extends Registration.Dynamic>
041                extends RegistrationBean {
042
043        private static final Log logger = LogFactory.getLog(RegistrationBean.class);
044
045        private String name;
046
047        private boolean asyncSupported = true;
048
049        private Map<String, String> initParameters = new LinkedHashMap<>();
050
051        /**
052         * Set the name of this registration. If not specified the bean name will be used.
053         * @param name the name of the registration
054         */
055        public void setName(String name) {
056                Assert.hasLength(name, "Name must not be empty");
057                this.name = name;
058        }
059
060        /**
061         * Sets if asynchronous operations are supported for this registration. If not
062         * specified defaults to {@code true}.
063         * @param asyncSupported if async is supported
064         */
065        public void setAsyncSupported(boolean asyncSupported) {
066                this.asyncSupported = asyncSupported;
067        }
068
069        /**
070         * Returns if asynchronous operations are supported for this registration.
071         * @return if async is supported
072         */
073        public boolean isAsyncSupported() {
074                return this.asyncSupported;
075        }
076
077        /**
078         * Set init-parameters for this registration. Calling this method will replace any
079         * existing init-parameters.
080         * @param initParameters the init parameters
081         * @see #getInitParameters
082         * @see #addInitParameter
083         */
084        public void setInitParameters(Map<String, String> initParameters) {
085                Assert.notNull(initParameters, "InitParameters must not be null");
086                this.initParameters = new LinkedHashMap<>(initParameters);
087        }
088
089        /**
090         * Returns a mutable Map of the registration init-parameters.
091         * @return the init parameters
092         */
093        public Map<String, String> getInitParameters() {
094                return this.initParameters;
095        }
096
097        /**
098         * Add a single init-parameter, replacing any existing parameter with the same name.
099         * @param name the init-parameter name
100         * @param value the init-parameter value
101         */
102        public void addInitParameter(String name, String value) {
103                Assert.notNull(name, "Name must not be null");
104                this.initParameters.put(name, value);
105        }
106
107        @Override
108        protected final void register(String description, ServletContext servletContext) {
109                D registration = addRegistration(description, servletContext);
110                if (registration == null) {
111                        logger.info(StringUtils.capitalize(description) + " was not registered "
112                                        + "(possibly already registered?)");
113                        return;
114                }
115                configure(registration);
116        }
117
118        protected abstract D addRegistration(String description,
119                        ServletContext servletContext);
120
121        protected void configure(D registration) {
122                registration.setAsyncSupported(this.asyncSupported);
123                if (!this.initParameters.isEmpty()) {
124                        registration.setInitParameters(this.initParameters);
125                }
126        }
127
128        /**
129         * Deduces the name for this registration. Will return user specified name or fallback
130         * to convention based naming.
131         * @param value the object used for convention based names
132         * @return the deduced name
133         */
134        protected final String getOrDeduceName(Object value) {
135                return (this.name != null) ? this.name : Conventions.getVariableName(value);
136        }
137
138}