All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.mobicents.slee.resource.http.HttpServletResourceAdaptor Maven / Gradle / Ivy

There is a newer version: 7.2.0-113
Show newest version
/*
 * JBoss, Home of Professional Open Source
 * Copyright 2011, Red Hat, Inc. and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.mobicents.slee.resource.http;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.slee.Address;
import javax.slee.facilities.EventLookupFacility;
import javax.slee.facilities.Tracer;
import javax.slee.resource.ActivityAlreadyExistsException;
import javax.slee.resource.ActivityHandle;
import javax.slee.resource.ConfigProperties;
import javax.slee.resource.EventFlags;
import javax.slee.resource.FailureReason;
import javax.slee.resource.FireableEventType;
import javax.slee.resource.InvalidConfigurationException;
import javax.slee.resource.Marshaler;
import javax.slee.resource.ReceivableService;
import javax.slee.resource.ResourceAdaptor;
import javax.slee.resource.ResourceAdaptorContext;
import javax.slee.resource.SleeEndpoint;

import net.java.slee.resource.http.events.HttpServletRequestEvent;

import org.mobicents.slee.resource.http.events.HttpServletRequestEventImpl;

/**
 *
 * @author martins
 *
 */
public class HttpServletResourceAdaptor implements ResourceAdaptor, HttpServletResourceEntryPoint {

    private static final String NAME_CONFIG_PROPERTY = "name";
    private ResourceAdaptorContext resourceAdaptorContext;
    private SleeEndpoint sleeEndpoint;
    private Tracer tracer;

    /**
     * the EventLookupFacility is used to look up the event id of incoming events
     */
    private EventLookupFacility eventLookup;

    private RequestLock requestLock;

    private HttpServletRaSbbInterfaceImpl httpRaSbbinterface;

    /**
     * caches the eventIDs, avoiding lookup in container
     */
    private EventIDCache eventIdCache;

    /**
     * tells the RA if an event with a specified ID should be filtered or not
     */
    private EventIDFilter eventIDFilter;

    /**
     * the ra entity name, which matches the servlet name
     */
    private String name;

    /**
     *
     */
    public HttpServletResourceAdaptor() {
    }

    /**
     *
     * @return
     */
    public ResourceAdaptorContext getResourceAdaptorContext() {
        return resourceAdaptorContext;
    }

    /**
     *
     * @return
     */
    public SleeEndpoint getSleeEndpoint() {
        return sleeEndpoint;
    }

    /**
     *
     * @return
     */
    public String getName() {
        return name;
    }

    // lifecycle methods

    /*
     * (non-Javadoc)
     * 
     * @see javax.slee.resource.ResourceAdaptor#setResourceAdaptorContext(javax.slee.resource.ResourceAdaptorContext)
     */
    public void setResourceAdaptorContext(ResourceAdaptorContext raContext) {
        this.resourceAdaptorContext = raContext;
        tracer = raContext.getTracer(HttpServletResourceAdaptor.class.getSimpleName());
        eventIdCache = new EventIDCache(raContext.getTracer(EventIDCache.class.getSimpleName()));
        eventIDFilter = new EventIDFilter();
        sleeEndpoint = raContext.getSleeEndpoint();
        eventLookup = raContext.getEventLookupFacility();
        requestLock = new RequestLock();
        httpRaSbbinterface = new HttpServletRaSbbInterfaceImpl(this);
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.slee.resource.ResourceAdaptor#raConfigure(javax.slee.resource.ConfigProperties)
     */
    public void raConfigure(ConfigProperties configProperties) {
        name = (String) configProperties.getProperty(NAME_CONFIG_PROPERTY).getValue();
    }

    /*
    /*
     * (non-Javadoc)
     * 
     * @see javax.slee.resource.ResourceAdaptor#raActive()
     */
    public void raActive() {
        // register in manager
        HttpServletResourceEntryPointManager.putResourceEntryPoint(name, this);
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.slee.resource.ResourceAdaptor#raStopping()
     */
    public void raStopping() {
    }

    /*
    /*
     * (non-Javadoc)
     * 
     * @see javax.slee.resource.ResourceAdaptor#raInactive()
     */
    public void raInactive() {
        // unregister from manager
        HttpServletResourceEntryPointManager.removeResourceEntryPoint(name);
    }

    /*
    /*
     * (non-Javadoc)
     * 
     * @see javax.slee.resource.ResourceAdaptor#raUnconfigure()
     */
    public void raUnconfigure() {
        name = null;
    }

    /*
    /*
     * (non-Javadoc)
     * 
     * @see javax.slee.resource.ResourceAdaptor#unsetResourceAdaptorContext()
     */
    public void unsetResourceAdaptorContext() {
        resourceAdaptorContext = null;
        tracer = null;
        eventIdCache = null;
        eventIDFilter = null;
        sleeEndpoint = null;
        eventLookup = null;
        requestLock = null;
        httpRaSbbinterface = null;
    }

    // config management methods

    /*
     * (non-Javadoc)
     * 
     * @see javax.slee.resource.ResourceAdaptor#raVerifyConfiguration(javax.slee.resource.ConfigProperties)
     */
    public void raVerifyConfiguration(ConfigProperties configProperties) throws InvalidConfigurationException {
        ConfigProperties.Property property = configProperties.getProperty(NAME_CONFIG_PROPERTY);
        if (property == null) {
            throw new InvalidConfigurationException("name property not found");
        }
        if (!property.getType().equals(String.class.getName())) {
            throw new InvalidConfigurationException("name property must be of type java.lang.String");
        }
        if (property.getValue() == null) {
            // don't think this can happen, but just to be sure
            throw new InvalidConfigurationException("name property must not have a null value");
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.slee.resource.ResourceAdaptor#raConfigurationUpdate(javax.slee.resource.ConfigProperties)
     */
    public void raConfigurationUpdate(ConfigProperties configProperties) {
        throw new UnsupportedOperationException();
    }

    // event filtering methods

    /*
     * (non-Javadoc)
     * 
     * @see javax.slee.resource.ResourceAdaptor#serviceActive(javax.slee.resource.ReceivableService)
     */
    public void serviceActive(ReceivableService receivableService) {
        eventIDFilter.serviceActive(receivableService);
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.slee.resource.ResourceAdaptor#serviceStopping(javax.slee.resource.ReceivableService)
     */
    public void serviceStopping(ReceivableService receivableService) {
        eventIDFilter.serviceStopping(receivableService);
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.slee.resource.ResourceAdaptor#serviceInactive(javax.slee.resource.ReceivableService)
     */
    public void serviceInactive(ReceivableService receivableService) {
        eventIDFilter.serviceInactive(receivableService);
    }

    // mandatory callbacks

    /*
     * (non-Javadoc)
     * 
     * @see javax.slee.resource.ResourceAdaptor#administrativeRemove(javax.slee.resource.ActivityHandle)
     */
    public void administrativeRemove(ActivityHandle activityHandle) {
        // nothing to do
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.slee.resource.ResourceAdaptor#getActivity(javax.slee.resource.ActivityHandle)
     */
    public Object getActivity(ActivityHandle activityHandle) {
        return activityHandle;
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.slee.resource.ResourceAdaptor#getActivityHandle(java.lang.Object)
     */
    public javax.slee.resource.ActivityHandle getActivityHandle(Object object) {
        return (ActivityHandle) object;
    }

    // optional callbacks

    /*
     * (non-Javadoc)
     * 
     * @see javax.slee.resource.ResourceAdaptor#activityEnded(javax.slee.resource.ActivityHandle)
     */
    public void activityEnded(ActivityHandle activityHandle) {
        // not used
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.slee.resource.ResourceAdaptor#activityUnreferenced(javax.slee.resource.ActivityHandle)
     */
    public void activityUnreferenced(ActivityHandle activityHandle) {
        // not used
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.slee.resource.ResourceAdaptor#eventProcessingFailed(javax.slee.resource.ActivityHandle,
     * javax.slee.resource.FireableEventType, java.lang.Object, javax.slee.Address,
	 * javax.slee.resource.ReceivableService, int, javax.slee.resource.FailureReason)
     */
    public void eventProcessingFailed(ActivityHandle activityHandle, FireableEventType fireableEventType,
            Object object, Address address, ReceivableService receivableService, int integer,
            FailureReason failureReason) {
        // not used
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.slee.resource.ResourceAdaptor#eventProcessingSuccessful(javax.slee.resource.ActivityHandle,
     * javax.slee.resource.FireableEventType, java.lang.Object, javax.slee.Address,
     * javax.slee.resource.ReceivableService, int)
     */
    public void eventProcessingSuccessful(ActivityHandle activityHandle, FireableEventType fireableEventType,
            Object object, Address address, ReceivableService receivableService, int integer) {
        // not used
    }

    /*
    /*
     * (non-Javadoc)
     * 
     * @see javax.slee.resource.ResourceAdaptor#eventUnreferenced(javax.slee.resource.ActivityHandle,
     * javax.slee.resource.FireableEventType, java.lang.Object, javax.slee.Address,
     * javax.slee.resource.ReceivableService, int)
     */
    public void eventUnreferenced(ActivityHandle arg0, FireableEventType fireableEventType,
            Object event, Address address, ReceivableService receivableService, int integer) {
        // release event thread
        releaseHttpRequest((HttpServletRequestEvent) event);
    }

    /**
     * Allows control to be returned back to the servlet conainer, which delivered the http request. The container will
     * mandatory close the response stream.
     *
     */
    private void releaseHttpRequest(HttpServletRequestEvent hreqEvent) {
        if (tracer.isFinestEnabled()) {
            tracer.finest("releaseHttpRequest() enter");
        }

        final Object lock = requestLock.removeLock(hreqEvent);
        if (lock != null) {
            synchronized (lock) {
                lock.notify();
            }
        }

        if (tracer.isFineEnabled()) {
            tracer.fine("released lock for http request " + hreqEvent.getId());
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.slee.resource.ResourceAdaptor#queryLiveness(javax.slee.resource.ActivityHandle)
     */
    public void queryLiveness(javax.slee.resource.ActivityHandle activityHandle) {
        // end any idle activity, it should be a leak, this is true assuming
        // that jboss web session timeout is smaller than the container timeout
        // to invoke this method
        if (tracer.isInfoEnabled()) {
            tracer.info("Activity " + activityHandle
                    + " is idle in the container, terminating.");
        }
        endActivity((AbstractHttpServletActivity) activityHandle);
    }

    // interface accessors

    /*
     * (non-Javadoc)
     * 
     * @see javax.slee.resource.ResourceAdaptor#getResourceAdaptorInterface(java.lang.String)
     */
    public Object getResourceAdaptorInterface(String arg0) {
        return httpRaSbbinterface;
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.slee.resource.ResourceAdaptor#getMarshaler()
     */
    public Marshaler getMarshaler() {
        return null;
    }

    // ra logic

    /*
     * (non-Javadoc)
     * 
     * @see org.mobicents.slee.resource.http.HttpServletResourceEntryPoint#onRequest
	 * (javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
     */
    public void onRequest(HttpServletRequest request, HttpServletResponse response) {
        AbstractHttpServletActivity activity = null;

        final HttpServletRequestWrapper requestWrapper = new HttpServletRequestWrapper(request);
        final HttpSessionWrapper sessionWrapper = (HttpSessionWrapper) requestWrapper.getSession(false);
        final HttpServletRequestEvent requestEvent = new HttpServletRequestEventImpl(requestWrapper, response, this);
        final FireableEventType eventType = eventIdCache.getEventType(eventLookup, requestEvent, sessionWrapper);

        response.setStatus(HttpServletResponse.SC_NOT_IMPLEMENTED);

        if (eventIDFilter.filterEvent(eventType)) {
            if (tracer.isInfoEnabled()) {
                tracer.info("Request event filtered: " + requestEvent);
            }
            // dude, get out of here
            return;
        }

        boolean createActivity = true;
        if (sessionWrapper == null) {
            // create request activity
            activity = new HttpServletRequestActivityImpl();
        } else {
            activity = new HttpSessionActivityImpl(sessionWrapper);
            if (sessionWrapper.getResourceEntryPoint() != null) {
                createActivity = false;
            }
        }

        if (createActivity) {
            // we have a session but its not activity yet, add it
            try {
                if (sessionWrapper != null) {
                    sessionWrapper.setResourceEntryPoint(this.name);
                }
                sleeEndpoint.startActivity(activity, activity);
            } catch (ActivityAlreadyExistsException e) {
                if (tracer.isFineEnabled()) {
                    tracer.fine("Failed to add activity " + activity, e);
                }
                // proceed, may be due to fail over
            } catch (Throwable e) {
                tracer.severe("Failed to add activity " + activity, e);
                return;
            }
        }

        if (tracer.isFineEnabled()) {
            tracer.fine("Firing event " + requestEvent + " in activity " + activity);
        }

        final Object lock = requestLock.getLock(requestEvent);
        synchronized (lock) {
            try {
                sleeEndpoint.fireEvent(activity, eventType, requestEvent, null, null,
                        EventFlags.REQUEST_EVENT_UNREFERENCED_CALLBACK);
                // block thread until event has been processed
                lock.wait(15000);
                // the event was unreferenced or 15s timeout, if the activity is the request then end it
                if (sessionWrapper == null) {
                    endActivity(activity);
                }
            } catch (Throwable e) {
                tracer.severe("Failure while firing event " + requestEvent + " on activity " + activity, e);
            }
        }
    }

    private void endActivity(AbstractHttpServletActivity activity) {
        if (tracer.isInfoEnabled()) {
            tracer.fine("Ending activity " + activity);
        }
        try {
            sleeEndpoint.endActivity(activity);
        } catch (Throwable e) {
            tracer.severe("Failed to end activity " + activity, e);
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.mobicents.slee.resource.http.HttpServletResourceEntryPoint#onSessionTerminated(java.lang.String)
     */
    public void onSessionTerminated(HttpSessionWrapper httpSessionWrapper) {
        endActivity(new HttpSessionActivityImpl(httpSessionWrapper));
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy