CVS: Tapestry/framework/src/net/sf/tapestry/record SessionPageRecorder.java,NONE,1.1.2.1 DefaultValuePersister.java,NONE,1.1.2.1 ImmutableValueCopier.java,NONE,1.1.2.1 EJBCopier.java,NONE,1.1.2.1 IValueCopier.java,NONE,1.1.2.1 ListCopier.java,NONE,1.1.2.1 EJBWrapperCopier.java,NONE,1.1.2.1 ArrayCopier.java,NONE,1.1.2.1 EJBWrapper.java,NONE,1.1.2.1 IValuePersister.java,NONE,1.1.2.1 ChangeKey.java,1.5,1.5.2.1 PageRecorder.java,1.9,1.9.2.1 PageChange.java,1.5,1.5.2.1 SimplePageRecorder.java,1.8,NONE
Howard Lewis Ship <[email protected]>
| Newsgroups | gmane.comp.java.tapestry.cvs |
|---|---|
| Message-ID | <[email protected]> |
Update of /cvsroot/tapestry/Tapestry/framework/src/net/sf/tapestry/record
In directory sc8-pr-cvs1:/tmp/cvs-serv9155/framework/src/net/sf/tapestry/record
Modified Files:
Tag: hship-2-3
ChangeKey.java PageRecorder.java PageChange.java
Added Files:
Tag: hship-2-3
SessionPageRecorder.java DefaultValuePersister.java
ImmutableValueCopier.java EJBCopier.java IValueCopier.java
ListCopier.java EJBWrapperCopier.java ArrayCopier.java
EJBWrapper.java IValuePersister.java
Removed Files:
Tag: hship-2-3
SimplePageRecorder.java
Log Message:
Automatically register components as page listeners if they implement necessary interfaces
Major rework on page property persistance
[ 653358 ] IPage.getName() == qualified name
[ 608768 ] Changes saved AFTER IPage.detach()
--- NEW FILE: SessionPageRecorder.java ---
package net.sf.tapestry.record;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.http.HttpSession;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import net.sf.tapestry.IRequestCycle;
import net.sf.tapestry.PageRecorderCommitException;
import net.sf.tapestry.RequestContext;
import net.sf.tapestry.Tapestry;
import net.sf.tapestry.util.StringSplitter;
/**
* Simple implementation of {@link net.sf.tapestry.IPageRecorder}
* that stores page changes as {@link javax.servlet.http.HttpSession} attributes.
*
*
* @author Howard Ship
* @version $Id: SessionPageRecorder.java,v 1.1.2.1 2002/12/30 03:04:55 hship Exp $
*
**/
public class SessionPageRecorder extends PageRecorder
{
private static final Log LOG = LogFactory.getLog(SessionPageRecorder.class);
/**
* Dictionary of changes, keyed on an instance of
* {@link ChangeKey}
* (which enapsulates component path and property name). The
* value is the new value for the object.
* The same information is stored into the
* {@link HttpSession}, which is used as a kind of
* write-behind cache.
*
**/
private Map _changes;
/**
* The session into which changes are recorded.
*
* @since 2.4
*
**/
private HttpSession _session;
/**
* The fully qualified name of the page being recorded.
*
* @since 2.4
*
**/
private String _pageName;
/**
* The prefix (for {@link HttpSession} attributes) used by this
* page recorder.
*
**/
private String _attributePrefix;
public void initialize(String pageName, IRequestCycle cycle)
{
if (LOG.isDebugEnabled())
LOG.debug("Initializing for " + pageName);
super.initialize(pageName, cycle);
RequestContext context = cycle.getRequestContext();
_pageName = pageName;
_session = context.getSession();
_attributePrefix = context.getServlet().getServletName() + "/" + _pageName + "/";
restorePageChanges();
}
public void discard()
{
if (Tapestry.isEmpty(_changes))
return;
Iterator i = _changes.keySet().iterator();
while (i.hasNext())
{
ChangeKey key = (ChangeKey)i.next();
String attributeKey = constructAttributeKey(key.getComponentPath(), key.getPropertyName());
if (LOG.isDebugEnabled())
LOG.debug("Removing session attribute " + attributeKey);
_session.removeAttribute(attributeKey);
}
}
/**
* Simply clears the dirty flag, because there is no external place
* to store changed page properties. Sets the locked flag to prevent
* subsequent changes from occuring now.
*
**/
public void commit() throws PageRecorderCommitException
{
setDirty(false);
setLocked(true);
}
/**
* Returns true if the recorder has any changes recorded.
*
**/
public boolean getHasChanges()
{
if (_changes == null)
return false;
return (_changes.size() > 0);
}
public Collection getChanges()
{
if (_changes == null)
return Collections.EMPTY_LIST;
int count = _changes.size();
Collection result = new ArrayList(count);
Iterator i = _changes.entrySet().iterator();
while (i.hasNext())
{
Map.Entry entry = (Map.Entry) i.next();
ChangeKey key = (ChangeKey) entry.getKey();
Object value = entry.getValue();
PageChange change = new PageChange(key.getComponentPath(), key.getPropertyName(), value);
result.add(change);
}
return result;
}
protected void recordChange(String componentPath, String propertyName, Object newValue)
{
ChangeKey key = new ChangeKey(componentPath, propertyName);
if (_changes == null)
_changes = new HashMap();
// Check the prior value. If this is not an actual change,
// then don't bother recording it, or marking this page recorder
// dirty.
Object oldValue = _changes.get(key);
if (newValue == oldValue)
return;
try
{
if (oldValue != null && oldValue.equals(newValue))
return;
}
catch (Exception ex)
{
// Ignore.
}
setDirty(true);
_changes.put(key, newValue);
// Now, build a key used to store the new value
// in the HttpSession
String attributeKey = constructAttributeKey(componentPath, propertyName);
_session.setAttribute(attributeKey, newValue);
if (LOG.isDebugEnabled())
LOG.debug("Stored session attribute " + attributeKey + " = " + newValue);
}
private String constructAttributeKey(String componentPath, String propertyName)
{
StringBuffer buffer = new StringBuffer(_attributePrefix);
if (componentPath != null)
{
buffer.append(componentPath);
buffer.append('/');
}
buffer.append(propertyName);
return buffer.toString();
}
private void restorePageChanges()
{
int count = 0;
Enumeration e = _session.getAttributeNames();
StringSplitter splitter = null;
while (e.hasMoreElements())
{
String key = (String) e.nextElement();
if (!key.startsWith(_attributePrefix))
continue;
if (LOG.isDebugEnabled())
LOG.debug("Restoring page change from session attribute " + key);
if (_changes == null)
{
_changes = new HashMap();
splitter = new StringSplitter('/');
}
String[] names = splitter.splitToArray(key);
// The first name is the servlet name, which allows
// multiple Tapestry apps to share a HttpSession, even
// when they use the same page names. The second name
// is the page name, which we already know.
int i = 2;
String componentPath = (names.length == 4) ? names[i++] : null;
String propertyName = names[i++];
Object value = _session.getAttribute(key);
ChangeKey changeKey = new ChangeKey(componentPath, propertyName);
_changes.put(changeKey, value);
count++;
}
if (LOG.isDebugEnabled())
LOG.debug(count == 0 ? "No recorded changes." : "Restored " + count + " recorded changes.");
}
}
--- NEW FILE: DefaultValuePersister.java ---
package net.sf.tapestry.record;
import java.rmi.RemoteException;
import java.util.Date;
import java.util.List;
import javax.ejb.EJBObject;
import javax.ejb.Handle;
import net.sf.tapestry.ApplicationRuntimeException;
import net.sf.tapestry.Tapestry;
import net.sf.tapestry.util.AdaptorRegistry;
import net.sf.tapestry.util.IImmutable;
/**
* Default implementation of {@link DefaultValuePersister}.
*
* @author Howard Lewis Ship
* @version $Id: DefaultValuePersister.java,v 1.1.2.1 2002/12/30 03:04:55 hship Exp $
* @since 2.4
*
**/
public class DefaultValuePersister implements IValuePersister
{
private AdaptorRegistry _registry = new AdaptorRegistry();
public DefaultValuePersister()
{
registerValueCopiers();
}
/**
* Invoked from {@link #registerValueCopiers()} to register the copier
* for a particular class.
*
**/
protected void registerValueCopier(Class registrationClass, IValueCopier copier)
{
_registry.register(registrationClass, copier);
}
protected IValueCopier getCopier(Object value)
{
Class valueClass = value.getClass();
try
{
return (IValueCopier) _registry.getAdaptor(valueClass);
}
catch (IllegalArgumentException ex)
{
throw new ApplicationRuntimeException(
Tapestry.getString("DefaultValuePersister.no-value-copier-for-class", valueClass.getName()),
ex);
}
}
/**
* Registers copiers. Subclasses may override to add additional registrations
* beyond the default set. An {@link net.sf.tapestry.record.ImmutableValueCopier}
* instance is registered for
* {@link net.sf.tapestry.util.IImmutable},
* String, Character, Number, Boolean and Date (even though Date is, technically, mutable)
*
* <p>
* An instance of {@link ListCopier} is registered for {@link java.util.List}.
*
* <p>
* An instance of {@link EJBCopier} for {@link EJBObject}, and {@link EJBWrapperCopier}
* for {@link EJBWrapper}.
*
* <p>
* An instance of {@link ArrayCopier} for <code>Object[]</code>.
*
**/
protected void registerValueCopiers()
{
IValueCopier immutable = new ImmutableValueCopier();
registerValueCopier(IImmutable.class, immutable);
registerValueCopier(String.class, immutable);
registerValueCopier(Character.class, immutable);
registerValueCopier(Number.class, immutable);
registerValueCopier(Boolean.class, immutable);
registerValueCopier(Date.class, immutable);
registerValueCopier(Handle.class, immutable);
registerValueCopier(List.class, new ListCopier());
registerValueCopier(EJBObject.class, new EJBCopier());
registerValueCopier(EJBWrapper.class, new EJBWrapperCopier());
registerValueCopier(Object[].class, new ArrayCopier());
}
protected Object copy(Object value)
{
IValueCopier copier = getCopier(value);
return copier.makeCopyOfValue(value);
}
public Object convertToActiveValue(Object value) throws PageRecorderSerializationException
{
if (value == null)
return null;
return copy(value);
}
public Object convertToStorableValue(Object value) throws PageRecorderSerializationException
{
if (value == null)
return null;
return copy(value);
}
}
--- NEW FILE: ImmutableValueCopier.java ---
package net.sf.tapestry.record;
/**
* Copier used when the value is immutable (and thus, no copy is really needed).
*
* @author Howard Lewis Ship
* @version $Id: ImmutableValueCopier.java,v 1.1.2.1 2002/12/30 03:04:55 hship Exp $
* @since 2.4
*
**/
public class ImmutableValueCopier implements IValueCopier
{
public Object makeCopyOfValue(Object value)
{
return value;
}
}
--- NEW FILE: EJBCopier.java ---
package net.sf.tapestry.record;
import javax.ejb.EJBObject;
/**
* Makes a copy of an EJB reference ({@link javax.ejb.EJBObject}) by wrapping
* the EJB in a {@link net.sf.tapestry.record.EJBWrapper}.
*
* @author Howard Lewis Ship
* @version $Id: EJBCopier.java,v 1.1.2.1 2002/12/30 03:04:55 hship Exp $
* @since 2.4
*
**/
public class EJBCopier implements IValueCopier
{
public Object makeCopyOfValue(Object value)
{
EJBObject ejb = (EJBObject) value;
return new EJBWrapper(ejb);
}
}
--- NEW FILE: IValueCopier.java ---
package net.sf.tapestry.record;
/**
* Interface used to define how to make a copy of an object to
*
* @author Howard Lewis Ship
* @version $Id: IValueCopier.java,v 1.1.2.1 2002/12/30 03:04:55 hship Exp $
* @since 2.4
*
**/
public interface IValueCopier
{
/**
* Passed an object, this should make a copy of that object.
*
**/
public Object makeCopyOfValue(Object value);
}
--- NEW FILE: ListCopier.java ---
package net.sf.tapestry.record;
import java.util.ArrayList;
import java.util.List;
/**
* Makes a copy of a {@link java.util.List} by
* creating a new {@link java.util.ArrayList}.
*
* @author Howard Lewis Ship
* @version $Id: ListCopier.java,v 1.1.2.1 2002/12/30 03:04:55 hship Exp $
* @since 2.4
*
**/
public class ListCopier implements IValueCopier
{
public Object makeCopyOfValue(Object value)
{
List list = (List)value;
return new ArrayList(list);
}
}
--- NEW FILE: EJBWrapperCopier.java ---
package net.sf.tapestry.record;
/**
* Converts an {@link net.sf.tapestry.record.EJBWrapper}
* back into an {@link javax.ejb.EJBObject}.
*
* @author Howard Lewis Ship
* @version $Id: EJBWrapperCopier.java,v 1.1.2.1 2002/12/30 03:04:55 hship Exp $
* @since 2.4
*
**/
public class EJBWrapperCopier implements IValueCopier
{
public Object makeCopyOfValue(Object value)
{
EJBWrapper wrapper = (EJBWrapper)value;
return wrapper.getEJBObject();
}
}
--- NEW FILE: ArrayCopier.java ---
package net.sf.tapestry.record;
import java.util.Arrays;
/**
* Makes a copy of the array, by invoking <code>clone()</code>.
*
* @author Howard Lewis Ship
* @version $Id: ArrayCopier.java,v 1.1.2.1 2002/12/30 03:04:55 hship Exp $
* @since 2.4
*
**/
public class ArrayCopier implements IValueCopier
{
public Object makeCopyOfValue(Object value)
{
Object[] array = (Object[])value;
return array.clone();
}
}
--- NEW FILE: EJBWrapper.java ---
package net.sf.tapestry.record;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import javax.ejb.EJBObject;
import javax.ejb.Handle;
import org.apache.commons.lang.builder.ToStringBuilder;
/**
* Wraps an EJBObject, serializing and deserializing the EJBObject's handle.
*
* @author Howard Lewis Ship
* @version $Id: EJBWrapper.java,v 1.1.2.1 2002/12/30 03:04:55 hship Exp $
* @since 2.4
*
**/
public class EJBWrapper implements Externalizable
{
private EJBObject _ejb;
public EJBWrapper()
{
}
public EJBWrapper(EJBObject ejb)
{
_ejb = ejb;
}
public EJBObject getEJBObject()
{
return _ejb;
}
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
{
Handle handle = (Handle)in.readObject();
_ejb = (EJBObject)handle.getEJBObject();
}
/**
* Writes the handle for the EJB.
*
**/
public void writeExternal(ObjectOutput out) throws IOException
{
Handle handle = _ejb.getHandle();
out.writeObject(handle);
}
public String toString()
{
ToStringBuilder builder = new ToStringBuilder(this);
builder.append("ejb", _ejb);
return builder.toString();
}
}
--- NEW FILE: IValuePersister.java ---
package net.sf.tapestry.record;
/**
* Responsible for persisting values on behalf of a {@link net.sf.tapestry.IPageRecorder}.
* The values provided to the page recorder are not stored as is; there are several
* conversions that occur:
* <ul>
* <li>{@link javax.ejb.EJBObject} is wrapped up in a {@link net.sf.tapestry.record.EJBWrapper}
* <li>Non-immutable objects are copied, using a {@link net.sf.tapestry.record.IValueCopier}
* <li>null passes through unchanged
* </ul>
*
* @author Howard Lewis Ship
* @version $Id: IValuePersister.java,v 1.1.2.1 2002/12/30 03:04:55 hship Exp $
* @since 2.4
*
**/
public interface IValuePersister
{
/**
* Converts an active value (used by the application) to
* a storable value (a value which can be persisted for later access).
*
**/
public Object convertToStorableValue(Object value)
throws PageRecorderSerializationException;
/**
* Reverses {@link #convertToStorableValue(Object)}, converting values
* back into active values.
*
**/
public Object convertToActiveValue(Object value)throws PageRecorderSerializationException;
}
Index: ChangeKey.java
===================================================================
RCS file: /cvsroot/tapestry/Tapestry/framework/src/net/sf/tapestry/record/ChangeKey.java,v
retrieving revision 1.5
retrieving revision 1.5.2.1
diff -C2 -d -r1.5 -r1.5.2.1
*** ChangeKey.java 27 Nov 2002 17:58:54 -0000 1.5
--- ChangeKey.java 30 Dec 2002 03:04:55 -0000 1.5.2.1
***************
*** 3,6 ****
--- 3,9 ----
import java.io.Serializable;
+ import org.apache.commons.lang.builder.EqualsBuilder;
+ import org.apache.commons.lang.builder.HashCodeBuilder;
+
/**
* Used to identify a property change.
***************
*** 13,30 ****
public class ChangeKey
{
! String componentPath;
! String propertyName;
public ChangeKey(String componentPath, String propertyName)
{
! this.componentPath = componentPath;
! this.propertyName = propertyName;
}
public boolean equals(Object object)
{
- boolean propertyNameIdentical;
- boolean componentPathIdentical;
-
if (object == null)
return false;
--- 16,31 ----
public class ChangeKey
{
! private int _hashCode = -1;
! private String _componentPath;
! private String _propertyName;
public ChangeKey(String componentPath, String propertyName)
{
! _componentPath = componentPath;
! _propertyName = propertyName;
}
public boolean equals(Object object)
{
if (object == null)
return false;
***************
*** 33,89 ****
return true;
! try
! {
! ChangeKey other = (ChangeKey) object;
!
! propertyNameIdentical = propertyName == other.propertyName;
! componentPathIdentical = componentPath == other.componentPath;
!
! if (propertyNameIdentical && componentPathIdentical)
! return true;
!
! // If not identical, then see if equal. If not equal, then
! // we don't equal the other key.
!
! if (!propertyNameIdentical)
! if (!propertyName.equals(other.propertyName))
! return false;
!
! // If this far, that propertyName is equal
!
! if (componentPathIdentical)
! return true;
!
! // If one's null and the other isn't then they can't
! // be equal.
!
! if (componentPath == null || other.componentPath == null)
! return false;
! // So it comes down to this ... are the two (non-null)
! // componentPath's equal?
! return componentPath.equals(other.componentPath);
! }
! catch (ClassCastException e)
! {
! return false;
! }
}
public String getComponentPath()
{
! return componentPath;
}
public String getPropertyName()
{
! return propertyName;
}
/**
*
! * Returns the propertyName's hash code, xor'ed with the
! * componentPath hash code (if componentPath is non-null).
*
**/
--- 34,64 ----
return true;
! if (!(object instanceof ChangeKey))
! return false;
! ChangeKey other = (ChangeKey) object;
! EqualsBuilder builder =new EqualsBuilder();
!
! builder.append(_propertyName, other._propertyName);
! builder.append(_componentPath, other._componentPath);
!
! return builder.isEquals();
}
public String getComponentPath()
{
! return _componentPath;
}
public String getPropertyName()
{
! return _propertyName;
}
/**
*
! * Returns a hash code computed from the
! * property name and component path.
*
**/
***************
*** 91,102 ****
public int hashCode()
{
! int result;
! result = propertyName.hashCode();
! if (componentPath != null)
! result ^= componentPath.hashCode();
! return result;
}
}
--- 66,80 ----
public int hashCode()
{
! if (_hashCode == -1)
! {
! HashCodeBuilder builder = new HashCodeBuilder(257, 23); // Random
! builder.append(_propertyName);
! builder.append(_componentPath);
! _hashCode = builder.toHashCode();
! }
! return _hashCode;
}
}
Index: PageRecorder.java
===================================================================
RCS file: /cvsroot/tapestry/Tapestry/framework/src/net/sf/tapestry/record/PageRecorder.java,v
retrieving revision 1.9
retrieving revision 1.9.2.1
diff -C2 -d -r1.9 -r1.9.2.1
*** PageRecorder.java 27 Nov 2002 17:58:54 -0000 1.9
--- PageRecorder.java 30 Dec 2002 03:04:55 -0000 1.9.2.1
***************
*** 1,20 ****
package net.sf.tapestry.record;
- import java.io.IOException;
- import java.io.Serializable;
- import java.rmi.RemoteException;
import java.util.Collection;
import java.util.Iterator;
! import javax.ejb.EJBObject;
! import javax.ejb.Handle;
import net.sf.tapestry.ApplicationRuntimeException;
import net.sf.tapestry.IComponent;
import net.sf.tapestry.IPage;
import net.sf.tapestry.IPageRecorder;
import net.sf.tapestry.IResourceResolver;
import net.sf.tapestry.PageRecorderCommitException;
import net.sf.tapestry.Tapestry;
import net.sf.tapestry.event.ObservedChangeEvent;
import net.sf.tapestry.util.prop.OgnlUtils;
--- 1,20 ----
package net.sf.tapestry.record;
import java.util.Collection;
import java.util.Iterator;
! import javax.servlet.ServletContext;
!
import net.sf.tapestry.ApplicationRuntimeException;
+ import net.sf.tapestry.ApplicationServlet;
import net.sf.tapestry.IComponent;
import net.sf.tapestry.IPage;
import net.sf.tapestry.IPageRecorder;
+ import net.sf.tapestry.IRequestCycle;
import net.sf.tapestry.IResourceResolver;
import net.sf.tapestry.PageRecorderCommitException;
import net.sf.tapestry.Tapestry;
import net.sf.tapestry.event.ObservedChangeEvent;
+ import net.sf.tapestry.spec.IApplicationSpecification;
import net.sf.tapestry.util.prop.OgnlUtils;
***************
*** 24,32 ****
*
* <p>This is an abstract implementation; specific implementations can choose where
! * and how to persist the data.
! *
! * <p>Implements {@link Serializable} but does not have any state of its own.
! * Subclasses must implement <code>readExternal()</code> and
! * <code>writeExternal()</code>.
*
* @author Howard Ship
--- 24,28 ----
*
* <p>This is an abstract implementation; specific implementations can choose where
! * and how to persist the data.
*
* @author Howard Ship
***************
*** 35,43 ****
**/
! public abstract class PageRecorder implements IPageRecorder, Serializable
{
! protected transient boolean dirty = false;
! protected transient boolean locked = false;
! protected transient boolean discard = false;
/**
--- 31,43 ----
**/
! public abstract class PageRecorder implements IPageRecorder
{
! public static final String VALUE_PERSISTER_EXTENSION_NAME = "net.sf.tapestry.value-persister";
!
! private IValuePersister _persister;
!
! private boolean _dirty = false;
! private boolean _locked = false;
! private boolean _discard = false;
/**
***************
*** 71,75 ****
{
! return dirty;
}
--- 71,75 ----
{
! return _dirty;
}
***************
*** 82,91 ****
public boolean isLocked()
{
! return locked;
}
public void setLocked(boolean value)
{
! locked = value;
}
--- 82,91 ----
public boolean isLocked()
{
! return _locked;
}
public void setLocked(boolean value)
{
! _locked = value;
}
***************
*** 110,139 ****
public void observeChange(ObservedChangeEvent event)
{
! IComponent component;
! String propertyName;
! Object newValue;
!
! component = event.getComponent();
! propertyName = event.getPropertyName();
! if (locked)
throw new ApplicationRuntimeException(
Tapestry.getString(
"PageRecorder.change-after-lock",
! component.getPage().getName(),
propertyName,
component.getExtendedId()));
if (propertyName == null)
! {
! dirty = true;
! return;
! }
! newValue = event.getNewValue();
try
{
! recordChange(component.getIdPath(), propertyName, newValue);
}
catch (Throwable t)
--- 110,135 ----
public void observeChange(ObservedChangeEvent event)
{
! IComponent component = event.getComponent();
! String propertyName = event.getPropertyName();
! if (_locked)
throw new ApplicationRuntimeException(
Tapestry.getString(
"PageRecorder.change-after-lock",
! component.getPage().getPageName(),
propertyName,
component.getExtendedId()));
if (propertyName == null)
! throw new ApplicationRuntimeException(
! Tapestry.getString("PageRecorder.null-property-name", component.getExtendedId()));
! Object activeValue = event.getNewValue();
try
{
! Object storableValue = _persister.convertToStorableValue(activeValue);
!
! recordChange(component.getIdPath(), propertyName, storableValue);
}
catch (Throwable t)
***************
*** 141,145 ****
t.printStackTrace();
throw new ApplicationRuntimeException(
! Tapestry.getString("PageRecorder.unable-to-persist", propertyName, component.getExtendedId(), newValue),
t);
}
--- 137,145 ----
t.printStackTrace();
throw new ApplicationRuntimeException(
! Tapestry.getString(
! "PageRecorder.unable-to-persist",
! propertyName,
! component.getExtendedId(),
! activeValue),
t);
}
***************
*** 176,184 ****
{
Collection changes = getChanges();
!
if (changes.isEmpty())
return;
!
! IResourceResolver resolver = page.getEngine().getResourceResolver();
Iterator i = changes.iterator();
--- 176,184 ----
{
Collection changes = getChanges();
!
if (changes.isEmpty())
return;
!
! IResourceResolver resolver = page.getEngine().getResourceResolver();
Iterator i = changes.iterator();
***************
*** 187,278 ****
PageChange change = (PageChange) i.next();
! IComponent component = page.getNestedComponent(change.componentPath);
try
{
! OgnlUtils.set(change.propertyName, resolver, component, change.newValue);
}
catch (Throwable t)
{
! throw new RollbackException(component, change.propertyName, change.newValue, t);
}
}
}
! /**
! * Invoked by subclasses to converts an object into
! * a {@link Serializable} value for for persistent storage.
! *
! * <p>This implementation implements a special case
! * for converting an {@link EJBObject} into a {@link Handle}
! * for storage.
! *
! * @since 0.2.9
! **/
! protected Serializable persistValue(Object value) throws IOException
{
! if (!(value instanceof EJBObject))
! {
! try
! {
! return (Serializable) value;
! }
! catch (ClassCastException ex)
! {
! throw new PageRecorderSerializationException(ex);
! }
! }
! try
! {
! EJBObject ejb = (EJBObject) value;
! return ejb.getHandle();
! }
! catch (RemoteException ex)
! {
! throw new PageRecorderSerializationException(ex);
! }
}
/**
! * Invoked by subclasses to restore a persisted value to its
! * runtime value. This implementation converts {@link Handle}s, stored
! * persistently, back into {@link EJBObject}s.
! *
! * @since 0.2.9
**/
! protected Object restoreValue(Object value) throws IOException
{
! if (!(value instanceof Handle))
! return value;
! try
! {
! Handle handle = (Handle) value;
! return handle.getEJBObject();
! }
! catch (RemoteException ex)
! {
! throw new PageRecorderSerializationException(ex);
! }
! }
! /** @since 2.0.2 **/
! public boolean isMarkedForDiscard()
! {
! return discard;
! }
! /** @since 2.0.2 **/
! public void markForDiscard()
! {
! discard = true;
}
--- 187,267 ----
PageChange change = (PageChange) i.next();
! String propertyName = change.getPropertyName();
!
! IComponent component = page.getNestedComponent(change.getComponentPath());
!
! Object storedValue = change.getNewValue();
try
{
+ Object activeValue = _persister.convertToActiveValue(storedValue);
! OgnlUtils.set(propertyName, resolver, component, activeValue);
}
catch (Throwable t)
{
! throw new RollbackException(component, propertyName, storedValue, t);
}
}
}
! /** @since 2.0.2 **/
! public boolean isMarkedForDiscard()
{
! return _discard;
! }
! /** @since 2.0.2 **/
! public void markForDiscard()
! {
! _discard = true;
! }
!
! protected void setDirty(boolean dirty)
! {
! this._dirty = dirty;
! }
!
! protected boolean getDirty()
! {
! return _dirty;
}
/**
! * Finds the {@link net.sf.tapestry.record.IValuePersister} as an
! * attribute in the {@link javax.servlet.ServletContext}. If not
! * found it is created. If an application extension named
! * <code>net.sf.tapestry.value-persister</code>
! * exists, it is used as the shared persister, otherwise
! * an instance of {@link net.sf.tapestry.record.DefaultValuePersister}
! * is created. Subclasses may override this method, but must
! * invoke this implementation.
! *
**/
! public void initialize(String pageName, IRequestCycle cycle)
{
! ApplicationServlet servlet = cycle.getRequestContext().getServlet();
! String servletName = servlet.getServletName();
! ServletContext context = servlet.getServletContext();
! String name = VALUE_PERSISTER_EXTENSION_NAME + "." + servletName;
! _persister = (IValuePersister) context.getAttribute(name);
! if (_persister == null)
! {
! IApplicationSpecification spec = cycle.getEngine().getSpecification();
! if (spec.checkExtension(VALUE_PERSISTER_EXTENSION_NAME))
! _persister = (IValuePersister) spec.getExtension(VALUE_PERSISTER_EXTENSION_NAME, IValuePersister.class);
! else
! _persister = new DefaultValuePersister();
! context.setAttribute(name, _persister);
! }
}
Index: PageChange.java
===================================================================
RCS file: /cvsroot/tapestry/Tapestry/framework/src/net/sf/tapestry/record/PageChange.java,v
retrieving revision 1.5
retrieving revision 1.5.2.1
diff -C2 -d -r1.5 -r1.5.2.1
*** PageChange.java 27 Nov 2002 17:58:54 -0000 1.5
--- PageChange.java 30 Dec 2002 03:04:55 -0000 1.5.2.1
***************
*** 1,4 ****
--- 1,6 ----
package net.sf.tapestry.record;
+ import org.apache.commons.lang.builder.ToStringBuilder;
+
import net.sf.tapestry.IPageChange;
***************
*** 13,25 ****
public class PageChange implements IPageChange
{
! String componentPath;
! String propertyName;
! Object newValue;
public PageChange(String componentPath, String propertyName, Object newValue)
{
! this.componentPath = componentPath;
! this.propertyName = propertyName;
! this.newValue = newValue;
}
--- 15,27 ----
public class PageChange implements IPageChange
{
! private String _componentPath;
! private String _propertyName;
! private Object _newValue;
public PageChange(String componentPath, String propertyName, Object newValue)
{
! _componentPath = componentPath;
! _propertyName = propertyName;
! _newValue = newValue;
}
***************
*** 32,36 ****
public String getComponentPath()
{
! return componentPath;
}
--- 34,38 ----
public String getComponentPath()
{
! return _componentPath;
}
***************
*** 42,46 ****
public Object getNewValue()
{
! return newValue;
}
--- 44,48 ----
public Object getNewValue()
{
! return _newValue;
}
***************
*** 52,80 ****
public String getPropertyName()
{
! return propertyName;
}
public String toString()
{
! StringBuffer buffer;
!
! buffer = new StringBuffer(getClass().getName());
!
! buffer.append('[');
!
! if (componentPath != null)
! {
! buffer.append(componentPath);
! buffer.append(' ');
! }
!
! buffer.append(propertyName);
!
! buffer.append(' ');
! buffer.append(newValue);
!
! buffer.append(']');
!
! return buffer.toString();
}
}
--- 54,69 ----
public String getPropertyName()
{
! return _propertyName;
}
public String toString()
{
! ToStringBuilder builder = new ToStringBuilder(this);
!
! builder.append("componentPath", _componentPath);
! builder.append("propertyName", _propertyName);
! builder.append("newValue", _newValue);
!
! return builder.toString();
}
}
--- SimplePageRecorder.java DELETED ---
-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf