You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by th...@apache.org on 2021/02/28 18:43:34 UTC

[tapestry-5] branch 5.6.x updated (2089b0d -> 78696d9)

This is an automated email from the ASF dual-hosted git repository.

thiagohp pushed a change to branch 5.6.x
in repository https://gitbox.apache.org/repos/asf/tapestry-5.git.


    from 2089b0d  TAP5-2663: ChecksumPath should ignore slashes at the end of URLs
     new bcd42f6  TAP5-2664: PropertyShadowBuilder fails when interface inherits same method more than once
     new 78696d9  TAP5-2664: adding unit test code

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../META-INF/modules/t5/core/ajax.html             | 316 +++++++++++++++++++++
 .../services/PropertyShadowBuilderImpl.java        |  63 +++-
 .../ioc/specs/PropertyShadowBuilderImplSpec.groovy |   6 +-
 3 files changed, 382 insertions(+), 3 deletions(-)
 create mode 100644 docs/home/thiago/workspace-tapestry/tapestry-5/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/ajax.html


[tapestry-5] 02/02: TAP5-2664: adding unit test code

Posted by th...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

thiagohp pushed a commit to branch 5.6.x
in repository https://gitbox.apache.org/repos/asf/tapestry-5.git

commit 78696d9cfbe0fd3b59a846f98d8d03a5c334fd6a
Author: Thiago H. de Paula Figueiredo <th...@arsmachina.com.br>
AuthorDate: Sun Feb 28 15:41:30 2021 -0300

    TAP5-2664: adding unit test code
---
 .../src/test/groovy/ioc/specs/PropertyShadowBuilderImplSpec.groovy  | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/tapestry-ioc/src/test/groovy/ioc/specs/PropertyShadowBuilderImplSpec.groovy b/tapestry-ioc/src/test/groovy/ioc/specs/PropertyShadowBuilderImplSpec.groovy
index 1f202aa..1246989 100644
--- a/tapestry-ioc/src/test/groovy/ioc/specs/PropertyShadowBuilderImplSpec.groovy
+++ b/tapestry-ioc/src/test/groovy/ioc/specs/PropertyShadowBuilderImplSpec.groovy
@@ -3,7 +3,11 @@ package ioc.specs
 import org.apache.tapestry5.ioc.services.PropertyShadowBuilder
 import spock.lang.Shared
 
-interface FooService {
+interface AnotherCloseable {
+  void close();    
+}
+
+interface FooService extends java.io.Closeable, AnotherCloseable {
 
   void foo();
 }


[tapestry-5] 01/02: TAP5-2664: PropertyShadowBuilder fails when interface inherits same method more than once

Posted by th...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

thiagohp pushed a commit to branch 5.6.x
in repository https://gitbox.apache.org/repos/asf/tapestry-5.git

commit bcd42f6b008e7a27aff64836cd235e6b7559e4f2
Author: Thiago H. de Paula Figueiredo <th...@arsmachina.com.br>
AuthorDate: Sun Feb 28 15:39:44 2021 -0300

    TAP5-2664: PropertyShadowBuilder fails when interface inherits same
    method more than once
    
    Thanks Hendrik Noot for noticing the problem and providing the patch
    used to fix it!
---
 .../META-INF/modules/t5/core/ajax.html             | 316 +++++++++++++++++++++
 .../services/PropertyShadowBuilderImpl.java        |  63 +++-
 2 files changed, 377 insertions(+), 2 deletions(-)

diff --git a/docs/home/thiago/workspace-tapestry/tapestry-5/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/ajax.html b/docs/home/thiago/workspace-tapestry/tapestry-5/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/ajax.html
new file mode 100644
index 0000000..08791ee
--- /dev/null
+++ b/docs/home/thiago/workspace-tapestry/tapestry-5/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/ajax.html
@@ -0,0 +1,316 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+  <title>ajax.coffee</title>
+  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+  <meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
+  <link rel="stylesheet" media="all" href="../../../../../../../../../../../../docco.css" />
+</head>
+<body>
+  <div id="container">
+    <div id="background"></div>
+    
+      <ul id="jump_to">
+        <li>
+          <a class="large" href="javascript:void(0);">Jump To &hellip;</a>
+          <a class="small" href="javascript:void(0);">+</a>
+          <div id="jump_wrapper">
+          <div id="jump_page_wrapper">
+            <div id="jump_page">
+              
+                
+                <a class="source" href="../../../../../../../../tapestry-beanvalidator/src/main/coffeescript/META-INF/modules/t5/beanvalidator/beanvalidator-validation.html">
+                  /home/thiago/workspace-tapestry/tapestry-5/tapestry-beanvalidator/src/main/coffeescript/META-INF/modules/t5/beanvalidator/beanvalidator-validation.coffee
+                </a>
+              
+                
+                <a class="source" href="../../../../../../../build/postprocessed-coffeescript/org/apache/tapestry5/t5-core-dom-jquery.html">
+                  /home/thiago/workspace-tapestry/tapestry-5/tapestry-core/build/postprocessed-coffeescript/org/apache/tapestry5/t5-core-dom-jquery.coffee
+                </a>
+              
+                
+                <a class="source" href="../../../../../../../build/postprocessed-coffeescript/org/apache/tapestry5/t5-core-dom-prototype.html">
+                  /home/thiago/workspace-tapestry/tapestry-5/tapestry-core/build/postprocessed-coffeescript/org/apache/tapestry5/t5-core-dom-prototype.coffee
+                </a>
+              
+                
+                <a class="source" href="ajax.html">
+                  /home/thiago/workspace-tapestry/tapestry-5/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/ajax.coffee
+                </a>
+              
+                
+                <a class="source" href="ajaxformloop.html">
+                  /home/thiago/workspace-tapestry/tapestry-5/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/ajaxformloop.coffee
+                </a>
+              
+                
+                <a class="source" href="alert.html">
+                  /home/thiago/workspace-tapestry/tapestry-5/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/alert.coffee
+                </a>
+              
+                
+                <a class="source" href="autocomplete.html">
+                  /home/thiago/workspace-tapestry/tapestry-5/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/autocomplete.coffee
+                </a>
+              
+                
+                <a class="source" href="bootstrap.html">
+                  /home/thiago/workspace-tapestry/tapestry-5/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/bootstrap.coffee
+                </a>
+              
+                
+                <a class="source" href="confirm-click.html">
+                  /home/thiago/workspace-tapestry/tapestry-5/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/confirm-click.coffee
+                </a>
+              
+                
+                <a class="source" href="console.html">
+                  /home/thiago/workspace-tapestry/tapestry-5/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/console.coffee
+                </a>
+              
+                
+                <a class="source" href="datefield.html">
+                  /home/thiago/workspace-tapestry/tapestry-5/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/datefield.coffee
+                </a>
+              
+                
+                <a class="source" href="events.html">
+                  /home/thiago/workspace-tapestry/tapestry-5/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/events.coffee
+                </a>
+              
+                
+                <a class="source" href="exception-display.html">
+                  /home/thiago/workspace-tapestry/tapestry-5/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/exception-display.coffee
+                </a>
+              
+                
+                <a class="source" href="exception-frame.html">
+                  /home/thiago/workspace-tapestry/tapestry-5/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/exception-frame.coffee
+                </a>
+              
+                
+                <a class="source" href="fields.html">
+                  /home/thiago/workspace-tapestry/tapestry-5/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/fields.coffee
+                </a>
+              
+                
+                <a class="source" href="form-fragment.html">
+                  /home/thiago/workspace-tapestry/tapestry-5/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/form-fragment.coffee
+                </a>
+              
+                
+                <a class="source" href="forms.html">
+                  /home/thiago/workspace-tapestry/tapestry-5/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/forms.coffee
+                </a>
+              
+                
+                <a class="source" href="init.html">
+                  /home/thiago/workspace-tapestry/tapestry-5/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/init.coffee
+                </a>
+              
+                
+                <a class="source" href="localdate.html">
+                  /home/thiago/workspace-tapestry/tapestry-5/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/localdate.coffee
+                </a>
+              
+                
+                <a class="source" href="messages.html">
+                  /home/thiago/workspace-tapestry/tapestry-5/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/messages.coffee
+                </a>
+              
+                
+                <a class="source" href="moment.html">
+                  /home/thiago/workspace-tapestry/tapestry-5/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/moment.coffee
+                </a>
+              
+                
+                <a class="source" href="pageinit.html">
+                  /home/thiago/workspace-tapestry/tapestry-5/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/pageinit.coffee
+                </a>
+              
+                
+                <a class="source" href="palette.html">
+                  /home/thiago/workspace-tapestry/tapestry-5/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/palette.coffee
+                </a>
+              
+                
+                <a class="source" href="select.html">
+                  /home/thiago/workspace-tapestry/tapestry-5/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/select.coffee
+                </a>
+              
+                
+                <a class="source" href="time-interval.html">
+                  /home/thiago/workspace-tapestry/tapestry-5/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/time-interval.coffee
+                </a>
+              
+                
+                <a class="source" href="tree.html">
+                  /home/thiago/workspace-tapestry/tapestry-5/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/tree.coffee
+                </a>
+              
+                
+                <a class="source" href="utils.html">
+                  /home/thiago/workspace-tapestry/tapestry-5/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/utils.coffee
+                </a>
+              
+                
+                <a class="source" href="validation.html">
+                  /home/thiago/workspace-tapestry/tapestry-5/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/validation.coffee
+                </a>
+              
+                
+                <a class="source" href="zone-refresh.html">
+                  /home/thiago/workspace-tapestry/tapestry-5/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/zone-refresh.coffee
+                </a>
+              
+                
+                <a class="source" href="zone.html">
+                  /home/thiago/workspace-tapestry/tapestry-5/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/zone.coffee
+                </a>
+              
+            </div>
+          </div>
+        </li>
+      </ul>
+    
+    <ul class="sections">
+        
+          <li id="title">
+              <div class="annotation">
+                  <h1>ajax.coffee</h1>
+              </div>
+          </li>
+        
+        
+        
+        <li id="section-1">
+            <div class="annotation">
+              
+              <div class="pilwrap ">
+                <a class="pilcrow" href="#section-1">&#182;</a>
+              </div>
+              <p>Copyright 2012-2014 The Apache Software Foundation</p>
+<p>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</p>
+<pre><code>http:<span class="hljs-comment">#www.apache.org/licenses/LICENSE-2.0</span></code></pre>
+<p>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.</p>
+
+            </div>
+            
+        </li>
+        
+        
+        <li id="section-2">
+            <div class="annotation">
+              
+              <div class="pilwrap ">
+                <a class="pilcrow" href="#section-2">&#182;</a>
+              </div>
+              <h2 id="t5coreajax">t5/core/ajax</h2>
+<p>Exports a single function, that invokes <code>t5/core/dom:ajaxRequest()</code> with the provided <code>url</code> and a modified version of the
+<code>options</code>.</p>
+<ul>
+<li>options.method - “post”, “get”, etc., default: “post”.</li>
+<li>options.element - if provided, the URL will be treated as a server-side event name
+ and the actual URL to be used will be obtained from dom.getEventUrl(url, element)</li>
+<li>options.contentType - request content, defaults to “application/x-www-form-urlencoded”</li>
+<li>options.data - optional, additional key/value pairs (for the default content type)</li>
+<li>options.success - handler to invoke on success. Passed the ResponseWrapper object.
+Default does nothing.</li>
+<li>options.failure - handler to invoke on failure (server responds with a non-2xx code).
+Passed the response. Default will throw the exception</li>
+<li>options.exception - handler to invoke when an exception occurs (often means the server is unavailable).
+Passed the exception. Default will generate an exception message and throw an <code>Error</code>.
+Note: not really supported under jQuery, a hold-over from Prototype.</li>
+<li>options.complete - handler to invoke after success, falure, or exception. The handler is passed no
+parameters.</li>
+</ul>
+<p>It wraps (or provides) <code>success</code>, <code>exception</code>, and <code>failure</code> handlers, extended to handle a partial page render
+response (for success), or properly log a server-side failure or client-side exception, including using the
+<code>t5/core/exception-frame</code> module to display a server-side processing exception.</p>
+
+            </div>
+            
+            <div class="content"><div class='highlight'><pre>define [<span class="hljs-string">&quot;./pageinit&quot;</span>, <span class="hljs-string">&quot;./dom&quot;</span>, <span class="hljs-string">&quot;./exception-frame&quot;</span>, <span class="hljs-string">&quot;./console&quot;</span>, <span class="hljs-string">&quot;underscore&quot;</span>],
+  <span class="hljs-function"><span class="hljs-params">(pageinit, dom, exceptionframe, <span class="hljs-built_in">console</span>, _)</span> -&gt;</span>
+    (url, options) -&gt;
+<span class="hljs-function">
+      <span class="hljs-title">complete</span> = -&gt;</span>
+        <span class="hljs-keyword">if</span> options.complete
+          options.complete()
+
+        <span class="hljs-keyword">return</span>
+        
+      <span class="hljs-keyword">if</span> options.hasOwnProperty <span class="hljs-string">&#x27;element&#x27;</span>
+        url = dom.getEventUrl(url, options.element)
+
+      newOptions = _.extend {}, options,</pre></div></div>
+            
+        </li>
+        
+        
+        <li id="section-3">
+            <div class="annotation">
+              
+              <div class="pilwrap ">
+                <a class="pilcrow" href="#section-3">&#182;</a>
+              </div>
+              <p>Logs the exception to the console before passing it to the
+provided exception handler or throwing the exception.</p>
+
+            </div>
+            
+            <div class="content"><div class='highlight'><pre>        exception: <span class="hljs-function"><span class="hljs-params">(exception)</span> -&gt;</span>
+          <span class="hljs-built_in">console</span>.error <span class="hljs-string">&quot;Request to <span class="hljs-subst">#{url}</span> failed with <span class="hljs-subst">#{exception}</span>&quot;</span>
+
+          <span class="hljs-keyword">if</span> options.exception
+            options.exception exception
+          <span class="hljs-keyword">else</span>
+            <span class="hljs-keyword">throw</span> exception
+
+          complete()
+
+          <span class="hljs-keyword">return</span>
+
+        failure: <span class="hljs-function"><span class="hljs-params">(response, failureMessage)</span> -&gt;</span>
+          raw = response.header <span class="hljs-string">&quot;X-Tapestry-ErrorMessage&quot;</span>
+          <span class="hljs-keyword">unless</span> _.isEmpty raw
+            message = <span class="hljs-built_in">window</span>.<span class="hljs-built_in">unescape</span> raw
+            <span class="hljs-built_in">console</span>.error <span class="hljs-string">&quot;Request to <span class="hljs-subst">#{url}</span> failed with &#x27;<span class="hljs-subst">#{message}</span>&#x27;.&quot;</span>
+
+            contentType = response.header <span class="hljs-string">&quot;content-type&quot;</span>
+
+            isHTML = contentType <span class="hljs-keyword">and</span> (contentType.split(<span class="hljs-string">&#x27;;&#x27;</span>)[<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">&quot;text/html&quot;</span>)
+
+            <span class="hljs-keyword">if</span> isHTML
+              exceptionframe response.text
+          <span class="hljs-keyword">else</span>
+            <span class="hljs-built_in">console</span>.error failureMessage
+
+          options.failure <span class="hljs-keyword">and</span> options.failure(response)
+
+          complete()
+
+          <span class="hljs-keyword">return</span>
+
+        success: <span class="hljs-function"><span class="hljs-params">(response)</span> -&gt;</span>
+          pageinit.handlePartialPageRenderResponse response, options.success
+
+          complete()
+
+          <span class="hljs-keyword">return</span>
+
+      dom.ajaxRequest url, newOptions</pre></div></div>
+            
+        </li>
+        
+    </ul>
+  </div>
+</body>
+</html>
diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/PropertyShadowBuilderImpl.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/PropertyShadowBuilderImpl.java
index 9011b6e..51b1fa3 100644
--- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/PropertyShadowBuilderImpl.java
+++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/PropertyShadowBuilderImpl.java
@@ -18,12 +18,21 @@ import org.apache.tapestry5.ioc.services.*;
 import org.apache.tapestry5.plastic.*;
 
 import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
 
 public class PropertyShadowBuilderImpl implements PropertyShadowBuilder
 {
     private final PropertyAccess propertyAccess;
 
     private final PlasticProxyFactory proxyFactory;
+    
+    final private static MethodSignatureUniqueComparator METHOD_COMPARATOR = new MethodSignatureUniqueComparator();
 
     public PropertyShadowBuilderImpl(@Builtin
                                      PlasticProxyFactory proxyFactory,
@@ -96,9 +105,13 @@ public class PropertyShadowBuilderImpl implements PropertyShadowBuilder
                     }
                 });
 
-                for (Method m : propertyType.getMethods())
+                for (Method m : METHOD_COMPARATOR.getUniqueMethods(propertyType)) 
                 {
-                    plasticClass.introduceMethod(m).delegateTo(delegateMethod);
+                    final MethodDescription description = new MethodDescription(m);
+                    if (Modifier.isStatic(description.modifiers)) {
+                        continue;
+                    }
+                    plasticClass.introduceMethod(description).delegateTo(delegateMethod);
                 }
 
                 plasticClass.addToString(String.format("<Shadow: property %s of %s>", propertyName, source));
@@ -107,4 +120,50 @@ public class PropertyShadowBuilderImpl implements PropertyShadowBuilder
 
         return propertyType.cast(instantiator.newInstance());
     }
+    
+    private final static class MethodSignatureUniqueComparator implements Comparator<Method> {
+
+        @Override
+        public int compare(Method o1, Method o2) {
+
+            int comparison = o1.getName().compareTo(o2.getName());
+
+            if (comparison == 0) {
+                comparison = o1.getParameterTypes().length - o2.getParameterTypes().length;
+            }
+
+            if (comparison == 0) {
+                final int count = o1.getParameterTypes().length;
+                for (int i = 0; i < count; i++) {
+                    Class p1 = o1.getParameterTypes()[i];
+                    Class p2 = o2.getParameterTypes()[i];
+                    if (!p1.equals(p2)) {
+                        comparison = p1.getName().compareTo(p2.getName());
+                        break;
+                    }
+                }
+            }
+
+            return comparison;
+        }
+
+        public List<Method> getUniqueMethods(Class interfaceType) 
+        {
+            final List<Method> unique = new ArrayList<>(Arrays.asList(interfaceType.getMethods()));
+            Collections.sort(unique, this);
+            Method last = null;
+            Iterator<Method> iterator = unique.iterator();
+            while (iterator.hasNext()) 
+            {
+                Method m = iterator.next();
+                if (last != null && compare(m, last) == 0) 
+                {
+                    iterator.remove();
+                }
+                last = m;
+            }
+            return unique;
+        }
+
+    }
 }