/* * Copyright 2004-2015 the Seasar Foundation and the Others. * * 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 org.seasar.framework.container.hotdeploy; import java.io.IOException; import java.io.InputStream; import java.io.Serializable; import javax.servlet.http.HttpSession; import org.seasar.framework.exception.IORuntimeException; import org.seasar.framework.exception.SessionObjectNotSerializableRuntimeException; import org.seasar.framework.unit.S2FrameworkTestCase; /** * @author koichik * */ public class HotdeployHttpSessionTest extends S2FrameworkTestCase { ClassLoader originalClassLoader; protected void setUp() throws Exception { super.setUp(); originalClassLoader = Thread.currentThread().getContextClassLoader(); } protected void tearDown() throws Exception { Thread.currentThread().setContextClassLoader(originalClassLoader); super.tearDown(); } /** * @throws Exception */ public void test() throws Exception { ClassLoader oldCl = new ChildFirstClassLoader(originalClassLoader); Thread.currentThread().setContextClassLoader(oldCl); Class fooClass = oldCl.loadClass(Foo.class.getName()); Object oldFoo = fooClass.newInstance(); assertEquals(Foo.class.getName(), oldFoo.getClass().getName()); assertEquals(oldCl, oldFoo.getClass().getClassLoader()); HotdeployHttpSession session = new HotdeployHttpSession(null, getRequest().getSession()); session.setAttribute("foo", oldFoo); assertSame(oldFoo, session.getAttribute("foo")); session.flush(); ClassLoader newCl = new ChildFirstClassLoader(originalClassLoader); Thread.currentThread().setContextClassLoader(newCl); session = new HotdeployHttpSession(null, getRequest().getSession()); Object newFoo = session.getAttribute("foo"); assertNotSame(oldFoo, newFoo); assertSame(newFoo, session.getAttribute("foo")); assertEquals(Foo.class.getName(), newFoo.getClass().getName()); assertEquals(newCl, newFoo.getClass().getClassLoader()); } /** * @throws Exception */ public void testNotSerializable() throws Exception { HotdeployHttpSession session = new HotdeployHttpSession(null, getRequest().getSession()); try { session.setAttribute("bar", new Bar()); fail(); } catch (SessionObjectNotSerializableRuntimeException expected) { expected.printStackTrace(); } } /** * @throws Exception */ public void testInvalidate() throws Exception { HotdeployHttpServletRequest request = new HotdeployHttpServletRequest( getRequest()); HttpSession s1 = request.getSession(); s1.setAttribute("a", "1"); s1.invalidate(); try { s1.getAttribute("a"); fail(); } catch (IllegalStateException expected) { } HttpSession s2 = request.getSession(); assertNotSame(s1, s2); } /** * @author koichik */ public static class ChildFirstClassLoader extends ClassLoader { /** * @param parent */ public ChildFirstClassLoader(ClassLoader parent) { super(parent); } protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { if (!name.startsWith(HotdeployHttpSession.class.getName()) && !name.equals(HotdeployUtil.REBUILDER_CLASS_NAME)) { return super.loadClass(name, resolve); } InputStream is = getParent().getResourceAsStream( name.replace('.', '/') + ".class"); if (is == null) { throw new ClassNotFoundException(name); } try { byte[] bytes = new byte[is.available()]; is.read(bytes); Class clazz = defineClass(name, bytes, 0, bytes.length); if (resolve) { resolveClass(clazz); } return clazz; } catch (IOException e) { throw new IORuntimeException(e); } } } /** * @author koichik */ public static class Foo implements Serializable { /** */ private static final long serialVersionUID = 1L; } /** * @author koichik */ public static class Bar { } }