This is an automated email from the ASF dual-hosted git repository. thiagohp pushed a commit to branch javax in repository https://gitbox.apache.org/repos/asf/tapestry-5.git
The following commit(s) were added to refs/heads/javax by this push: new 199c89f7a TAP5-2786: don't override final method in subclass 199c89f7a is described below commit 199c89f7af2a5bd11d0c55372a528a56225a2a57 Author: Thiago H. de Paula Figueiredo <thi...@arsmachina.com.br> AuthorDate: Sat Aug 24 15:57:24 2024 -0300 TAP5-2786: don't override final method in subclass when in multiple classloader mode --- .../internal/plastic/PlasticFieldImpl.java | 2 +- .../plastic/MethodAlreadyExistsException.java | 35 ++++++++++++++++ .../tapestry5/internal/transform/CachedWorker.java | 14 ++++++- .../internal/transform/PropertyWorker.java | 11 ++++- .../components/SubclassWithFinalCachedMethod.java | 36 +++++++++++++++++ .../SuperclassWithFinalCachedMethod.java | 47 ++++++++++++++++++++++ .../pages/SubclassWithFinalCachedMethodDemo.java | 19 +++++++++ .../components/SuperclassWithFinalCachedMethod.tml | 12 ++++++ .../pages/SubclassWithFinalCachedMethodDemo.tml | 10 +++++ 9 files changed, 183 insertions(+), 3 deletions(-) diff --git a/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticFieldImpl.java b/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticFieldImpl.java index d490750d6..8b1fe9310 100644 --- a/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticFieldImpl.java +++ b/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticFieldImpl.java @@ -360,7 +360,7 @@ class PlasticFieldImpl extends PlasticMember implements PlasticField, Comparable if (plasticClass.inheritanceData.isImplemented(name, desc)) { - throw new IllegalArgumentException(String.format( + throw new MethodAlreadyExistsException(String.format( "Unable to create new accessor method %s on class %s as the method is already implemented.", description.toString(), plasticClass.className)); } diff --git a/plastic/src/main/java/org/apache/tapestry5/plastic/MethodAlreadyExistsException.java b/plastic/src/main/java/org/apache/tapestry5/plastic/MethodAlreadyExistsException.java new file mode 100644 index 000000000..4f434ac8f --- /dev/null +++ b/plastic/src/main/java/org/apache/tapestry5/plastic/MethodAlreadyExistsException.java @@ -0,0 +1,35 @@ +// Copyright 2024 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.tapestry5.plastic; + +/** + * Exception raised when there's an attempt to create a method which + * already exists in a class. + * + * This extends {@linkplain IllegalArgumentException} for backward compatibility. + * + * @since 5.9.0 + */ +public class MethodAlreadyExistsException extends IllegalArgumentException +{ + + private static final long serialVersionUID = 1L; + + public MethodAlreadyExistsException(String message) + { + super(message); + } + +} diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/CachedWorker.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/CachedWorker.java index e5848dcd3..045188d09 100644 --- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/CachedWorker.java +++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/CachedWorker.java @@ -36,6 +36,7 @@ import org.apache.tapestry5.services.TransformConstants; import org.apache.tapestry5.services.transform.ComponentClassTransformWorker2; import org.apache.tapestry5.services.transform.TransformationSupport; +import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -219,7 +220,11 @@ public class CachedWorker implements ComponentClassTransformWorker2 for (int i = 0; i < array.size(); i++) { final JSONObject jsonObject = array.getJSONObject(i); - methods.add(toPlasticMethod(jsonObject, plasticClass, extraMethodCachedWatchMap)); + final PlasticMethod plasticMethod = toPlasticMethod(jsonObject, plasticClass, extraMethodCachedWatchMap); + if (plasticMethod != null) + { + methods.add(plasticMethod); + } } return methods; } @@ -229,6 +234,13 @@ public class CachedWorker implements ComponentClassTransformWorker2 Map<String, String> extraMethodCachedWatchMap) { final int modifiers = jsonObject.getInt(MODIFIERS); + + // We cannot override final methods + if (Modifier.isFinal(modifiers)) + { + return null; + } + final String returnType = jsonObject.getString(RETURN_TYPE); final String methodName = jsonObject.getString(NAME); final String genericSignature = jsonObject.getStringOrDefault(GENERIC_SIGNATURE, null); diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/PropertyWorker.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/PropertyWorker.java index bc95f6f4b..05677467c 100644 --- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/PropertyWorker.java +++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/PropertyWorker.java @@ -16,6 +16,7 @@ package org.apache.tapestry5.internal.transform; import org.apache.tapestry5.annotations.Property; import org.apache.tapestry5.model.MutableComponentModel; +import org.apache.tapestry5.plastic.MethodAlreadyExistsException; import org.apache.tapestry5.plastic.PlasticClass; import org.apache.tapestry5.plastic.PlasticField; import org.apache.tapestry5.plastic.PropertyAccessType; @@ -36,7 +37,15 @@ public class PropertyWorker implements ComponentClassTransformWorker2 { for (PlasticField field : plasticClass.getFieldsWithAnnotation(Property.class)) { - createAccessorsForField(field); + try + { + createAccessorsForField(field); + } + catch (MethodAlreadyExistsException e) + { + // Method was already created somewhere else, so + // nothing to do here + } } } diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/SubclassWithFinalCachedMethod.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/SubclassWithFinalCachedMethod.java new file mode 100644 index 000000000..e556d17f1 --- /dev/null +++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/SubclassWithFinalCachedMethod.java @@ -0,0 +1,36 @@ +// Copyright 2024 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.tapestry5.integration.app1.components; + +import java.util.Arrays; +import java.util.List; + +import org.apache.tapestry5.annotations.Property; + +public class SubclassWithFinalCachedMethod extends SuperclassWithFinalCachedMethod +{ + + @Property + private int clientId = 2; + + private int counter = 10; + + @Override + protected List<?> createList() + { + return Arrays.asList("subclass", String.valueOf(counter++)); + } + +} diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/SuperclassWithFinalCachedMethod.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/SuperclassWithFinalCachedMethod.java new file mode 100644 index 000000000..fbe026c8f --- /dev/null +++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/SuperclassWithFinalCachedMethod.java @@ -0,0 +1,47 @@ +// Copyright 2024 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.tapestry5.integration.app1.components; + +import java.util.Arrays; +import java.util.List; + +import org.apache.tapestry5.annotations.Cached; +import org.apache.tapestry5.annotations.Property; + +public class SuperclassWithFinalCachedMethod +{ + + @Property + private int clientId = 1; + + private int counter = 0; + + @Cached(watch = "clientId") + protected final List<?> getList() + { + return createList(); + } + + protected List<?> createList() + { + return Arrays.asList("superclass", String.valueOf(counter++)); + } + + public final List<?> getListPublic() + { + return getList(); + } + +} diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/SubclassWithFinalCachedMethodDemo.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/SubclassWithFinalCachedMethodDemo.java new file mode 100644 index 000000000..64f64bd43 --- /dev/null +++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/SubclassWithFinalCachedMethodDemo.java @@ -0,0 +1,19 @@ +// Copyright 2024 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.tapestry5.integration.app1.pages; + +public class SubclassWithFinalCachedMethodDemo +{ +} diff --git a/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/components/SuperclassWithFinalCachedMethod.tml b/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/components/SuperclassWithFinalCachedMethod.tml new file mode 100644 index 000000000..80c393ab1 --- /dev/null +++ b/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/components/SuperclassWithFinalCachedMethod.tml @@ -0,0 +1,12 @@ +<t:container + xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd"> + <p> + Client id: ${clientId}. + </p> + <p> + List: ${listPublic}. + </p> + <p> + List: ${listPublic}. + </p> +</t:container> \ No newline at end of file diff --git a/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/SubclassWithFinalCachedMethodDemo.tml b/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/SubclassWithFinalCachedMethodDemo.tml new file mode 100644 index 000000000..bd1c273fd --- /dev/null +++ b/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/SubclassWithFinalCachedMethodDemo.tml @@ -0,0 +1,10 @@ +<html t:type="Border" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_0.xsd"> + <h1>Trigger Demo</h1> + + <h3>Superclass:</h3> + <t:superclassWithFinalCachedMethod/> + + <h3>Subclass:</h3> + <t:subclassWithFinalCachedMethod/> + +</html>