diff --git a/src/main/java/org/apache/sling/api/resource/PersistenceException.java b/src/main/java/org/apache/sling/api/resource/PersistenceException.java index 659005bc..6e94840c 100644 --- a/src/main/java/org/apache/sling/api/resource/PersistenceException.java +++ b/src/main/java/org/apache/sling/api/resource/PersistenceException.java @@ -19,6 +19,8 @@ package org.apache.sling.api.resource; import java.io.IOException; +import java.util.Objects; +import java.util.Set; /** * This exception will be thrown during the commit to persist @@ -29,6 +31,8 @@ public class PersistenceException extends IOException { private static final long serialVersionUID = 2454225989618227698L; + private static final Set PUNCTUATION = Set.of('.', ':', '!'); + /** Optional resource path. */ private final String resourcePath; @@ -91,4 +95,34 @@ public String getResourcePath() { public String getPropertyName() { return this.propertyName; } + + /** + * Returns a message for this exception. + * If the cause is not null, it will be appended to the message. + * @return The message for this exception + */ + @Override + public String getMessage() { + StringBuilder sb = new StringBuilder(); + if (this.getCause() != null && !Objects.equals(this.getCause().getMessage(), super.getMessage())) { + sb.append(stripTailingPunctuation(super.getMessage())) + .append(" caused by ") + .append(this.getCause().getMessage()); + } else { + sb.append(super.getMessage()); + } + + return sb.toString(); + } + + private static String stripTailingPunctuation(String str) { + if (str == null || str.isEmpty()) { + return str; + } + int len = str.length(); + if (len > 0 && PUNCTUATION.contains(str.charAt(len - 1))) { + return str.substring(0, len - 1); + } + return str; + } } diff --git a/src/test/java/org/apache/sling/api/resource/PersistenceExceptionTest.java b/src/test/java/org/apache/sling/api/resource/PersistenceExceptionTest.java new file mode 100644 index 00000000..72112d47 --- /dev/null +++ b/src/test/java/org/apache/sling/api/resource/PersistenceExceptionTest.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.sling.api.resource; + +import javax.jcr.RepositoryException; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class PersistenceExceptionTest { + + @Test + public void testGetMessage() { + Throwable cause = new RepositoryException("JCR error"); + PersistenceException e = new PersistenceException("Test message"); + assertEquals("Test message", e.getMessage()); + e = new PersistenceException("Test message", cause); + assertEquals("Test message caused by JCR error", e.getMessage()); + e = new PersistenceException("Test message!", cause); + assertEquals("Test message caused by JCR error", e.getMessage()); + e = new PersistenceException("Test message.", cause); + assertEquals("Test message caused by JCR error", e.getMessage()); + e = new PersistenceException(cause.getMessage(), cause); + assertEquals("JCR error", e.getMessage()); + } +}