Added: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/record/LazyProxyDelegate.java URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/record/LazyProxyDelegate.java?view=auto&rev=509035 ============================================================================== --- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/record/LazyProxyDelegate.java (added) +++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/record/LazyProxyDelegate.java Sun Feb 18 16:04:24 2007 @@ -0,0 +1,48 @@ +// Copyright 2004, 2005 The Apache Software Foundation +// +// 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.apache.tapestry.record; + +import net.sf.cglib.proxy.LazyLoader; + + +/** + * Implementation of [EMAIL PROTECTED] LazyLoader} interface for [EMAIL PROTECTED] CglibProxiedPropertyChangeObserverImpl}. + */ +public class LazyProxyDelegate implements LazyLoader +{ + + Object _target; + + /** + * Creates a new lazily loaded proxy delegate object used to create efficient + * pass through proxied calls to a specific property instance. + * + * @param target + * The object being proxied. + */ + public LazyProxyDelegate(Object target) + { + _target = target; + } + + /** + * [EMAIL PROTECTED] + */ + public Object loadObject() + throws Exception + { + return _target; + } + +}
Added: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/record/ObservableMethodFilter.java URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/record/ObservableMethodFilter.java?view=auto&rev=509035 ============================================================================== --- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/record/ObservableMethodFilter.java (added) +++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/record/ObservableMethodFilter.java Sun Feb 18 16:04:24 2007 @@ -0,0 +1,43 @@ +// Copyright 2004, 2005 The Apache Software Foundation +// +// 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.apache.tapestry.record; + +import java.lang.reflect.Method; + +import net.sf.cglib.proxy.CallbackFilter; + + +/** + * Acts as a filter for cglib property watching semantics used + * by [EMAIL PROTECTED] CglibProxiedPropertyChangeObserverImpl}. + */ +public class ObservableMethodFilter implements CallbackFilter +{ + + /** + * [EMAIL PROTECTED] + */ + public int accept(Method method) + { + boolean hasParams = method.getParameterTypes() != null && method.getParameterTypes().length > 0; + + if (method.getReturnType() == void.class && hasParams + || method.getReturnType() != boolean.class && hasParams) { + + return 1; + } + + return 0; + } +} Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/record/PageRecorderImpl.java URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/record/PageRecorderImpl.java?view=diff&rev=509035&r1=509034&r2=509035 ============================================================================== --- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/record/PageRecorderImpl.java (original) +++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/record/PageRecorderImpl.java Sun Feb 18 16:04:24 2007 @@ -42,8 +42,7 @@ private ErrorLog _log; - public PageRecorderImpl(String pageName, PropertyPersistenceStrategySource strategySource, - ErrorLog log) + public PageRecorderImpl(String pageName, PropertyPersistenceStrategySource strategySource, ErrorLog log) { Defense.notNull(pageName, "pageName"); Defense.notNull(strategySource, "strategySource"); @@ -59,6 +58,11 @@ _locked = true; } + public boolean isLocked() + { + return _locked; + } + public Collection getChanges() { return _strategySource.getAllStoredChanges(_pageName); @@ -82,11 +86,9 @@ { String idPath = change.getComponentPath(); - IComponent component = (idPath == null) ? page : page - .getNestedComponent(idPath); - - PropertyUtils.write(component, change.getPropertyName(), change - .getNewValue()); + IComponent component = (idPath == null) ? page : page.getNestedComponent(idPath); + + PropertyUtils.write(component, change.getPropertyName(), change.getNewValue()); } public void observeChange(ObservedChangeEvent event) @@ -96,33 +98,27 @@ if (_locked) { - _log.error(RecordMessages.recorderLocked(propertyName, component), - null, null); + _log.error(RecordMessages.recorderLocked(propertyName, component), null, null); return; } - - PropertyPersistenceStrategy strategy = findStrategy(component, - propertyName); + + PropertyPersistenceStrategy strategy = findStrategy(component, propertyName); if (strategy != null) - strategy.store(_pageName, component.getIdPath(), propertyName, - event.getNewValue()); + strategy.store(_pageName, component.getIdPath(), propertyName, event.getNewValue()); } // package private for testing - PropertyPersistenceStrategy findStrategy(IComponent component, - String propertyName) + PropertyPersistenceStrategy findStrategy(IComponent component, String propertyName) { // So much for Law of Demeter! - IPropertySpecification propertySpecification = component - .getSpecification().getPropertySpecification(propertyName); + IPropertySpecification propertySpecification = component.getSpecification().getPropertySpecification(propertyName); if (propertySpecification == null) { - _log.error(RecordMessages.missingPropertySpecification( - propertyName, component), null, null); + _log.error(RecordMessages.missingPropertySpecification(propertyName, component), null, null); return null; } @@ -139,10 +135,7 @@ } catch (ApplicationRuntimeException ex) { - _log - .error(ex.getMessage(), - propertySpecification.getLocation(), ex); - + _log.error(ex.getMessage(), propertySpecification.getLocation(), ex); return null; } } Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/record/PersistentPropertyData.java URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/record/PersistentPropertyData.java?view=diff&rev=509035&r1=509034&r2=509035 ============================================================================== --- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/record/PersistentPropertyData.java (original) +++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/record/PersistentPropertyData.java Sun Feb 18 16:04:24 2007 @@ -119,9 +119,8 @@ ChangeKey changeKey = (ChangeKey) me.getKey(); Object value = me.getValue(); - PropertyChange change = new PropertyChangeImpl(changeKey - .getComponentPath(), changeKey.getPropertyName(), value); - + PropertyChange change = new PropertyChangeImpl(changeKey.getComponentPath(), changeKey.getPropertyName(), value); + result.add(change); } Added: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/record/PropertyChangeObserver.java URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/record/PropertyChangeObserver.java?view=auto&rev=509035 ============================================================================== --- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/record/PropertyChangeObserver.java (added) +++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/record/PropertyChangeObserver.java Sun Feb 18 16:04:24 2007 @@ -0,0 +1,45 @@ +// Copyright 2004, 2005 The Apache Software Foundation +// +// 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.apache.tapestry.record; + +import org.apache.tapestry.IComponent; +import org.apache.tapestry.Tapestry; + + +/** + * Core service that is consulted anytime a specified component property is set. This service + * is intended to be used as a means of intercepting component property state objects so that + * their individual properties can be observed independently from basic set/get operations + * done on page/component properties. + * + */ +public interface PropertyChangeObserver +{ + + /** + * Invoked by the enhanced property workers any time a [EMAIL PROTECTED] IComponent} property is set, either + * by an initial value binding or explicitly through an abstract setter. + * + * @param component + * The component that this property is attached to. + * @param property + * The object to observe changes on, may be null. + * @param propertyName + * The name of the property being observed - needed for doing things like calling + * [EMAIL PROTECTED] Tapestry#fireObservedChange(IComponent, String, Object)}. + * @return Expected to return either the same exact instance passed in or one that is proxied but still + * maintains the original state of the object. + */ + Object observePropertyChanges(IComponent component, Object property, String propertyName); +} Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/record/SessionPropertyPersistenceStrategy.java URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/record/SessionPropertyPersistenceStrategy.java?view=diff&rev=509035&r1=509034&r2=509035 ============================================================================== --- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/record/SessionPropertyPersistenceStrategy.java (original) +++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/record/SessionPropertyPersistenceStrategy.java Sun Feb 18 16:04:24 2007 @@ -45,16 +45,14 @@ private WebRequest _request; - public void store(String pageName, String idPath, String propertyName, - Object newValue) + public void store(String pageName, String idPath, String propertyName, Object newValue) { Defense.notNull(pageName, "pageName"); Defense.notNull(propertyName, "propertyName"); WebSession session = _request.getSession(true); - String attributeName = RecordUtils.buildChangeKey(STRATEGY_ID, - _applicationId, pageName, idPath, propertyName); + String attributeName = RecordUtils.buildChangeKey(STRATEGY_ID, _applicationId, pageName, idPath, propertyName); session.setAttribute(attributeName, newValue); } @@ -65,24 +63,22 @@ WebSession session = _request.getSession(false); - if (session == null) return Collections.EMPTY_LIST; + if (session == null) + return Collections.EMPTY_LIST; final Collection result = new ArrayList(); WebSessionAttributeCallback callback = new WebSessionAttributeCallback() { - public void handleAttribute(WebSession sess, String name) { - PropertyChange change = RecordUtils.buildChange(name, sess - .getAttribute(name)); + PropertyChange change = RecordUtils.buildChange(name, sess.getAttribute(name)); result.add(change); } }; - RecordUtils.iterateOverMatchingAttributes(STRATEGY_ID, _applicationId, - pageName, session, callback); + RecordUtils.iterateOverMatchingAttributes(STRATEGY_ID, _applicationId, pageName, session, callback); return result; } @@ -95,7 +91,6 @@ WebSessionAttributeCallback callback = new WebSessionAttributeCallback() { - public void handleAttribute(WebSession sess, String name) { sess.setAttribute(name, null); Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/RequestLocaleManagerImpl.java URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/RequestLocaleManagerImpl.java?view=diff&rev=509035&r1=509034&r2=509035 ============================================================================== --- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/RequestLocaleManagerImpl.java (original) +++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/RequestLocaleManagerImpl.java Sun Feb 18 16:04:24 2007 @@ -91,9 +91,8 @@ { String localeName = _cookieSource.readCookieValue(TapestryConstants.LOCALE_COOKIE_NAME); - String requestedLocale = (localeName != null) ? localeName : _request.getLocale() - .toString(); - + String requestedLocale = (localeName != null) ? localeName : _request.getLocale().toString(); + _requestLocale = filterRequestedLocale(requestedLocale); _threadLocale.setLocale(_requestLocale); Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/spec/IPropertySpecification.java URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/spec/IPropertySpecification.java?view=diff&rev=509035&r1=509034&r2=509035 ============================================================================== --- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/spec/IPropertySpecification.java (original) +++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/spec/IPropertySpecification.java Sun Feb 18 16:04:24 2007 @@ -51,7 +51,38 @@ void setName(String name); void setType(String type); - + + /** + * Checks if this property has previously had it's type information examined to + * determine if it is elligable for proxying. Meaning [EMAIL PROTECTED] #canProxy()} should + * be a real value. + * + * @return True if the proxy type has been checked, false otherwise. + */ + boolean isProxyChecked(); + + /** + * Sets the state of this property so that it is known whether or not the type + * it represents has been checked as being compatible with proxying or not. + * + * @param checked + */ + void setProxyChecked(boolean checked); + + /** + * Checks if this parameter can be proxied. + * + * @return True if the type can be proxied, false otherwise. + */ + boolean canProxy(); + + /** + * Sets whether or not this property can be proxied. + * + * @param canProxy + */ + void setCanProxy(boolean canProxy); + /** * A string indicating how the property is persisted. * Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/spec/PropertySpecification.java URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/spec/PropertySpecification.java?view=diff&rev=509035&r1=509034&r2=509035 ============================================================================== --- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/spec/PropertySpecification.java (original) +++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/spec/PropertySpecification.java Sun Feb 18 16:04:24 2007 @@ -38,6 +38,10 @@ private String _persistence; + private boolean _proxyChecked; + + private boolean _canProxy; + public String getInitialValue() { return _initialValue; @@ -96,5 +100,37 @@ public void setPersistence(String persistence) { _persistence = persistence; + } + + /** + * [EMAIL PROTECTED] + */ + public boolean canProxy() + { + return _canProxy; + } + + /** + * [EMAIL PROTECTED] + */ + public boolean isProxyChecked() + { + return _proxyChecked; + } + + /** + * [EMAIL PROTECTED] + */ + public void setCanProxy(boolean canProxy) + { + _canProxy = canProxy; + } + + /** + * [EMAIL PROTECTED] + */ + public void setProxyChecked(boolean checked) + { + _proxyChecked = checked; } } Modified: tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestDefaultParameterValues.xml URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestDefaultParameterValues.xml?view=diff&rev=509035&r1=509034&r2=509035 ============================================================================== --- tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestDefaultParameterValues.xml (original) +++ tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestDefaultParameterValues.xml Sun Feb 18 16:04:24 2007 @@ -92,18 +92,6 @@ ]]> </assert-output> - <assert-output name="b tag"> -<![CDATA[ -<b id="Any_1">b tag</b> -]]> - </assert-output> - - <assert-output name="i tag"> -<![CDATA[ -<i id="Any_2">i tag</i> -]]> - </assert-output> - </request> </mock-test> Modified: tapestry/tapestry4/trunk/tapestry-framework/src/test-data/context27/Home.html URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/test-data/context27/Home.html?view=diff&rev=509035&r1=509034&r2=509035 ============================================================================== --- tapestry/tapestry4/trunk/tapestry-framework/src/test-data/context27/Home.html (original) +++ tapestry/tapestry4/trunk/tapestry-framework/src/test-data/context27/Home.html Sun Feb 18 16:04:24 2007 @@ -15,9 +15,5 @@ <div jwcid="@Any">div tag</div> - <div jwcid="@Any" templateTag="b">b tag</div> - - <div jwcid="any">i tag</div> - </body> </html> Modified: tapestry/tapestry4/trunk/tapestry-framework/src/test-data/context27/WEB-INF/Home.page URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/test-data/context27/WEB-INF/Home.page?view=diff&rev=509035&r1=509034&r2=509035 ============================================================================== --- tapestry/tapestry4/trunk/tapestry-framework/src/test-data/context27/WEB-INF/Home.page (original) +++ tapestry/tapestry4/trunk/tapestry-framework/src/test-data/context27/WEB-INF/Home.page Sun Feb 18 16:04:24 2007 @@ -20,9 +20,5 @@ "http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd"> <page-specification> - - <component id="any" type="Any"> - <binding name="templateTag" expression='"i"'/> - </component> </page-specification> Modified: tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/enhance/TestSpecifiedPropertyWorker.java URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/enhance/TestSpecifiedPropertyWorker.java?view=diff&rev=509035&r1=509034&r2=509035 ============================================================================== --- tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/enhance/TestSpecifiedPropertyWorker.java (original) +++ tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/enhance/TestSpecifiedPropertyWorker.java Sun Feb 18 16:04:24 2007 @@ -98,6 +98,19 @@ return buildComponentSpecification(buildPropertySpecs(name, type, persistent)); } + public enum TestEnum { + First, + Second + } + + public void test_Can_Proxy_Enum() + { + Object obj = TestEnum.First; + + assert !EnhanceUtils.canProxyPropertyType(obj.getClass()); + assert EnhanceUtils.canProxyPropertyType(List.class); + } + public void testAddNormal() throws Exception { Location l = newLocation(); @@ -218,7 +231,7 @@ verify(); } - public void testAddPersistent() throws Exception + public void test_Add_Persistent() throws Exception { IComponentSpecification spec = buildComponentSpecification( "barney", Modified: tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/junit/mock/TestMockApplications.java URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/junit/mock/TestMockApplications.java?view=diff&rev=509035&r1=509034&r2=509035 ============================================================================== --- tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/junit/mock/TestMockApplications.java (original) +++ tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/junit/mock/TestMockApplications.java Sun Feb 18 16:04:24 2007 @@ -54,7 +54,8 @@ import org.jdom.Document; import org.jdom.Element; import org.jdom.input.SAXBuilder; -import org.testng.annotations.Configuration; +import org.testng.annotations.AfterClass; +import org.testng.annotations.AfterMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -126,7 +127,7 @@ /** * Closes System.out and System.err, then restores them to their original values. */ - @Configuration(afterTestMethod = true) + @AfterMethod public void tearDown() throws Exception { System.err.close(); @@ -483,9 +484,6 @@ private boolean evaluate(String expression) throws DocumentParseException { - // if (_ognlContext == null) - // _ognlContext = Ognl.createDefaultContext(this); - Object value = null; try @@ -615,9 +613,6 @@ private PatternMatcher getMatcher() { - //if (_matcher == null) - // _matcher = new Perl5Matcher(); - return _matcher; } @@ -629,9 +624,6 @@ if (result != null) return result; - // if (_compiler == null) - // _compiler = new Perl5Compiler(); - try { result = _compiler.compile(pattern, Perl5Compiler.MULTILINE_MASK); @@ -945,7 +937,7 @@ return new PrintStream(bos, true); } - @Configuration(afterTestClass = true) + @AfterClass public static void deleteDir() { File file = new File(getBaseDirectory() + "/target/.private"); Modified: tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/record/PageFixture.java URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/record/PageFixture.java?view=diff&rev=509035&r1=509034&r2=509035 ============================================================================== --- tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/record/PageFixture.java (original) +++ tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/record/PageFixture.java Sun Feb 18 16:04:24 2007 @@ -15,16 +15,14 @@ package org.apache.tapestry.record; import org.apache.tapestry.html.BasePage; -import org.testng.annotations.Test; /** * @author Howard Lewis Ship * @since 4.0 */ [EMAIL PROTECTED] public abstract class PageFixture extends BasePage { public abstract String getCartoonName(); public abstract void setCartoonName(String value); -} \ No newline at end of file +} Added: tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/record/SimpleState.java URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/record/SimpleState.java?view=auto&rev=509035 ============================================================================== --- tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/record/SimpleState.java (added) +++ tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/record/SimpleState.java Sun Feb 18 16:04:24 2007 @@ -0,0 +1,119 @@ +// Copyright 2004, 2005 The Apache Software Foundation +// +// 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.apache.tapestry.record; + +import java.io.Serializable; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; + + +/** + * Simple object used for testing object property changes. + */ +public class SimpleState implements Serializable +{ + /** serialVersionUID */ + private static final long serialVersionUID = 8466422593705479396L; + + long _id; + String _name; + boolean _isValid; + Date _date; + Map _keys = new HashMap(); + + public SimpleState() {} + + public SimpleState(long id, String name) + { + _id = id; + _name = name; + } + + public long getId() + { + return _id; + } + + public void setId(long id) + { + _id = id; + } + + /** + * @return Returns the name. + */ + public String getName() + { + return _name; + } + + /** + * @param name The name to set. + */ + public void setName(String name) + { + _name = name; + } + + /** + * @return Returns the isValid. + */ + public boolean isValid() + { + return _isValid; + } + + /** + * @param isValid The isValid to set. + */ + public void setValid(boolean isValid) + { + _isValid = isValid; + } + + /** + * @return Returns the date. + */ + public Date getDate() + { + return _date; + } + + /** + * @param date The date to set. + */ + public void setDate(Date date) + { + _date = date; + } + + public Map getKeys() + { + return _keys; + } + + public String toString() + { + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) + .append("id", _id) + .append("name", _name) + .append("isValid", _isValid) + .append("date", _date) + .toString(); + } +} Added: tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/record/TestPropertyChangeObserver.java URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/record/TestPropertyChangeObserver.java?view=auto&rev=509035 ============================================================================== --- tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/record/TestPropertyChangeObserver.java (added) +++ tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/record/TestPropertyChangeObserver.java Sun Feb 18 16:04:24 2007 @@ -0,0 +1,272 @@ +// Copyright 2004, 2005 The Apache Software Foundation +// +// 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.apache.tapestry.record; + +import static org.easymock.EasyMock.checkOrder; +import static org.easymock.EasyMock.expect; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import net.sf.cglib.proxy.Enhancer; + +import org.apache.tapestry.BaseComponentTestCase; +import org.apache.tapestry.IPage; +import org.apache.tapestry.dojo.form.DefaultAutocompleteModel; +import org.apache.tapestry.dojo.form.IAutocompleteModel; +import org.apache.tapestry.event.ChangeObserver; +import org.apache.tapestry.event.ObservedChangeEvent; +import org.testng.annotations.Test; + + +/** + * Tests watching persistent object properties via proxy objects. + */ [EMAIL PROTECTED] +public class TestPropertyChangeObserver extends BaseComponentTestCase +{ + static final long NANOSECONDS_IN_MILLIS = 1000000; + + class CglibChangeObserver implements ChangeObserver { + + int _changes = 0; + + public int getChanges() + { + return _changes; + } + + public boolean isLocked() + { + return false; + } + + /** + * [EMAIL PROTECTED] + */ + public void observeChange(ObservedChangeEvent event) + { + _changes++; + } + } + + public void test_Null_Property_Proxy() + throws Exception + { + PropertyChangeObserver propObserver = new CglibProxiedPropertyChangeObserverImpl(); + IPage page = newMock(IPage.class); + + replay(); + + assert propObserver.observePropertyChanges(page, null, "state") == null; + + verify(); + } + + void callState(SimpleState o1, SimpleState o2) + { + o1.getDate(); + o2.getDate(); + } + + public void test_Proxy_Access_Changes() + throws Exception + { + SimpleState rawState = new SimpleState(); + CglibChangeObserver pageObserver = new CglibChangeObserver(); + PropertyChangeObserver propObserver = new CglibProxiedPropertyChangeObserverImpl(); + + IPage page = newMock(IPage.class); + checkOrder(page, false); + + expect(page.getPage()).andReturn(page).anyTimes(); + expect(page.getIdPath()).andReturn(null).anyTimes(); + expect(page.getChangeObserver()).andReturn(pageObserver).anyTimes(); + + replay(); + + SimpleState state = (SimpleState) propObserver.observePropertyChanges(page, rawState, "state"); + + // test that same instance is returned unmolested + assert state == (SimpleState) propObserver.observePropertyChanges(page, state, "state"); + + assert state != null; + assert state.getKeys().size() == 0; + assert SimpleState.class.isAssignableFrom(state.getClass()); + + assertEquals(pageObserver.getChanges(), 0); + + for (int i=0; i < 40; i++) { + callState(rawState, state); + } + + assertEquals(pageObserver.getChanges(), 0); + + long otime = System.nanoTime(); + rawState.getDate(); + otime = System.nanoTime() - otime; + + long etime = System.nanoTime(); + state.getDate(); + etime = System.nanoTime() - etime; + + long otimems = otime / NANOSECONDS_IN_MILLIS; + long etimems = etime / NANOSECONDS_IN_MILLIS; + + assertEquals(otimems, etimems, "Enhanced property access times not equal to normal access times: \n" + + "original time: " + otime + "ns : " + otimems + " ms , " + + "enhanced time: " + etime + "ns : " + etimems + " ms"); + + verify(); + } + + void setState(SimpleState raw, SimpleState enhanced, Date date) + { + raw.setDate(date); + enhanced.setDate(date); + } + + public void test_Proxy_Set_Changes() + throws Exception + { + SimpleState rawState = new SimpleState(); + CglibChangeObserver pageObserver = new CglibChangeObserver(); + PropertyChangeObserver propObserver = new CglibProxiedPropertyChangeObserverImpl(); + + IPage page = newMock(IPage.class); + checkOrder(page, false); + + expect(page.getPage()).andReturn(page).anyTimes(); + expect(page.getIdPath()).andReturn(null).anyTimes(); + expect(page.getChangeObserver()).andReturn(pageObserver).anyTimes(); + + replay(); + + SimpleState state = (SimpleState) propObserver.observePropertyChanges(page, rawState, "state"); + + assertEquals(pageObserver.getChanges(), 0); + + Date testDate = new Date(); + for (int i=0; i < 2000; i++) { + setState(rawState, state, testDate); + } + + assertEquals(pageObserver.getChanges(), 2000); + + long otime = System.nanoTime(); + rawState.setDate(new Date()); + otime = System.nanoTime() - otime; + + long etime = System.nanoTime(); + state.setDate(new Date()); + etime = System.nanoTime() - etime; + + long otimems = otime / NANOSECONDS_IN_MILLIS; + long etimems = etime / NANOSECONDS_IN_MILLIS; + + assertEquals(otimems, etimems, "Enhanced property set times not equal to normal set times: \n" + + "original setDate() time: " + otime + "ns : " + otimems + " ms , " + + "enhanced setDate() time: " + etime + "ns : " + etimems + " ms"); + + verify(); + } + + public void test_Proxy_Class_Cached() + { + SimpleState rawState = new SimpleState(); + CglibChangeObserver pageObserver = new CglibChangeObserver(); + PropertyChangeObserver propObserver = new CglibProxiedPropertyChangeObserverImpl(); + + IPage page = newMock(IPage.class); + checkOrder(page, false); + + expect(page.getPage()).andReturn(page).anyTimes(); + + expect(page.getIdPath()).andReturn(null).anyTimes(); + + expect(page.getChangeObserver()).andReturn(pageObserver).anyTimes(); + + replay(); + + SimpleState state = (SimpleState) propObserver.observePropertyChanges(page, rawState, "fooBar"); + + SimpleState state2 = (SimpleState) propObserver.observePropertyChanges(page, state, "fooBar"); + + assert state == state2; + + SimpleState newState = new SimpleState(); + + SimpleState enewState = (SimpleState) propObserver.observePropertyChanges(page, newState, "fooBar"); + + assert enewState != state; + + assert enewState != newState; + + SimpleState newState2 = (SimpleState) propObserver.observePropertyChanges(page, newState, "fooBar"); + + assert Enhancer.isEnhanced(state.getClass()); + assert Enhancer.isEnhanced(state.getClass()); + assert Enhancer.isEnhanced(state2.getClass()); + assert !Enhancer.isEnhanced(newState.getClass()); + assert Enhancer.isEnhanced(enewState.getClass()); + assert Enhancer.isEnhanced(newState2.getClass()); + + assert newState2 != enewState; + assert newState2.getClass() == enewState.getClass(); + assert state.getClass() == state2.getClass(); + assert state.getClass() != newState.getClass(); + assert enewState.getClass() == state2.getClass(); + + verify(); + } + + public void test_Proxy_Values_Equal() + { + CglibChangeObserver pageObserver = new CglibChangeObserver(); + PropertyChangeObserver propObserver = new CglibProxiedPropertyChangeObserverImpl(); + + IPage page = newMock(IPage.class); + checkOrder(page, false); + + expect(page.getPage()).andReturn(page).anyTimes(); + expect(page.getIdPath()).andReturn(null).anyTimes(); + expect(page.getChangeObserver()).andReturn(pageObserver).anyTimes(); + + replay(); + + List list = new ArrayList(); + list.add(new SimpleState(1, "First")); + list.add(new SimpleState(2, "Second")); + list.add(new SimpleState(3, "Third")); + + IAutocompleteModel model = new DefaultAutocompleteModel( list , "id", "name"); + + SimpleState selected = (SimpleState)list.get(1); + + assertEquals(model.getPrimaryKey(selected), Long.valueOf(2)); + assertEquals(model.getLabelFor(selected), "Second"); + + assertEquals(selected.getId(), 2); + + SimpleState sel = (SimpleState)propObserver.observePropertyChanges(page, selected, "foo"); + + assertEquals(sel.getId(), selected.getId()); + + assertEquals(model.getPrimaryKey(sel), Long.valueOf(2)); + assertEquals(model.getLabelFor(sel), "Second"); + + verify(); + } +}
