[Status] Improve default implementations of status loggers

  - Improve logging of multiline status messages
  - Make use of StackWalker
  - Fix caller in records of JUL

Change-Id: I40e7f882eba0b1397409f7f7f8abd4c1f55d1727
diff --git a/jcommons/org.eclipse.statet.jcommons.util/src/org/eclipse/statet/jcommons/lang/ObjectUtils.java b/jcommons/org.eclipse.statet.jcommons.util/src/org/eclipse/statet/jcommons/lang/ObjectUtils.java
index 9b0cf6b..8de56ca 100644
--- a/jcommons/org.eclipse.statet.jcommons.util/src/org/eclipse/statet/jcommons/lang/ObjectUtils.java
+++ b/jcommons/org.eclipse.statet.jcommons.util/src/org/eclipse/statet/jcommons/lang/ObjectUtils.java
@@ -35,7 +35,8 @@
 		private static final String INDENT= "  "; //$NON-NLS-1$
 		private static final String CONT_INDENT= INDENT + INDENT;
 		
-		private static final String PROP_PREFIX= "\n" + INDENT; //$NON-NLS-1$
+		private static final String LINE_PREFIX= "\n";
+		private static final String PROP_PREFIX= LINE_PREFIX + INDENT;
 		private static final String PROP_ASSIGN= "= "; //$NON-NLS-1$
 		
 		private static final Object NULL= "<null>"; //$NON-NLS-1$
@@ -87,13 +88,25 @@
 			this.sb.append(c);
 		}
 		
+		public final void append(final int number) {
+			this.sb.append(number);
+		}
+		
 		public final void append(final char sep, final String s) {
 			this.sb.append(sep);
 			this.sb.append(s);
 		}
 		
-		public final void append(final int number) {
+		public final void append(final char open, final String s, final char close) {
+			this.sb.append(open);
+			this.sb.append(s);
+			this.sb.append(close);
+		}
+		
+		public final void append(final char open, final int number, final char close) {
+			this.sb.append(open);
 			this.sb.append(number);
+			this.sb.append(close);
 		}
 		
 		public final void appendFormat(final String valueFormat, final @Nullable Object... valueArgs) {
@@ -105,6 +118,26 @@
 			formatter.format(valueFormat, valueArgs);
 		}
 		
+		public final void appendLines(final String lines) {
+			appendLines(lines, LINE_PREFIX + CONT_INDENT);
+		}
+		
+		public final void appendLines(final char sep, final String lines) {
+			this.sb.append(sep);
+			appendLines(lines, LINE_PREFIX + CONT_INDENT);
+		}
+		
+		public final void appendLines(final List<@NonNull String> lines) {
+			final int n= lines.size();
+			if (n == 0) {
+				return;
+			}
+			append(lines.get(0));
+			for (int i= 1; i < n; i++) {
+				append(LINE_PREFIX + CONT_INDENT);
+				lines.get(i);
+			}
+		}
 		
 		private void appendLines(final String s, final String contPrefix) {
 			int start= 0;
@@ -138,6 +171,7 @@
 			}
 		}
 		
+		
 		public void addProp(final String name) {
 			this.sb.append(PROP_PREFIX);
 			this.sb.append(name);
diff --git a/jcommons/org.eclipse.statet.jcommons.util/src/org/eclipse/statet/jcommons/status/util/ACommonsLoggingStatusLogger.java b/jcommons/org.eclipse.statet.jcommons.util/src/org/eclipse/statet/jcommons/status/util/ACommonsLoggingStatusLogger.java
index 38d0244..dd4132e 100644
--- a/jcommons/org.eclipse.statet.jcommons.util/src/org/eclipse/statet/jcommons/status/util/ACommonsLoggingStatusLogger.java
+++ b/jcommons/org.eclipse.statet.jcommons.util/src/org/eclipse/statet/jcommons/status/util/ACommonsLoggingStatusLogger.java
@@ -69,24 +69,16 @@
 	
 	protected String createMessage(final Status status) {
 		final ToStringBuilder sb= new ToStringBuilder();
+		sb.append('[', status.getCode(), ']');
 		switch (status.getSeverity()) {
 		case Status.OK:
 		case Status.CANCEL:
-			sb.append(Statuses.getSeverityString(status.getSeverity()));
-			sb.append(' ');
+			sb.append(' ', Statuses.getSeverityString(status.getSeverity()));
 			break;
 		default:
 			break;
 		}
-		sb.append('[');
-		sb.append(status.getCode());
-		sb.append(']');
-		if (status.getMessage().length() <= 80 && status.getMessage().indexOf('\n') == -1) {
-			sb.append(' ', status.getMessage());
-		}
-		else {
-			sb.addProp("message", status.getMessage()); //$NON-NLS-1$
-		}
+		sb.appendLines(' ', status.getMessage());
 		if (status.isMultiStatus()) {
 			final ImList<Status> children= status.getChildren();
 			if (children != null && !children.isEmpty()) {
diff --git a/jcommons/org.eclipse.statet.jcommons.util/src/org/eclipse/statet/jcommons/status/util/JUtilLoggingStatusLogger.java b/jcommons/org.eclipse.statet.jcommons.util/src/org/eclipse/statet/jcommons/status/util/JUtilLoggingStatusLogger.java
index 0899dc9..882881f 100644
--- a/jcommons/org.eclipse.statet.jcommons.util/src/org/eclipse/statet/jcommons/status/util/JUtilLoggingStatusLogger.java
+++ b/jcommons/org.eclipse.statet.jcommons.util/src/org/eclipse/statet/jcommons/status/util/JUtilLoggingStatusLogger.java
@@ -73,24 +73,16 @@
 	
 	protected String createMessage(final Status status) {
 		final ToStringBuilder sb= new ToStringBuilder();
+		sb.append('[', status.getCode(), ']');
 		switch (status.getSeverity()) {
 		case Status.OK:
 		case Status.CANCEL:
-			sb.append(Statuses.getSeverityString(status.getSeverity()));
-			sb.append(' ');
+			sb.append(' ', Statuses.getSeverityString(status.getSeverity()));
 			break;
 		default:
 			break;
 		}
-		sb.append('[');
-		sb.append(status.getCode());
-		sb.append(']');
-		if (status.getMessage().length() <= 80 && status.getMessage().indexOf('\n') == -1) {
-			sb.append(' ', status.getMessage());
-		}
-		else {
-			sb.addProp("message", status.getMessage()); //$NON-NLS-1$
-		}
+		sb.appendLines(' ', status.getMessage());
 		if (status.isMultiStatus()) {
 			final ImList<Status> children= status.getChildren();
 			if (children != null && !children.isEmpty()) {
@@ -109,13 +101,13 @@
 	protected void enrichRecord(final LogRecord record, final Status status) {
 		// set correct caller
 		try {
-			final StackTraceElement[] stackTrace= Thread.currentThread().getStackTrace();
-			for (int i= 1; i < stackTrace.length; i++) {
-				if (!stackTrace[i].getMethodName().startsWith("log")) { //$NON-NLS-1$
-					record.setSourceClassName(stackTrace[i].getClassName());
-					record.setSourceMethodName(stackTrace[i].getMethodName());
-					break;
-				}
+			final StackWalker.StackFrame caller= StackWalker.getInstance().walk((stream) -> stream
+					.dropWhile((frame) -> !frame.getMethodName().startsWith("log")) //$NON-NLS-1$
+					.dropWhile((frame) -> frame.getMethodName().startsWith("log")) //$NON-NLS-1$
+					.findFirst().orElse(null) );
+			if (caller != null) {
+				record.setSourceClassName(caller.getClassName());
+				record.setSourceMethodName(caller.getMethodName());
 			}
 		}
 		catch (final Exception ignore) {}