code: static private String serialize(Throwable ex, int depth, int level)
      {
          StringBuffer buff = new StringBuffer();
          String str = ex.toString();
  
          // Split the first line if it's too long
          int pos = str.indexOf(":");
          if(str.length() < 80 || pos == -1)
          {
              buff.append(str);
          }
          else
          {
              String str1 = str.substring(0, pos);
              String str2 = str.substring(pos+2);
              if(str2.indexOf(str1) == -1)
              {
                  buff.append(str1);
                  buff.append(": \n\t");
              }
              buff.append(str2);
          }
  
          if(depth > 0)
          {
              StackTraceElement[] elements = ex.getStackTrace();
              for(int i = 0; i < elements.length; i++)
              {
                  buff.append("\n\tat ");
                  buff.append(elements[i]);
                  if(i == (depth-1) && elements.length > depth)
                  {
                      buff.append("\n\t... "+(elements.length-depth)+" more ...");
                      i = elements.length;
                  }
              }
          }
  
          if(ex.getCause() != null && level < 3)
          {
              buff.append("\nCaused by: ");
              buff.append(serialize(ex.getCause(), depth, ++level));
          }
  
          return buff.toString();
      }
docs: Serializes the given exception as a stack trace string.
  @param ex The exception to be serialized
  @param depth The maximum depth of the stack trace returned
  @param level The current level of nesting of the exception
  @return The serialized exception