You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by gn...@apache.org on 2016/11/29 16:58:57 UTC

karaf git commit: [KARAF-4868] Fix encoding problems with shell table formatting

Repository: karaf
Updated Branches:
  refs/heads/master 5f87ec263 -> d3e170bda


[KARAF-4868] Fix encoding problems with shell table formatting

Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/d3e170bd
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/d3e170bd
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/d3e170bd

Branch: refs/heads/master
Commit: d3e170bdab9b6d502c9a9f5c83c35bce9dd2d41d
Parents: 5f87ec2
Author: Guillaume Nodet <gn...@apache.org>
Authored: Tue Nov 29 17:58:35 2016 +0100
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Tue Nov 29 17:58:35 2016 +0100

----------------------------------------------------------------------
 .../karaf/shell/support/table/ShellTable.java   | 66 ++++++++++++++++----
 .../shell/support/table/ShellTableTest.java     | 41 ++++++++++++
 2 files changed, 96 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/d3e170bd/shell/core/src/main/java/org/apache/karaf/shell/support/table/ShellTable.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/support/table/ShellTable.java b/shell/core/src/main/java/org/apache/karaf/shell/support/table/ShellTable.java
index 8f3f245..476ba7c 100644
--- a/shell/core/src/main/java/org/apache/karaf/shell/support/table/ShellTable.java
+++ b/shell/core/src/main/java/org/apache/karaf/shell/support/table/ShellTable.java
@@ -16,17 +16,33 @@
  */
 package org.apache.karaf.shell.support.table;
 
+import java.io.OutputStreamWriter;
 import java.io.PrintStream;
+import java.lang.reflect.Field;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
 public class ShellTable {
 
-    private List<Col> cols = new ArrayList<Col>();
-    private List<Row> rows = new ArrayList<Row>();
-    boolean showHeaders = true;
-    private String separator = " \u2502 ";
+    private static final char SEP_HORIZONTAL = '\u2500';
+    private static final char SEP_VERTICAL = '|';
+    private static final char SEP_CROSS = '\u253c';
+
+    private static final char SEP_HORIZONTAL_ASCII = '-';
+    private static final char SEP_VERTICAL_ASCII = '|';
+    private static final char SEP_CROSS_ASCII = '+';
+
+    private static final String DEFAULT_SEPARATOR = " " + SEP_VERTICAL + " ";
+    private static final String DEFAULT_SEPARATOR_ASCII = " " + SEP_VERTICAL_ASCII + " ";
+    private static final String DEFAULT_SEPARATOR_NO_FORMAT = "\t";
+
+    private List<Col> cols = new ArrayList<>();
+    private List<Row> rows = new ArrayList<>();
+    private boolean showHeaders = true;
+    private String separator = DEFAULT_SEPARATOR;
     private int size;
     private String emptyTableText;
 
@@ -82,6 +98,15 @@ public class ShellTable {
     }
 
     public void print(PrintStream out, boolean format)  {
+        boolean supported = false;
+        String encoding = getEncoding(out);
+        if (encoding != null) {
+            CharsetEncoder encoder = Charset.forName(encoding).newEncoder();
+            supported = encoder.canEncode(separator)
+                    && encoder.canEncode(SEP_HORIZONTAL)
+                    && encoder.canEncode(SEP_CROSS);
+        }
+        String separator = supported ? this.separator : DEFAULT_SEPARATOR_ASCII;
 
         // "normal" table rendering, with borders
         Row headerRow = new Row(cols);
@@ -100,9 +125,9 @@ public class ShellTable {
             int iCol = 0;
             for (Col col : cols) {
                 if (iCol++ == 0) {
-                    out.print(underline(col.getSize(), false));
+                    out.print(underline(col.getSize(), false, supported));
                 } else {
-                    out.print(underline(col.getSize() + 3, true));
+                    out.print(underline(col.getSize() + 3, true, supported));
                 }
                 iCol++;
             }
@@ -111,8 +136,8 @@ public class ShellTable {
 
         for (Row row : rows) {
             if (!format) {
-                if (separator == null || separator.equals(" \u2502 "))
-                    out.println(row.getContent(cols, "\t"));
+                if (separator == null || separator.equals(DEFAULT_SEPARATOR))
+                    out.println(row.getContent(cols, DEFAULT_SEPARATOR_NO_FORMAT));
                 else out.println(row.getContent(cols, separator));
             } else {
                 out.println(row.getContent(cols, separator));
@@ -124,6 +149,25 @@ public class ShellTable {
         }
     }
 
+    private String getEncoding(PrintStream ps) {
+        if (ps.getClass().getName().equals("org.apache.felix.gogo.runtime.threadio.ThreadPrintStream")) {
+            try {
+                ps = (PrintStream) ps.getClass().getMethod("getCurrent").invoke(ps);
+            } catch (Throwable t) {
+                // ignore
+            }
+        }
+        try {
+            Field f = ps.getClass().getDeclaredField("charOut");
+            f.setAccessible(true);
+            OutputStreamWriter osw = (OutputStreamWriter) f.get(ps);
+            return osw.getEncoding();
+        } catch (Throwable t) {
+            // ignore
+        }
+        return null;
+    }
+
     private void adjustSize() {
         int currentSize = 0;
         for (Col col : cols) {
@@ -142,11 +186,11 @@ public class ShellTable {
 
     }
 
-    private String underline(int length, boolean crossAtBeg) {
+    private String underline(int length, boolean crossAtBeg, boolean supported) {
         char[] exmarks = new char[length];
-        Arrays.fill(exmarks, '\u2500');
+        Arrays.fill(exmarks,  supported ? SEP_HORIZONTAL : SEP_HORIZONTAL_ASCII);
         if (crossAtBeg) {
-            exmarks[1] = '\u253c';
+            exmarks[1] = supported ? SEP_CROSS : SEP_CROSS_ASCII;
         }
         return new String(exmarks);
     }

http://git-wip-us.apache.org/repos/asf/karaf/blob/d3e170bd/shell/core/src/test/java/org/apache/karaf/shell/support/table/ShellTableTest.java
----------------------------------------------------------------------
diff --git a/shell/core/src/test/java/org/apache/karaf/shell/support/table/ShellTableTest.java b/shell/core/src/test/java/org/apache/karaf/shell/support/table/ShellTableTest.java
index 575493d..0826e88 100644
--- a/shell/core/src/test/java/org/apache/karaf/shell/support/table/ShellTableTest.java
+++ b/shell/core/src/test/java/org/apache/karaf/shell/support/table/ShellTableTest.java
@@ -19,8 +19,12 @@
 package org.apache.karaf.shell.support.table;
 
 import java.io.ByteArrayOutputStream;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
 import java.io.PrintStream;
 
+import org.apache.felix.gogo.runtime.threadio.ThreadIOImpl;
+import org.apache.felix.service.threadio.ThreadIO;
 import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
@@ -66,4 +70,41 @@ public class ShellTableTest {
                 "                     |quite long"), baos.toString());
     }
 
+    @Test
+    public void testCP1252() throws Exception {
+        testNonUtf8("cp1252");
+    }
+
+    @Test
+    public void testANSI() throws Exception {
+        testNonUtf8("ANSI_X3.4-1968");
+    }
+
+    private void testNonUtf8(String encoding)  throws Exception {
+        ShellTable table = new ShellTable();
+        table.column("col1");
+        table.column("col2").maxSize(-1).wrap();
+        table.addRow().addContent("my first column value", "my second column value is quite long");
+        table.size(50);
+
+        ThreadIO tio = new ThreadIOImpl();
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        PrintStream ps = new PrintStream(baos, false, encoding);
+        table.print(ps, true);
+        tio.setStreams(new FileInputStream(FileDescriptor.in), ps, ps);
+
+        table.print(System.out);
+
+        assertEquals(
+                "col1                  | col2\n" +
+                "----------------------+---------------------------\n" +
+                "my first column value | my second column value is\n" +
+                "                      | quite long\n" +
+                "col1                  | col2\n" +
+                "----------------------+---------------------------\n" +
+                "my first column value | my second column value is\n" +
+                "                      | quite long\n",
+                baos.toString());
+
+    }
 }