source: main/trunk/greenstone3/src/java/org/greenstone/util/Misc.java@ 33045

Last change on this file since 33045 was 33045, checked in by ak19, 5 years ago
  1. Dr Bainbridge's fix for the Windows encoding issue when online doc editing Title meta containing non-ASCII/non-basic unicode chars, was to URL encode the QUERY_STRING so that CGI.pm would then do the right thing. This was because the problem had turned out not to be env vars on Windows, which could set and recall unicode and win-1252 chars just fine and therefore retained what was entered. The problem was that on Windows, the perl did not get the actual chars transmitted in the case of UTF-8 whereas win-1252 was received looking apparently like a unicode codepoint, but then in the latter case the utf82unicode call in metadataaction would then clobber the codepoint in attempting to do utf82unicode on it. On linux, perl happened to receive the chars as utf8-encoded bytes and so utf82unicode worked (to make them unicode aware strings?). The real problem was that it could go wrong in different ways on windows, since utf8 chars weren't even received properly by perl/CGI, so we didn't even need to start worrying about them getting sometimes clobbered in metadataaction. URL encoding the QUERY_STRING was meant to solve this. Except that URL encoding the whole QUERY_STRING made CGI.pm choke on the equals signs between param name and param value and possibly other chars. I don't know why. I found that URL encoding just the param values in the QUERY_STRING works, so I am committing that. 2. Renaming the recently introduced string2hex() in JavaScript to debug_unicode_string and stringToHex() in Java to debugUnicodeString() to be more consistent with the perl variant, debug_unicode_string. Also like in the perl, the JavaScript and Java now print the unicode value inside curly braces for better legibility. 3. Leaving in some commented out encoding debugging statements in the Java and JavaScript code, but not committing the debugging on the perl side. 4. Some further improvements to overloaded functions in GSXML using debug_unicode_string for converting XML elements or printing them to logs.
  • Property svn:keywords set to Author Date Id Revision
File size: 7.9 KB
Line 
1 /*
2 * Misc.java
3 * Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20package org.greenstone.util;
21
22import java.util.HashMap;
23import java.util.Set;
24import java.util.Map;
25import java.util.Iterator;
26import java.util.Properties;
27import java.io.InputStream;
28import java.io.BufferedReader;
29import java.io.InputStreamReader;
30import java.io.IOException;
31import java.net.HttpURLConnection;
32import java.net.URL;
33import java.net.URLConnection;
34
35/** contains miscellaneous functions */
36public class Misc {
37
38 // Can initialise static final vars on declaration or in static initialisation code block
39 // http://stackoverflow.com/questions/2339932/java-can-final-variables-be-initialized-in-static-initialization-block
40 // Initialise object member final vars on declaration or in constructors
41 public static final String NEWLINE;
42
43 // Before Java 7, no System.lineSeparator() or System.getProperty("line.separator")
44 // And on local linux, am compiling with JDK 6, so need this.
45 // http://stackoverflow.com/questions/207947/how-do-i-get-a-platform-dependent-new-line-character
46
47 static {
48 // http://stackoverflow.com/questions/2591083/getting-java-version-at-runtime
49 // https://www.tutorialspoint.com/java/lang/package_getspecificationversion.htm
50
51 double java_version = Double.parseDouble(System.getProperty("java.specification.version"));
52 if(java_version >= 1.7) { // https://docs.oracle.com/javase/tutorial/essential/environment/sysprop.html
53 NEWLINE = System.getProperty("line.separator");
54 } else {
55 NEWLINE = isWindows() ? "\r\n" : "\n";
56 }
57 }
58
59
60 // Debugging function to print a string's non-basic chars in hex, so stringToHex on all non-basic and non-printable ASCII
61 // Dr Bainbridge said that printing anything with charCode over 128 in hex is okay, but I'd already made extra allowances for non-printable ASCII
62 // Based on https://stackoverflow.com/questions/923863/converting-a-string-to-hexadecimal-in-java
63 public static String debugUnicodeString(String str) {
64 String result = "";
65 for(int i = 0; i < str.length(); i++) {
66 int charCode = str.codePointAt(i); // unicode codepoint / ASCII code
67
68 // ASCII table: https://cdn.sparkfun.com/assets/home_page_posts/2/1/2/1/ascii_table_black.png
69 // If the unicode character code pt is less than the ASCII code for space and greater than for tilda, let's display the char in hex (x0000 format)
70 if((charCode >= 20 && charCode <= 126) || charCode == 9 || charCode == 10 || charCode == 13) { // space, tilda, TAB, LF, CR are printable, leave them in for XML element printing
71 result += str.charAt(i);
72 } else {
73 result += "x{" + String.format("%04x", charCode) + "}"; // looks like: x{4-char-codepoint}
74 }
75 }
76
77 return result;
78 }
79
80
81 public static void printHash(HashMap map) {
82 Set entries = map.entrySet();
83 Iterator i = entries.iterator();
84 while (i.hasNext()) {
85 Map.Entry m = (Map.Entry)i.next();
86 String name = (String)m.getKey();
87 String value = (String)m.getValue();
88 }
89 }
90
91
92 /**
93 * Handy function to display the list of calling functions by
94 * printing out the stack trace even when you don't have an exception
95 */
96 static public void printStackTrace() {
97 // https://stackoverflow.com/questions/1069066/get-current-stack-trace-in-java
98
99 //Thread.dumpStack(); // looks too much like an exception, though the newlines separating each function call is handy
100 //new Exception().printStackTrace(); // outputs in the format of an exception too
101 //System.err.println("\n@@@@ stacktrace:\n" + Arrays.toString(Thread.currentThread().getStackTrace()) + "\n"); // outputs all in one line
102
103 System.err.println("\n@@@@ stacktrace:");
104 StackTraceElement[] els = new Throwable().getStackTrace(); // starts at index 1, which is this function
105 //StackTraceElement[] els = Thread.currentThread().getStackTrace(); starts at index 0, "java.lang.Thread.getStackTrace()"
106 for(StackTraceElement ste : els) {
107 System.err.println(" " + ste);
108 }
109 }
110
111 /**
112 * Handy function to display the parent of the calling function
113 * (the function that called the function that called printCaller())
114 */
115 static public void printCaller() {
116 int parent = 1;
117 // this function printCaller() itself adds another layer on the callstack since
118 // it calls the overloaded method, so need to add 1 more to parent
119 printCaller(parent++);
120 }
121
122 /**
123 * Handy function to display the nth ancestor of the calling function
124 * where ancestor=0 would be the calling function itself
125 */
126 static public void printCaller(int ancestor) {
127 // https://stackoverflow.com/questions/1069066/get-current-stack-trace-in-java
128
129 // Thread.currentThread().getStackTrace() starts at index 0: "java.lang.Thread.getStackTrace()"
130 // index 1 will be this method (printCaller) and index 2 will be the calling function itself who wants
131 // to know who called it. So need to at least start at index 3 to get informative caller information
132
133 StackTraceElement[] callstack = Thread.currentThread().getStackTrace();
134 StackTraceElement requestor = callstack[2]; // the calling function, the function that called this one
135 StackTraceElement caller_requested = callstack[ancestor+3]; // the function requested
136 System.err.println("@@@ Function " + requestor + " called by:\n "
137 + caller_requested + " at " + ancestor + " ancestors back");
138 }
139
140
141 /** Method to determine if the host system is Windows based.
142 * @return a boolean which is true if the platform is Windows,
143 * false otherwise
144 */
145 public static boolean isWindows() {
146 Properties props = System.getProperties();
147 String os_name = props.getProperty("os.name","");
148 if(os_name.startsWith("Windows")) {
149 return true;
150 }
151 return false;
152 }
153
154 public static boolean isWindows9x() {
155 Properties props = System.getProperties();
156 String os_name = props.getProperty("os.name","");
157 if(os_name.startsWith("Windows") && os_name.indexOf("9") != -1) {
158 return true;
159 }
160 return false;
161 }
162
163 /** Method to determine if the host system is MacOS based.
164 * @return a boolean which is true if the platform is MacOS, false otherwise
165 */
166 public static boolean isMac() {
167 Properties props = System.getProperties();
168 String os_name = props.getProperty("os.name","");
169 if(os_name.startsWith("Mac OS")) {
170 return true;
171 }
172 return false;
173 }
174
175 public static String getGsdlOS() {
176 if (isWindows()) {
177 return "windows";
178 }
179 if (isMac()) {
180 return "darwin";
181 }
182 return "linux";
183 }
184
185 public static boolean isBigEndian() {
186
187 if (System.getProperty("sun.cpu.endian").equals("big")) {
188 return true;
189 }
190 return false;
191
192 }
193
194 public static BufferedReader makeHttpConnection(String url_string)
195 throws java.net.MalformedURLException, java.io.IOException {
196 BufferedReader reader = null;
197 URL url = new URL(url_string);
198 HttpURLConnection connection = (HttpURLConnection)url.openConnection();
199 InputStream input = connection.getInputStream();
200 reader = new BufferedReader(new InputStreamReader(input));
201 return reader;
202 }
203
204 public static void main(String [] args) {
205 isBigEndian();
206 }
207
208}
209
Note: See TracBrowser for help on using the repository browser.