com.servoy.j2db.server.headlessclient.eventthread.WicketEvent.java Source code

Java tutorial

Introduction

Here is the source code for com.servoy.j2db.server.headlessclient.eventthread.WicketEvent.java

Source

/*
 This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2011 Servoy BV
    
 This program is free software; you can redistribute it and/or modify it under
 the terms of the GNU Affero General Public License as published by the Free
 Software Foundation; either version 3 of the License, or (at your option) any
 later version.
    
 This program 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 Affero General Public License for more details.
    
 You should have received a copy of the GNU Affero General Public License along
 with this program; if not, see http://www.gnu.org/licenses or write to the Free
 Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
 */

package com.servoy.j2db.server.headlessclient.eventthread;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.wicket.Application;
import org.apache.wicket.IClusterable;
import org.apache.wicket.Page;
import org.apache.wicket.RequestCycle;
import org.apache.wicket.Session;
import org.mozilla.javascript.Function;

import com.servoy.j2db.IServiceProvider;
import com.servoy.j2db.J2DBGlobals;
import com.servoy.j2db.server.headlessclient.ServoyRequestCycle;
import com.servoy.j2db.server.headlessclient.WebClient;
import com.servoy.j2db.server.headlessclient.WebClientSession;
import com.servoy.j2db.util.Debug;

/**
 * An implementation of {@link Event} that executes {@link Function} when {@link #execute()} is called.
 * Will set and reset all the wicket thread locals from the creation thread (the http thread) to the execution thread.
 * 
 * @author jcompagner
 * 
 * @since 6.1
 */
public final class WicketEvent extends Event {
    private final RequestCycle requestCycle;
    private final Session session;
    private final Application application;

    private volatile boolean wasSuspended;

    private final List<IClusterable> dirtyObjectsList;
    private final List<Page> touchedPages;
    private volatile Thread httpThread;
    private final IServiceProvider serviceProvider;
    private volatile List<Runnable> events;
    private final WebClient client;
    private final List<Page> pagesToRelease;

    /**
     * @param f
     * @param scope
     * @param thisObject
     * @param args
     * @param focusEvent
     * @param throwException
     * @param scriptEngine TODO
     */
    public WicketEvent(WebClient client, Runnable runnable) {
        super(runnable);
        this.client = client;
        requestCycle = RequestCycle.get();
        session = Session.get();
        serviceProvider = J2DBGlobals.getServiceProvider();
        application = Application.get();
        dirtyObjectsList = session.getDirtyObjectsList();
        touchedPages = session.getTouchedPages();
        httpThread = Thread.currentThread();
        pagesToRelease = ((WebClientSession) session).getPagesToRelease();
        if (pagesToRelease.size() > 0) {
            Debug.error("there are already locked pages for the wicket event, expect to be 0 " + pagesToRelease);
        }
    }

    /**
     * @param last
     */
    public void updateHttpThread(Event last) {
        if (last instanceof WicketEvent) {
            httpThread = ((WicketEvent) last).httpThread;
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.servoy.j2db.server.headlessclient.IExecuteEvent#execute()
     */
    @Override
    public final void execute() {
        try {
            ServoyRequestCycle.set(requestCycle);
            Session.set(session);
            Application.set(application);
            J2DBGlobals.setServiceProvider(serviceProvider);

            // if somehow there where already locked pages copy them over to the current execute thread. 
            // so that this thread has them as there own lock.
            if (pagesToRelease.size() > 0) {
                List<Page> toReleasePages = ((WebClientSession) session).getPagesToRelease();
                toReleasePages.addAll(pagesToRelease);
            }

            session.moveUsedPage(httpThread, Thread.currentThread());

            super.execute();
        } finally {
            // store the current request events of the client that are 
            // created in this thread on this event object. (see addEvent)
            // but only if it was never suspended. if it was suspended then on this event no http thread is waiting any more on.
            if (!wasSuspended) {
                setEvents(client.getRequestEvents());
            }
            cleanup();
        }
    }

    /**
     * 
     */
    private void cleanup() {
        List<IClusterable> lst = session.getDirtyObjectsList();
        for (IClusterable dirtyObject : lst) {
            if (!dirtyObjectsList.contains(dirtyObject)) {
                dirtyObjectsList.add(dirtyObject);
            }
        }
        lst.clear();

        List<Page> pages = session.getTouchedPages();
        for (Page page : pages) {
            if (!touchedPages.contains(page)) {
                touchedPages.add(page);
            }
        }
        pages.clear();

        // copy over the current owned pages to the http threads list so that it owns and will release it.
        List<Page> toReleasePages = ((WebClientSession) session).getPagesToRelease();
        for (Page page : toReleasePages) {
            if (!pagesToRelease.contains(page)) {
                pagesToRelease.add(page);
            }
        }
        toReleasePages.clear();
        session.moveUsedPage(Thread.currentThread(), httpThread);

    }

    /**
     * 
     */
    @Override
    public void willSuspend() {
        // store the current request events of the client that are 
        // created in this thread on this event object. (see addEvent)
        // but only if it was never suspended. if it was suspended then on this event no http thread is waiting any more on.
        if (!wasSuspended) {
            setEvents(client.getRequestEvents());
        }
        cleanup();
        super.willSuspend();
        wasSuspended = true;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.servoy.j2db.server.headlessclient.eventthread.Event#willResume()
     */
    @Override
    public void willResume() {
        super.willResume();
        // when resuming move all used pages back to this thread.
        // the httpThread should be updated 
        session.moveUsedPage(httpThread, Thread.currentThread());
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.servoy.j2db.server.headlessclient.eventthread.Event#executeInBackground()
     */
    @Override
    public void executeInBackground() {
        cleanup();
        super.executeInBackground();
    }

    /**
     * @return
     */
    public List<Runnable> getEvents() {
        List<Runnable> retval = events;
        events = null;
        return retval == null ? Collections.<Runnable>emptyList() : retval;
    }

    public void setEvents(List<Runnable> requestEvents) {
        if (events != null) {
            Debug.error(new IllegalStateException("events set twice!"));
            events = new ArrayList<Runnable>(events);
            events.addAll(requestEvents);
        } else {
            events = requestEvents;
        }
    }
}