From: Maciej PrzepioĢra Date: Wed, 22 Oct 2014 12:28:15 +0000 (+0300) Subject: Change the way classloader for VaadinService is selected (fixes #11295) X-Git-Tag: 7.3.5~11 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=5b76975df4216f48710476b44f1013bbed47f6d2;p=vaadin-framework.git Change the way classloader for VaadinService is selected (fixes #11295) Change-Id: I2a25b4149f927ee7940edf596e8cebaaa48dcd0d --- diff --git a/server/src/com/vaadin/server/Constants.java b/server/src/com/vaadin/server/Constants.java index 14113fda3c..5841bfac4d 100644 --- a/server/src/com/vaadin/server/Constants.java +++ b/server/src/com/vaadin/server/Constants.java @@ -115,6 +115,15 @@ public interface Constants { + Constants.SERVLET_PARAMETER_LEGACY_PROPERTY_TOSTRING + ". Supported values are 'false','warning','true'"; + static final String CANNOT_ACQUIRE_CLASSLOADER_SEVERE = "\n" + + "=================================================================\n" + + "Vaadin was unable to acquire class loader from servlet container\n" + + "to load your application classes. Setup appropriate security\n" + + "policy to allow invoking Thread.getContextClassLoader() from\n" + + "VaadinService if you're not using custom class loader.\n" + + "NullPointerExceptions will be thrown later." + + "================================================================="; + static final String URL_PARAMETER_THEME = "theme"; static final String SERVLET_PARAMETER_PRODUCTION_MODE = "productionMode"; @@ -164,4 +173,5 @@ public interface Constants { static final String PORTAL_PARAMETER_VAADIN_THEME = "vaadin.theme"; static final String PORTLET_CONTEXT = "PORTLET_CONTEXT"; + } diff --git a/server/src/com/vaadin/server/VaadinPortletService.java b/server/src/com/vaadin/server/VaadinPortletService.java index c6d9b8e46a..9f467401f4 100644 --- a/server/src/com/vaadin/server/VaadinPortletService.java +++ b/server/src/com/vaadin/server/VaadinPortletService.java @@ -46,16 +46,6 @@ public class VaadinPortletService extends VaadinService { throws ServiceException { super(deploymentConfiguration); this.portlet = portlet; - - // Set default class loader if not already set - if (getClassLoader() == null) { - /* - * The portlet is most likely to be loaded with a class loader - * specific to the application instead of some generic system class - * loader that loads the Vaadin classes. - */ - setClassLoader(portlet.getClass().getClassLoader()); - } } @Override @@ -164,7 +154,7 @@ public class VaadinPortletService extends VaadinService { if (Constants.PORTLET_CONTEXT.equals(staticFileLocation)) { return request.getContextPath(); - } else{ + } else { return trimTrailingSlashes(staticFileLocation); } } diff --git a/server/src/com/vaadin/server/VaadinService.java b/server/src/com/vaadin/server/VaadinService.java index 0f2daa4242..b74e8c44ff 100644 --- a/server/src/com/vaadin/server/VaadinService.java +++ b/server/src/com/vaadin/server/VaadinService.java @@ -168,6 +168,10 @@ public abstract class VaadinService implements Serializable { + classLoaderName, e); } } + + if (getClassLoader() == null) { + setDefaultClassLoader(); + } } /** @@ -1855,4 +1859,25 @@ public abstract class VaadinService implements Serializable { eventRouter.fireEvent(new ServiceDestroyEvent(this)); } + /** + * Tries to acquire default class loader and sets it as a class loader for + * this {@link VaadinService} if found. If current security policy disallows + * acquiring class loader instance it will log a message and re-throw + * {@link SecurityException} + * + * @throws SecurityException + * If current security policy forbids acquiring class loader + * + * @since + */ + protected void setDefaultClassLoader() { + try { + setClassLoader(VaadinServiceClassLoaderUtil + .findDefaultClassLoader()); + } catch (SecurityException e) { + getLogger().log(Level.SEVERE, + Constants.CANNOT_ACQUIRE_CLASSLOADER_SEVERE, e); + throw e; + } + } } diff --git a/server/src/com/vaadin/server/VaadinServiceClassLoaderUtil.java b/server/src/com/vaadin/server/VaadinServiceClassLoaderUtil.java new file mode 100644 index 0000000000..c9e73e2a29 --- /dev/null +++ b/server/src/com/vaadin/server/VaadinServiceClassLoaderUtil.java @@ -0,0 +1,57 @@ +/* + * Copyright 2000-2014 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.security.AccessController; +import java.security.PrivilegedAction; + +/** + * Utility class used by {@link VaadinService#setDefaultClassLoader()}. + * + * @since + * @author Vaadin Ltd + */ +class VaadinServiceClassLoaderUtil { + + private static class GetClassLoaderPrivilegedAction implements + PrivilegedAction { + @Override + public ClassLoader run() { + return Thread.currentThread().getContextClassLoader(); + } + } + + /** + * Called by {@link VaadinService#setDefaultClassLoader()} to acquire + * appropriate class loader to load application's classes (e.g. UI). Calls + * should be guarded by try/catch block to catch SecurityException and log + * appropriate message. The code for this method is modeled after + * recommendations laid out by JEE 5 specification sections EE.6.2.4.7 and + * EE.8.2.5 + * + * @return Instance of {@link ClassLoader} that should be used by this + * instance of {@link VaadinService} + * @throws SecurityException + * if current security policy doesn't allow acquiring current + * thread's context class loader + */ + static protected ClassLoader findDefaultClassLoader() + throws SecurityException { + return AccessController + .doPrivileged(new VaadinServiceClassLoaderUtil.GetClassLoaderPrivilegedAction()); + } + +} diff --git a/server/src/com/vaadin/server/VaadinServletService.java b/server/src/com/vaadin/server/VaadinServletService.java index a4ff3943c9..0b431306e0 100644 --- a/server/src/com/vaadin/server/VaadinServletService.java +++ b/server/src/com/vaadin/server/VaadinServletService.java @@ -51,16 +51,6 @@ public class VaadinServletService extends VaadinService { throws ServiceException { super(deploymentConfiguration); this.servlet = servlet; - - // Set default class loader if not already set - if (getClassLoader() == null) { - /* - * The servlet is most likely to be loaded with a class loader - * specific to the application instead of some generic system class - * loader that loads the Vaadin classes. - */ - setClassLoader(servlet.getClass().getClassLoader()); - } } private static boolean checkAtmosphereSupport() { diff --git a/server/tests/src/com/vaadin/tests/server/CsrfTokenMissingTestServer.java b/server/tests/src/com/vaadin/tests/server/CsrfTokenMissingTestServer.java index 30f1c85fef..59bb712907 100644 --- a/server/tests/src/com/vaadin/tests/server/CsrfTokenMissingTestServer.java +++ b/server/tests/src/com/vaadin/tests/server/CsrfTokenMissingTestServer.java @@ -19,6 +19,7 @@ import java.util.UUID; import java.util.logging.Level; import java.util.logging.Logger; +import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import org.easymock.EasyMock; @@ -27,6 +28,7 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import com.vaadin.server.MockServletConfig; import com.vaadin.server.ServiceException; import com.vaadin.server.VaadinService; import com.vaadin.server.VaadinServlet; @@ -38,6 +40,7 @@ import com.vaadin.shared.ApplicationConstants; import com.vaadin.tests.util.AlwaysLockedVaadinSession; import com.vaadin.tests.util.MockDeploymentConfiguration; + /** * Test the actual csrf token validation by the server. * @@ -62,10 +65,12 @@ public class CsrfTokenMissingTestServer { /** * Initialize the mock servlet and other stuff for our tests. + * */ @Before - public void initMockStuff() throws ServiceException { + public void initMockStuff() throws ServiceException, ServletException { mockServlet = new VaadinServlet(); + mockServlet.init(new MockServletConfig()); mockDeploymentConfiguration = new MockDeploymentConfiguration(); mockService = new VaadinServletService(mockServlet, diff --git a/server/tests/src/com/vaadin/tests/server/TestClassesSerializable.java b/server/tests/src/com/vaadin/tests/server/TestClassesSerializable.java index 63f79504ff..10cc7634fd 100644 --- a/server/tests/src/com/vaadin/tests/server/TestClassesSerializable.java +++ b/server/tests/src/com/vaadin/tests/server/TestClassesSerializable.java @@ -47,6 +47,8 @@ public class TestClassesSerializable extends TestCase { "com\\.vaadin\\.server\\.MockServletConfig", // "com\\.vaadin\\.server\\.MockServletContext", // "com\\.vaadin\\.server\\.Constants", // + "com\\.vaadin\\.server\\.VaadinServiceClassLoaderUtil", // + "com\\.vaadin\\.server\\.VaadinServiceClassLoaderUtil\\$GetClassLoaderPrivilegedAction", // "com\\.vaadin\\.server\\.communication\\.FileUploadHandler\\$SimpleMultiPartInputStream", // "com\\.vaadin\\.server\\.communication\\.PushRequestHandler.*", "com\\.vaadin\\.server\\.communication\\.PushHandler.*", // PushHandler diff --git a/server/tests/src/com/vaadin/tests/server/TestStreamVariableMapping.java b/server/tests/src/com/vaadin/tests/server/TestStreamVariableMapping.java index fcc54a989d..b2faca1ed6 100644 --- a/server/tests/src/com/vaadin/tests/server/TestStreamVariableMapping.java +++ b/server/tests/src/com/vaadin/tests/server/TestStreamVariableMapping.java @@ -80,11 +80,11 @@ public class TestStreamVariableMapping extends TestCase { private LegacyCommunicationManager createCommunicationManager() throws Exception { VaadinServlet servlet = new VaadinServlet(); + servlet.init(new MockServletConfig()); VaadinServletService vss = new VaadinServletService(servlet, new MockDeploymentConfiguration()); servlet.init(new MockServletConfig()); return new LegacyCommunicationManager( new AlwaysLockedVaadinSession(vss)); } - }