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

org.directwebremoting.impl.DefaultScriptSession Maven / Gradle / Ivy

Go to download

DWR is easy Ajax for Java. It makes it simple to call Java code directly from Javascript. It gets rid of almost all the boiler plate code between the web browser and your Java code.

There is a newer version: 3.0.2-RELEASE
Show newest version
/*
 * Copyright 2005 Joe Walker
 *
 * 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 org.directwebremoting.impl;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.directwebremoting.ScriptBuffer;
import org.directwebremoting.extend.EnginePrivate;
import org.directwebremoting.extend.MarshallException;
import org.directwebremoting.extend.RealScriptSession;
import org.directwebremoting.extend.ScriptConduit;

/**
 * An implementation of ScriptSession and RealScriptSession.
 * 

There are synchronization constraints on this class. See the field * comments of the type: GuardedBy("lock"). *

In addition you should note that {@link DefaultScriptSession} and * {@link DefaultScriptSessionManager} make calls to each other and you should * take care not to break any constraints in inheriting from these classes. * @author Joe Walker [joe at getahead dot ltd dot uk] */ public class DefaultScriptSession implements RealScriptSession { /** * Simple constructor * @param id The new unique identifier for this session * @param manager The manager that created us * @param page The URL of the page on which we sit * @param httpSessionId The cookie based id of the browser */ protected DefaultScriptSession(String id, DefaultScriptSessionManager manager, String page, String httpSessionId) { this.id = id; if (id == null) { throw new IllegalArgumentException("id can not be null"); } this.httpSessionId = httpSessionId; this.page = page; this.manager = manager; this.creationTime = System.currentTimeMillis(); this.lastAccessedTime = creationTime; } /* (non-Javadoc) * @see org.directwebremoting.ScriptSession#getAttribute(java.lang.String) */ public Object getAttribute(String name) { invalidateIfNeeded(); synchronized (attributes) { return attributes.get(name); } } /* (non-Javadoc) * @see org.directwebremoting.ScriptSession#setAttribute(java.lang.String, java.lang.Object) */ public void setAttribute(String name, Object value) { invalidateIfNeeded(); synchronized (attributes) { attributes.put(name, value); } } /* (non-Javadoc) * @see org.directwebremoting.ScriptSession#removeAttribute(java.lang.String) */ public void removeAttribute(String name) { invalidateIfNeeded(); synchronized (attributes) { attributes.remove(name); } } /* (non-Javadoc) * @see org.directwebremoting.ScriptSession#getAttributeNames() */ public Iterator getAttributeNames() { invalidateIfNeeded(); synchronized (attributes) { Set keys = Collections.unmodifiableSet(attributes.keySet()); return keys.iterator(); } } /* (non-Javadoc) * @see org.directwebremoting.ScriptSession#invalidate() */ public void invalidate() { synchronized (invalidLock) { invalidated = true; manager.invalidate(this); } } /* (non-Javadoc) * @see org.directwebremoting.ScriptSession#isInvalidated() */ public boolean isInvalidated() { synchronized (invalidLock) { return invalidated; } } /* (non-Javadoc) * @see org.directwebremoting.ScriptSession#getId() */ public String getId() { return id; } /* (non-Javadoc) * @see org.directwebremoting.ScriptSession#getCreationTime() */ public long getCreationTime() { invalidateIfNeeded(); return creationTime; } /* (non-Javadoc) * @see org.directwebremoting.ScriptSession#getLastAccessedTime() */ public long getLastAccessedTime() { synchronized (invalidLock) { // For many accesses here we check to see if we should invalidate // ourselves, but getLastAccessedTime() is used as part of the process // that DefaultScriptSessionManager goes through in order to check // everything for validity. So if we do this check here then DSSM will // give a ConcurrentModificationException if anything does timeout // checkNotInvalidated(); return lastAccessedTime; } } /* (non-Javadoc) * @see org.directwebremoting.ScriptSession#addScript(java.lang.String) */ public void addScript(ScriptBuffer script) { invalidateIfNeeded(); if (script == null) { throw new NullPointerException("null script"); } // First we try to add the script to an existing conduit synchronized (scriptLock) { if (conduits.isEmpty()) { // Are there any other script sessions in the same browser // that could proxy the script for us? Collection sessions = manager.getScriptSessionsByHttpSessionId(httpSessionId); ScriptBuffer proxyScript = EnginePrivate.createForeignWindowProxy(getWindowName(), script); boolean written = false; for (Iterator it = sessions.iterator(); !written && it.hasNext();) { RealScriptSession session = it.next(); written = session.addScriptImmediately(proxyScript); } if (!written) { scripts.add(script); } } else { // Try all the conduits, starting with the first boolean written = false; for (Iterator it = conduits.iterator(); !written && it.hasNext();) { ScriptConduit conduit = it.next(); try { written = conduit.addScript(script); } catch (Exception ex) { it.remove(); log.debug("Failed to write to ScriptConduit, removing from list: " + conduit); } } if (!written) { scripts.add(script); } } } } /* (non-Javadoc) * @see org.directwebremoting.extend.RealScriptSession#addScriptConduit(org.directwebremoting.extend.ScriptConduit) */ public void addScriptConduit(ScriptConduit conduit) throws IOException { invalidateIfNeeded(); synchronized (scriptLock) { writeScripts(conduit); conduits.add(conduit); } } /* (non-Javadoc) * @see org.directwebremoting.extend.RealScriptSession#writeScripts(org.directwebremoting.extend.ScriptConduit) */ public void writeScripts(ScriptConduit conduit) throws IOException { invalidateIfNeeded(); synchronized (scriptLock) { for (Iterator it = scripts.iterator(); it.hasNext();) { ScriptBuffer script = it.next(); try { if (conduit.addScript(script)) { it.remove(); } else { // If we didn't write this one, don't bother with any more break; } } catch (MarshallException ex) { log.warn("Failed to convert data. Dropping Javascript: " + script, ex); it.remove(); } } } } /* (non-Javadoc) * @see org.directwebremoting.extend.RealScriptSession#removeScriptConduit(org.directwebremoting.extend.ScriptConduit) */ public void removeScriptConduit(ScriptConduit conduit) { invalidateIfNeeded(); synchronized (scriptLock) { boolean removed = conduits.remove(conduit); if (!removed) { log.debug("Removing unattached ScriptConduit: " + conduit); debug(); } } } /* (non-Javadoc) * @see org.directwebremoting.extend.RealScriptSession#hasWaitingScripts() */ public boolean hasWaitingScripts() { synchronized (scriptLock) { return !scripts.isEmpty(); } } /* (non-Javadoc) * @see org.directwebremoting.ScriptSession#getPage() */ public String getPage() { return page; } /* (non-Javadoc) * @see org.directwebremoting.extend.RealScriptSession#setWindowName(java.lang.String) */ public void setWindowName(String windowName) { this.windowName = windowName; } /* (non-Javadoc) * @see org.directwebremoting.extend.RealScriptSession#getWindowName() */ public String getWindowName() { return windowName; } /* (non-Javadoc) * @see org.directwebremoting.extend.RealScriptSession#updateLastAccessedTime() */ public void updateLastAccessedTime() { // It's a bad idea to call native methods with locks held long temp = System.currentTimeMillis(); synchronized (invalidLock) { lastAccessedTime = temp; } } /** * Check that we are still valid and throw an IllegalStateException if not. * At the same time set the lastAccessedTime flag. * @throws IllegalStateException If this object has become invalid */ protected void invalidateIfNeeded() { if (invalidated) { return; } // It's a bad idea to call native methods with locks held long now = System.currentTimeMillis(); synchronized (invalidLock) { long age = now - lastAccessedTime; if (age > manager.getScriptSessionTimeout()) { invalidate(); } } } /** * Some debug output */ private void debug() { if (log.isDebugEnabled()) { log.debug("Known ScriptConduits:"); for (ScriptConduit scriptConduit : conduits) { log.debug("- " + scriptConduit); } } } /* (non-Javadoc) * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return 572 + id.hashCode(); } /* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (obj == this) { return true; } if (!this.getClass().equals(obj.getClass())) { return false; } DefaultScriptSession that = (DefaultScriptSession) obj; return this.id.equals(that.id); } /* (non-Javadoc) * @see java.lang.Object#toString() */ @Override public String toString() { return "DefaultScriptSession[id=" + id + "]"; } /** * The server side attributes for this page. *

GuardedBy("attributes") */ protected final Map attributes = Collections.synchronizedMap(new HashMap()); /** * When the the web page that we represent last contact us using DWR? *

GuardedBy("invalidLock") */ private long lastAccessedTime = 0L; /** * Have we been made invalid? *

GuardedBy("invalidLock") */ private boolean invalidated = false; /** * The object that we use to synchronize against when we want to work with * the invalidation state of this object */ private final Object invalidLock = new Object(); /** * The script conduits that we can use to transfer data to the browser. *

GuardedBy("scriptLock") */ protected final SortedSet conduits = new TreeSet(); /** * The list of waiting scripts. *

GuardedBy("scriptLock") */ protected final List scripts = new ArrayList(); /** * The object that we use to synchronize against when we want to alter * the path of scripts (to conduits or the scripts list) */ private final Object scriptLock = new Object(); /** * What is our page session id? *

This should not need careful synchronization since it is unchanging */ protected final String id; /** * When we we created? *

This should not need careful synchronization since it is unchanging */ protected final long creationTime; /** * The page being viewed. */ protected final String page; /** * We track window names to link script sessions together and to help * foil the 2 connection limit */ private String windowName; /** * The cookie based id of the browser, or null if no http session is active */ private String httpSessionId; /** * The session manager that collects sessions together *

This should not need careful synchronization since it is unchanging */ protected final DefaultScriptSessionManager manager; /** * The log stream */ private static final Log log = LogFactory.getLog(DefaultScriptSession.class); /* (non-Javadoc) * @see org.directwebremoting.extend.RealScriptSession#addScriptImmediately(org.directwebremoting.ScriptBuffer) */ public boolean addScriptImmediately(ScriptBuffer script) { // TODO Auto-generated method stub return false; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy