/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
* Copyright (c) Ericsson AB, 2004-2008. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [year]
* [name of copyright owner]"
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package com.ericsson.ssa.container.sim;
import com.ericsson.ssa.config.ConvergedContextImpl;
import com.ericsson.ssa.config.SipFactoryFacade;
import com.ericsson.ssa.container.reporter.Reporter;
import com.ericsson.ssa.sip.persistence.ReplicationUnitOfWork;
import com.sun.enterprise.deployment.web.InitializationParameter;
import org.apache.catalina.InstanceEvent;
import org.apache.catalina.Loader;
import org.apache.catalina.core.StandardWrapper;
import org.jvnet.glassfish.comms.deployment.backend.SipApplicationListeners;
import org.jvnet.glassfish.comms.util.LogUtil;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.ListIterator;
import java.util.logging.Level;
// inserted by hockey (automatic)
import java.util.logging.Logger;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.sip.SipServlet;
import javax.servlet.sip.SipServletContextEvent;
import javax.servlet.sip.SipServletListener;
import javax.servlet.sip.SipServletRequest;
import javax.servlet.sip.TooManyHopsException;
import org.jvnet.glassfish.comms.extensions.Extension;
public class SipServletWrapper extends StandardWrapper {
private static final long serialVersionUID = 3545793282447063096L;
private static Logger logger = LogUtil.SIP_LOGGER.getLogger();
private org.jvnet.glassfish.comms.deployment.backend.Servlet servlet;
private boolean unloading = false;
private SipServletFacade instance;
private SipFactoryFacade sipFactory = null;
javax.servlet.Servlet servletInstance;
public SipServletWrapper(SipFactoryFacade sipFactory,
org.jvnet.glassfish.comms.deployment.backend.Servlet servlet) {
super();
this.sipFactory = sipFactory;
this.servlet = servlet;
setName(servlet.getServletName());
}
public void service(ServletRequest request) throws Exception {
getInstanceSupport()
.fireInstanceEvent(InstanceEvent.BEFORE_DISPATCH_EVENT, instance);
try {
allocate().service(request, null);
} catch (ServletException e) {
logger.log(Level.SEVERE, "Exception in Servlet.service()", e);
} catch (IOException e) {
logger.log(Level.SEVERE, "Exception in Servlet.service()", e);
}
getInstanceSupport()
.fireInstanceEvent(InstanceEvent.AFTER_DISPATCH_EVENT, instance);
}
void beforeService(SipServletFacade instance) {
// Trigger J2EEInstanceListener
getInstanceSupport()
.fireInstanceEvent(InstanceEvent.BEFORE_SERVICE_EVENT, instance);
}
void afterService(SipServletFacade instance) {
getInstanceSupport()
.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT, instance);
}
public void invokeServlet(SipServletRequest request)
throws ServletInvocationException, TooManyHopsException {
try {
if (instance == null) {
allocate();
}
instance.service(request, null);
} catch (TooManyHopsException e) {
//Handled in Application Dispatcher
throw e;
} catch (Exception e) {
logger.log(Level.SEVERE, "Exception allocating servlet ", e);
throw new ServletInvocationException(e);
}
}
public Servlet allocate() throws ServletException {
if (unloading) {
throw new ServletException("The servlet is currently unloading: " +
getName());
}
synchronized (this) {
if (instance == null) {
instance = doLoad();
}
}
return instance;
}
public synchronized void load() throws ServletException {
instance = doLoad();
}
public synchronized void unload() throws ServletException {
unloading = true;
try {
if(servletInstance != null ) {
getInstanceSupport()
.fireInstanceEvent(InstanceEvent.BEFORE_DESTROY_EVENT,
servletInstance);
}
//check against nullpointer if the app is not deployed.
if (instance != null) {
instance.destroy();
}
} catch (Throwable t) {
throw new ServletException(sm.getString(
"standardWrapper.destroyException", getName()), t);
} finally {
try {
if( servletInstance != null) {
getInstanceSupport()
.fireInstanceEvent(InstanceEvent.AFTER_DESTROY_EVENT,
servletInstance);
}
} catch (Throwable t) {
logger.log(Level.WARNING, "Should not happen!!! (TR reported)",
t);
}
instance = null;
unloading = false;
}
}
public String getInitParameter(String name) {
InitializationParameter parameter = servlet.getInitializationParameterByName(name);
if (parameter != null) {
return parameter.getValue();
}
return null;
}
/*
public Enumeration getInitParameters() {
synchronized (servlet) {
return servlet.getInitializationParameters();
}
}
*/
/* (non-Javadoc)
* @see org.apache.catalina.core.StandardWrapper#getInitParameterNames()
*/
public Enumeration getInitParameterNames() {
Enumeration initParams = servlet.getInitParameterNames();
if ((initParams == null) || (!initParams.hasMoreElements())) {
// will return empty enumeration.
return Collections.enumeration(Collections.emptyMap().keySet());
}
return initParams;
}
public String getServletName() {
return servlet.getServletName();
}
private Servlet createSipServlet() throws ServletException, InstantiationException, IllegalAccessException {
ArrayList<SipServlet> sipServletsWithListeners = sipFactory.getSipApplicationListeners()
.getSipServletsWithListeners();
ListIterator<SipServlet> it = sipServletsWithListeners.listIterator();
while (it.hasNext()) {
SipServlet servlet = it.next();
if (servlet.getClass().getName().equals(getServletClass())) {
return servlet;
}
}
Loader loader = getLoader();
if (loader == null) {
unavailable(null);
throw new ServletException("Missing loader: " + getName());
}
ClassLoader classLoader = getLoader().getClassLoader();
Class servletClass = null;
try {
if (classLoader != null) {
try {
// On the first load, we should uase the class loader to load the
// servlet byte code
servletClass = classLoader.loadClass(getServletClass());
} catch (ClassNotFoundException e) {
// This can occcur in servlet reload since the ClassLoader
// doesn't contain /WEB-INF/classes in
// the class loader (but still can throw a
// ClassNotFoundException)
servletClass = Class.forName(getServletClass());
}
} else {
servletClass = Class.forName(getServletClass());
}
} catch (ClassNotFoundException ex) {
unavailable(null);
throw new ServletException(String.format(
"Wrapper cannot find servlet class %1$s or a " +
"class it depends on", getServletClass()), ex);
}
return (Servlet) servletClass.newInstance();
}
protected SipServletFacade doLoad() throws ServletException {
SipServletFacade facade;
Servlet target = null;
try {
target = createSipServlet();
servletInstance = target;
initializeContainer();
facade = new SipServletFacade(target, this, servlet);
// Trigger J2EEInstanceListener
getInstanceSupport()
.fireInstanceEvent(InstanceEvent.BEFORE_INIT_EVENT, target);
ReplicationUnitOfWork uow = ReplicationUnitOfWork.getThreadLocalUnitOfWork();
if (uow == null) {
/**
* If load-on-startup=true, then it will be OOB access and UOW
* will be null. So, we create a new UOW and save it after the
* Servlet's init method is called and all the
* SipServletListener's are called.
*/
uow = new ReplicationUnitOfWork();
try {
initialize(facade, target);
uow.saveAndUnlock(); // TODO : check whether Replication Framework is ready.
} finally {
uow.clearThreadLocal();
}
} else {
/**
* If load-on-startup=false, then the Servlet initialization
* happens during the first traffic to the Servlet.
* So, we will have UOW created by ServletDispatcher.
*/
initialize(facade, target);
}
// Trigger J2EEInstanceListener
getInstanceSupport()
.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT, target);
} catch (InstantiationException ex) {
unavailable(null);
// Trigger J2EEInstanceListener
getInstanceSupport()
.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT, target);
throw new ServletException(String.format(
"Servlet class %1$s cannot be instantiated.",
getServletClass()), ex);
} catch (IllegalAccessException ex) {
unavailable(null);
// Trigger J2EEInstanceListener
getInstanceSupport()
.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT, target);
throw new ServletException(ex);
}
return facade;
}
private void initialize(SipServletFacade facade, Servlet target)
throws ServletException {
facade.init(this);
// After init call SipServletListeners.
SipServletContextEvent ce = new SipServletContextEvent(getServletContext(),
(SipServlet) target);
ConvergedContextImpl context = (ConvergedContextImpl) getParent();
SipApplicationListeners sipApplicationListeners = context.getSipApplicationListeners();
ArrayList<SipServletListener> sipServletListeners = sipApplicationListeners.getSipServletListeners();
for (SipServletListener listener : sipServletListeners) {
listener.servletInitialized(ce);
}
}
private void initializeContainer() {
Extension.getInstance().initializeExtensions
(servletInstance, servlet, getLoader().getClassLoader());
}
}