myfaces-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From gcrawf...@apache.org
Subject svn commit: r776491 - in /myfaces/trinidad/trunk: trinidad-api/src/main/java/org/apache/myfaces/trinidad/context/ trinidad-api/src/main/java/org/apache/myfaces/trinidad/event/ trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/application/...
Date Tue, 19 May 2009 22:44:56 GMT
Author: gcrawford
Date: Tue May 19 22:44:56 2009
New Revision: 776491

URL: http://svn.apache.org/viewvc?rev=776491&view=rev
Log:
TRINIDAD-1474 Add Window abstraction to Trinidad

Added:
    myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/context/Window.java
    myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/context/WindowManager.java
    myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/context/WindowManagerFactory.java
    myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/event/WindowEvent.java
    myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/event/WindowLifecycleEvent.java
    myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/event/WindowLifecycleListener.java
    myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/event/WindowLifecycleNavigateEvent.java
Modified:
    myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/context/RequestContext.java
    myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/application/StateManagerImpl.java
    myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/context/RequestContextImpl.java
    myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/FormRenderer.java
    myfaces/trinidad/trunk/trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/renderkit/MFacesContext.java

Modified: myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/context/RequestContext.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/context/RequestContext.java?rev=776491&r1=776490&r2=776491&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/context/RequestContext.java
(original)
+++ myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/context/RequestContext.java
Tue May 19 22:44:56 2009
@@ -20,7 +20,10 @@
 
 import java.awt.Color;
 
+import java.io.IOException;
+
 import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -32,6 +35,7 @@
 
 import javax.faces.component.UIComponent;
 import javax.faces.component.UIViewRoot;
+import javax.faces.context.ExternalContext;
 import javax.faces.context.FacesContext;
 
 import javax.faces.event.PhaseId;
@@ -40,7 +44,9 @@
 import org.apache.myfaces.trinidad.component.visit.VisitContext;
 import org.apache.myfaces.trinidad.component.visit.VisitHint;
 import org.apache.myfaces.trinidad.config.RegionManager;
+import org.apache.myfaces.trinidad.event.WindowLifecycleListener;
 import org.apache.myfaces.trinidad.logging.TrinidadLogger;
+import org.apache.myfaces.trinidad.util.ClassLoaderUtils;
 import org.apache.myfaces.trinidad.webapp.UploadedFileProcessor;
 
 /**
@@ -549,6 +555,79 @@
                                    IllegalAccessException;
 
   /**
+   * <p>
+   * Returns the WindowManager for this request.  A non-null WindowManager
+   * will always be returned.
+   * </p><p>
+   * The default implementation uses the first WindowManagerFactory specified
+   * implementation class in a file named
+   * <code>org.apache.myfaces.trinidad.context.WindowManagerFactory</code>
+   * in the <code>META-INF/services</code> directory and uses the WindowManagerFactory
+   * to create the WindowManager for this Session.  If no WindowManagerFactory is
+   * found, a default WindowManager that never returns any Windows is used.
+   * </p>
+   * @return the WindowManager used for this Session.
+   */
+  public WindowManager getWindowManager()
+  {
+    // implement getWindowManager() in RequestContext for backwards compatibility
+
+    // check if we have cached it for the request
+    WindowManager windowManager = _windowManager;
+    
+    // get instance using the WindowManagerFactory
+    if (windowManager == null)
+    {
+      // check if we have cached it per session
+      ExternalContext extContext = FacesContext.getCurrentInstance().getExternalContext();
+          
+      // create a new instance using the WindowManagerFactory
+      ConcurrentMap<String, Object> concurrentAppMap =
+                                         getCurrentInstance().getApplicationScopedConcurrentMap();
+          
+      WindowManagerFactory windowManagerFactory = (WindowManagerFactory)concurrentAppMap.get(
+                                                            _WINDOW_MANAGER_FACTORY_CLASS_NAME);
+    
+      if (windowManagerFactory == null)
+      {
+        // we haven't registered a WindowManagerFactory yet, so use the services api to see
+        // if a factory has been registered
+        List<WindowManagerFactory> windowManagerFactories =
+                                ClassLoaderUtils.getServices(_WINDOW_MANAGER_FACTORY_CLASS_NAME);
+        
+        if (windowManagerFactories.isEmpty())
+        {
+          // no factory registered so use the factory that returns dummy stub WindowManagers
+          windowManagerFactory = _STUB_WINDOW_MANAGER_FACTORY;
+        }
+        else
+        {
+          // only one WindowManager is allowed, use it
+          windowManagerFactory = windowManagerFactories.get(0);
+        }
+
+        // save the WindowManagerFactory to the application if it hasn't already been saved
+        // if it has been saved, use the previously registered WindowManagerFactory
+        WindowManagerFactory oldWindowManagerFactory = (WindowManagerFactory)
+                            concurrentAppMap.putIfAbsent(_WINDOW_MANAGER_FACTORY_CLASS_NAME,
+                                                         windowManagerFactory);
+        
+        if (oldWindowManagerFactory != null)
+          windowManagerFactory = oldWindowManagerFactory;
+      } // create WindowManagerFactory
+      
+      // get the WindowManager from the factory.  The factory will create a new instance
+      // for this session if necessary
+      windowManager = windowManagerFactory.getWindowManager(extContext);
+      
+      // remember for the next call on this thread
+      _windowManager = windowManager;
+    }
+
+    return windowManager;
+  }
+  
+  /**
    * Releases the RequestContext object.  This method must only
    * be called by the code that created the RequestContext.
    * @exception IllegalStateException if no RequestContext is attached
@@ -617,6 +696,66 @@
     return Thread.currentThread().getContextClassLoader();
   }
 
+  /**
+   * Default WindowManagerFactory implementation that returns the StubWindowManager
+   */
+  private static final class StubWindowManagerFactory extends WindowManagerFactory
+  {
+    public WindowManager getWindowManager(ExternalContext extContext)
+    {
+      return _STUB_WINDOW_MANAGER;
+    }
+    
+    private static final WindowManager _STUB_WINDOW_MANAGER = new StubWindowManager();
+  }
+  
+  /**
+   * Default WindowManager implementation that returns no Windows
+   */
+  private static final class StubWindowManager extends WindowManager
+  {
+    @Override
+    public Window getCurrentWindow(ExternalContext extContext)
+    {
+      return null;
+    }
+    
+    @Override
+    public Map<String, Window> getWindows(ExternalContext extContext)
+    {
+      return Collections.emptyMap();
+    }
+        
+    @Override
+    public void addWindowLifecycleListener(
+      ExternalContext extContext,
+      WindowLifecycleListener windowListener)
+    { 
+      // do nothing
+    }
+    
+    @Override
+    public void removeWindowLifecycleListener(
+      ExternalContext extContext,
+      WindowLifecycleListener windowListener)
+    {
+      // do nothing
+    }
+
+    @Override
+    public void writeState(FacesContext context) throws IOException
+    {
+      // do nothing
+    }
+  }
+
+  /* singleton for WindowManagerFactory that returns WindowManagers that don't do anything
*/
+  private static final WindowManagerFactory _STUB_WINDOW_MANAGER_FACTORY = 
+                                                                    new StubWindowManagerFactory();
+  
+  private static final String _WINDOW_MANAGER_FACTORY_CLASS_NAME = 
+                                                              WindowManagerFactory.class.getName();
+  
   @SuppressWarnings({"CollectionWithoutInitialCapacity"})
   private static final ConcurrentMap<ClassLoader, ConcurrentMap<String, Object>>
_APPLICATION_MAPS =
        new ConcurrentHashMap<ClassLoader, ConcurrentMap<String, Object>>();
@@ -624,4 +763,7 @@
     new ThreadLocal<RequestContext>();
   static private final TrinidadLogger _LOG =
     TrinidadLogger.createTrinidadLogger(RequestContext.class);
+
+  // window manager for this request
+  private WindowManager _windowManager;
 }

Added: myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/context/Window.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/context/Window.java?rev=776491&view=auto
==============================================================================
--- myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/context/Window.java
(added)
+++ myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/context/Window.java
Tue May 19 22:44:56 2009
@@ -0,0 +1,92 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.myfaces.trinidad.context;
+
+import java.io.Serializable;
+
+import javax.faces.context.ExternalContext;
+
+/**
+ * Represents a Window in the current user's Session.  Windows are created and vended
+ * by the Session's WindowManager and the Window for the current request is
+ * available from <code>WindowManager.getCurrentWindow</code>
+ * @see WindowManager#getCurrentWindow
+ */
+public abstract class Window implements Serializable
+{
+  /**
+   * <p>
+   * Represents the current state of the Window.  Windows start out <code>OPEN</code>,
+   * when the current window's document is being unloaded, they move to the <code>UNLOADING</code>
+   * state and then either move back to the <code>OPEN</code> state if the Window's
content
+   * is populated with a new document from the same application, or to the <code>CLOSED</code>
+   * state if it is not.
+   * </p><p>
+   * This represents the framework's best guess at the current status of the Window.
+   * </p>
+   */
+  public enum LifecycleState
+  {
+    /** The Window is currently open */
+    OPEN,
+
+    /** The Window is being unloaded */
+    UNLOADING,
+
+    /** The Window is believed to be closed, either because the window was explicitly closed
+     *  or because the window is suspected to have been closed
+     */
+    CLOSED
+  }
+ 
+  /**
+   * Represents how the window is used in the application
+   */
+  public enum Usage
+  {
+    /** Used as a top-level application window */
+    FRAME,
+
+    /** Used as a dialog */
+    DIALOG
+  }
+ 
+  /**
+   * @return The unique identifier for this Window within the Session
+   */
+  public abstract String getId();
+
+  /**
+   * @return The current state of the Window
+   */
+  public abstract LifecycleState getLifecycleState();
+
+  /**
+   * Returns the Usage of the Window--either a top-level frame or a dialog
+   * @return how the window is used
+   */
+  public abstract Usage getUsage();
+  
+  /**
+   * @return <code>true</code> if the window's document hasn't been rendered
since the Window
+   * was created.
+   */
+  public abstract boolean isNew();
+}
+

Added: myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/context/WindowManager.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/context/WindowManager.java?rev=776491&view=auto
==============================================================================
--- myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/context/WindowManager.java
(added)
+++ myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/context/WindowManager.java
Tue May 19 22:44:56 2009
@@ -0,0 +1,88 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.myfaces.trinidad.context;
+
+import java.io.IOException;
+
+import java.util.Map;
+
+import javax.faces.context.ExternalContext;
+
+import javax.faces.context.FacesContext;
+
+import org.apache.myfaces.trinidad.event.WindowLifecycleListener;
+
+/**
+ * <p>
+ * Manages the set of Windows currently in the Session and allows listeners on the Windows'
+ * lifecycles to be registered.
+ * </p>
+ * @see org.apache.myfaces.trinidad.context.RequestContext#getWindowManager
+ */
+abstract public class WindowManager
+{
+  /**
+   * @param extContext ExternalContext so that the WindowManager may be called before the
+   * FacesContext is available
+   * @return The Window that contains the document making the current request
+   */
+  public abstract Window getCurrentWindow(ExternalContext extContext);
+  
+  /**
+   * @param extContext ExternalContext so that the WindowManager may be called before the
+   * FacesContext is available
+   * @return The Unmodifiable Map of WindowIds to Windows
+   */
+  public abstract Map<String, ? extends Window> getWindows(ExternalContext extContext);
+
+  /**
+   * <p>
+   * Registers a listener that will be informed of changes to the Lifecylce state of any
of
+   * the known Windows.
+   * </p>
+   * <p>
+   * WindowLifecycleListener may be registered automatically by adding a file
+   * containing the names of the classes implementing the WindowListener in a file named
+   * <code>org.apache.myfaces.trinidad.event.WindowListener</code> inside of
+   * the <code>META_INF/services</code> directory.
+   * </p>
+   * @param extContext ExternalContext so that the WindowManager may be called before the
+   * FacesContext is available
+   * @param windowListener
+   */
+  public abstract void addWindowLifecycleListener(
+    ExternalContext extContext, WindowLifecycleListener windowListener);
+
+  /**
+   * Removes a listener that will be informed of changes to the Lifecylce state of any of
+   * the known Windows
+   * @param extContext ExternalContext so that the WindowManager may be called before the
+   * FacesContext is available
+   * @param windowListener
+   */
+  public abstract void removeWindowLifecycleListener(
+    ExternalContext extContext, WindowLifecycleListener windowListener);
+
+  /**
+   * Performs any necessary action to embed the current window identifier into the output
+   * @param context FacesContext to use to write the output
+   * @throws IOException if an output exception occurs
+   */
+  public abstract void writeState(FacesContext context) throws IOException;
+}

Added: myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/context/WindowManagerFactory.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/context/WindowManagerFactory.java?rev=776491&view=auto
==============================================================================
--- myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/context/WindowManagerFactory.java
(added)
+++ myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/context/WindowManagerFactory.java
Tue May 19 22:44:56 2009
@@ -0,0 +1,49 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.myfaces.trinidad.context;
+
+import javax.faces.context.ExternalContext;
+
+/**
+ * <p>
+ * Application-scoped factory for creating per-Session WindowManager instances.  It is the
+ * WindowManagerFactory implementation's responsibility to ensure that only one
+ * WindowManager instance is created per-session.  The WindowManagerFactory is also responsible
+ * for ensuring that any mutable state in the WindowManager instances will be successfully
failed
+ * over.
+ * </p>
+ * <p>
+ * The factory is usually specified by placing the name of the WindowManagerFactory
+ * implementation class in a file named
+ * <code>org.apache.myfaces.trinidad.context.WindowManagerFactory</code>
+ * in the <code>META-INF/services</code> directory
+ * </p>
+ * @see org.apache.myfaces.trinidad.context.WindowManager
+ * @see org.apache.myfaces.trinidad.context.RequestContext#getWindowManager
+ */
+abstract public class WindowManagerFactory
+{
+  /**
+   * Returns the WindowManager to use for this session, creating a new instance if one doesn't
+   * already exist.
+   * @param extContext ExternalContext
+   * @return WindowManager to use for this Session
+   */
+  public abstract WindowManager getWindowManager(ExternalContext extContext);
+}

Added: myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/event/WindowEvent.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/event/WindowEvent.java?rev=776491&view=auto
==============================================================================
--- myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/event/WindowEvent.java
(added)
+++ myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/event/WindowEvent.java
Tue May 19 22:44:56 2009
@@ -0,0 +1,63 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.myfaces.trinidad.event;
+
+import java.util.EventObject;
+import org.apache.myfaces.trinidad.context.Window;
+
+/**
+ * Represents an event delivered with a Window as the source.
+ * @see org.apache.myfaces.trinidad.context.Window
+ * @see org.apache.myfaces.trinidad.event.WindowLifecycleListener
+ */
+public abstract class WindowEvent extends EventObject
+{
+  /**
+   * Constructs a WindowEvent for the specified Window
+   * @param source the Window that tis the source of this event.
+   */
+  protected WindowEvent(Window source)
+  {
+    super(source);
+    
+    if (source == null)
+      throw new NullPointerException();
+  }
+ 
+  /**
+   * @return the Window that this event ocurred on.
+   */
+  @Override
+  public Window getSource()
+  {
+    return (Window)super.getSource();
+  }
+
+  /**
+   * Called by subclass <code>equals</code> implementation to check the WindowEvent
+   * portion of equivalence.
+   * @param e Non-null WindowEvent to compare for equality
+   * @return <code>true</code> if the the WindowEvent satisfies the WindowEvent
portion
+   * of equivalence.
+   */
+  protected final boolean subclassEquals(WindowEvent e)
+  {
+    return getSource().equals(e.getSource());
+  }
+}

Added: myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/event/WindowLifecycleEvent.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/event/WindowLifecycleEvent.java?rev=776491&view=auto
==============================================================================
--- myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/event/WindowLifecycleEvent.java
(added)
+++ myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/event/WindowLifecycleEvent.java
Tue May 19 22:44:56 2009
@@ -0,0 +1,158 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.myfaces.trinidad.event;
+
+import org.apache.myfaces.trinidad.context.Window;
+import org.apache.myfaces.trinidad.context.Window.LifecycleState;
+
+/**
+ * Event delivered when the LifecycleState of a Window changes.  The <code>cause</code>
+ * indicates the cause ot the state change.  The state diagram for theWindow LifecycleStates
+ * is
+ <pre>
+                      +-----------load---------------+
+                      |                              |       ---expire---
+                      V      /---unload----\         |      /            \
+ <start> ---open--->OPEN-----               ----->UNLOADED--              -->CLOSED
+                      |      \--navigate---/         ^      \            /
+                      |                              |       ---close----
+                      +---------closing--------------+
+
+ </pre>
+ * The new LifecycleStates can be retrieved by calling <code>getLifecycleState</code>
on the
+ * source Window or by calling the <code>getNewLifecycleState</code> convenience
function
+ * on the WindowLifecycleEvent
+ * @see org.apache.myfaces.trinidad.context.Window
+ * @see org.apache.myfaces.trinidad.context.Window.LifecycleState
+ */
+public class WindowLifecycleEvent extends WindowEvent
+{
+  /**
+   * What caused the delivery of the WindowLifecycleEvent.
+   */
+  public enum Cause
+  {
+    /**
+     * Delivered when a new Window is open
+     */
+    OPEN,
+    /**
+     * Delivered when the content of a Window have been unloaded but cause of the unloading
+     * isn't known.
+     */
+    UNLOAD,
+    /**
+     * Delivered when the content of a Window have been unloaded as a result of
+     * navigating within the application
+     */
+    NAVIGATE,
+    /**
+     * Delivered when the content of a Window have been unloaded in order to
+     * close the window
+     */
+    CLOSING,
+    
+    /**
+     * The contents of an existing Window are being reloaded
+     */
+    RELOAD,
+    
+    /**
+     * The Window is believed to have been closed by the user
+     */
+    EXPIRE,
+
+    /**
+     * The Window is believed to have been closed by the user
+     */
+    CLOSE
+  }
+
+  /**
+   * Creates a WindowOpenEvent event for the specified Window and cause.
+   */
+  public WindowLifecycleEvent(Window source, Cause cause)
+  {
+    super(source);
+    
+    if (cause == null)
+      throw new NullPointerException();
+    
+    _cause = cause;
+  }
+ 
+  /**
+   * @return the cause of the WindowOpen event.
+   */
+  public Cause getCause()
+  {
+    return _cause;
+  }
+  
+  /**
+   * Returns the new LifecycleState that the Window has moved to.
+   */
+  public final LifecycleState getNewLifecycleState()
+  {
+    return getSource().getLifecycleState();
+  }
+
+  @Override  
+  public int hashCode()
+  {
+    return getSource().hashCode() * 37 + _cause.hashCode();
+  }
+  
+  @Override
+  public boolean equals(Object o)
+  {
+    if (this == o)
+      return true;
+    else if ((o != null) && (o.getClass() == WindowLifecycleEvent.class))
+    {
+      return subclassEquals((WindowLifecycleEvent)o);
+    }
+    else
+    {
+      return false;
+    }
+  }
+  
+  @Override
+  public String toString()
+  {
+    return super.toString() + ",cause=" + _cause;
+  }
+  
+  /**
+   * Called by subclass <code>equals</code> implementation to check the WindowEvent
+   * portion of equivalence.
+   * @param e Non-null WindowEvent to compare for equality
+   * @return <code>true</code> if the the WindowEvent satisfies the WindowEvent
portion
+   * of equivalence.
+   */
+  protected final boolean subclassEquals(WindowLifecycleEvent e)
+  {
+    return super.subclassEquals(e) && _cause.equals(e._cause);
+  }
+
+  private final Cause _cause;
+  
+  private static final long serialVersionUID = 1L;
+}

Added: myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/event/WindowLifecycleListener.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/event/WindowLifecycleListener.java?rev=776491&view=auto
==============================================================================
--- myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/event/WindowLifecycleListener.java
(added)
+++ myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/event/WindowLifecycleListener.java
Tue May 19 22:44:56 2009
@@ -0,0 +1,58 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.myfaces.trinidad.event;
+
+import java.util.EventListener;
+
+import javax.faces.context.ExternalContext;
+
+/**
+ * <p>
+ * A listener called when the Lifecyle of a Window changes.
+ * </p>
+ * <p>
+ * Window listeners may be registered automatically by adding a file
+ * containing the names of the classes implementing the WindowLifecycleListener in a file
named
+ * <code>org.apache.myfaces.trinidad.event.WindowLifecycleListener</code> inside
of
+ * the <code>META_INF/services</code> directory or manually by calling
+ * <code>WindowManager.addWindowLifecycleListener</code>
+ * @see org.apache.myfaces.trinidad.context.WindowManager
+ */
+public interface WindowLifecycleListener extends EventListener
+{
+  /**
+   * <p>
+   * Called when the LifecycleState of a Window changes.
+   * </p>
+   * <p>
+   * The current lifecycle state of a Window is the framework's best guess and may not be
accurate.
+   * In particular, the last remaining open window may never move into the <code>CLOSED</code>
state
+   * once it has moved into the <code>UNLOADED</code> state.  In addition, no
Window lifecycle events
+   * are delivered if the Session ceases to exist.
+   * </p>
+   * <p>
+   * The FacesContext may not be available at the time that this event is delivered.
+   * </p>
+   * @param extContext ExternalContext available for this event
+   * @param event WindowLifecycleEvent indicating the cause of the change to the Window's
+   * LifecycleState
+   */
+  public abstract void processWindowLifecylce(
+    ExternalContext extContext, WindowLifecycleEvent event);
+}

Added: myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/event/WindowLifecycleNavigateEvent.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/event/WindowLifecycleNavigateEvent.java?rev=776491&view=auto
==============================================================================
--- myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/event/WindowLifecycleNavigateEvent.java
(added)
+++ myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/event/WindowLifecycleNavigateEvent.java
Tue May 19 22:44:56 2009
@@ -0,0 +1,85 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.myfaces.trinidad.event;
+
+import org.apache.myfaces.trinidad.context.Window;
+
+/**
+ * WindowLifecycleEvent delivered when the current window is being unloaded
+ * in order to navigate to a new location
+ */
+public final class WindowLifecycleNavigateEvent extends WindowLifecycleEvent
+{
+  public WindowLifecycleNavigateEvent(Window source, String destination)
+  {
+    super(source, WindowLifecycleEvent.Cause.NAVIGATE);
+    
+    if (destination == null)
+      throw new NullPointerException();
+    
+    _destination = destination;
+  }
+  
+  /**
+   * Returns the URL to which the page is navigating.
+   * <p>
+   * The destination is not guaranteed to be normalized;  it may
+   * be absolute, page-relative, or server-relative.  It is also
+   * not guaranteed to be correct, as a browser
+   * may be redirected to an alternate destination.
+   */
+  public String getDestination()
+  {
+    return _destination;
+  }
+
+  @Override  
+  public int hashCode()
+  {
+    return super.hashCode() * 37 + _destination.hashCode();
+  }
+
+
+  @Override
+  public boolean equals(Object o)
+  {
+    if (this == o)
+      return true;
+    else if ((o != null) && (o instanceof WindowLifecycleNavigateEvent))
+    {
+      return subclassEquals((WindowLifecycleEvent)o) &&
+             _destination.equals(((WindowLifecycleNavigateEvent)o)._destination);
+    }
+    else
+    {
+      return false;
+    }
+  }
+
+  @Override
+  public String toString()
+  {
+    return super.toString() + ",destination=" + _destination;
+  }
+
+
+  private final String _destination;
+  
+  private static final long serialVersionUID = 1L;
+}

Modified: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/application/StateManagerImpl.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/application/StateManagerImpl.java?rev=776491&r1=776490&r2=776491&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/application/StateManagerImpl.java
(original)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/application/StateManagerImpl.java
Tue May 19 22:44:56 2009
@@ -52,6 +52,7 @@
 import java.io.ObjectOutputStream;
 
 import org.apache.myfaces.trinidad.bean.util.StateUtils;
+import org.apache.myfaces.trinidad.context.Window;
 import org.apache.myfaces.trinidadinternal.context.RequestContextImpl;
 import org.apache.myfaces.trinidadinternal.context.TrinidadPhaseListener;
 
@@ -312,9 +313,12 @@
 
         Map<String, Object> sessionMap = extContext.getSessionMap();
 
-        // Store bits of the session as subkeys off of the session
-        Map<String, PageState> stateMap = new SubKeyMap<PageState>(sessionMap,
-                                                                   _VIEW_CACHE_KEY + ".");
+        RequestContext trinContext = RequestContext.getCurrentInstance();
+        
+        // get view cache key with "." separator suffix to separate the SubKeyMap keys
+        String subkey = _getViewCacheKey(extContext, trinContext, _SUBKEY_SEPARATOR);
+        
+        Map<String, PageState> stateMap = new SubKeyMap<PageState>(sessionMap,
subkey);
 
         // Sadly, we can't save just a SerializedView, because we should
         // save a serialized object, and SerializedView is a *non*-static
@@ -332,12 +336,14 @@
         // laying around if the user navigates off of a page using a GET
         synchronized(extContext.getSession(true))
         {
-          PageState activePageState = (PageState)sessionMap.get(_ACTIVE_PAGE_STATE_SESSION_KEY);
+          // get the per-window key for the active page state
+          String activePageStateKey = _getActivePageStateKey(extContext, trinContext);
+          PageState activePageState = (PageState)sessionMap.get(activePageStateKey);
 
           if (activePageState != null)
             activePageState.clearViewRootState();
 
-          sessionMap.put(_ACTIVE_PAGE_STATE_SESSION_KEY, pageState);
+          sessionMap.put(activePageStateKey, pageState);
         }
         
         String requestToken = _getRequestTokenForResponse(context);
@@ -497,10 +503,12 @@
   public UIViewRoot restoreView(FacesContext context, String viewId,
                                 String renderKitId)
   {
+    final ExternalContext extContext = context.getExternalContext();
+    
     // If we're being asked to execute a "return" event from, say, a dialog, always 
     // restore the "launch view", which was set over in the TrinidadFilter.
     UIViewRoot launchView = (UIViewRoot)
-      context.getExternalContext().getRequestMap().remove(RequestContextImpl.LAUNCH_VIEW);
+                            extContext.getRequestMap().remove(RequestContextImpl.LAUNCH_VIEW);
     if (launchView != null)
     {
       TrinidadPhaseListener.markPostback(context);
@@ -561,9 +569,14 @@
       }
       else
       {
+        // get view cache key with "." separator suffix to separate the SubKeyMap keys
+        String subkey = _getViewCacheKey(extContext,
+                                         RequestContext.getCurrentInstance(),
+                                         _SUBKEY_SEPARATOR);
+        
         Map<String, PageState> stateMap = new SubKeyMap<PageState>(
-                         context.getExternalContext().getSessionMap(),
-                         _VIEW_CACHE_KEY + ".");
+                         extContext.getSessionMap(),
+                         subkey);
         viewState = stateMap.get(token);
 
         if (viewState != null)
@@ -702,10 +715,111 @@
 
   private TokenCache _getViewCache(FacesContext context)
   {
+    ExternalContext extContext = context.getExternalContext();
+    
     return TokenCache.getTokenCacheFromSession(context,
-                                               _VIEW_CACHE_KEY,
+                                               _getViewCacheKey(extContext,
+                                                                RequestContext.getCurrentInstance(),
+                                                                null),
                                                true,
-                                               _getCacheSize(context));
+                                               _getCacheSize(extContext));
+  }
+
+  
+
+  /**
+   * Returns a key suitable for finding the per-window active page state key
+   * @param extContext
+   * @param trinContext
+   * @return
+   */
+  static private String _getActivePageStateKey(
+    ExternalContext extContext,
+    RequestContext trinContext)
+  {
+    return _getPerWindowCacheKey(extContext, trinContext, _ACTIVE_PAGE_STATE_SESSION_KEY,
null);
+  }
+  
+  /**
+   * Returns a key suitable for finding the per-window cache key
+   * @param extContext
+   * @param trinContext
+   * @param suffix
+   * @return
+   */
+  static private String _getViewCacheKey(
+    ExternalContext extContext,
+    RequestContext trinContext,
+    Character suffix)
+  {
+    return _getPerWindowCacheKey(extContext, trinContext, _VIEW_CACHE_KEY, suffix);
+  }
+  
+  /**
+   * Returns a key of the form <prefix>.<windowid><suffix> if a window
and a suffix are available
+   *                           <prefix>.<window> if just a window is available
+   *                           <prefix> if neither a window or a suffix is available
+   * @param eContext
+   * @param trinContext
+   * @param prefix
+   * @param suffix
+   * @return
+   */
+  static private String _getPerWindowCacheKey(
+    ExternalContext eContext,
+    RequestContext trinContext,
+    String    prefix,
+    Character suffix)
+  {
+    Window currWindow = trinContext.getWindowManager().getCurrentWindow(eContext);
+    
+    // if we have a current window or a suffix, we need a StringBuilder to calculate the
cache key
+    if ((currWindow != null) || (suffix != null))
+    {
+      // get the window id and the extra size neeeded to store it and its separator
+      String windowId;
+      int windowPartSize;
+    
+      if (currWindow != null)
+      {
+        windowId = currWindow.getId();
+        
+        // add 1 for separator
+        windowPartSize = windowId.length() + 1;
+      }
+      else
+      {
+        windowId = null;
+        windowPartSize = 0;
+      }
+      
+      int builderSize =  prefix.length() + windowPartSize;
+      
+      // add extra space for the suffix Character
+      if (suffix != null)
+        builderSize += 1;
+      
+      // add the constant part to the StringBuilder
+      StringBuilder keyBuilder = new StringBuilder(builderSize);
+      keyBuilder.append(prefix);
+      
+      // add the windowId and its separator
+      if (currWindow != null)
+      {
+        keyBuilder.append('.');
+        keyBuilder.append(windowId);
+      }
+      
+      // add the suffix if any
+      if (suffix != null)
+        keyBuilder.append(suffix);
+      
+      return keyBuilder.toString();
+    }
+    else
+    {
+      return prefix;
+    }
   }
 
   /**
@@ -725,11 +839,10 @@
     return true;
   }
 
-  private int _getCacheSize(FacesContext context)
+  private int _getCacheSize(ExternalContext extContext)
   {
-    ExternalContext external = context.getExternalContext();
     Object maxTokens =
-      external.getInitParameterMap().get(CLIENT_STATE_MAX_TOKENS_PARAM_NAME);
+      extContext.getInitParameterMap().get(CLIENT_STATE_MAX_TOKENS_PARAM_NAME);
     if (maxTokens != null)
     {
       try
@@ -767,7 +880,7 @@
       return cache;
     }
   }
-
+  
   @SuppressWarnings("unchecked")
   static private Map<String, PageState> _getPerSessionApplicationViewCache(FacesContext
context)
   {
@@ -1110,9 +1223,13 @@
   private       Boolean      _useApplicationViewCache;
   private       Boolean      _structureGeneratedByTemplate;
 
+  private static final Character _SUBKEY_SEPARATOR = new Character('.');
+  
   private static final int _DEFAULT_CACHE_SIZE = 15;
 
   private static final Object _APPLICATION_VIEW_CACHE_LOCK = new Object();
+  
+  // base key used to identify the view cache.  The window name, if any, is appended to this
   private static final String _VIEW_CACHE_KEY =
     "org.apache.myfaces.trinidadinternal.application.VIEW_CACHE";
 

Modified: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/context/RequestContextImpl.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/context/RequestContextImpl.java?rev=776491&r1=776490&r2=776491&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/context/RequestContextImpl.java
(original)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/context/RequestContextImpl.java
Tue May 19 22:44:56 2009
@@ -871,7 +871,6 @@
   {
     private MockPartialPageContext(FacesContext facesContext)
     {
-      _facesContext = facesContext;
     }
 
     @Override
@@ -942,8 +941,7 @@
       throw new NotImplementedException();
     }
 
-    private FacesContext _facesContext;
-    private HashSet<String> _componentIds = new HashSet<String>();
+    private final HashSet<String> _componentIds = new HashSet<String>();
   }
 
   private RequestContextBean _bean;

Modified: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/FormRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/FormRenderer.java?rev=776491&r1=776490&r2=776491&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/FormRenderer.java
(original)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/FormRenderer.java
Tue May 19 22:44:56 2009
@@ -386,6 +386,9 @@
     // Include JSF state.
     context.getApplication().getViewHandler().writeState(context);
 
+    // Include the Window state, if any
+    RequestContext.getCurrentInstance().getWindowManager().writeState(context);
+
     // Render any needed values
     //VAC this condition is needed for bug 4526850- It ensures that only
     //state token and form name parameters are overwritten when there is

Modified: myfaces/trinidad/trunk/trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/renderkit/MFacesContext.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/renderkit/MFacesContext.java?rev=776491&r1=776490&r2=776491&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/renderkit/MFacesContext.java
(original)
+++ myfaces/trinidad/trunk/trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/renderkit/MFacesContext.java
Tue May 19 22:44:56 2009
@@ -54,7 +54,7 @@
   {
     super(application);
     setCurrentInstance(this);
-    _external = new External(testMode);
+    _external = new External(testMode, application);
   }
 
   @Override
@@ -201,11 +201,13 @@
 
   private static final class External extends MockExternalContext
   {
-    public External(boolean testMode)
+    public External(boolean testMode, Object contextObject)
     {
       super(null, null, null);
       
       _testMode = testMode;
+      _contextObject = contextObject;
+      
       File file = null;
       try
       {
@@ -223,16 +225,27 @@
     }
 
     @Override
-    public Object getContext() { return null; }
+    public Object getContext() { return _contextObject; }
     
     @Override
-    public Object getRequest() { return null; }
+    public Object getRequest() { return _requestObject; }
     
     @Override
-    public Object getResponse() { return null; }
+    public Object getResponse() { return _responseObject; }
     
     @Override
-    public Object getSession(boolean create) { return null; }
+    public Object getSession(boolean create)
+    {
+      // implement lazy behavior for session creation
+      if (create)
+      {
+        // force SessionMap to be created
+        getSessionMap();
+      }
+      
+      // use the session Map as the session object 
+      return _sessionMap;
+    }
     
     @Override
     public String getRequestContextPath() { return "/test-context-path"; }
@@ -320,6 +333,17 @@
       // we shouldn't use any servlet APIs.  So, intercept the
       // session map.   Ideally, renderers shouldn't write into
       // the session map, but see above...
+      if (_sessionMap == null)
+      {
+        synchronized (_contextObject)
+        {
+          if (_sessionMap == null)
+          {
+            _sessionMap = Collections.synchronizedMap(new HashMap<String, Object>(2));
+          }
+        }
+      }
+      
       return _sessionMap;
     }
 
@@ -331,9 +355,16 @@
       return _requestMap;
     }
 
+    private final Object _contextObject;
+    private final Object _requestObject = new String("request object");
+    private final Object _responseObject = new String("response object");
+    
     private final Map<String, Object> _requestMap = new HashMap<String, Object>(2);
-    private final Map<String, Object> _sessionMap = new HashMap<String, Object>(2);
-    private final Map<String, Object> _applicationMap = new HashMap<String, Object>(2);
+    private final Map<String, Object> _applicationMap = 
+                                        Collections.synchronizedMap(new HashMap<String,
Object>(2));
+    
+    private volatile Map<String, Object> _sessionMap = null;
+    
     private final boolean _testMode;
   }
   private static final String _GLOBAL_MESSAGE = "org.apache.myfaces.trinidadinternal.renderkit.MFacesContext.GLOBAL_MESSAGE";



Mime
View raw message