Improve JID error handling

Sam Whited created

Change summary

src/main/java/eu/siacs/conversations/xmpp/jid/InvalidJidException.java | 48 
src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java                 | 18 
2 files changed, 57 insertions(+), 9 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/xmpp/jid/InvalidJidException.java 🔗

@@ -0,0 +1,48 @@
+package eu.siacs.conversations.xmpp.jid;
+
+public class InvalidJidException extends Exception {
+
+    // This is probably not the "Java way", but the "Java way" means we'd have a ton of extra tiny,
+    // annoying classes floating around. I like this.
+    public final static String INVALID_LENGTH = "JID must be between 0 and 3071 characters";
+    public final static String INVALID_PART_LENGTH = "JID part must be between 0 and 1023 characters";
+    public final static String INVALID_CHARACTER = "JID contains an invalid character";
+    public final static String STRINGPREP_FAIL = "The STRINGPREP operation has failed for the given JID";
+
+    /**
+     * Constructs a new {@code Exception} that includes the current stack trace.
+     */
+    public InvalidJidException() {
+    }
+
+    /**
+     * Constructs a new {@code Exception} with the current stack trace and the
+     * specified detail message.
+     *
+     * @param detailMessage the detail message for this exception.
+     */
+    public InvalidJidException(final String detailMessage) {
+        super(detailMessage);
+    }
+
+    /**
+     * Constructs a new {@code Exception} with the current stack trace, the
+     * specified detail message and the specified cause.
+     *
+     * @param detailMessage the detail message for this exception.
+     * @param throwable the cause of this exception.
+     */
+    public InvalidJidException(final String detailMessage, final Throwable throwable) {
+        super(detailMessage, throwable);
+    }
+
+    /**
+     * Constructs a new {@code Exception} with the current stack trace and the
+     * specified cause.
+     *
+     * @param throwable the cause of this exception.
+     */
+    public InvalidJidException(final Throwable throwable) {
+        super(throwable);
+    }
+}

src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java 🔗

@@ -10,8 +10,6 @@ import gnu.inet.encoding.StringprepException;
  */
 public final class Jid {
 
-    public final static class InvalidJidException extends Exception { }
-
     private final String localpart;
     private final String domainpart;
     private final String resourcepart;
@@ -53,11 +51,13 @@ public final class Jid {
         final int slashCount = jid.length() - jid.replace("/", "").length();
 
         // Throw an error if there's anything obvious wrong with the JID...
+        if (jid.isEmpty() || jid.length() > 3071) {
+            throw new InvalidJidException(InvalidJidException.INVALID_LENGTH);
+        }
         if (atCount > 1 || slashCount > 1 ||
-                jid.length() == 0 || jid.length() > 3071 ||
                 jid.startsWith("@") || jid.endsWith("@") ||
                 jid.startsWith("/") || jid.endsWith("/")) {
-            throw new InvalidJidException();
+            throw new InvalidJidException(InvalidJidException.INVALID_CHARACTER);
         }
 
         String finaljid;
@@ -69,10 +69,10 @@ public final class Jid {
             try {
                 localpart = Stringprep.nodeprep(lp);
             } catch (final StringprepException e) {
-                throw new InvalidJidException();
+                throw new InvalidJidException(InvalidJidException.STRINGPREP_FAIL, e);
             }
             if (localpart.isEmpty() || localpart.length() > 1023) {
-                throw new InvalidJidException();
+                throw new InvalidJidException(InvalidJidException.INVALID_PART_LENGTH);
             }
             domainpartStart = atLoc;
             finaljid = lp + "@";
@@ -89,10 +89,10 @@ public final class Jid {
             try {
                 resourcepart = Stringprep.resourceprep(rp);
             } catch (final StringprepException e) {
-                throw new InvalidJidException();
+                throw new InvalidJidException(InvalidJidException.STRINGPREP_FAIL, e);
             }
             if (resourcepart.isEmpty() || resourcepart.length() > 1023) {
-                throw new InvalidJidException();
+                throw new InvalidJidException(InvalidJidException.INVALID_PART_LENGTH);
             }
             dp = jid.substring(domainpartStart, slashLoc);
             finaljid = finaljid + dp + "/" + rp;
@@ -111,7 +111,7 @@ public final class Jid {
 
         // TODO: Find a proper domain validation library; validate individual parts, separators, etc.
         if (domainpart.isEmpty() || domainpart.length() > 1023) {
-            throw new InvalidJidException();
+            throw new InvalidJidException(InvalidJidException.INVALID_PART_LENGTH);
         }
 
         this.displayjid = finaljid;