--- /dev/null
+/*
+ * Copyright 2000-2013 Vaadin Ltd.
+ *
+ * Licensed 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 com.vaadin.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import com.vaadin.server.Constants;
+import com.vaadin.server.DefaultDeploymentConfiguration;
+import com.vaadin.server.DeploymentConfiguration;
+import com.vaadin.server.DeploymentConfiguration.LegacyProperyToStringMode;
+import com.vaadin.server.VaadinServlet;
+import com.vaadin.server.VaadinSession;
+import com.vaadin.ui.UI;
+
+/**
+ * Annotation for configuring subclasses of {@link VaadinServlet}. For a
+ * {@link VaadinServlet} class that has this annotation, the defined values are
+ * read during initialization and will be available using
+ * {@link DeploymentConfiguration#getApplicationOrSystemProperty(String, String)}
+ * as well as from specific methods in {@link DeploymentConfiguration}. Init
+ * params defined in <code>web.xml</code> or the <code>@WebServlet</code>
+ * annotation take precedence over values defined in this annotation.
+ *
+ * @since 7.1
+ * @author Vaadin Ltd
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface VaadinServletConfiguration {
+ /**
+ * Defines the init parameter name for methods in
+ * {@link VaadinServletConfiguration}.
+ *
+ * @since 7.1
+ * @author Vaadin Ltd
+ */
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.METHOD)
+ @Documented
+ public @interface InitParameterName {
+ /**
+ * The name of the init parameter that the annotated method controls.
+ *
+ * @return the parameter name
+ */
+ public String value();
+ }
+
+ /**
+ * Whether Vaadin is in production mode.
+ *
+ * @return true if in production mode, false otherwise.
+ *
+ * @see DeploymentConfiguration#isProductionMode()
+ */
+ @InitParameterName(Constants.SERVLET_PARAMETER_PRODUCTION_MODE)
+ public boolean productionMode();
+
+ /**
+ * Gets the default UI class to use for the servlet.
+ *
+ * @return the default UI class
+ */
+ @InitParameterName(VaadinSession.UI_PARAMETER)
+ public Class<? extends UI> ui();
+
+ /**
+ * The time resources can be cached in the browser, in seconds. The default
+ * value is
+ * {@value DefaultDeploymentConfiguration#DEFAULT_RESOURCE_CACHE_TIME}.
+ *
+ * @return the resource cache time
+ *
+ * @see DeploymentConfiguration#getResourceCacheTime()
+ */
+ @InitParameterName(Constants.SERVLET_PARAMETER_RESOURCE_CACHE_TIME)
+ public int resourceCacheTime() default DefaultDeploymentConfiguration.DEFAULT_RESOURCE_CACHE_TIME;
+
+ /**
+ * The number of seconds between heartbeat requests of a UI, or a
+ * non-positive number if heartbeat is disabled. The default value is
+ * {@value DefaultDeploymentConfiguration#DEFAULT_HEARTBEAT_INTERVAL}.
+ *
+ * @return the time between heartbeats
+ *
+ * @see DeploymentConfiguration#getHeartbeatInterval()
+ */
+ @InitParameterName(Constants.SERVLET_PARAMETER_HEARTBEAT_INTERVAL)
+ public int heartbeatInterval() default DefaultDeploymentConfiguration.DEFAULT_HEARTBEAT_INTERVAL;
+
+ /**
+ * Whether a session should be closed when all its open UIs have been idle
+ * for longer than its configured maximum inactivity time. The default value
+ * is {@value DefaultDeploymentConfiguration#DEFAULT_CLOSE_IDLE_SESSIONS}.
+ *
+ * @return true if UIs and sessions receiving only heartbeat requests are
+ * eventually closed; false if heartbeat requests extend UI and
+ * session lifetime indefinitely
+ *
+ * @see DeploymentConfiguration#isCloseIdleSessions()
+ */
+ @InitParameterName(Constants.SERVLET_PARAMETER_CLOSE_IDLE_SESSIONS)
+ public boolean closeIdleSessions() default DefaultDeploymentConfiguration.DEFAULT_CLOSE_IDLE_SESSIONS;
+
+ /**
+ * The default widgetset to use for the servlet. The default value is
+ * {@value VaadinServlet#DEFAULT_WIDGETSET}.
+ *
+ * @return the default widgetset name
+ */
+ @InitParameterName(VaadinServlet.PARAMETER_WIDGETSET)
+ public String widgetset() default VaadinServlet.DEFAULT_WIDGETSET;
+
+ /**
+ * The legacy Property.toString() mode used. The default value is
+ * {@link LegacyProperyToStringMode#DISABLED}
+ *
+ * @return The Property.toString() mode in use.
+ *
+ * @deprecated as of 7.1, should only be used to ease migration
+ */
+ @Deprecated
+ @InitParameterName(Constants.SERVLET_PARAMETER_LEGACY_PROPERTY_TOSTRING)
+ public LegacyProperyToStringMode legacyPropertyToStringMode() default LegacyProperyToStringMode.DISABLED;
+}
* @since 7.0.0
*/
public class DefaultDeploymentConfiguration implements DeploymentConfiguration {
+ /**
+ * Default value for {@link #getResourceCacheTime()} = {@value} .
+ */
+ public static final int DEFAULT_RESOURCE_CACHE_TIME = 3600;
+
+ /**
+ * Default value for {@link #getHeartbeatInterval()} = {@value} .
+ */
+ public static final int DEFAULT_HEARTBEAT_INTERVAL = 300;
+
+ /**
+ * Default value for {@link #isCloseIdleSessions()} = {@value} .
+ */
+ public static final boolean DEFAULT_CLOSE_IDLE_SESSIONS = false;
+
+ /**
+ * Default value for {@link #getLegacyPropertyToStringMode()} =
+ * {@link LegacyProperyToStringMode#WARNING}.
+ */
+ public static final LegacyProperyToStringMode DEFAULT_LEGACY_PROPERTY_TO_STRING = LegacyProperyToStringMode.WARNING;
+
private final Properties initParameters;
private boolean productionMode;
private boolean xsrfProtectionEnabled;
private void checkLegacyPropertyToString() {
String param = getApplicationOrSystemProperty(
- Constants.SERVLET_PARAMETER_LEGACY_PROPERTY_TOSTRING, "warning");
- if ("true".equals(param)) {
- legacyPropertyToStringMode = LegacyProperyToStringMode.ENABLED;
- } else if ("false".equals(param)) {
- legacyPropertyToStringMode = LegacyProperyToStringMode.DISABLED;
- } else {
- if (!"warning".equals(param)) {
- getLogger()
- .log(Level.WARNING,
- Constants.WARNING_UNKNOWN_LEGACY_PROPERTY_TOSTRING_VALUE,
- param);
- }
- legacyPropertyToStringMode = LegacyProperyToStringMode.WARNING;
+ Constants.SERVLET_PARAMETER_LEGACY_PROPERTY_TOSTRING,
+ DEFAULT_LEGACY_PROPERTY_TO_STRING.name().toLowerCase());
+ try {
+ legacyPropertyToStringMode = LegacyProperyToStringMode
+ .valueOf(param.toUpperCase());
+ } catch (IllegalArgumentException e) {
+ getLogger().log(Level.WARNING,
+ Constants.WARNING_UNKNOWN_LEGACY_PROPERTY_TOSTRING_VALUE,
+ param);
+ legacyPropertyToStringMode = DEFAULT_LEGACY_PROPERTY_TO_STRING;
}
}
resourceCacheTime = Integer
.parseInt(getApplicationOrSystemProperty(
Constants.SERVLET_PARAMETER_RESOURCE_CACHE_TIME,
- "3600"));
+ Integer.toString(DEFAULT_RESOURCE_CACHE_TIME)));
} catch (NumberFormatException e) {
getLogger().warning(
Constants.WARNING_RESOURCE_CACHING_TIME_NOT_NUMERIC);
- resourceCacheTime = 3600;
+ resourceCacheTime = DEFAULT_RESOURCE_CACHE_TIME;
}
}
heartbeatInterval = Integer
.parseInt(getApplicationOrSystemProperty(
Constants.SERVLET_PARAMETER_HEARTBEAT_INTERVAL,
- "300"));
+ Integer.toString(DEFAULT_HEARTBEAT_INTERVAL)));
} catch (NumberFormatException e) {
getLogger().warning(
Constants.WARNING_HEARTBEAT_INTERVAL_NOT_NUMERIC);
- heartbeatInterval = 300;
+ heartbeatInterval = DEFAULT_HEARTBEAT_INTERVAL;
}
}
private void checkCloseIdleSessions() {
closeIdleSessions = getApplicationOrSystemProperty(
- Constants.SERVLET_PARAMETER_CLOSE_IDLE_SESSIONS, "false")
- .equals("true");
+ Constants.SERVLET_PARAMETER_CLOSE_IDLE_SESSIONS,
+ Boolean.toString(DEFAULT_CLOSE_IDLE_SESSIONS)).equals("true");
}
private void checkPushMode() {
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
+import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import com.vaadin.annotations.VaadinServletConfiguration;
+import com.vaadin.annotations.VaadinServletConfiguration.InitParameterName;
import com.vaadin.sass.internal.ScssStylesheet;
import com.vaadin.server.communication.ServletUIInitHandler;
import com.vaadin.shared.JsonConstants;
super.init(servletConfig);
Properties initParameters = new Properties();
+ readConfigurationAnnotation(initParameters);
+
// Read default parameters from server.xml
final ServletContext context = servletConfig.getServletContext();
for (final Enumeration<String> e = context.getInitParameterNames(); e
CurrentInstance.clearAll();
}
+ private void readConfigurationAnnotation(Properties initParameters)
+ throws ServletException {
+ VaadinServletConfiguration configAnnotation = UIProvider
+ .getAnnotationFor(getClass(), VaadinServletConfiguration.class);
+ if (configAnnotation != null) {
+ Method[] methods = VaadinServletConfiguration.class
+ .getDeclaredMethods();
+ for (Method method : methods) {
+ InitParameterName name = method
+ .getAnnotation(InitParameterName.class);
+ assert name != null : "All methods declared in VaadinServletConfiguration should have a @InitParameterName annotation";
+
+ try {
+ Object value = method.invoke(configAnnotation);
+
+ String stringValue;
+ if (value instanceof Class<?>) {
+ stringValue = ((Class<?>) value).getName();
+ } else {
+ stringValue = value.toString();
+ }
+
+ initParameters.setProperty(name.value(), stringValue);
+ } catch (Exception e) {
+ // This should never happen
+ throw new ServletException(
+ "Could not read @VaadinServletConfiguration value "
+ + method.getName(), e);
+ }
+ }
+ }
+ }
+
protected void servletInitialized() throws ServletException {
// Empty by default
}
*/
package com.vaadin.server;
-import java.util.Collections;
import java.util.Enumeration;
+import java.util.Properties;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
public class MockServletConfig implements ServletConfig {
private ServletContext context = new MockServletContext();
+ private final Properties initParameters;
+
+ public MockServletConfig() {
+ this(new Properties());
+ }
+
+ public MockServletConfig(Properties initParameters) {
+ this.initParameters = initParameters;
+ }
/*
* (non-Javadoc)
*/
@Override
public String getInitParameter(String name) {
- return null;
+ return initParameters.getProperty(name);
}
/*
*/
@Override
public Enumeration getInitParameterNames() {
- return Collections.enumeration(Collections.EMPTY_LIST);
+ return initParameters.propertyNames();
}
}
--- /dev/null
+/*
+ * Copyright 2000-2013 Vaadin Ltd.
+ *
+ * Licensed 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 com.vaadin.server;
+
+import java.util.Properties;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+
+import junit.framework.Assert;
+
+import org.easymock.EasyMock;
+import org.junit.Test;
+
+import com.vaadin.annotations.VaadinServletConfiguration;
+import com.vaadin.server.DeploymentConfiguration.LegacyProperyToStringMode;
+import com.vaadin.server.VaadinServletConfigurationTest.MockUI;
+import com.vaadin.ui.UI;
+
+public class VaadinServletConfigurationTest {
+ public static class MockUI extends UI {
+ @Override
+ protected void init(VaadinRequest request) {
+ // Do nothing
+ }
+ }
+
+ @Test
+ public void testValuesFromAnnotation() throws ServletException {
+ TestServlet servlet = new TestServlet();
+ servlet.init(new MockServletConfig());
+ DeploymentConfiguration configuration = servlet.getService()
+ .getDeploymentConfiguration();
+
+ Assert.assertEquals(true, configuration.isProductionMode());
+ Assert.assertEquals(LegacyProperyToStringMode.DISABLED,
+ configuration.getLegacyPropertyToStringMode());
+ Assert.assertEquals(true, configuration.isCloseIdleSessions());
+ Assert.assertEquals(1234, configuration.getHeartbeatInterval());
+ Assert.assertEquals(4321, configuration.getResourceCacheTime());
+
+ Class<? extends UI> uiClass = new DefaultUIProvider()
+ .getUIClass(new UIClassSelectionEvent(new VaadinServletRequest(
+ EasyMock.createMock(HttpServletRequest.class), servlet
+ .getService())));
+ Assert.assertEquals(MockUI.class, uiClass);
+ }
+
+ @Test
+ public void testValuesOverriddenForServlet() throws ServletException {
+ Properties servletInitParams = new Properties();
+ servletInitParams.setProperty("productionMode", "false");
+ servletInitParams.setProperty("heartbeatInterval", "1111");
+
+ TestServlet servlet = new TestServlet();
+ servlet.init(new MockServletConfig(servletInitParams));
+ DeploymentConfiguration configuration = servlet.getService()
+ .getDeploymentConfiguration();
+
+ // Values from servlet init params take precedence
+ Assert.assertEquals(1111, configuration.getHeartbeatInterval());
+ Assert.assertEquals(false, configuration.isProductionMode());
+
+ // Other params are as defined in the annotation
+ Assert.assertEquals(LegacyProperyToStringMode.DISABLED,
+ configuration.getLegacyPropertyToStringMode());
+ Assert.assertEquals(true, configuration.isCloseIdleSessions());
+ Assert.assertEquals(4321, configuration.getResourceCacheTime());
+
+ Class<? extends UI> uiClass = new DefaultUIProvider()
+ .getUIClass(new UIClassSelectionEvent(new VaadinServletRequest(
+ EasyMock.createMock(HttpServletRequest.class), servlet
+ .getService())));
+ Assert.assertEquals(MockUI.class, uiClass);
+ }
+}
+
+@VaadinServletConfiguration(productionMode = true, ui = MockUI.class, closeIdleSessions = true, heartbeatInterval = 1234, resourceCacheTime = 4321)
+class TestServlet extends VaadinServlet {
+
+}