Index: modules/http-servlet/src/main/java/com/sun/grizzly/http/servlet/ServletAdapter.java =================================================================== --- modules/http-servlet/src/main/java/com/sun/grizzly/http/servlet/ServletAdapter.java (revision 3408) +++ modules/http-servlet/src/main/java/com/sun/grizzly/http/servlet/ServletAdapter.java (working copy) @@ -53,17 +53,21 @@ import com.sun.grizzly.util.http.HttpRequestURIDecoder; import java.io.IOException; import java.util.ArrayList; +import java.util.EventListener; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.locks.ReentrantLock; import java.util.logging.Level; +import java.util.logging.Logger; import javax.servlet.Filter; import javax.servlet.Servlet; import javax.servlet.ServletContext; import javax.servlet.ServletContextAttributeListener; import javax.servlet.ServletContextListener; import javax.servlet.ServletException; +import javax.servlet.http.HttpSessionAttributeListener; +import javax.servlet.http.HttpSessionListener; /** * Adapter class that can initiate a {@link javax.servlet.FilterChain} and execute its @@ -92,10 +96,10 @@ // Any ServletConfig.getXXX method can be configured using this call. // The same apply for ServletContext.getXXX. sa.setProperty("display-name","myServlet"); - sa.addListener("foo.bar.myHttpSessionListener"); - sa.addListener(MyOtherHttpSessionListener.class); - sa.addServletContextListener(new FooServletContextListener()); - sa.addServletContextAttributeListener(new BarServletCtxAttListener()); + sa.addListener("foo.bar.MyHttpSessionListener"); + sa.addListener(MyOtherHttpSessionAttListener.class); + sa.addListener(new FooServletContextListener()); + sa.addListener(new BarServletCtxAttListener()); sa.addContextParameter("databaseURI","jdbc://"); sa.addInitParameter("password","hello"); sa.setServletPath("/MyServletPath"); @@ -118,7 +122,7 @@ protected volatile Servlet servletInstance = null; private FilterChainImpl filterChain = new FilterChainImpl(); - private transient ArrayList listeners; + private transient List listeners = new ArrayList(); private String servletPath = ""; @@ -222,21 +226,24 @@ * @param servletCtx {@link ServletContextImpl} to be used by new instance. * @param contextParameters Context parameters. * @param servletInitParameters servlet initialization parameres. - * @param listeners Listeners. + * @param listenerNames Listeners. * @param initialze false only when the {@link #newServletAdapter()} is invoked. */ protected ServletAdapter(String publicDirectory, ServletContextImpl servletCtx, HashMap contextParameters, HashMap servletInitParameters, - ArrayList listeners, boolean initialize){ + ArrayList listenerNames, boolean initialize){ super(publicDirectory); this.servletCtx = servletCtx; servletConfig = new ServletConfigImpl(servletCtx, servletInitParameters); this.contextParameters = contextParameters; this.servletInitParameters = servletInitParameters; - this.listeners = listeners; + for (String listenerName : listenerNames) { + addServletListener(listenerName); + } this.initialize = initialize; } + /** * Convenience constructor. * @@ -249,6 +256,31 @@ */ protected ServletAdapter(String publicDirectory, ServletContextImpl servletCtx, HashMap contextParameters, HashMap servletInitParameters, + List listeners, boolean initialize){ + super(publicDirectory); + this.servletCtx = servletCtx; + servletConfig = new ServletConfigImpl(servletCtx, servletInitParameters); + this.contextParameters = contextParameters; + this.servletInitParameters = servletInitParameters; + for (EventListener listener : listeners) { + addListener(listener); + } + this.initialize = initialize; + } + + + /** + * Convenience constructor. + * + * @param publicDirectory The folder where the static resource are located. + * @param servletCtx {@link ServletContextImpl} to be used by new instance. + * @param contextParameters Context parameters. + * @param servletInitParameters servlet initialization parameres. + * @param listeners Listeners. + * @param initialze false only when the {@link #newServletAdapter()} is invoked. + */ + protected ServletAdapter(String publicDirectory, ServletContextImpl servletCtx, + HashMap contextParameters, HashMap servletInitParameters, boolean initialize){ super(publicDirectory); this.servletCtx = servletCtx; @@ -587,18 +619,74 @@ public void setContextPath(String contextPath) { this.contextPath = contextPath; } - + + /** - * Add Servlet listeners that implement {@link EventListener} + * Add Servlet or HTTP Session listeners that implement {@link EventListener} * - * @param listenerName name of a Servlet listener + * @param listenerName name of a listener class + * @deprecated use {@link addListener(String)} instead */ public void addServletListener(String listenerName){ + addListener(listenerName); + } + + + /** + * Add Servlet or HTTP Session listeners that implement {@link EventListener} + * + * @param listenerName name of a listener class + * @param listenerName + */ + public void addListener(String listenerName){ if (listenerName == null) return; - listeners.add(listenerName); + Class klazz = null; + try { + klazz = Thread.currentThread(). + getContextClassLoader().loadClass(listenerName); + } catch (Throwable e) { + throw new IllegalArgumentException("Unable to load listener class: " + listenerName, e); + } + + addListener(klazz); } + /** + * Add Servlet or HTTP Session listener by class. + * + * @param listenerClass servlet or http session listener class with noarg + * constructor which can be called without throwing an exception + */ + public void addListener(Class listenerClass) { + EventListener listener = null; + + try { + listener = listenerClass.newInstance(); + } catch (InstantiationException ex) { + throw new IllegalArgumentException("Listener's noarg constructor should" + + "throw no exceptions", ex); + } catch (IllegalAccessException ex) { + throw new IllegalArgumentException("Listener's noarg constructor should" + + "throw no exceptions", ex); + } + + addListener(listener); + } + + + /** + * Add Servlet or HTTP Session listener by instance. + * + * @param listener servlet or http session listener + */ + public void addListener(EventListener listener) { + validateListenerClass(listener.getClass()); + listeners.add(listener); + } + + + /** * Use reflection to configure Object setter. * * @param object Populate this object with available properties. @@ -698,10 +786,41 @@ } protected ArrayList getListeners() { - return listeners; + ArrayList listenerNames = new ArrayList(); + + for (EventListener listener : listeners) { + listenerNames.add(listener.getClass().getName()); + } + + return listenerNames; } + protected HashMap getContextParameters() { return contextParameters; } + + + /** + * Throws an exception if klazz does not implement at least one of + * ServletContextListener, ServletContextAttributeListener, HttpSessionListener + * or HttpSessionAttributeListener. + * + * @param klazz + * @throws IllegalArgumentException + */ + private void validateListenerClass(Class klazz) { + if (ServletContextListener.class.isAssignableFrom(klazz) || + ServletContextAttributeListener.class.isAssignableFrom(klazz) || + HttpSessionListener.class.isAssignableFrom(klazz) || + HttpSessionAttributeListener.class.isAssignableFrom(klazz)) { + } else { + throw new IllegalArgumentException("Invalid listener class: " + klazz.getName() + + " - valid listener must implement at least one of " + + "javax.servlet.ServletContextListener, " + + "javax.servlet.ServletContextAttributeListener, " + + "javax.servlet.http.HttpSessionListener, " + + "javax.servlet.http.HttpSessionAttributeListener"); + } + } } Index: modules/http-servlet/src/main/java/com/sun/grizzly/http/servlet/ServletContextImpl.java =================================================================== --- modules/http-servlet/src/main/java/com/sun/grizzly/http/servlet/ServletContextImpl.java (revision 3408) +++ modules/http-servlet/src/main/java/com/sun/grizzly/http/servlet/ServletContextImpl.java (working copy) @@ -126,32 +126,24 @@ /** * Notify the {@link ServletContextListener} that we are starting. */ - protected void initListeners(ArrayList listeners){ + protected void initListeners(List listeners){ + eventListeners.addAll(listeners); - for(String listenerClass: listeners){ - EventListener el = null; - try { - el = (EventListener)Thread.currentThread().getContextClassLoader() - .loadClass(listenerClass).newInstance(); - eventListeners.add(el); - } catch (Throwable e) { - logger.warning("Unable to load listener: " + el); - } - } - ServletContextEvent event = null; - for (int i = 0; i < eventListeners.size(); i++) { - if (!(eventListeners.get(i) instanceof ServletContextListener)) + for (EventListener eListener : eventListeners) { + if (!(eListener instanceof ServletContextListener)) continue; - ServletContextListener listener = - (ServletContextListener) eventListeners.get(i); + ServletContextListener listener = (ServletContextListener) eListener; + if (event == null) { event = new ServletContextEvent(this); } + try { listener.contextInitialized(event); } catch (Throwable t) { - logger.log(Level.SEVERE,"",t); + logger.log(Level.SEVERE,"Failed to send 'contextInitialized' " + + "notification to listener: " + listener.getClass().getName(), t); } } } @@ -162,18 +154,21 @@ */ protected void destroyListeners(){ ServletContextEvent event = null; - for (int i = 0; i < eventListeners.size(); i++) { - if (!(eventListeners.get(i) instanceof ServletContextListener)) + + for (EventListener eListener : eventListeners) { + if (!(eListener instanceof ServletContextListener)) continue; - ServletContextListener listener = - (ServletContextListener) eventListeners.get(i); + ServletContextListener listener = (ServletContextListener) eListener; + if (event == null) { event = new ServletContextEvent(this); } + try { listener.contextDestroyed(event); } catch (Throwable t) { - logger.log(Level.SEVERE,"",t); + logger.log(Level.SEVERE,"Failed to send 'contextDestroyed' " + + "notification to listener: " + listener.getClass().getName(), t); } } }