/* * Copyright (c) 2002-2012 Alibaba Group Holding Limited. * All rights reserved. * * 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.alibaba.citrus.service.velocity; import static com.alibaba.citrus.test.TestUtil.*; import static org.junit.Assert.*; import java.util.Iterator; import com.alibaba.citrus.service.velocity.impl.CloneableEventCartridge; import org.apache.commons.collections.ExtendedProperties; import org.apache.velocity.app.event.EventCartridge; import org.apache.velocity.app.event.EventHandler; import org.apache.velocity.app.event.MethodExceptionEventHandler; import org.apache.velocity.app.event.ReferenceInsertionEventHandler; import org.apache.velocity.context.Context; import org.apache.velocity.runtime.RuntimeInstance; import org.apache.velocity.runtime.RuntimeServices; import org.apache.velocity.util.ContextAware; import org.apache.velocity.util.RuntimeServicesAware; import org.junit.Before; import org.junit.Test; public class CloneableEventCartridgeTests { private RuntimeServices rsvc; private CloneableEventCartridge eventCartridge; private MyHandler handler; @Before public void init() throws Exception { ExtendedProperties config = new ExtendedProperties(); rsvc = new RuntimeInstance(); rsvc.setConfiguration(config); rsvc.init(); eventCartridge = new CloneableEventCartridge(); handler = new MyHandler(); eventCartridge.addEventHandler(handler); } @Test public void initOnce() throws Exception { assertNull(handler.getRuntimeServices()); eventCartridge.initOnce(rsvc); assertSame(rsvc, handler.getRuntimeServices()); // 第二次初始化无效 eventCartridge.initOnce(new RuntimeInstance()); assertSame(rsvc, handler.getRuntimeServices()); } @Test public void initialize() throws Exception { try { eventCartridge.initialize(rsvc); fail(); } catch (IllegalStateException e) { assertThat(e, exception("not initialized yet")); } eventCartridge.initOnce(rsvc); eventCartridge.initialize(rsvc); assertSame(rsvc, handler.getRuntimeServices()); } @Test public void addEventHandlers() { // 正常handler assertTrue(eventCartridge.addEventHandler(new MyHandler())); // not supported handler assertFalse(eventCartridge.addEventHandler(new NotSupportedContextAwareHandler())); // context aware but not cloneable try { eventCartridge.addEventHandler(new ContextAwareButNotCloneable()); fail(); } catch (IllegalArgumentException e) { assertThat( e, exception("EventHandler which implements ContextAware " + "should also implements FastCloneable or Cloneable: " + ContextAwareButNotCloneable.class.getName())); } // context aware and fast cloneable assertTrue(eventCartridge.addEventHandler(new MyFastLocalHandler())); } @Test public void getRuntimeInstance_needNotClone() { eventCartridge.addEventHandler(new MyHandler()); assertSame(eventCartridge, eventCartridge.getRuntimeInstance()); Iterator<?> i = eventCartridge.getReferenceInsertionEventHandlers(); assertSame(handler, i.next()); i.next(); assertFalse(i.hasNext()); } @Test public void getRuntimeInstance_needsClone() { MyLocalHandler localHandler = new MyLocalHandler(); MyFastLocalHandler localHandler2 = new MyFastLocalHandler(); eventCartridge.addEventHandler(localHandler); eventCartridge.addEventHandler(localHandler2); // cloned instance EventCartridge ecruntime = eventCartridge.getRuntimeInstance(); assertNotSame(eventCartridge, ecruntime); Iterator<?> i = ecruntime.getReferenceInsertionEventHandlers(); // 1. same as handler assertSame(handler, i.next()); // 2. cloned localHandler MyLocalHandler newLocalHandler = (MyLocalHandler) i.next(); assertNotNull(newLocalHandler); assertNotSame(localHandler, newLocalHandler); // 3. fast cloned localHandler MyFastLocalHandler newLocalHandler2 = (MyFastLocalHandler) i.next(); assertNotNull(newLocalHandler2); assertNotSame(localHandler2, newLocalHandler2); assertFalse(i.hasNext()); // other handlers i = ecruntime.getMethodExceptionEventHandlers(); // same as newLocalHandler assertSame(newLocalHandler, i.next()); // same as newLocalHandler assertSame(newLocalHandler2, i.next()); assertFalse(i.hasNext()); } @Test public void getRuntimeInstance_cloneFailed() { eventCartridge.addEventHandler(new MyHandler()); eventCartridge.addEventHandler(new CloneableButFailed()); try { eventCartridge.getRuntimeInstance(); fail(); } catch (RuntimeException e) { assertThat(e, exception(UnsupportedOperationException.class, "failed to clone object")); } } @Test public void getRuntimeInstance_fastCloneFailed() { eventCartridge.addEventHandler(new MyHandler()); eventCartridge.addEventHandler(new FastCloneableButFailed()); try { eventCartridge.getRuntimeInstance(); fail(); } catch (RuntimeException e) { assertThat(e, exception(UnsupportedOperationException.class, "failed to copy object")); } } public static class MyHandler implements ReferenceInsertionEventHandler, RuntimeServicesAware { private RuntimeServices rs; public RuntimeServices getRuntimeServices() { return rs; } public void setRuntimeServices(RuntimeServices rs) { this.rs = rs; } public Object referenceInsert(String reference, Object value) { return value; } } public static class MyLocalHandler implements ReferenceInsertionEventHandler, MethodExceptionEventHandler, ContextAware, Cloneable { private Context context; public void setContext(Context context) { this.context = context; } public Object referenceInsert(String reference, Object value) { return String.valueOf(context.get("mark")) + value; } @SuppressWarnings("rawtypes") public Object methodException(Class claz, String method, Exception e) throws Exception { return e.getMessage(); } @Override public Object clone() { try { return super.clone(); } catch (CloneNotSupportedException e) { fail(); return null; } } } public static class MyFastLocalHandler extends MyLocalHandler implements FastCloneable { public Object createCopy() { return super.clone(); } } public static class NotSupportedContextAwareHandler implements ContextAware, EventHandler { public void setContext(Context context) { } } public static class ContextAwareButNotCloneable implements ContextAware, ReferenceInsertionEventHandler { public void setContext(Context context) { } public Object referenceInsert(String reference, Object value) { return null; } } public static class CloneableButFailed implements ContextAware, ReferenceInsertionEventHandler, Cloneable { public void setContext(Context context) { } public Object referenceInsert(String reference, Object value) { return null; } @Override public Object clone() { throw new UnsupportedOperationException("failed to clone object"); } } public static class FastCloneableButFailed implements ContextAware, ReferenceInsertionEventHandler, FastCloneable { public void setContext(Context context) { } public Object referenceInsert(String reference, Object value) { return null; } public Object createCopy() { throw new UnsupportedOperationException("failed to copy object"); } } }