diff --git a/bundles/org.jkiss.utils/META-INF/MANIFEST.MF b/bundles/org.jkiss.utils/META-INF/MANIFEST.MF deleted file mode 100644 index 50c633dd37fd6..0000000000000 --- a/bundles/org.jkiss.utils/META-INF/MANIFEST.MF +++ /dev/null @@ -1,17 +0,0 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: DBeaver Utils -Bundle-Vendor: DBeaver Corp -Bundle-SymbolicName: org.jkiss.utils -Bundle-Version: 2.1.207.qualifier -Bundle-Release-Date: 20240205 -Bundle-RequiredExecutionEnvironment: JavaSE-17 -Require-Bundle: com.google.gson -Export-Package: org.jkiss.code, - org.jkiss.utils, - org.jkiss.utils.csv, - org.jkiss.utils.io, - org.jkiss.utils.rest, - org.jkiss.utils.time, - org.jkiss.utils.xml -Automatic-Module-Name: org.jkiss.utils diff --git a/bundles/org.jkiss.utils/build.properties b/bundles/org.jkiss.utils/build.properties deleted file mode 100644 index 3335c5d91cbc6..0000000000000 --- a/bundles/org.jkiss.utils/build.properties +++ /dev/null @@ -1,3 +0,0 @@ -source.. = src/ -output.. = target/classes/ -bin.includes = META-INF/,. diff --git a/bundles/org.jkiss.utils/pom.xml b/bundles/org.jkiss.utils/pom.xml deleted file mode 100644 index 94e81311b7249..0000000000000 --- a/bundles/org.jkiss.utils/pom.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - 4.0.0 - - org.jkiss.dbeaver - bundles - 1.0.0-SNAPSHOT - ../ - - org.jkiss.utils - 2.1.207-SNAPSHOT - eclipse-plugin - diff --git a/bundles/org.jkiss.utils/src/org/jkiss/code/NotNull.java b/bundles/org.jkiss.utils/src/org/jkiss/code/NotNull.java deleted file mode 100644 index bff9bf18a575d..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/code/NotNull.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jkiss.code; - -/** - * NotNull annotation - */ -public @interface NotNull { - -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/code/Nullable.java b/bundles/org.jkiss.utils/src/org/jkiss/code/Nullable.java deleted file mode 100644 index 88a5ebf0de304..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/code/Nullable.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jkiss.code; - -/** - * Nullable annotation - */ -public @interface Nullable { - -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/AlphanumericComparator.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/AlphanumericComparator.java deleted file mode 100644 index e1c37a536846b..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/AlphanumericComparator.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jkiss.utils; - -import org.jkiss.code.NotNull; - -import java.util.Comparator; - -/** - * A comparator for comparing two strings lexicographically, treating them as sequences of alphanumeric characters. - *

- * This comparator compares strings based on their alphanumeric content. It considers - * the characters in the strings as a sequence of alphanumeric characters (letters and digits) - * and compares them lexicographically. The comparison is case-insensitive. - */ -public class AlphanumericComparator implements Comparator { - private static final AlphanumericComparator INSTANCE = new AlphanumericComparator(); - - private AlphanumericComparator() { - // prevents instantiation - } - - @NotNull - public static AlphanumericComparator getInstance() { - return INSTANCE; - } - - @Override - public int compare(CharSequence o1, CharSequence o2) { - final int len1 = o1.length(); - final int len2 = o2.length(); - - int i = 0; - int j = 0; - - while (i < len1 && j < len2) { - final char ch1 = Character.toUpperCase(o1.charAt(i)); - final char ch2 = Character.toUpperCase(o2.charAt(i)); - - if (Character.isDigit(ch1) && Character.isDigit(ch2)) { - int num1 = 0; - int num2 = 0; - - while (i < len1 && Character.isDigit(o1.charAt(i))) { - num1 = num1 * 10 + Character.digit(o1.charAt(i), 10); - i += 1; - } - - while (j < len2 && Character.isDigit(o2.charAt(j))) { - num2 = num2 * 10 + Character.digit(o2.charAt(j), 10); - j += 1; - } - - if (num1 != num2) { - return num1 - num2; - } - } else { - if (ch1 != ch2) { - return ch1 - ch2; - } - - i += 1; - j += 1; - } - } - - return len1 - len2; - } -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/ArgumentTokenizer.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/ArgumentTokenizer.java deleted file mode 100644 index 46e12bd0d03d7..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/ArgumentTokenizer.java +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright (c) 2001-2010, JavaPLT group at Rice University (drjava@rice.edu) - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * This software is Open Source Initiative approved Open Source Software. - * Open Source Initative Approved is a trademark of the Open Source Initiative. - * - * This file is part of DrJava. Download the current version of this project - * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/ - */ - -package org.jkiss.utils; - -import java.util.LinkedList; -import java.util.List; - -/** - * Utility class which can tokenize a String into a list of String arguments, - * with behavior similar to parsing command line arguments to a program. - * Quoted Strings are treated as single arguments, and escaped characters - * are translated so that the tokenized arguments have the same meaning. - * Since all methods are static, the class is declared abstract to prevent - * instantiation. - * - * @version $Id$ - */ -public abstract class ArgumentTokenizer { - private static final int NO_TOKEN_STATE = 0; - private static final int NORMAL_TOKEN_STATE = 1; - private static final int SINGLE_QUOTE_STATE = 2; - private static final int DOUBLE_QUOTE_STATE = 3; - - /** - * Tokenizes the given String into String tokens - * - * @param arguments A String containing one or more command-line style arguments to be tokenized. - * @return A list of parsed and properly escaped arguments. - */ - public static List tokenize(String arguments) { - return tokenize(arguments, false); - } - - /** - * Tokenizes the given String into String tokens. - * - * @param arguments A String containing one or more command-line style arguments to be tokenized. - * @param stringify whether or not to include escape special characters - * @return A list of parsed and properly escaped arguments. - */ - public static List tokenize(String arguments, boolean stringify) { - - LinkedList argList = new LinkedList(); - StringBuilder currArg = new StringBuilder(); - boolean escaped = false; - int state = NO_TOKEN_STATE; // start in the NO_TOKEN_STATE - int len = arguments.length(); - - // Loop over each character in the string - for (int i = 0; i < len; i++) { - char c = arguments.charAt(i); - if (escaped) { - // Escaped state: just append the next character to the current arg. - escaped = false; - if (c != 'n' && c != 't' && c != '\\') { - // This was just a regular slash - currArg.append('\\'); - } - currArg.append(c); - } else { - switch (state) { - case SINGLE_QUOTE_STATE: - if (c == '\'') { - // Seen the close quote; continue this arg until whitespace is seen - state = NORMAL_TOKEN_STATE; - } else { - currArg.append(c); - } - break; - case DOUBLE_QUOTE_STATE: - if (c == '"') { - // Seen the close quote; continue this arg until whitespace is seen - state = NORMAL_TOKEN_STATE; - } else if (c == '\\') { - // Look ahead, and only escape quotes or backslashes - i++; - char next = arguments.charAt(i); - if (next == '"' || next == '\\') { - currArg.append(next); - } else { - currArg.append(c); - currArg.append(next); - } - } else { - currArg.append(c); - } - break; -// case NORMAL_TOKEN_STATE: -// if (Character.isWhitespace(c)) { -// // Whitespace ends the token; start a new one -// argList.add(currArg.toString()); -// currArg = new StringBuffer(); -// state = NO_TOKEN_STATE; -// } -// else if (c == '\\') { -// // Backslash in a normal token: escape the next character -// escaped = true; -// } -// else if (c == '\'') { -// state = SINGLE_QUOTE_STATE; -// } -// else if (c == '"') { -// state = DOUBLE_QUOTE_STATE; -// } -// else { -// currArg.append(c); -// } -// break; - case NO_TOKEN_STATE: - case NORMAL_TOKEN_STATE: - switch (c) { - case '\\': - escaped = true; - state = NORMAL_TOKEN_STATE; - break; - case '\'': - state = SINGLE_QUOTE_STATE; - break; - case '"': - state = DOUBLE_QUOTE_STATE; - break; - default: - if (!Character.isWhitespace(c)) { - currArg.append(c); - state = NORMAL_TOKEN_STATE; - } else if (state == NORMAL_TOKEN_STATE) { - // Whitespace ends the token; start a new one - argList.add(currArg.toString()); - currArg = new StringBuilder(); - state = NO_TOKEN_STATE; - } - } - break; - default: - throw new IllegalStateException("ArgumentTokenizer state " + state + " is invalid!"); - } - } - } - - // If we're still escaped, put in the backslash - if (escaped) { - currArg.append('\\'); - argList.add(currArg.toString()); - } - // Close the last argument if we haven't yet - else if (state != NO_TOKEN_STATE) { - argList.add(currArg.toString()); - } - // Format each argument if we've been told to stringify them - if (stringify) { - for (int i = 0; i < argList.size(); i++) { - argList.set(i, "\"" + _escapeQuotesAndBackslashes(argList.get(i)) + "\""); - } - } - return argList; - } - - /** - * Inserts backslashes before any occurrences of a backslash or - * quote in the given string. Also converts any special characters - * appropriately. - */ - protected static String _escapeQuotesAndBackslashes(String s) { - final StringBuilder buf = new StringBuilder(s); - - // Walk backwards, looking for quotes or backslashes. - // If we see any, insert an extra backslash into the buffer at - // the same index. (By walking backwards, the index into the buffer - // will remain correct as we change the buffer.) - for (int i = s.length() - 1; i >= 0; i--) { - char c = s.charAt(i); - if ((c == '\\') || (c == '"')) { - buf.insert(i, '\\'); - } - // Replace any special characters with escaped versions - else if (c == '\n') { - buf.deleteCharAt(i); - buf.insert(i, "\\n"); - } else if (c == '\t') { - buf.deleteCharAt(i); - buf.insert(i, "\\t"); - } else if (c == '\r') { - buf.deleteCharAt(i); - buf.insert(i, "\\r"); - } else if (c == '\b') { - buf.deleteCharAt(i); - buf.insert(i, "\\b"); - } else if (c == '\f') { - buf.deleteCharAt(i); - buf.insert(i, "\\f"); - } - } - return buf.toString(); - } -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/ArrayUtils.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/ArrayUtils.java deleted file mode 100644 index deb37abc82b03..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/ArrayUtils.java +++ /dev/null @@ -1,311 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jkiss.utils; - -import org.jkiss.code.NotNull; -import org.jkiss.code.Nullable; - -import java.lang.reflect.Array; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.function.Predicate; - -/** - * Common utils - */ -public class ArrayUtils { - - - public static boolean isEmpty(@Nullable Object[] arr) - { - return arr == null || arr.length == 0; - } - - public static boolean isEmpty(@Nullable short[] array) - { - return array == null || array.length == 0; - } - - public static boolean isArray(@Nullable Object value) { - return value != null && value.getClass().isArray(); - } - - public static boolean contains(@Nullable short[] array, short value) - { - if (array == null) - return false; - for (short item : array) { - if (item == value) - return true; - } - return false; - } - - public static boolean contains(@Nullable char[] array, char value) - { - if (array == null || array.length == 0) - return false; - for (char c : array) { - if (c == value) - return true; - } - return false; - } - - public static boolean isEmpty(@Nullable int[] array) - { - return array == null || array.length == 0; - } - - public static boolean contains(@Nullable int[] array, int value) - { - if (array == null) - return false; - for (int v : array) { - if (v == value) - return true; - } - return false; - } - - public static boolean isEmpty(@Nullable long[] array) - { - return array == null || array.length == 0; - } - - public static boolean contains(@Nullable long[] array, long value) - { - if (array == null) - return false; - for (long v : array) { - if (v == value) - return true; - } - return false; - } - - public static boolean contains(OBJECT_TYPE[] array, OBJECT_TYPE value) - { - if (isEmpty(array)) - return false; - for (OBJECT_TYPE object_type : array) { - if (CommonUtils.equalObjects(value, object_type)) - return true; - } - return false; - } - - public static boolean containsIgnoreCase(String[] array, String value) - { - if (isEmpty(array) || value == null) - return false; - for (String s : array) { - if (value.equalsIgnoreCase(s)) - return true; - } - return false; - } - - public static boolean containsRef(@NotNull OBJECT_TYPE[] array, @Nullable OBJECT_TYPE value) - { - final int length = array.length; - for (OBJECT_TYPE object_type : array) { - if (value == object_type) - return true; - } - return false; - } - - @SafeVarargs - public static boolean containsAny(OBJECT_TYPE[] array, OBJECT_TYPE... values) { - for (OBJECT_TYPE item : array) { - for (OBJECT_TYPE value : values) { - if (CommonUtils.equalObjects(item, value)) - return true; - } - } - return false; - } - - @SafeVarargs - public static boolean containsAll(OBJECT_TYPE[] array, OBJECT_TYPE... values) { - if (isEmpty(array)) { - return false; - } - for (OBJECT_TYPE value : values) { - if (!ArrayUtils.contains(array, value)) - return false; - } - return true; - } - - @NotNull - public static T[] concatArrays(@NotNull T[] first, @NotNull T[] second) - { - T[] result = Arrays.copyOf(first, first.length + second.length); - System.arraycopy(second, 0, result, first.length, second.length); - return result; - } - - @NotNull - public static List safeArray(@Nullable T[] array) - { - if (array == null) { - return Collections.emptyList(); - } else { - return Arrays.asList(array); - } - } - - /** - * Returns index of the first found element satisfying a given predicate in the provided array - */ - public static int indexOf(@NotNull T[] array, @NotNull Predicate condition) { - for (int i = 0; i < array.length; i++) { - if (condition.test(array[i])) { - return i; - } - } - return -1; - } - - public static int indexOf(T[] array, T element) { - for (int i = 0; i < array.length; i++) { - if (CommonUtils.equalObjects(array[i], element)) { - return i; - } - } - return -1; - } - - public static int indexOf(int[] array, int offset, int element) { - for (int i = offset; i < array.length; i++) { - if (array[i] == element) { - return i; - } - } - return -1; - } - - public static int indexOf(byte[] array, int offset, byte element) { - for (int i = offset; i < array.length; i++) { - if (array[i] == element) { - return i; - } - } - return -1; - } - - @SuppressWarnings("unchecked") - public static T[] deleteArea(Class type, T[] elements, int from, int to) { - int delCount = to - from + 1; - T[] newArray = (T[]) Array.newInstance(type, elements.length - delCount); - System.arraycopy(elements, 0, newArray, 0, from); - if (to < elements.length - 1) { - System.arraycopy(elements, to + 1, newArray, from, elements.length - from - delCount); - } - - return newArray; - } - - @SuppressWarnings("unchecked") - public static T[] insertArea(Class type, Object[] elements, int pos, Object[] add) { - T[] newArray = (T[]) Array.newInstance(type, elements.length + add.length); - System.arraycopy(elements, 0, newArray, 0, pos); - System.arraycopy(add, 0, newArray, pos, add.length); - System.arraycopy(elements, pos, newArray, pos + add.length, elements.length - pos); - return newArray; - } - - @SuppressWarnings("unchecked") - public static T[] add(Class type, T[] elements, T add) { - T[] newArray = (T[]) Array.newInstance(type, elements.length + 1); - System.arraycopy(elements, 0, newArray, 0, elements.length); - newArray[elements.length] = add; - return newArray; - } - - @SuppressWarnings("unchecked") - public static T[] remove(Class type, T[] elements, int index) { - T[] newArray = (T[]) Array.newInstance(type, elements.length - 1); - System.arraycopy(elements, 0, newArray, 0, index); - if (index < elements.length - 1) { - System.arraycopy(elements, index + 1, newArray, index, elements.length - index - 1); - } - return newArray; - } - - public static T[] remove(Class type, T[] elements, T element) { - for (int i = 0; i < elements.length; i++) { - if (elements[i] == element) { - return remove(type, elements, i); - } - } - return elements; - } - - public static int[] add(int[] elements, int add) { - int[] newArray = new int[elements.length + 1]; - System.arraycopy(elements, 0, newArray, 0, elements.length); - newArray[elements.length] = add; - return newArray; - } - - public static void main(String[] args) { - String[] arr = new String[0]; - - for (int i = 0; i < 100; i++) { - arr = add(String.class, arr, String.valueOf(i)); - } - System.out.println(Arrays.toString(arr)); - for (int i = 0; i < 100; i++) { - arr = remove(String.class, arr, 0); - } - System.out.println(Arrays.toString(arr)); - } - - @SuppressWarnings("unchecked") - public static T[] toArray(Class type, Collection list) { - return list.toArray((T[]) Array.newInstance(type, list.size())); - } - - @Nullable - public static boolean[] unbox(@Nullable Boolean[] source) { - if (source == null) { - return null; - } - final boolean[] result = new boolean[source.length]; - for (int i = 0; i < source.length; i++) { - result[i] = source[i]; - } - return result; - } - - public static void reverse(@Nullable Object[] array) { - if (array == null || array.length <= 1) { - return; - } - for (int i = 0, j = array.length - 1; j > i; ++i, j--) { - final Object tmp = array[j]; - array[j] = array[i]; - array[i] = tmp; - } - } -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/Base64.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/Base64.java deleted file mode 100644 index d936daa7ede26..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/Base64.java +++ /dev/null @@ -1,330 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jkiss.utils; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.Writer; - -public final class Base64 { - - private static final char[] S_BASE64CHAR = { - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', - 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', - 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', - 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', - 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', - 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', '+', '/' - }; - - private static final char S_BASE64PAD = '='; - - private static final byte[] S_DECODETABLE = new byte[128]; - - static { - for (int i = 0; i < S_DECODETABLE.length; i ++) - S_DECODETABLE[i] = Byte.MAX_VALUE; // 127 - for (int i = 0; i < S_BASE64CHAR.length; i ++) // 0 to 63 - S_DECODETABLE[S_BASE64CHAR[i]] = (byte)i; - } - - private static int decode0(char[] ibuf, byte[] obuf, int wp) { - int outlen = 3; - if (ibuf[3] == S_BASE64PAD) outlen = 2; - if (ibuf[2] == S_BASE64PAD) outlen = 1; - int b0 = S_DECODETABLE[ibuf[0]]; - int b1 = S_DECODETABLE[ibuf[1]]; - int b2 = S_DECODETABLE[ibuf[2]]; - int b3 = S_DECODETABLE[ibuf[3]]; - switch (outlen) { - case 1: - obuf[wp] = (byte)(b0 << 2 & 0xfc | b1 >> 4 & 0x3); - return 1; - case 2: - obuf[wp++] = (byte)(b0 << 2 & 0xfc | b1 >> 4 & 0x3); - obuf[wp] = (byte)(b1 << 4 & 0xf0 | b2 >> 2 & 0xf); - return 2; - case 3: - default: - obuf[wp++] = (byte)(b0 << 2 & 0xfc | b1 >> 4 & 0x3); - obuf[wp++] = (byte)(b1 << 4 & 0xf0 | b2 >> 2 & 0xf); - obuf[wp] = (byte)(b2 << 6 & 0xc0 | b3 & 0x3f); - return 3; - } - } - - /** - * - */ - public static byte[] decode(char[] data, int off, int len) { - char[] ibuf = new char[4]; - int ibufcount = 0; - byte[] obuf = new byte[len/4*3+3]; - int obufcount = 0; - for (int i = off; i < off+len; i ++) { - char ch = data[i]; - if (ch == S_BASE64PAD - || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != Byte.MAX_VALUE) { - ibuf[ibufcount++] = ch; - if (ibufcount == ibuf.length) { - ibufcount = 0; - obufcount += decode0(ibuf, obuf, obufcount); - } - } - } - if (obufcount == obuf.length) - return obuf; - byte[] ret = new byte[obufcount]; - System.arraycopy(obuf, 0, ret, 0, obufcount); - return ret; - } - - /** - * - */ - public static byte[] decode(String data) { - char[] ibuf = new char[4]; - int ibufcount = 0; - byte[] obuf = new byte[data.length()/4*3+3]; - int obufcount = 0; - for (int i = 0; i < data.length(); i ++) { - char ch = data.charAt(i); - if (ch == S_BASE64PAD - || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != Byte.MAX_VALUE) { - ibuf[ibufcount++] = ch; - if (ibufcount == ibuf.length) { - ibufcount = 0; - obufcount += decode0(ibuf, obuf, obufcount); - } - } - } - if (obufcount == obuf.length) - return obuf; - byte[] ret = new byte[obufcount]; - System.arraycopy(obuf, 0, ret, 0, obufcount); - return ret; - } - - /** - * - */ - public static void decode(char[] data, int off, int len, OutputStream ostream) throws IOException { - char[] ibuf = new char[4]; - int ibufcount = 0; - byte[] obuf = new byte[3]; - for (int i = off; i < off+len; i ++) { - char ch = data[i]; - if (ch == S_BASE64PAD - || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != Byte.MAX_VALUE) { - ibuf[ibufcount++] = ch; - if (ibufcount == ibuf.length) { - ibufcount = 0; - int obufcount = decode0(ibuf, obuf, 0); - ostream.write(obuf, 0, obufcount); - } - } - } - } - - /** - * - */ - public static void decode(String data, OutputStream ostream) throws IOException { - char[] ibuf = new char[4]; - int ibufcount = 0; - byte[] obuf = new byte[3]; - for (int i = 0; i < data.length(); i ++) { - char ch = data.charAt(i); - if (ch == S_BASE64PAD - || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != Byte.MAX_VALUE) { - ibuf[ibufcount++] = ch; - if (ibufcount == ibuf.length) { - ibufcount = 0; - int obufcount = decode0(ibuf, obuf, 0); - ostream.write(obuf, 0, obufcount); - } - } - } - } - - /** - * Returns base64 representation of specified byte array. - */ - public static String encode(byte[] data) { - return encode(data, 0, data.length); - } - - public static String splitLines(String bigString, int lineLength) { - return bigString.replaceAll("(.{" + lineLength + "})", "$1\n"); - } - - /** - * Returns base64 representation of specified byte array. - */ - public static String encode(byte[] data, int off, int len) - { - if (len <= 0) return ""; - char[] out = new char[len/3*4+4]; - int rindex = off; - int windex = 0; - int rest = len-off; - while (rest >= 3) { - int i = ((data[rindex]&0xff)<<16) - +((data[rindex+1]&0xff)<<8) - +(data[rindex+2]&0xff); - out[windex++] = S_BASE64CHAR[i>>18]; - out[windex++] = S_BASE64CHAR[(i>>12)&0x3f]; - out[windex++] = S_BASE64CHAR[(i>>6)&0x3f]; - out[windex++] = S_BASE64CHAR[i&0x3f]; - rindex += 3; - rest -= 3; - } - if (rest == 1) { - int i = data[rindex]&0xff; - out[windex++] = S_BASE64CHAR[i>>2]; - out[windex++] = S_BASE64CHAR[(i<<4)&0x3f]; - out[windex++] = S_BASE64PAD; - out[windex++] = S_BASE64PAD; - } else if (rest == 2) { - int i = ((data[rindex]&0xff)<<8)+(data[rindex+1]&0xff); - out[windex++] = S_BASE64CHAR[i>>10]; - out[windex++] = S_BASE64CHAR[(i>>4)&0x3f]; - out[windex++] = S_BASE64CHAR[(i<<2)&0x3f]; - out[windex++] = S_BASE64PAD; - } - return new String(out, 0, windex); - } - - /** - * Outputs base64 representation of the specified byte array to a byte stream. - */ - public static void encode(byte[] data, int off, int len, OutputStream ostream) throws IOException { - if (len <= 0) return; - byte[] out = new byte[4]; - int rindex = off; - int rest = len-off; - while (rest >= 3) { - int i = ((data[rindex]&0xff)<<16) - +((data[rindex+1]&0xff)<<8) - +(data[rindex+2]&0xff); - out[0] = (byte)S_BASE64CHAR[i>>18]; - out[1] = (byte)S_BASE64CHAR[(i>>12)&0x3f]; - out[2] = (byte)S_BASE64CHAR[(i>>6)&0x3f]; - out[3] = (byte)S_BASE64CHAR[i&0x3f]; - ostream.write(out, 0, 4); - rindex += 3; - rest -= 3; - } - if (rest == 1) { - int i = data[rindex]&0xff; - out[0] = (byte)S_BASE64CHAR[i>>2]; - out[1] = (byte)S_BASE64CHAR[(i<<4)&0x3f]; - out[2] = (byte)S_BASE64PAD; - out[3] = (byte)S_BASE64PAD; - ostream.write(out, 0, 4); - } else if (rest == 2) { - int i = ((data[rindex]&0xff)<<8)+(data[rindex+1]&0xff); - out[0] = (byte)S_BASE64CHAR[i>>10]; - out[1] = (byte)S_BASE64CHAR[(i>>4)&0x3f]; - out[2] = (byte)S_BASE64CHAR[(i<<2)&0x3f]; - out[3] = (byte)S_BASE64PAD; - ostream.write(out, 0, 4); - } - } - - /** - * Outputs base64 representation of the specified byte array to a character stream. - */ - public static void encode(byte[] data, int off, int len, Writer writer) throws IOException { - if (len <= 0) return; - char[] out = new char[4]; - int rindex = off; - int rest = len-off; - while (rest >= 3) { - int i = ((data[rindex]&0xff)<<16) - +((data[rindex+1]&0xff)<<8) - +(data[rindex+2]&0xff); - out[0] = S_BASE64CHAR[i>>18]; - out[1] = S_BASE64CHAR[(i>>12)&0x3f]; - out[2] = S_BASE64CHAR[(i>>6)&0x3f]; - out[3] = S_BASE64CHAR[i&0x3f]; - writer.write(out, 0, 4); - rindex += 3; - rest -= 3; -/* - if (output % 76 == 0) - writer.write("\n"); -*/ - } - if (rest == 1) { - int i = data[rindex]&0xff; - out[0] = S_BASE64CHAR[i>>2]; - out[1] = S_BASE64CHAR[(i<<4)&0x3f]; - out[2] = S_BASE64PAD; - out[3] = S_BASE64PAD; - writer.write(out, 0, 4); - } else if (rest == 2) { - int i = ((data[rindex]&0xff)<<8)+(data[rindex+1]&0xff); - out[0] = S_BASE64CHAR[i>>10]; - out[1] = S_BASE64CHAR[(i>>4)&0x3f]; - out[2] = S_BASE64CHAR[(i<<2)&0x3f]; - out[3] = S_BASE64PAD; - writer.write(out, 0, 4); - } - } - - /** - * Outputs base64 representation of the specified input stream to a character stream. - */ - public static void encode(InputStream stream, long len, Writer writer) - throws IOException - { - if (len <= 0) return; - char[] out = new char[4]; - long rest = len; - while (rest >= 3) { - int i = ((stream.read()&0xff)<<16) - +((stream.read()&0xff)<<8) - +(stream.read()&0xff); - out[0] = S_BASE64CHAR[i>>18]; - out[1] = S_BASE64CHAR[(i>>12)&0x3f]; - out[2] = S_BASE64CHAR[(i>>6)&0x3f]; - out[3] = S_BASE64CHAR[i&0x3f]; - writer.write(out, 0, 4); - rest -= 3; - } - if (rest == 1) { - int i = stream.read()&0xff; - out[0] = S_BASE64CHAR[i>>2]; - out[1] = S_BASE64CHAR[(i<<4)&0x3f]; - out[2] = S_BASE64PAD; - out[3] = S_BASE64PAD; - writer.write(out, 0, 4); - } else if (rest == 2) { - int i = ((stream.read()&0xff)<<8)+(stream.read()&0xff); - out[0] = S_BASE64CHAR[i>>10]; - out[1] = S_BASE64CHAR[(i>>4)&0x3f]; - out[2] = S_BASE64CHAR[(i<<2)&0x3f]; - out[3] = S_BASE64PAD; - writer.write(out, 0, 4); - } - } - -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/BeanUtils.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/BeanUtils.java deleted file mode 100644 index 5a686adbd543e..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/BeanUtils.java +++ /dev/null @@ -1,488 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jkiss.utils; - -import org.jkiss.code.NotNull; -import org.jkiss.code.Nullable; - -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; -import java.lang.reflect.*; -import java.util.*; -import java.util.function.Supplier; - -/** - * BeanUtils - */ -public class BeanUtils { - - public static boolean isGetterName(String name) { - return name.startsWith("get") || name.startsWith("is") || name.startsWith("has"); - } - - public static String getPropertyNameFromGetter(String getterName) { - if (getterName.startsWith("get")) { - return - Character.toLowerCase(getterName.charAt(3)) + - getterName.substring(4); - } else if (getterName.startsWith("is")) { - return - Character.toLowerCase(getterName.charAt(2)) + - getterName.substring(3); - } else if (getterName.startsWith("has")) { - return - Character.toLowerCase(getterName.charAt(3)) + - getterName.substring(4); - } else { - // Unrecognized getter name - return null; - } - } - - public static String getSetterName(String getterName) { - if (getterName.startsWith("get")) { - return "set" + getterName.substring(3); - } else if (getterName.startsWith("is")) { - return "set" + getterName.substring(2); - } else if (getterName.startsWith("has")) { - return "set" + getterName.substring(3); - } else { - // Unrecognized getter name - return null; - } - } - - /** - * Returns a set method matching the property name. - */ - public static Method getSetMethod(Class cl, String propertyName) { - Method method = getSetMethod(cl, propertyName, false); - - if (method != null) { - return method; - } - - return getSetMethod(cl, propertyName, true); - } - - /** - * Returns a set method matching the property name. - */ - public static Method getSetMethod( - Class cl, - String propertyName, - boolean ignoreCase) { - String setName = "set" + propertyNameToMethodName(propertyName); - - return getSetMethod( - cl.getMethods(), - setName, - ignoreCase); - } - - /** - * Returns a get method matching the property name. - */ - public static Method getGetMethod(Class cl, String propertyName) { - Method method = getGetMethod(cl, propertyName, false); - - return method != null ? - method : - getGetMethod(cl, propertyName, true); - } - - /** - * Returns a get method matching the property name. - */ - public static Method getGetMethod( - Class cl, - String propertyName, - boolean ignoreCase) { - String methodName = propertyNameToMethodName(propertyName); - return getGetMethod( - cl.getMethods(), - "get" + methodName, - "is" + methodName, - ignoreCase); - } - - /** - * Converts a user's property name to a bean method name. - * - * @param propertyName the user property name - * @return the equivalent bean method name - */ - public static String propertyNameToMethodName(String propertyName) { - char ch = propertyName.charAt(0); - if (Character.isLowerCase(ch)) - propertyName = Character.toUpperCase(ch) + propertyName.substring(1); - - return propertyName; - } - - /** - * Converts a user's property name to a bean method name. - * - * @param methodName the method name - * @return the equivalent property name - */ - public static String methodNameToPropertyName(String methodName) { - if (methodName.startsWith("get")) - methodName = methodName.substring(3); - else if (methodName.startsWith("set")) - methodName = methodName.substring(3); - else if (methodName.startsWith("is")) - methodName = methodName.substring(2); - - if (methodName.length() == 0) - return null; - - char ch = methodName.charAt(0); - if (Character.isUpperCase(ch) && (methodName.length() == 1 || !Character.isUpperCase(methodName.charAt(1)))) { - methodName = Character.toLowerCase(ch) + methodName.substring(1); - } - - return methodName; - } - - public static boolean isArrayType(Type type) { - return (type instanceof Class && ((Class) type).isArray()); - } - - public static boolean isCollectionType(Type type) { - if (type instanceof Class && Collection.class.isAssignableFrom((Class) type)) { -/* - if (type instanceof ParameterizedType) { - ParameterizedType pt = (ParameterizedType)type; - if (pt.getActualTypeArguments().length == 1) { - return true; - } - } -*/ - return true; - } - return isArrayType(type); - } - - public static Class getCollectionType(Type type) { - if (type instanceof ParameterizedType) { - ParameterizedType pt = (ParameterizedType) type; - if (pt.getActualTypeArguments().length == 1) { - final Type argType = pt.getActualTypeArguments()[0]; - if (argType instanceof Class) { - return (Class) argType; - } else if (argType instanceof WildcardType) { - final Type[] upperBounds = ((WildcardType) argType).getUpperBounds(); - if (upperBounds.length > 0 && upperBounds[0] instanceof Class) { - return (Class) upperBounds[0]; - } - final Type[] lowerBounds = ((WildcardType) argType).getLowerBounds(); - if (lowerBounds.length > 0 && lowerBounds[0] instanceof Class) { - return (Class) lowerBounds[0]; - } - } - } - } - return null; - } - - public static Object readObjectProperty(Object object, String propName) - throws IllegalAccessException, InvocationTargetException { - if (propName.indexOf('.') == -1) { - Method getter = getGetMethod(object.getClass(), propName); - return getter == null ? null : getter.invoke(object); - } - // Parse property path - StringTokenizer st = new StringTokenizer(propName, "."); - Object value = object; - while (value != null && st.hasMoreTokens()) { - String pathItem = st.nextToken(); - Method getter = getGetMethod(value.getClass(), pathItem); - if (getter == null) { - return null; - } - value = getter.invoke(value); - } - return value; - } - - /** - * Finds the matching set method - */ - private static Method getGetMethod( - Method[] methods, - String getName, - String isName, - boolean ignoreCase) { - for (int i = 0; i < methods.length; i++) { - Method method = methods[i]; - - // The method must be public - if ( - (!Modifier.isPublic(method.getModifiers())) || - (!Modifier.isPublic(method.getDeclaringClass().getModifiers())) || - (method.getParameterTypes().length != 0) || - (method.getReturnType().equals(void.class))) { - continue; - } else if (!ignoreCase && method.getName().equals(getName)) { - // If it matches the get name, it's the right method - return method; - } else if (ignoreCase && method.getName().equalsIgnoreCase(getName)) { - // If it matches the get name, it's the right method - return method; - } else if (!method.getReturnType().equals(boolean.class)) { - // The is methods must return boolean - continue; - } else if (!ignoreCase && method.getName().equals(isName)) { - // If it matches the is name, it must return boolean - return method; - } else if (ignoreCase && method.getName().equalsIgnoreCase(isName)) { - // If it matches the is name, it must return boolean - return method; - } - } - - return null; - } - - /** - * Finds the matching set method - * - * @param setName the method name - */ - private static Method getSetMethod( - Method[] methods, - String setName, - boolean ignoreCase) { - for (int i = 0; i < methods.length; i++) { - Method method = methods[i]; - - // The method name must match - if ( - !(ignoreCase ? method.getName().equalsIgnoreCase(setName) : method.getName().equals(setName)) || - !Modifier.isPublic(method.getModifiers()) || - !Modifier.isPublic(method.getDeclaringClass().getModifiers()) || - method.getParameterTypes().length != 1 - ) - continue; - - return method; - } - - return null; - } - - public static final Short DEFAULT_SHORT = (short) 0; - public static final Integer DEFAULT_INTEGER = 0; - public static final Long DEFAULT_LONG = 0L; - public static final Float DEFAULT_FLOAT = (float) 0.0; - public static final Double DEFAULT_DOUBLE = 0.0; - public static final Byte DEFAULT_BYTE = (byte) 0; - public static final Character DEFAULT_CHAR = (char) 0; - - public static boolean isBooleanType(Type paramClass) { - return paramClass == Boolean.class || paramClass == Boolean.TYPE; - } - - public static Object getDefaultPrimitiveValue(Class paramClass) { - if (paramClass == Boolean.TYPE) { - return Boolean.FALSE; - } else if (paramClass == Short.TYPE) { - return DEFAULT_SHORT; - } else if (paramClass == Integer.TYPE) { - return DEFAULT_INTEGER; - } else if (paramClass == Long.TYPE) { - return DEFAULT_LONG; - } else if (paramClass == Float.TYPE) { - return DEFAULT_FLOAT; - } else if (paramClass == Double.TYPE) { - return DEFAULT_DOUBLE; - } else if (paramClass == Byte.TYPE) { - return DEFAULT_BYTE; - } else if (paramClass == Character.TYPE) { - return DEFAULT_CHAR; - } else { - throw new IllegalArgumentException("Class " + paramClass.getName() + " is not primitive type"); - } - } - - public static boolean isNumericType(Class paramClass) { - return - Number.class.isAssignableFrom(paramClass) || - paramClass == Short.TYPE || - paramClass == Integer.TYPE || - paramClass == Long.TYPE || - paramClass == Double.TYPE || - paramClass == Float.TYPE || - paramClass == Byte.TYPE; - } - - public static Object invokeObjectMethod(Object object, String name, Class paramTypes[], Object args[]) - throws Throwable { - Method method = object.getClass().getMethod(name, paramTypes); - method.setAccessible(true); - try { - return method.invoke(object, args); - } catch (InvocationTargetException e) { - throw e.getTargetException(); - } - } - - public static Object invokeObjectMethod(Object object, String name) - throws Throwable { - Method method = object.getClass().getMethod(name); - method.setAccessible(true); - try { - return method.invoke(object); - } catch (InvocationTargetException e) { - throw e.getTargetException(); - } - } - - @Nullable - public static Object invokeObjectDeclaredMethod( - @NotNull Object object, - @NotNull String methodName, - @NotNull Class[] paramTypes, - @NotNull Object[] args) throws Throwable - { - for (Class cls = object.getClass(); cls != null; cls = cls.getSuperclass()) { - for (Method method : cls.getDeclaredMethods()) { - if (method.getName().equals(methodName) && Arrays.equals(method.getParameterTypes(), paramTypes)) { - method.setAccessible(true); - try { - return method.invoke(object, args); - } catch (InvocationTargetException e) { - throw e.getTargetException(); - } - } - } - } - throw new NoSuchMethodException("Cannot find declared method " + methodName + "(" + Arrays.toString(paramTypes) + ")"); - } - - public static Object invokeStaticMethod(Class objectType, String name, Class paramTypes[], Object args[]) - throws Throwable { - Method method = objectType.getMethod(name, paramTypes); - method.setAccessible(true); - try { - return method.invoke(null, args); - } catch (InvocationTargetException e) { - throw e.getTargetException(); - } - } - - public static Class findAssignableType(Class[] types, Class type) { - for (Class childType : types) { - if (type.isAssignableFrom(childType)) { - return (Class) childType; - } - } - return null; - } - - /** - * Determines the distance of the given object to the given class in the - * inheritance tree. - *

- * @param object the root object - * @param clazz the class to determine the distance to - * @return the distance of the object to the class. If the object is not an - * instance of the class {@code -1} will return. - */ - public static int getInheritanceDistance(Object object, Class clazz) { - if (clazz.isInstance(object)) { - int distance = 0; - Class compared = object.getClass(); - while (compared != clazz) { - compared = compared.getSuperclass(); - distance++; - if (compared == Object.class) { - break; - } - } - return distance; - } else { - return -1; - } - } - - @SuppressWarnings("unchecked") - public static T getFieldValue(@NotNull Object object, @NotNull String name) throws Throwable { - final Field field = object.getClass().getDeclaredField(name); - if (!field.canAccess(object)) { - field.setAccessible(true); - } - return (T) field.get(object); - } - - @Nullable - public static Object handleObjectMethod(@NotNull Object proxy, @NotNull Method method, Object[] args) { - switch (method.getName()) { - case "toString": - return "Proxy"; - case "hashCode": - return System.identityHashCode(proxy); - case "equals": - return proxy == args[0]; - default: - return null; - } - } - - @NotNull - public static List deepCopy(@NotNull List src) { - final List dst = tryInstantiateOrDefault(src.getClass(), ArrayList::new); - for (T element : src) { - dst.add(deepCopy(element)); - } - return dst; - } - - @NotNull - public static Map deepCopy(@NotNull Map src) { - final Map dst = tryInstantiateOrDefault(src.getClass(), LinkedHashMap::new); - for (Map.Entry entry : src.entrySet()) { - dst.put(entry.getKey(), deepCopy(entry.getValue())); - } - return dst; - } - - @SuppressWarnings("unchecked") - private static T deepCopy(@Nullable T object) { - if (object == null) { - return null; - } else if (object instanceof Map) { - return (T) deepCopy((Map) object); - } else if (object instanceof List) { - return (T) deepCopy((List) object); - } else { - return object; - } - } - - @SuppressWarnings("unchecked") - @NotNull - private static T tryInstantiateOrDefault(@NotNull Class cls, @NotNull Supplier supplier) { - try { - return (T) MethodHandles.lookup().findConstructor(cls, MethodType.methodType(void.class)).invoke(); - } catch (Throwable ignored) { - return supplier.get(); - } - } -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/ByteNumberFormat.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/ByteNumberFormat.java deleted file mode 100644 index f858287ac75a0..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/ByteNumberFormat.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jkiss.utils; - -import org.jkiss.code.NotNull; - -import java.text.DecimalFormat; -import java.text.FieldPosition; -import java.text.NumberFormat; -import java.text.ParsePosition; - -/** - * Bytes formatter - */ -public class ByteNumberFormat extends NumberFormat { - private static final long serialVersionUID = 1; - - public static final Unit[] UNITS = Unit.values(); - - private static final DecimalFormat fpFormat = new DecimalFormat("#.#"); - - private final BinaryPrefix binaryPrefix; - - /** - * Creates a new formatter. - */ - public ByteNumberFormat() { - binaryPrefix = BinaryPrefix.JEDEC; - } - - public ByteNumberFormat(@NotNull BinaryPrefix binaryPrefix) { - this.binaryPrefix = binaryPrefix; - } - - public static int computeIndex(double bytes) { - int index = 0; - - for (int i = 0; i < UNITS.length; i++) { - int result = (int)(bytes / 1024); - if (result == 0) { - break; - } else { - bytes /= 1024; - if (bytes < 1) { - break; - } - index++; - } - } - - return index; - } - - /** - * Returns a string representing the bytes. - * - * @param bytes the number of bytes. - * - * @return A string. - */ - public String getBytes(double bytes) { - - int index = computeIndex(bytes); - if (index >= UNITS.length) { - index = UNITS.length - 1; - } - - double intBytes = bytes; - if (intBytes == 0) { - return String.valueOf(0); - } - - for (int i = 0; i < index; i++) { - intBytes /= 1024; - } - - - String str; - if ((long)intBytes >= 10) { - str = String.valueOf((long)intBytes); - } else { - str = fpFormat.format(intBytes); - } - final Unit unit = UNITS[index]; - if (unit == Unit.BYTE) { - return str; - } - return str + (binaryPrefix == BinaryPrefix.ISO ? unit.isoPrefix : unit.jedecPrefix); - } - - /** - * Formats a number into the specified string buffer. - * - * @param number the number to format. - * @param toAppendTo the string buffer. - * @param pos the field position (ignored here). - * - * @return The string buffer. - */ - @Override - public StringBuffer format(double number, StringBuffer toAppendTo, - FieldPosition pos) { - return toAppendTo.append(getBytes(number)); - } - - /** - * Formats a number into the specified string buffer. - * - * @param number the number to format. - * @param toAppendTo the string buffer. - * @param pos the field position (ignored here). - * - * @return The string buffer. - */ - @Override - public StringBuffer format(long number, StringBuffer toAppendTo, - FieldPosition pos) { - return toAppendTo.append(getBytes(number)); - } - - /** - * This method returns null for all inputs. This class cannot - * be used for parsing. - * - * @param source the source string. - * @param parsePosition the parse position. - * - * @return null. - */ - @Override - public Number parse(String source, ParsePosition parsePosition) { - return null; - } - - private enum Unit { - BYTE("B", "B"), - KILOBYTE("K", "KiB"), - MEGABYTE("M", "MiB"), - GIGABYTE("G", "GiB"), - TERABYTE("T", "TiB"), - PETABYTE("P", "PiB"); - - private final String jedecPrefix; - private final String isoPrefix; - - Unit(String jedecPrefix, String isoPrefix) { - this.jedecPrefix = jedecPrefix; - this.isoPrefix = isoPrefix; - } - } - - /** - * A unit prefix for multiples of byte. - */ - public enum BinaryPrefix { - /** - * JEDEC-compliant prefixes (K, M, G, T, etc.). It's easy to confuse such prefixes with SI prefixes, leading to ambiguity. - */ - JEDEC, - - /** - * ISO 80000-13 format. This format explicitly states the binary nature of prefixes right in their names (kibi, mibi, gibi, etc.) - */ - ISO, - } -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/CommonUtils.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/CommonUtils.java deleted file mode 100644 index baad78ae23776..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/CommonUtils.java +++ /dev/null @@ -1,1066 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jkiss.utils; - -import org.jkiss.code.NotNull; -import org.jkiss.code.Nullable; - -import java.lang.reflect.InvocationTargetException; -import java.util.*; -import java.util.function.Function; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Common utils - */ -public class CommonUtils { - - public static final char PARAGRAPH_CHAR = (char) 182; - - public static boolean isJavaIdentifier(@NotNull CharSequence str) { - if (str.length() == 0 || !Character.isJavaIdentifierStart(str.charAt(0))) { - return false; - } - for (int i = 1; i < str.length(); i++) { - if (!Character.isJavaIdentifierPart(str.charAt(i))) { - return false; - } - } - return true; - } - - @NotNull - public static String escapeJavaString(@NotNull String str) { - StringBuilder res = new StringBuilder(str.length() + 5); - for (int i = 0; i < str.length(); i++) { - char c = str.charAt(i); - switch (c) { - case '"' -> res.append("\\\""); - case '\n' -> res.append("\\n"); - case '\r' -> res.append("\\r"); - case '\t' -> res.append("\\t"); - default -> res.append(c); - } - } - return res.toString(); - } - - @Nullable - public static String escapeIdentifier(@Nullable String str) { - if (str == null) { - return null; - } - StringBuilder res = new StringBuilder(str.length()); - for (int i = 0; i < str.length(); i++) { - char c = str.charAt(i); - if (Character.isJavaIdentifierPart(c)) { - res.append(c); - } else { - if (res.length() == 0 || res.charAt(res.length() - 1) != '_') { - res.append('_'); - } - } - } - return res.toString(); - } - - @NotNull - public static String escapeFileName(@Nullable String str) { - if (str == null) { - return ""; - } - StringBuilder res = new StringBuilder(str.length()); - for (int i = 0; i < str.length(); i++) { - char c = str.charAt(i); - if (Character.isISOControl(c) || c == '\\' || c == '/' || c == '<' || c == '>' || c == '|' || c == '"' || c == ':' - || c == '*' || c == '?') { - res.append('_'); - } else { - res.append(c); - } - } - return res.toString(); - } - - public static String makeDirectoryName(@NotNull String str) { - if (!str.endsWith("/")) { - str += "/"; - } - return str; - } - - @NotNull - public static String removeTrailingSlash(@NotNull String str) { - while (str.endsWith("/") || str.endsWith("\\")) { - str = str.substring(0, str.length() - 1); - } - return str; - } - - @NotNull - public static String removeLeadingSlash(@NotNull String str) { - while (str.startsWith("/") || str.startsWith("\\")) { - str = str.substring(1); - } - return str; - } - - public static String capitalizeWord(String str) { - if (isEmpty(str) || Character.isUpperCase(str.charAt(0))) { - return str; - } - return Character.toUpperCase(str.charAt(0)) + str.substring(1); - } - - - public static String toCamelCase(String str) { - if (isEmpty(str)) { - return str; - } - - final StringBuilder ret = new StringBuilder(str.length()); - - boolean isWordStart = true; - for (int i = 0; i < str.length(); i++) { - char ch = str.charAt(i); - if (Character.isLetterOrDigit(ch)) { - if (isWordStart) { - ret.append(Character.toUpperCase(ch)); - isWordStart = false; - } else { - ret.append(Character.toLowerCase(ch)); - } - } else { - ret.append(ch); - isWordStart = true; - } - } - - return ret.toString(); - } - - @NotNull - public static T notNull(@Nullable T value, @NotNull T defaultValue) { - return value != null ? value : defaultValue; - } - - public static boolean isEmpty(@Nullable CharSequence value) { - return value == null || value.length() == 0; - } - - public static boolean isEmpty(@Nullable String value) { - return value == null || value.length() == 0; - } - - public static boolean isNotEmpty(@Nullable String value) { - return !isEmpty(value); - } - - public static boolean isEmpty(@Nullable Collection value) { - return value == null || value.isEmpty(); - } - - public static boolean isEmpty(@Nullable Map value) { - return value == null || value.isEmpty(); - } - - @Nullable - public static T getFirstOrNull(@NotNull Iterable iterable) { - Iterator iterator = iterable.iterator(); - if (iterator.hasNext()) { - return iterator.next(); - } - return null; - } - - @NotNull - public static Collection safeCollection(@Nullable Collection theList) { - if (theList == null) { - theList = Collections.emptyList(); - } - return theList; - } - - @NotNull - public static List singletonOrEmpty(@Nullable T object) { - if (object == null) { - return Collections.emptyList(); - } - return Collections.singletonList(object); - } - - @NotNull - public static List safeList(@Nullable List theList) { - if (theList == null) { - theList = Collections.emptyList(); - } - return theList; - } - - @NotNull - public static List copyList(@Nullable Collection theList) { - if (theList == null) { - return new ArrayList<>(); - } else { - return new ArrayList<>(theList); - } - } - - /** - * Swaps the element with its neighbor to the left in the specified list. - * If the element is not present in the list or it is the leftmost element in the list, - * the list remains unchanged. - * - * @param list list - * @param element element - * @param type of the list - */ - public static void shiftLeft(@NotNull List list, @NotNull T element) { - int idx = list.indexOf(element); - if (idx > 0) { - Collections.swap(list, idx - 1, idx); - } - } - - /** - * Swaps the element with its neighbor to the right in the specified list. - * If the element is not present in the list or it is the rightmost element in the list, - * the list remains unchanged. - * - * @param list list - * @param element element - * @param type of the list - */ - public static void shiftRight(@NotNull List list, @NotNull T element) { - int idx = list.indexOf(element); - if (idx != -1 && idx != list.size() - 1) { - Collections.swap(list, idx, idx + 1); - } - } - - @NotNull - public static String notEmpty(@Nullable String value) { - return value == null ? "" : value; - } - - @Nullable - public static String nullIfEmpty(@Nullable String value) { - return value == null || value.isEmpty() ? null : value; - } - - public static boolean isTrue(Boolean value) { - return value != null && value; - } - - public static boolean getBoolean(String value) { - return Boolean.parseBoolean(value); - } - - public static boolean getBoolean(@Nullable String value, boolean defaultValue) { - return isEmpty(value) ? defaultValue : Boolean.parseBoolean(value); - } - - public static boolean getBoolean(@Nullable Object value, boolean defaultValue) { - if (value == null) { - return defaultValue; - } else if (value instanceof Boolean b) { - return b; - } else { - return getBoolean(value.toString(), defaultValue); - } - } - - @NotNull - public static String getLineSeparator() { - String lineSeparator = System.getProperty(StandardConstants.ENV_LINE_SEPARATOR); - return lineSeparator == null ? "\n" : lineSeparator; - } - - @NotNull - public static Throwable getRootCause(@NotNull Throwable ex) { - Throwable rootCause = ex; - for (; ; ) { - if (rootCause.getCause() != null) { - rootCause = rootCause.getCause(); - } else if (rootCause instanceof InvocationTargetException ite && ite.getTargetException() != null) { - rootCause = ite.getTargetException(); - } else { - break; - } - } - return rootCause; - } - - public static boolean equalObjects(@Nullable Object o1, @Nullable Object o2) { - if (o1 == o2) { - return true; - } - if (o1 == null || o2 == null) { - return false; - } -// if (o1.getClass() != o2.getClass()) { -// return false; -// } - return o1.equals(o2); - } - - public static boolean equalOrEmptyStrings(@Nullable String s1, @Nullable String s2) { - return equalObjects(s1, s2) || (isEmpty(s1) && isEmpty(s2)); - } - - public static boolean equalsContents(@Nullable Collection c1, @Nullable Collection c2) { - if (CommonUtils.isEmpty(c1) && CommonUtils.isEmpty(c2)) { - return true; - } - if (c1 == null || c2 == null || c1.size() != c2.size()) { - return false; - } - for (Object o : c1) { - if (!c2.contains(o)) { - return false; - } - } - return true; - } - - @NotNull - public static String toString(@Nullable Object object) { - if (object == null) { - return ""; - } else if (object instanceof String s) { - return s; - } else { - String strValue = object.toString(); - return strValue == null ? "" : strValue; - } - } - - public static String toString(@Nullable Object object, String def) { - if (object == null) { - return def; - } else if (object instanceof String s) { - return s; - } else { - return object.toString(); - } - } - - public static boolean toBoolean(@Nullable Object object) { - return object != null && getBoolean(object.toString()); - } - - public static int toInt(@Nullable Object object, int def) { - if (object == null) { - return def; - } else if (object instanceof Number n) { - return n.intValue(); - } else { - try { - return Integer.parseInt(toString(object)); - } catch (NumberFormatException e) { - try { - return (int)Double.parseDouble(toString(object)); - } catch (NumberFormatException e1) { - e1.printStackTrace(); - return def; - } - } - } - } - - public static int toInt(@Nullable Object object) { - return toInt(object, 0); - } - - public static boolean isInt(@Nullable Object object) { - if (object == null) { - return false; - } else if (object instanceof Number) { - return true; - } else { - try { - Integer.parseInt(toString(object)); - return true; - } catch (NumberFormatException e) { - return false; - } - } - } - public static long toLong(@Nullable Object object) { - return toLong(object, 0); - } - - public static long toLong(@Nullable Object object, long defValue) { - if (object == null) { - return defValue; - } else if (object instanceof Number n) { - return n.longValue(); - } else { - try { - return Long.parseLong(toString(object)); - } catch (NumberFormatException e) { - try { - return (int)Double.parseDouble(toString(object)); - } catch (NumberFormatException e1) { - return defValue; - } - } - } - } - - public static boolean isLong(@Nullable Object object) { - if (object == null) { - return false; - } else if (object instanceof Number) { - return true; - } else { - try { - Long.parseLong(toString(object)); - return true; - } catch (NumberFormatException e) { - return false; - } - } - } - - public static boolean isNumber(@Nullable Object object) { - if (object == null) { - return false; - } else if (object instanceof Number) { - return true; - } else { - try { - Double.parseDouble(toString(object)); - return true; - } catch (NumberFormatException e) { - return false; - } - } - } - - public static double toDouble(@Nullable Object object) { - if (object == null) { - return 0.0; - } else if (object instanceof Number) { - return ((Number) object).doubleValue(); - } else { - try { - return Double.parseDouble(toString(object)); - } catch (NumberFormatException e) { - return Double.NaN; - } - } - } - - public static double toDouble(@Nullable Object object, double def) { - if (object == null) { - return def; - } else if (object instanceof Number) { - return ((Number) object).doubleValue(); - } else { - try { - return Double.parseDouble(toString(object)); - } catch (NumberFormatException e) { - return def; - } - } - } - - public static float toFloat(@Nullable Object object) { - if (object == null) { - return 0.0f; - } else if (object instanceof Number) { - return ((Number) object).floatValue(); - } else { - try { - return Float.parseFloat(toString(object)); - } catch (NumberFormatException e) { - return Float.NaN; - } - } - } - - public static float toFloat(@Nullable Object object, float def) { - if (object == null) { - return def; - } else if (object instanceof Number) { - return ((Number) object).floatValue(); - } else { - try { - return Float.parseFloat(toString(object)); - } catch (NumberFormatException e) { - return def; - } - } - } - - public static boolean isNaN(@Nullable Object value) { - return (value instanceof Float && ((Float) value).isNaN()) - || (value instanceof Double && ((Double) value).isNaN()); - } - - public static boolean isInfinite(@Nullable Object value) { - return (value instanceof Float && ((Float) value).isInfinite()) - || (value instanceof Double && ((Double) value).isInfinite()); - } - - @NotNull - public static String toHexString(@Nullable byte[] bytes) { - return bytes == null ? "" : toHexString(bytes, 0, bytes.length); - } - - final protected static char[] hexArray = "0123456789ABCDEF".toCharArray(); - - @NotNull - public static String toHexString(@Nullable byte[] bytes, int offset, int length) { - if (bytes == null || bytes.length == 0) { - return ""; - } - char[] hexChars = new char[length * 2]; - for (int i = 0; i < length; i++) { - int v = bytes[offset + i] & 0xFF; - hexChars[i * 2] = hexArray[v >>> 4]; - hexChars[i * 2 + 1] = hexArray[v & 0x0F]; - } - return new String(hexChars); - } - - public static byte[] parseHexString(String hex) { - int strLength = hex.length(); - byte[] data = new byte[strLength / 2]; - for (int i = 0; i < strLength; i += 2) { - data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4) + Character.digit(hex.charAt(i+1), 16)); - } - return data; - } - - public static String toBinaryString(long longValue, int bitCount) { - String strValue = Long.toString(longValue, 2); - if (strValue.length() < bitCount) { - char[] headZeroes = new char[bitCount - strValue.length()]; - Arrays.fill(headZeroes, '0'); - strValue = String.valueOf(headZeroes) + strValue; - } - return strValue; - } - - public static String[] splitWithDelimiter(String s, String delimiter) { - if (s == null) { - return null; - } - String delimiterReplacement = "DRDRDR"; //$NON-NLS-1$ - s = s.replace(delimiter, delimiterReplacement + delimiter); - return s.split(delimiterReplacement); - } - - @NotNull - public static List splitString(@Nullable String str, char delimiter) { - if (CommonUtils.isEmpty(str)) { - return Collections.emptyList(); - } else { - List result = new ArrayList<>(); - StringTokenizer st = new StringTokenizer(str, String.valueOf(delimiter)); - while (st.hasMoreTokens()) { - result.add(st.nextToken()); - } - return result; - } - } - - @NotNull - public static String[] split(@Nullable String str, String delimiter) { - if (CommonUtils.isEmpty(str)) { - return new String[0]; - } else { - return str.split(delimiter); - } - } - - @NotNull - public static String makeString(@Nullable List tokens, char delimiter) { - if (tokens == null) { - return ""; - } else if (tokens.size() == 1) { - return tokens.get(0); - } else { - StringBuilder buf = new StringBuilder(); - for (String token : tokens) { - if (buf.length() > 0) { - buf.append(delimiter); - } - buf.append(token); - } - return buf.toString(); - } - } - - @Nullable - public static String truncateString(@Nullable String str, int maxLength) { - if (str != null && str.length() > maxLength) { - return str.substring(0, maxLength); - } - return str; - } - - public static String joinStrings(String divider, String ... array) { - if (array == null) return ""; - StringBuilder str = new StringBuilder(); - for (int i = 0; i < array.length; i++) { - if (i > 0) str.append(divider); - str.append(array[i]); - } - return str.toString(); - } - - public static String joinStrings(String divider, Collection col) { - if (col == null) return ""; - StringBuilder str = new StringBuilder(); - for (String item : col) { - if (str.length() > 0) str.append(divider); - str.append(item); - } - return str.toString(); - } - - public static boolean isEmptyTrimmed(@Nullable String str) { - return str == null || str.length() == 0 || str.trim().length() == 0; - } - - public static boolean isBitSet(int value, int mask) { - return (value & mask) == mask; - } - - public static boolean isBitSet(long value, long mask) { - return (value & mask) == mask; - } - - @Nullable - public static > T valueOf(@NotNull Class type, @Nullable String name) { - return valueOf(type, name, null, false); - } - - @Nullable - public static > T valueOf(@NotNull Class type, @Nullable String name, T defValue, boolean underscoreSpaces) { - if (name == null) { - return defValue; - } - name = name.trim(); - if (name.length() == 0) { - return defValue; - } - if (underscoreSpaces) { - name = name.replace(' ', '_'); - } - try { - return Enum.valueOf(type, name); - } catch (Exception e) { - e.printStackTrace(); - return defValue; - } - } - - public static > T valueOf(Class enumType, String str, T defValue) { - if (isEmpty(str)) { - return defValue; - } - try { - return Enum.valueOf(enumType, str); - } catch (Exception e) { - e.printStackTrace(); - return defValue; - } - } - - @NotNull - public static T getItem(@NotNull Collection collection, int index) { - if (collection instanceof List) { - return ((List) collection).get(index); - } else { - Iterator iter = collection.iterator(); - for (int i = 0; i < index; i++) { - iter.next(); - } - return iter.next(); - } - } - - @NotNull - public static > T fromOrdinal(Class enumClass, int ordinal) { - T[] enumConstants = enumClass.getEnumConstants(); - for (T value : enumConstants) { - if (value.ordinal() == ordinal) { - return value; - } - } - IllegalArgumentException error = new IllegalArgumentException("Invalid ordinal " + ordinal + " for type " + enumClass.getName()); - if (enumConstants.length == 0) { - throw error; - } else { - error.printStackTrace(System.err); - return enumConstants[0]; - } - } - - @NotNull - public static List filterCollection(@NotNull Collection collection, @NotNull Class type) { - List result = new ArrayList<>(); - for (Object item : collection) { - if (type.isInstance(item)) { - result.add(type.cast(item)); - } - } - return result; - } - - @NotNull - public static String escapeDisplayString(@NotNull final String delim) { - StringBuilder str = new StringBuilder(); - for (int i = 0; i < delim.length(); i++) { - char c = delim.charAt(i); - if (c == '\n') { - str.append("\\n"); - } else if (c == '\r') { - str.append("\\r"); - } else if (c == '\t') { - str.append("\\t"); - } else { - str.append(c); - } - } - return str.toString(); - } - - @NotNull - public static String unescapeDisplayString(@NotNull final String delim) { - return delim.replace("\\t", "\t").replace("\\n", "\n").replace("\\r", "\r"); - } - - public static int hashCode(@Nullable Object obj) { - return obj == null ? 0 : obj.hashCode(); - } - - public static T getOption(Map options, String name, T defValue) { - Object optionValue = options.get(name); - if (optionValue == null) { - return defValue; - } - return (T)optionValue; - } - - public static boolean getOption(Map options, String name) { - return getOption(options, name, false); - } - - public static boolean getOption(Map options, String name, boolean defValue) { - if (options == null) { - return false; - } - Object optionValue = options.get(name); - return getBoolean(optionValue, defValue); - } - - public static Map makeStringMap(Map objMap) { - Map strMap = new LinkedHashMap<>(objMap.size()); - for (Map.Entry e : objMap.entrySet()) { - strMap.put(toString(e.getKey(), null), e.getValue()); - } - return strMap; - } - - public static String fixedLengthString(String string, int length) { - return String.format("%1$"+length+ "s", string); - } - - public static boolean startsWithIgnoreCase(@Nullable String str, @Nullable String startPart) { - if (isEmpty(str) || isEmpty(startPart)) { - return false; - } - return str.regionMatches(true, 0, startPart, 0, startPart.length()); - } - - public static String niceFormatFloat(float val) { - if (val == (int) val) - return String.valueOf((int)val); - else - return String.valueOf(val); - } - - public static String niceFormatDouble(double val) { - if (val == (long) val) - return String.valueOf((long)val); - else - return String.valueOf(val); - } - - public static String trim(String str) { - return str == null ? null : str.trim(); - } - - public static String compactWhiteSpaces(String str) { - return str.replaceAll("\\s+", " "); - } - - public static String getSingleLineString(String displayString) { - return displayString - .replace('\n', PARAGRAPH_CHAR) - .replace("\r", "") - .replace("\t", " ") - .replace((char)0, ' '); - } - - public static int compare(Object o1, Object o2) { - if (o1 == o2) { - return 0; - } - if (o1 == null) { - return -1; - } else if (o2 == null) { - return 1; - } - if (o1.getClass() == o2.getClass() && o1 instanceof Comparable) { - return ((Comparable) o1).compareTo(o2); - } - return toString(o1).compareTo(toString(o2)); - } - - public static int compareNumbers(Number value1, Number value2) { - double numDiff = value1.doubleValue() - value2.doubleValue(); - return numDiff < 0 ? -1 : (numDiff > 0 ? 1 : 0); - } - - public static String cutExtraLines(String message, int maxLines) { - if (message == null || message.indexOf('\n') == -1) { - return message; - } - int lfCount = 0; - StringBuilder buf = new StringBuilder(); - for (int i = 0; i < message.length(); i++) { - char c = message.charAt(i); - if (c == '\n') { - lfCount++; - } - buf.append(c); - if (lfCount == maxLines) { - buf.append("..."); - break; - } - } - return buf.toString(); - } - - public static boolean isSameDay(@NotNull Date date1, @NotNull Date date2) { - Calendar cal1 = Calendar.getInstance(); - cal1.setTime(date1); - Calendar cal2 = Calendar.getInstance(); - cal2.setTime(date2); - return isSameDay(cal1, cal2); - } - - public static boolean isSameDay(@NotNull Calendar cal1, @NotNull Calendar cal2) { - return (cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA) && - cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) && - cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR)); - } - - public static String escapeBourneShellString(@NotNull String s) { - return "'" + s.replace("'", "'\\''") + "'"; - } - - public static String unescapeBourneShellString(@NotNull String s) { - if (!s.startsWith("'") || !s.endsWith("'") || s.length() < 2) { //not an escaped bourne shell string - return s; - } - return s.substring(1, s.length() - 1).replace("'\\''", "'"); - } - - /** - * Checks whether the supplied ch is within - * the range of the specified radix value. - * - * @param ch character codepoint to be checked - * @param radix desired radix - * @return true if the character fits - * into the radix, false otherwise - */ - public static boolean isDigit(int ch, int radix) { - if (radix <= 0 || radix > 36) - return false; - if (ch >= '0' && ch <= '9') - return radix > ch - '0'; - if (ch >= 'a' && ch <= 'z') - return radix > ch - 'a' + 10; - if (ch >= 'A' && ch <= 'Z') - return radix > ch - 'A' + 10; - return false; - } - - /** - * Checks if the {@code index} is within the bounds of the range from - * {@code 0} (inclusive) to {@code length} (exclusive). - * - *

The {@code index} is defined to be out of bounds if any of the - * following inequalities is true: - *

- * - * @param index the index - * @param length the upper-bound (exclusive) of the range - * @return {@code true} if it is within bounds of the range - */ - public static boolean isValidIndex(int index, int length) { - return 0 <= index && index < length; - } - - @NotNull - public static String escapeHtml(@Nullable String text) { - if (text == null) { - return " "; - } - return text - .replace("&", "&") - .replace("<", "<") - .replace(">", ">") - .replace("\r\n", "
") - .replace("\r", "
") - .replace("\n", "
"); - } - - /** - * Finds the object with the best matching name. Here we consider a case sensitive match better then a case insensitive one. - * - * @param objects container with objects - * @param name to match - * @param nameExtractor function which extracts the name from object - * @param type of objects to search from - * @return the best match or {@code null} if nothing found - */ - @Nullable - public static T findBestCaseAwareMatch(@NotNull Iterable objects, @NotNull String name, - @NotNull Function nameExtractor) { - T firstCaseInsensitiveMatch = null; - for (T obj: objects) { - String objectName = nameExtractor.apply(obj); - if (name.equals(objectName)) { //case sensitive match - return obj; - } - if (firstCaseInsensitiveMatch == null && name.equalsIgnoreCase(objectName)) { - firstCaseInsensitiveMatch = obj; - } - } - return firstCaseInsensitiveMatch; - } - - /** - * Groups values into a map of their shared key and a list of matching values using that key. - *

- *

Group strings by their first character

- *
{@code
-     * final List values = Arrays.asList("aaa", "abb", "bbb", "bab", "ccc");
-     * final Map> groups = group(values, x -> x.charAt(0));
-     *
-     * Assert.assertEquals(Arrays.asList("aaa", "abb"), groups.get('a'));
-     * Assert.assertEquals(Arrays.asList("bbb", "bab"), groups.get('b'));
-     * Assert.assertEquals(Arrays.asList("ccc"), groups.get('c'));
-     * }
- * @param values values to group - * @param keyExtractor a function that extracts key from value that is used to group values - * @return map of a shared key and a list of matching values - */ - @NotNull - public static Map> group(@NotNull Collection values, @NotNull Function keyExtractor) { - final Map> grouped = new HashMap<>(); - for (V value : values) { - final K key = keyExtractor.apply(value); - final List group = grouped.computeIfAbsent(key, k -> new ArrayList<>()); - group.add(value); - } - return grouped; - } - - /** - * Clamps given value to range between lower and upper bounds. - * - * @param value the value to clamp - * @param min the lower boundary to clamp {@code value} to - * @param max the upper boundary to clamp {@code value} to - * @return {@code min} if {@code value} is less than {@code min}, {@code max} if {@code value} is greater than {@code max}, otherwise {@code value} - */ - public static int clamp(int value, int min, int max) { - return Math.max(min, Math.min(value, max)); - } - - /** - * Replaces every subsequence of the input sequence that matches the - * pattern with the result of applying the given replacer function to the - * match result of this matcher corresponding to that subsequence. - */ - @NotNull - public static String replaceAll(@NotNull String input, @NotNull String regex, @NotNull Function replacer) { - Matcher matcher = Pattern.compile(regex).matcher(input); - StringBuilder sb = new StringBuilder(); - while (matcher.find()) { - matcher.appendReplacement(sb, replacer.apply(matcher)); - } - matcher.appendTail(sb); - return sb.toString(); - } - - @SafeVarargs - public static T[] array(T... elems) { - return elems; - } - - /** - * Removes (single or multiple) starting '/' from {@code resourcePath} and replaces all '\' with '/' - */ - @NotNull - public static String normalizeResourcePath(@NotNull String resourcePath) { - while (resourcePath.startsWith("/")) { - resourcePath = resourcePath.substring(1); - } - resourcePath = resourcePath.replace('\\', '/'); - return resourcePath; - } - - /** - * Replaces the last {@code toReplace} entry in {@code string} with {@code replacement} - */ - @NotNull - public static String replaceLast(@NotNull String string, @NotNull String toReplace, @NotNull String replacement) { - int pos = string.lastIndexOf(toReplace); - if (pos > -1) { - return string.substring(0, pos) - + replacement - + string.substring(pos + toReplace.length()); - } else { - return string; - } - } - - /** - * Sets prefix for sql queries params (f.e. schema names for tables) - */ - @NotNull - public static String normalizeTableNames(@NotNull String sql, @Nullable String prefix) { - return sql.replaceAll("\\{table_prefix}", isEmpty(prefix) ? "" : prefix + "."); - } -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/IOUtils.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/IOUtils.java deleted file mode 100644 index 27eeb4943acc4..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/IOUtils.java +++ /dev/null @@ -1,444 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jkiss.utils; - -import org.jkiss.code.NotNull; -import org.jkiss.code.Nullable; - -import java.io.*; -import java.net.ServerSocket; -import java.net.URI; -import java.nio.Buffer; -import java.nio.ByteBuffer; -import java.nio.channels.Channels; -import java.nio.channels.ReadableByteChannel; -import java.nio.channels.WritableByteChannel; -import java.nio.file.Files; -import java.nio.file.InvalidPathException; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.Comparator; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; -import java.util.zip.ZipOutputStream; - -/** - * Some IO helper functions - */ -public final class IOUtils { - - public static final int DEFAULT_BUFFER_SIZE = 16384; - - private static final boolean USE_NIO_STREAMS = false; - - public static void close(Closeable closeable) { - try { - closeable.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - public static void close(AutoCloseable closeable) { - try { - closeable.close(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - public static void fastCopy(final InputStream src, final OutputStream dest) throws IOException { - fastCopy(src, dest, DEFAULT_BUFFER_SIZE); - } - - public static void fastCopy(final InputStream src, final OutputStream dest, int bufferSize) throws IOException { - if (USE_NIO_STREAMS) { - final ReadableByteChannel inputChannel = Channels.newChannel(src); - final WritableByteChannel outputChannel = Channels.newChannel(dest); - fastCopy(inputChannel, outputChannel, bufferSize); - } else { - copyStream(src, dest, bufferSize); - } - } - - public static void fastCopy(final ReadableByteChannel src, final WritableByteChannel dest, int bufferSize) throws IOException { - final ByteBuffer buffer = ByteBuffer.allocateDirect(bufferSize); - - while (src.read(buffer) != -1) { - flipBuffer(buffer); - dest.write(buffer); - buffer.compact(); - } - - flipBuffer(buffer); - - while (buffer.hasRemaining()) { - dest.write(buffer); - } - } - - public static void flipBuffer(Buffer buffer) { - buffer.flip(); - } - - public static void copyStream( - java.io.InputStream inputStream, - java.io.OutputStream outputStream) - throws IOException { - copyStream(inputStream, outputStream, DEFAULT_BUFFER_SIZE); - } - - /** - * Read entire input stream and writes all data to output stream - * then closes input and flushed output - */ - public static void copyStream( - java.io.InputStream inputStream, - java.io.OutputStream outputStream, - int bufferSize) - throws IOException { - try { - byte[] writeBuffer = new byte[bufferSize]; - for (int br = inputStream.read(writeBuffer); br != -1; br = inputStream.read(writeBuffer)) { - outputStream.write(writeBuffer, 0, br); - } - outputStream.flush(); - } finally { - // Close input stream - inputStream.close(); - } - } - - /** - * Read entire input stream portion and writes it data to output stream - */ - public static void copyStreamPortion( - java.io.InputStream inputStream, - java.io.OutputStream outputStream, - int portionSize, - int bufferSize) - throws IOException { - if (bufferSize > portionSize) { - bufferSize = portionSize; - } - byte[] writeBuffer = new byte[bufferSize]; - int totalRead = 0; - while (totalRead < portionSize) { - int bytesToRead = bufferSize; - if (bytesToRead > portionSize - totalRead) { - bytesToRead = portionSize - totalRead; - } - int bytesRead = inputStream.read(writeBuffer, 0, bytesToRead); - outputStream.write(writeBuffer, 0, bytesRead); - totalRead += bytesRead; - } - - // Close input stream - outputStream.flush(); - } - - public static String toString(File file, String encoding) throws IOException { - try (InputStream is = new FileInputStream(file)) { - try (Reader reader = new InputStreamReader(is, encoding)) { - StringWriter writer = new StringWriter(); - copyText(reader, writer, DEFAULT_BUFFER_SIZE); - return writer.toString(); - } - } - } - - /** - * Read entire reader content and writes it to writer - * then closes reader and flushed output. - */ - public static void copyText( - java.io.Reader reader, - java.io.Writer writer, - int bufferSize) - throws IOException { - char[] writeBuffer = new char[bufferSize]; - for (int br = reader.read(writeBuffer); br != -1; br = reader.read(writeBuffer)) { - writer.write(writeBuffer, 0, br); - } - writer.flush(); - } - - public static void copyText( - java.io.Reader reader, - java.io.Writer writer) - throws IOException { - copyText(reader, writer, DEFAULT_BUFFER_SIZE); - } - - public static byte[] readFileToBuffer(File file) throws IOException { - byte[] buffer = new byte[(int) file.length()]; - try (InputStream is = new FileInputStream(file)) { - readStreamToBuffer(is, buffer); - } - return buffer; - } - - public static void writeFileFromBuffer(File file, byte[] buffer) throws IOException { - try (OutputStream os = new FileOutputStream(file)) { - os.write(buffer); - } - } - - public static void writeFileFromString(File file, String str) throws IOException { - try (Writer os = new FileWriter(file)) { - os.write(str); - } - } - - public static int readStreamToBuffer( - java.io.InputStream inputStream, - byte[] buffer) - throws IOException { - int totalRead = 0; - while (totalRead != buffer.length) { - int br = inputStream.read(buffer, totalRead, buffer.length - totalRead); - if (br == -1) { - break; - } - totalRead += br; - } - return totalRead; - } - - public static String readLine(java.io.InputStream input) - throws IOException { - StringBuilder linebuf = new StringBuilder(); - for (int b = input.read(); b != '\n'; b = input.read()) { - if (b == -1) { - if (linebuf.length() == 0) { - return null; - } else { - break; - } - } - if (b != '\r') { - linebuf.append((char) b); - } - } - return linebuf.toString(); - } - - public static String readFullLine(java.io.InputStream input) - throws IOException { - StringBuilder linebuf = new StringBuilder(); - for (int b = input.read(); ; b = input.read()) { - if (b == -1) { - if (linebuf.length() == 0) { - return null; - } else { - break; - } - } - linebuf.append((char) b); - if (b == '\n') { - break; - } - } - return linebuf.toString(); - } - - public static int findFreePort(int minPort, int maxPort) { - int portRange = Math.abs(maxPort - minPort); - while (true) { - int portNum = minPort + SecurityUtils.getRandom().nextInt(portRange); - try { - ServerSocket socket = new ServerSocket(portNum); - try { - socket.close(); - } catch (IOException e) { - // just skip - } - return portNum; - } catch (IOException e) { - // Port is busy - } - } - } - - public static String readToString(Reader is) throws IOException { - StringBuilder result = new StringBuilder(4000); - char[] buffer = new char[4000]; - for (; ; ) { - int count = is.read(buffer); - if (count <= 0) { - break; - } - result.append(buffer, 0, count); - } - return result.toString(); - } - - static void copyZipStream(InputStream inputStream, OutputStream outputStream) - throws IOException - { - byte[] writeBuffer = new byte[IOUtils.DEFAULT_BUFFER_SIZE]; - for (int br = inputStream.read(writeBuffer); br != -1; br = inputStream.read(writeBuffer)) { - outputStream.write(writeBuffer, 0, br); - } - outputStream.flush(); - } - - public static void extractZipArchive(InputStream stream, Path targetFolder) throws IOException { - try (ZipInputStream zipStream = new ZipInputStream(stream)) { - for (; ; ) { - ZipEntry zipEntry = zipStream.getNextEntry(); - if (zipEntry == null) { - break; - } - try { - if (!zipEntry.isDirectory()) { - String zipEntryName = zipEntry.getName(); - checkAndExtractEntry(zipStream, zipEntry, targetFolder); - } - } finally { - zipStream.closeEntry(); - } - } - } - } - - private static void checkAndExtractEntry(InputStream zipStream, ZipEntry zipEntry, Path targetFolder) throws IOException { - if (!Files.exists(targetFolder)) { - try { - Files.createDirectories(targetFolder); - } catch (IOException e) { - throw new IOException("Can't create local cache folder '" + targetFolder.toAbsolutePath() + "'", e); - } - } - Path localFile = targetFolder.resolve(zipEntry.getName()); - if (!localFile.normalize().startsWith(targetFolder.normalize())) { - throw new IOException("Zip entry is outside of the target directory"); - } - if (Files.exists(localFile)) { - // Already extracted? - return; - } - Path localDir = localFile.getParent(); - if (!Files.exists(localDir)) { // in case of localFile located in subdirectory inside zip archive - try { - Files.createDirectories(localDir); - } catch (IOException e) { - throw new IOException("Can't create local file directory in the cache '" + localDir.toAbsolutePath() + "'", e); - } - } - try (OutputStream os = Files.newOutputStream(localFile)) { - copyZipStream(zipStream, os); - } - } - - - public static void zipFolder(final File folder, final OutputStream outputStream) throws IOException { - try (ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream)) { - processFolder(folder, zipOutputStream, folder.getPath().length() + 1); - } - } - - private static void processFolder(final File folder, final ZipOutputStream zipOutputStream, final int prefixLength) throws IOException { - File[] folderFiles = folder.listFiles(); - if (folderFiles == null) { - return; - } - for (File file : folderFiles) { - BasicFileAttributes fAttrs = Files.readAttributes(file.toPath(), BasicFileAttributes.class); - if (fAttrs.isRegularFile()) { - final ZipEntry zipEntry = new ZipEntry(file.getPath().substring(prefixLength)); - zipOutputStream.putNextEntry(zipEntry); - try (FileInputStream inputStream = new FileInputStream(file)) { - IOUtils.copyStream(inputStream, zipOutputStream); - } - zipOutputStream.closeEntry(); - } else if (fAttrs.isDirectory()) { - processFolder(file, zipOutputStream, prefixLength); - } - } - } - public static void deleteDirectory(@NotNull Path path) throws IOException { - Files.walk(path) - .sorted(Comparator.reverseOrder()) - .map(Path::toFile) - .forEach(File::delete); - } - - @Nullable - public static String getDirectoryPath(@NotNull String sPath) throws InvalidPathException { - final Path path = Paths.get(sPath); - if (Files.isDirectory(path)) { - return path.toString(); - } else { - final Path parent = path.getParent(); - if (parent != null) { - return parent.toString(); - } - } - return null; - } - - @NotNull - public static String getFileNameWithoutExtension(Path file) { - String fileName = file.getFileName().toString(); - int divPos = fileName.lastIndexOf('.'); - if (divPos != -1) { - return fileName.substring(0, divPos); - } - return fileName; - } - - @Nullable - public static String getFileExtension(Path file) { - String fileName = file.getFileName().toString(); - return getFileExtension(fileName); - } - - @Nullable - public static String getFileExtension(String fileName) { - int divPos = fileName.lastIndexOf('.'); - if (divPos != -1) { - return fileName.substring(divPos + 1); - } - return null; - } - - @NotNull - public static Path getPathFromString(@NotNull String pathOrUri) { - if (pathOrUri.contains("://")) { - return Path.of(URI.create(pathOrUri)); - } else { - return Path.of(pathOrUri); - } - } - - - public static boolean isLocalFile(String filePath) { - return !filePath.contains("://") || filePath.startsWith("file:"); - } - - public static boolean isLocalURI(URI uri) { - return uri.getScheme().equals("file"); - } - - public static boolean isLocalPath(Path filePath) { - return isLocalURI(filePath.toUri()); - } - -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/IntKeyMap.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/IntKeyMap.java deleted file mode 100644 index b97960eee9c7f..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/IntKeyMap.java +++ /dev/null @@ -1,807 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jkiss.utils; - -import java.util.*; - -/** - Map with int key. -*/ -@SuppressWarnings("unchecked") -public class IntKeyMap implements Map { - /** - * The default initial capacity - MUST be a power of two. - */ - static final int DEFAULT_INITIAL_CAPACITY = 16; - - /** - * The maximum capacity, used if a higher value is implicitly specified - * by either of the constructors with arguments. - * MUST be a power of two <= 1<<30. - */ - static final int MAXIMUM_CAPACITY = 1 << 30; - - /** - * The load fast used when none specified in constructor. - **/ - static final float DEFAULT_LOAD_FACTOR = 0.75f; - - /** - * The table, resized as necessary. Length MUST Always be a power of two. - */ - transient IntEntry[] table; - - /** - * The number of key-value mappings contained in this identity hash map. - */ - transient int size; - - /** - * The next size value at which to resize (capacity * load factor). - * @serial - */ - int threshold; - - /** - * The load factor for the hash table. - * - * @serial - */ - final float loadFactor; - - /** - * The number of times this IntKeyMap has been structurally modified - */ - transient volatile int modCount; - - /** - * Constructs an empty IntKeyMap with the specified initial - * capacity and load factor. - * - * @param initialCapacity The initial capacity. - * @param loadFactor The load factor. - * @throws IllegalArgumentException if the initial capacity is negative - * or the load factor is nonpositive. - */ - public IntKeyMap(int initialCapacity, float loadFactor) { - if (initialCapacity < 0) - throw new IllegalArgumentException("Illegal initial capacity: " + - initialCapacity); - if (initialCapacity > MAXIMUM_CAPACITY) - initialCapacity = MAXIMUM_CAPACITY; - if (loadFactor <= 0 || Float.isNaN(loadFactor)) - throw new IllegalArgumentException("Illegal load factor: " + - loadFactor); - - // Find a power of 2 >= initialCapacity - int capacity = 1; - while (capacity < initialCapacity) - capacity <<= 1; - - this.loadFactor = loadFactor; - threshold = (int)(capacity * loadFactor); - table = new IntEntry[capacity]; - } - - /** - * Constructs an empty IntKeyMap with the specified initial - * capacity and the default load factor (0.75). - * - * @param initialCapacity the initial capacity. - * @throws IllegalArgumentException if the initial capacity is negative. - */ - public IntKeyMap(int initialCapacity) { - this(initialCapacity, DEFAULT_LOAD_FACTOR); - } - - /** - * Constructs an empty IntKeyMap with the default initial capacity - * (16) and the default load factor (0.75). - */ - public IntKeyMap() { - this.loadFactor = DEFAULT_LOAD_FACTOR; - threshold = DEFAULT_INITIAL_CAPACITY; - table = new IntEntry[DEFAULT_INITIAL_CAPACITY]; - } - - static int hash(long x) { - int h = (int)(x ^ (x >>> 32)); - h += ~(h << 9); - h ^= (h >>> 14); - h += (h << 4); - h ^= (h >>> 10); - return h; - } - - /** - * Returns index for hash code h. - */ - static int indexFor(int h, int length) { - return h & (length-1); - } - - /** - * Returns the number of key-value mappings in this map. - * - * @return the number of key-value mappings in this map. - */ - @Override - public int size() { - return size; - } - - /** - * Returns true if this map contains no key-value mappings. - * - * @return true if this map contains no key-value mappings. - */ - @Override - public boolean isEmpty() - { - return size == 0; - } - - @Override - public boolean containsKey(Object key) - { - return containsKey(((Number)key).intValue()); - } - - /** - * Returns the value to which the specified key is mapped in this identity - * hash map, or null if the map contains no mapping for this key. - * A return value of null does not necessarily indicate - * that the map contains no mapping for the key; it is also possible that - * the map explicitly maps the key to null. The - * containsKey method may be used to distinguish these two cases. - * - * @param key the key whose associated value is to be returned. - * @return the value to which this map maps the specified key, or - * null if the map contains no mapping for this key. - * @see #put(int, Object) - */ - public VALUE get(int key) { - int hash = hash(key); - int i = indexFor(hash, table.length); - IntEntry e = table[i]; - while (true) { - if (e == null) - return null; - if (e.hash == hash && key == e.key) - return e.value; - e = e.next; - } - } - - /** - * Returns true if this map contains a mapping for the - * specified key. - */ - public boolean containsKey(int key) - { - int hash = hash(key); - int i = indexFor(hash, table.length); - IntEntry e = table[i]; - while (e != null) { - if (e.hash == hash && key == e.key) - return true; - e = e.next; - } - return false; - } - - /** - * Returns the entry associated with the specified key in the - * IntKeyMap. Returns null if the IntKeyMap contains no mapping - * for this key. - */ - IntEntry getEntry(int key) { - int hash = hash(key); - int i = indexFor(hash, table.length); - IntEntry e = table[i]; - while (e != null && !(e.hash == hash && key == e.key)) - e = e.next; - return e; - } - - /** - * Associates the specified value with the specified key in this map. - * If the map previously contained a mapping for this key, the old - * value is replaced. - * - * @param key key with which the specified value is to be associated. - * @param value value to be associated with the specified key. - * @return previous value associated with specified key, or null - * if there was no mapping for key. A null return can - * also indicate that the IntKeyMap previously associated - * null with the specified key. - */ - public VALUE put(int key, VALUE value) { - int hash = hash(key); - int i = indexFor(hash, table.length); - - for (IntEntry e = table[i]; e != null; e = e.next) { - if (e.hash == hash && key == e.key) { - VALUE oldValue = e.value; - e.value = value; - return oldValue; - } - } - - modCount++; - addEntry(hash, key, value, i); - return null; - } - - /** - * This method is used instead of put by constructors and - * pseudoconstructors (clone, readObject). It does not resize the table, - * check for comodification, etc. It calls createEntry rather than - * addEntry. - */ - private void putForCreate(int key, VALUE value) { - int hash = hash(key); - int i = indexFor(hash, table.length); - - /** - * Look for preexisting entry for key. This will never happen for - * clone or deserialize. It will only happen for construction if the - * input Map is a sorted map whose ordering is inconsistent w/ equals. - */ - for (IntEntry e = table[i]; e != null; e = e.next) { - if (e.hash == hash && key == e.key) { - e.value = value; - return; - } - } - - createEntry(hash, key, value, i); - } - - void putAllForCreate(IntKeyMap m) { - for (Iterator i = m.entrySet().iterator(); i.hasNext(); ) { - IntEntry e = (IntEntry) i.next(); - putForCreate(e.key, e.value); - } - } - - /** - * Rehashes the contents of this map into a new IntKeyMap instance - * with a larger capacity. This method is called automatically when the - * number of keys in this map exceeds its capacity and load factor. - * - * @param newCapacity the new capacity, MUST be a power of two. - */ - void resize(int newCapacity) { - // assert (newCapacity & -newCapacity) == newCapacity; // power of 2 - IntEntry[] oldTable = table; - int oldCapacity = oldTable.length; - - // check if needed - if (size < threshold || oldCapacity > newCapacity) - return; - - IntEntry[] newTable = new IntEntry[newCapacity]; - transfer(newTable); - table = newTable; - threshold = (int)(newCapacity * loadFactor); - } - - /** - * Transfer all entries from current table to newTable. - */ - void transfer(IntEntry[] newTable) { - IntEntry[] src = table; - int newCapacity = newTable.length; - for (int j = 0; j < src.length; j++) { - IntEntry e = src[j]; - if (e != null) { - src[j] = null; - do { - IntEntry next = e.next; - int i = indexFor(e.hash, newCapacity); - e.next = newTable[i]; - newTable[i] = e; - e = next; - } while (e != null); - } - } - } - - /** - * Copies all of the mappings from the specified map to this map - * These mappings will replace any mappings that - * this map had for any of the keys currently in the specified map. - * - * @param t mappings to be stored in this map. - * @throws NullPointerException if the specified map is null. - */ - public void putAll(IntKeyMap t) { - // Expand enough to hold t's elements without resizing. - int n = t.size(); - if (n == 0) - return; - if (n >= threshold) { - n = (int)(n / loadFactor + 1); - if (n > MAXIMUM_CAPACITY) - n = MAXIMUM_CAPACITY; - int capacity = table.length; - while (capacity < n) - capacity <<= 1; - resize(capacity); - } - - for (Iterator i = t.entrySet().iterator(); i.hasNext(); ) { - IntEntry e = (IntEntry) i.next(); - put(e.key, e.value); - } - } - - /** - * Removes the mapping for this key from this map if present. - * - * @param key key whose mapping is to be removed from the map. - * @return previous value associated with specified key, or null - * if there was no mapping for key. A null return can - * also indicate that the map previously associated null - * with the specified key. - */ - public VALUE remove(int key) { - IntEntry e = removeEntryForKey(key); - return (e == null ? null : e.value); - } - - /** - * Removes and returns the entry associated with the specified key - * in the IntKeyMap. Returns null if the IntKeyMap contains no mapping - * for this key. - */ - IntEntry removeEntryForKey(int key) { - int hash = hash(key); - int i = indexFor(hash, table.length); - IntEntry prev = table[i]; - IntEntry e = prev; - - while (e != null) { - IntEntry next = e.next; - if (e.hash == hash && key == e.key) { - modCount++; - size--; - if (prev == e) - table[i] = next; - else - prev.next = next; - return e; - } - prev = e; - e = next; - } - - return e; - } - - /** - * Special version of remove for EntrySet. - */ - IntEntry removeMapping(Object o) { - if (!(o instanceof IntEntry)) - return null; - - IntEntry entry = (IntEntry)o; - int hash = hash(entry.key); - int i = indexFor(hash, table.length); - IntEntry prev = table[i]; - IntEntry e = prev; - - while (e != null) { - IntEntry next = e.next; - if (e.hash == hash && e.equals(entry)) { - modCount++; - size--; - if (prev == e) - table[i] = next; - else - prev.next = next; - return e; - } - prev = e; - e = next; - } - - return e; - } - - /** - * Removes all mappings from this map. - */ - @Override - public void clear() { - modCount++; - IntEntry tab[] = table; - for (int i = 0; i < tab.length; i++) - tab[i] = null; - size = 0; - } - - /** - * Returns true if this map maps one or more keys to the - * specified value. - * - * @param value value whose presence in this map is to be tested. - * @return true if this map maps one or more keys to the - * specified value. - */ - @Override - public boolean containsValue(Object value) - { - if (value == null) - return containsNullValue(); - - IntEntry tab[] = table; - for (int i = 0; i < tab.length ; i++) - for (IntEntry e = tab[i] ; e != null ; e = e.next) - if (value.equals(e.value)) - return true; - return false; - } - - @Override - public VALUE get(Object key) - { - return get(((Number)key).intValue()); - } - - @Override - public VALUE put(Integer key, VALUE value) - { - return put(key.intValue(), value); - } - - @Override - public VALUE remove(Object key) - { - return remove(((Number)key).intValue()); - } - - @Override - public void putAll(Map t) - { - throw new UnsupportedOperationException(); - } - - /** - * Special-case code for containsValue with null argument - **/ - private boolean containsNullValue() - { - IntEntry tab[] = table; - for (int i = 0; i < tab.length ; i++) - for (IntEntry e = tab[i] ; e != null ; e = e.next) - if (e.value == null) - return true; - return false; - } - - public static class IntEntry implements Entry { - final int key; - VALUE value; - final int hash; - IntEntry next; - - /** - * Create new entry. - */ - IntEntry(int h, int k, VALUE v, IntEntry n) { - value = v; - next = n; - key = k; - hash = h; - } - - public int getInt() { - return key; - } - - @Override - public Integer getKey() - { - return key; - } - - @Override - public VALUE getValue() { - return value; - } - - @Override - public VALUE setValue(VALUE newValue) { - VALUE oldValue = value; - value = newValue; - return oldValue; - } - - public boolean equals(Object o) { - if (!(o instanceof IntEntry)) - return false; - IntEntry e = (IntEntry)o; - if (key == e.key) { - VALUE v1 = getValue(); - VALUE v2 = e.getValue(); - if (v1 == v2 || (v1 != null && v1.equals(v2))) - return true; - } - return false; - } - - public int hashCode() { - return hash(key) ^ (value==null ? 0 : value.hashCode()); - } - - public String toString() { - return String.valueOf(key) + "=" + getValue(); - } - - } - - /** - * Add a new entry with the specified key, value and hash code to - * the specified bucket. It is the responsibility of this - * method to resize the table if appropriate. - * - * Subclass overrides this to alter the behavior of put method. - */ - void addEntry(int hash, int key, VALUE value, int bucketIndex) { - table[bucketIndex] = new IntEntry<>(hash, key, value, table[bucketIndex]); - if (size++ >= threshold) - resize(2 * table.length); - } - - /** - * Like addEntry except that this version is used when creating entries - * as part of Map construction or "pseudo-construction" (cloning, - * deserialization). This version needn't worry about resizing the table. - * - * Subclass overrides this to alter the behavior of IntKeyMap(Map), - * clone, and readObject. - */ - void createEntry(int hash, int key, VALUE value, int bucketIndex) { - table[bucketIndex] = new IntEntry<>(hash, key, value, table[bucketIndex]); - size++; - } - - private abstract class HashIterator implements Iterator { - IntEntry next; // next entry to return - int expectedModCount; // For fast-fail - int index; // current slot - IntEntry current; // current entry - - HashIterator() { - expectedModCount = modCount; - IntEntry[] t = table; - int i = t.length; - IntEntry n = null; - if (size != 0) { // advance to first entry - while (i > 0 && (n = t[--i]) == null) - ; - } - next = n; - index = i; - } - - @Override - public boolean hasNext() { - return next != null; - } - - IntEntry nextEntry() { - if (modCount != expectedModCount) - throw new ConcurrentModificationException(); - IntEntry e = next; - if (e == null) - throw new NoSuchElementException(); - - IntEntry n = e.next; - IntEntry[] t = table; - int i = index; - while (n == null && i > 0) - n = t[--i]; - index = i; - next = n; - return current = e; - } - - @Override - public void remove() { - if (current == null) - throw new IllegalStateException(); - if (modCount != expectedModCount) - throw new ConcurrentModificationException(); - int k = current.key; - current = null; - IntKeyMap.this.removeEntryForKey(k); - expectedModCount = modCount; - } - - } - - private class ValueIterator extends HashIterator { - @Override - public VALUE next() { - return nextEntry().value; - } - } - - private class KeyIterator extends HashIterator { - @Override - public Integer next() { - return nextEntry().key; - } - public int nextInt() { - return nextEntry().key; - } - } - - private class EntryIterator extends HashIterator> { - @Override - public IntEntry next() { - return nextEntry(); - } - } - - // Subclass overrides these to alter behavior of views' iterator() method - Iterator newKeyIterator() - { - return new KeyIterator(); - } - Iterator newValueIterator() - { - return new ValueIterator(); - } - Iterator> newEntryIterator() - { - return new EntryIterator(); - } - - - // Views - - private transient Set> entrySet = null; - transient volatile Set keySet = null; - transient volatile Collection values = null; - - /** - * Returns a set view of the keys contained in this map. The set is - * backed by the map, so changes to the map are reflected in the set, and - * vice-versa. The set supports element removal, which removes the - * corresponding mapping from this map, via the Iterator.remove, - * Set.remove, removeAll, retainAll, and - * clear operations. It does not support the add or - * addAll operations. - * - * @return a set view of the keys contained in this map. - */ - @Override - public Set keySet() { - Set ks = keySet; - return (ks != null ? ks : (keySet = new KeySet())); - } - - private class KeySet extends AbstractSet { - @Override - public Iterator iterator() { - return newKeyIterator(); - } - @Override - public int size() { - return size; - } - @Override - public boolean contains(Object o) { - if (o instanceof Number) { - return containsKey(((Number)o).intValue()); - } else { - return false; - } - } - @Override - public boolean remove(Object o) { - if (o instanceof Number) { - return IntKeyMap.this.removeEntryForKey(((Number)o).intValue()) != null; - } else { - return false; - } - } - @Override - public void clear() { - IntKeyMap.this.clear(); - } - } - - /** - * Returns a collection view of the values contained in this map. The - * collection is backed by the map, so changes to the map are reflected in - * the collection, and vice-versa. The collection supports element - * removal, which removes the corresponding mapping from this map, via the - * Iterator.remove, Collection.remove, - * removeAll, retainAll, and clear operations. - * It does not support the add or addAll operations. - * - * @return a collection view of the values contained in this map. - */ - @Override - public Collection values() { - Collection vs = values; - return (vs != null ? vs : (values = new Values())); - } - - private class Values extends AbstractCollection { - @Override - public Iterator iterator() { - return newValueIterator(); - } - @Override - public int size() { - return size; - } - @Override - public boolean contains(Object o) { - return containsValue(o); - } - @Override - public void clear() { - IntKeyMap.this.clear(); - } - } - - @Override - public Set entrySet() - { - Set> es = entrySet; - return (es != null ? es : (entrySet = new EntrySet())); - } - - private class EntrySet extends AbstractSet> { - @Override - public Iterator> iterator() { - return newEntryIterator(); - } - @Override - public boolean contains(Object o) { - if (!(o instanceof IntEntry)) - return false; - IntEntry e = (IntEntry)o; - IntEntry candidate = getEntry(e.key); - return candidate != null && candidate.equals(e); - } - @Override - public boolean remove(Object o) { - return removeMapping(o) != null; - } - @Override - public int size() { - return size; - } - @Override - public void clear() { - IntKeyMap.this.clear(); - } - } - - // These methods are used when serializing HashSets - int capacity() { return table.length; } - float loadFactor() { return loadFactor; } -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/LongKeyMap.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/LongKeyMap.java deleted file mode 100644 index 40807b68422d0..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/LongKeyMap.java +++ /dev/null @@ -1,806 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jkiss.utils; - -import java.util.*; - -/** - Map with long key. -*/ -public class LongKeyMap implements Map { - /** - * The default initial capacity - MUST be a power of two. - */ - static final int DEFAULT_INITIAL_CAPACITY = 16; - - /** - * The maximum capacity, used if a higher value is implicitly specified - * by either of the constructors with arguments. - * MUST be a power of two <= 1<<30. - */ - static final int MAXIMUM_CAPACITY = 1 << 30; - - /** - * The load fast used when none specified in constructor. - **/ - static final float DEFAULT_LOAD_FACTOR = 0.75f; - - /** - * The table, resized as necessary. Length MUST Always be a power of two. - */ - transient LongEntry[] table; - - /** - * The number of key-value mappings contained in this identity hash map. - */ - transient int size; - - /** - * The next size value at which to resize (capacity * load factor). - * @serial - */ - int threshold; - - /** - * The load factor for the hash table. - * - * @serial - */ - final float loadFactor; - - /** - * The number of times this LongKeyMap has been structurally modified - */ - transient volatile int modCount; - - /** - * Constructs an empty LongKeyMap with the specified initial - * capacity and load factor. - * - * @param initialCapacity The initial capacity. - * @param loadFactor The load factor. - * @throws IllegalArgumentException if the initial capacity is negative - * or the load factor is nonpositive. - */ - public LongKeyMap(int initialCapacity, float loadFactor) { - if (initialCapacity < 0) - throw new IllegalArgumentException("Illegal initial capacity: " + - initialCapacity); - if (initialCapacity > MAXIMUM_CAPACITY) - initialCapacity = MAXIMUM_CAPACITY; - if (loadFactor <= 0 || Float.isNaN(loadFactor)) - throw new IllegalArgumentException("Illegal load factor: " + - loadFactor); - - // Find a power of 2 >= initialCapacity - int capacity = 1; - while (capacity < initialCapacity) - capacity <<= 1; - - this.loadFactor = loadFactor; - threshold = (int)(capacity * loadFactor); - table = new LongEntry[capacity]; - } - - /** - * Constructs an empty LongKeyMap with the specified initial - * capacity and the default load factor (0.75). - * - * @param initialCapacity the initial capacity. - * @throws IllegalArgumentException if the initial capacity is negative. - */ - public LongKeyMap(int initialCapacity) { - this(initialCapacity, DEFAULT_LOAD_FACTOR); - } - - /** - * Constructs an empty LongKeyMap with the default initial capacity - * (16) and the default load factor (0.75). - */ - public LongKeyMap() { - this.loadFactor = DEFAULT_LOAD_FACTOR; - threshold = DEFAULT_INITIAL_CAPACITY; - table = new LongEntry[DEFAULT_INITIAL_CAPACITY]; - } - - static int hash(long x) { - int h = (int)(x ^ (x >>> 32)); - h += ~(h << 9); - h ^= (h >>> 14); - h += (h << 4); - h ^= (h >>> 10); - return h; - } - - /** - * Returns index for hash code h. - */ - static int indexFor(int h, int length) { - return h & (length-1); - } - - /** - * Returns the number of key-value mappings in this map. - * - * @return the number of key-value mappings in this map. - */ - @Override - public int size() { - return size; - } - - /** - * Returns true if this map contains no key-value mappings. - * - * @return true if this map contains no key-value mappings. - */ - @Override - public boolean isEmpty() - { - return size == 0; - } - - @Override - public boolean containsKey(Object key) - { - return containsKey(((Number)key).longValue()); - } - - /** - * Returns the value to which the specified key is mapped in this identity - * hash map, or null if the map contains no mapping for this key. - * A return value of null does not necessarily indicate - * that the map contains no mapping for the key; it is also possible that - * the map explicitly maps the key to null. The - * containsKey method may be used to distinguish these two cases. - * - * @param key the key whose associated value is to be returned. - * @return the value to which this map maps the specified key, or - * null if the map contains no mapping for this key. - * @see #put(long, Object) - */ - public VALUE get(long key) { - int hash = hash(key); - int i = indexFor(hash, table.length); - LongEntry e = table[i]; - while (true) { - if (e == null) - return null; - if (e.hash == hash && key == e.key) - return e.value; - e = e.next; - } - } - - /** - * Returns true if this map contains a mapping for the - * specified key. - */ - public boolean containsKey(long key) - { - int hash = hash(key); - int i = indexFor(hash, table.length); - LongEntry e = table[i]; - while (e != null) { - if (e.hash == hash && key == e.key) - return true; - e = e.next; - } - return false; - } - - /** - * Returns the entry associated with the specified key in the - * LongKeyMap. Returns null if the LongKeyMap contains no mapping - * for this key. - */ - LongEntry getEntry(long key) { - int hash = hash(key); - int i = indexFor(hash, table.length); - LongEntry e = table[i]; - while (e != null && !(e.hash == hash && key == e.key)) - e = e.next; - return e; - } - - /** - * Associates the specified value with the specified key in this map. - * If the map previously contained a mapping for this key, the old - * value is replaced. - * - * @param key key with which the specified value is to be associated. - * @param value value to be associated with the specified key. - * @return previous value associated with specified key, or null - * if there was no mapping for key. A null return can - * also indicate that the LongKeyMap previously associated - * null with the specified key. - */ - public VALUE put(long key, VALUE value) { - int hash = hash(key); - int i = indexFor(hash, table.length); - - for (LongEntry e = table[i]; e != null; e = e.next) { - if (e.hash == hash && key == e.key) { - VALUE oldValue = e.value; - e.value = value; - return oldValue; - } - } - - modCount++; - addEntry(hash, key, value, i); - return null; - } - - /** - * This method is used instead of put by constructors and - * pseudoconstructors (clone, readObject). It does not resize the table, - * check for comodification, etc. It calls createEntry rather than - * addEntry. - */ - private void putForCreate(long key, VALUE value) { - int hash = hash(key); - int i = indexFor(hash, table.length); - - /** - * Look for preexisting entry for key. This will never happen for - * clone or deserialize. It will only happen for construction if the - * input Map is a sorted map whose ordering is inconsistent w/ equals. - */ - for (LongEntry e = table[i]; e != null; e = e.next) { - if (e.hash == hash && key == e.key) { - e.value = value; - return; - } - } - - createEntry(hash, key, value, i); - } - - void putAllForCreate(LongKeyMap m) { - for (Iterator> i = m.entrySet().iterator(); i.hasNext(); ) { - LongEntry e = i.next(); - putForCreate(e.key, e.value); - } - } - - /** - * Rehashes the contents of this map into a new LongKeyMap instance - * with a larger capacity. This method is called automatically when the - * number of keys in this map exceeds its capacity and load factor. - * - * @param newCapacity the new capacity, MUST be a power of two. - */ - void resize(int newCapacity) { - // assert (newCapacity & -newCapacity) == newCapacity; // power of 2 - LongEntry[] oldTable = table; - int oldCapacity = oldTable.length; - - // check if needed - if (size < threshold || oldCapacity > newCapacity) - return; - - LongEntry[] newTable = new LongEntry[newCapacity]; - transfer(newTable); - table = newTable; - threshold = (int)(newCapacity * loadFactor); - } - - /** - * Transfer all entries from current table to newTable. - */ - void transfer(LongEntry[] newTable) { - LongEntry[] src = table; - int newCapacity = newTable.length; - for (int j = 0; j < src.length; j++) { - LongEntry e = src[j]; - if (e != null) { - src[j] = null; - do { - LongEntry next = e.next; - int i = indexFor(e.hash, newCapacity); - e.next = newTable[i]; - newTable[i] = e; - e = next; - } while (e != null); - } - } - } - - /** - * Copies all of the mappings from the specified map to this map - * These mappings will replace any mappings that - * this map had for any of the keys currently in the specified map. - * - * @param t mappings to be stored in this map. - * @throws NullPointerException if the specified map is null. - */ - public void putAll(LongKeyMap t) { - // Expand enough to hold t's elements without resizing. - int n = t.size(); - if (n == 0) - return; - if (n >= threshold) { - n = (int)(n / loadFactor + 1); - if (n > MAXIMUM_CAPACITY) - n = MAXIMUM_CAPACITY; - int capacity = table.length; - while (capacity < n) - capacity <<= 1; - resize(capacity); - } - - for (Iterator> i = t.entrySet().iterator(); i.hasNext(); ) { - LongEntry e = i.next(); - put(e.key, e.value); - } - } - - /** - * Removes the mapping for this key from this map if present. - * - * @param key key whose mapping is to be removed from the map. - * @return previous value associated with specified key, or null - * if there was no mapping for key. A null return can - * also indicate that the map previously associated null - * with the specified key. - */ - public VALUE remove(long key) { - LongEntry e = removeEntryForKey(key); - return (e == null ? null : e.value); - } - - /** - * Removes and returns the entry associated with the specified key - * in the LongKeyMap. Returns null if the LongKeyMap contains no mapping - * for this key. - */ - LongEntry removeEntryForKey(long key) { - int hash = hash(key); - int i = indexFor(hash, table.length); - LongEntry prev = table[i]; - LongEntry e = prev; - - while (e != null) { - LongEntry next = e.next; - if (e.hash == hash && key == e.key) { - modCount++; - size--; - if (prev == e) - table[i] = next; - else - prev.next = next; - return e; - } - prev = e; - e = next; - } - - return e; - } - - /** - * Special version of remove for EntrySet. - */ - LongEntry removeMapping(Object o) { - if (!(o instanceof LongEntry)) - return null; - - LongEntry entry = (LongEntry)o; - int hash = hash(entry.key); - int i = indexFor(hash, table.length); - LongEntry prev = table[i]; - LongEntry e = prev; - - while (e != null) { - LongEntry next = e.next; - if (e.hash == hash && e.equals(entry)) { - modCount++; - size--; - if (prev == e) - table[i] = next; - else - prev.next = next; - return e; - } - prev = e; - e = next; - } - - return e; - } - - /** - * Removes all mappings from this map. - */ - @Override - public void clear() { - modCount++; - LongEntry tab[] = table; - for (int i = 0; i < tab.length; i++) - tab[i] = null; - size = 0; - } - - /** - * Returns true if this map maps one or more keys to the - * specified value. - * - * @param value value whose presence in this map is to be tested. - * @return true if this map maps one or more keys to the - * specified value. - */ - @Override - public boolean containsValue(Object value) - { - if (value == null) - return containsNullValue(); - - LongEntry tab[] = table; - for (int i = 0; i < tab.length ; i++) - for (LongEntry e = tab[i] ; e != null ; e = e.next) - if (value.equals(e.value)) - return true; - return false; - } - - @Override - public VALUE get(Object key) - { - return get(((Number)key).longValue()); - } - - @Override - public VALUE put(Long key, VALUE value) - { - return put(key.longValue(), value); - } - - @Override - public VALUE remove(Object key) - { - return remove(((Number)key).longValue()); - } - - @Override - public void putAll(Map t) - { - throw new UnsupportedOperationException(); - } - - /** - * Special-case code for containsValue with null argument - **/ - private boolean containsNullValue() - { - LongEntry tab[] = table; - for (int i = 0; i < tab.length ; i++) - for (LongEntry e = tab[i] ; e != null ; e = e.next) - if (e.value == null) - return true; - return false; - } - - public static class LongEntry implements Entry { - final long key; - VALUE value; - final int hash; - LongEntry next; - - /** - * Create new entry. - */ - LongEntry(int h, long k, VALUE v, LongEntry n) { - value = v; - next = n; - key = k; - hash = h; - } - - public long getLong() { - return key; - } - - @Override - public Long getKey() - { - return key; - } - - @Override - public VALUE getValue() { - return value; - } - - @Override - public VALUE setValue(VALUE newValue) { - VALUE oldValue = value; - value = newValue; - return oldValue; - } - - public boolean equals(Object o) { - if (!(o instanceof LongEntry)) - return false; - LongEntry e = (LongEntry)o; - if (key == e.key) { - VALUE v1 = getValue(); - VALUE v2 = e.getValue(); - if (v1 == v2 || (v1 != null && v1.equals(v2))) - return true; - } - return false; - } - - public int hashCode() { - return hash(key) ^ (value==null ? 0 : value.hashCode()); - } - - public String toString() { - return String.valueOf(key) + "=" + getValue(); - } - - } - - /** - * Add a new entry with the specified key, value and hash code to - * the specified bucket. It is the responsibility of this - * method to resize the table if appropriate. - * - * Subclass overrides this to alter the behavior of put method. - */ - void addEntry(int hash, long key, VALUE value, int bucketIndex) { - table[bucketIndex] = new LongEntry<>(hash, key, value, table[bucketIndex]); - if (size++ >= threshold) - resize(2 * table.length); - } - - /** - * Like addEntry except that this version is used when creating entries - * as part of Map construction or "pseudo-construction" (cloning, - * deserialization). This version needn't worry about resizing the table. - * - * Subclass overrides this to alter the behavior of LongKeyMap(Map), - * clone, and readObject. - */ - void createEntry(int hash, long key, VALUE value, int bucketIndex) { - table[bucketIndex] = new LongEntry<>(hash, key, value, table[bucketIndex]); - size++; - } - - private abstract class HashIterator implements Iterator { - LongEntry next; // next entry to return - int expectedModCount; // For fast-fail - int index; // current slot - LongEntry current; // current entry - - HashIterator() { - expectedModCount = modCount; - LongEntry[] t = table; - int i = t.length; - LongEntry n = null; - if (size != 0) { // advance to first entry - while (i > 0 && (n = t[--i]) == null) - ; - } - next = n; - index = i; - } - - @Override - public boolean hasNext() { - return next != null; - } - - LongEntry nextEntry() { - if (modCount != expectedModCount) - throw new ConcurrentModificationException(); - LongEntry e = next; - if (e == null) - throw new NoSuchElementException(); - - LongEntry n = e.next; - LongEntry[] t = table; - int i = index; - while (n == null && i > 0) - n = t[--i]; - index = i; - next = n; - return current = e; - } - - @Override - public void remove() { - if (current == null) - throw new IllegalStateException(); - if (modCount != expectedModCount) - throw new ConcurrentModificationException(); - long k = current.key; - current = null; - LongKeyMap.this.removeEntryForKey(k); - expectedModCount = modCount; - } - - } - - private class ValueIterator extends HashIterator { - @Override - public VALUE next() { - return nextEntry().value; - } - } - - private class KeyIterator extends HashIterator { - @Override - public Long next() { - return nextEntry().key; - } - public long nextLong() { - return nextEntry().key; - } - } - - private class EntryIterator extends HashIterator> { - @Override - public LongEntry next() { - return nextEntry(); - } - } - - // Subclass overrides these to alter behavior of views' iterator() method - Iterator newKeyIterator() - { - return new KeyIterator(); - } - Iterator newValueIterator() - { - return new ValueIterator(); - } - Iterator> newEntryIterator() - { - return new EntryIterator(); - } - - - // Views - - private transient Set> entrySet = null; - transient volatile Set keySet = null; - transient volatile Collection values = null; - - /** - * Returns a set view of the keys contained in this map. The set is - * backed by the map, so changes to the map are reflected in the set, and - * vice-versa. The set supports element removal, which removes the - * corresponding mapping from this map, via the Iterator.remove, - * Set.remove, removeAll, retainAll, and - * clear operations. It does not support the add or - * addAll operations. - * - * @return a set view of the keys contained in this map. - */ - @Override - public Set keySet() { - Set ks = keySet; - return (ks != null ? ks : (keySet = new KeySet())); - } - - private class KeySet extends AbstractSet { - @Override - public Iterator iterator() { - return newKeyIterator(); - } - @Override - public int size() { - return size; - } - @Override - public boolean contains(Object o) { - if (o instanceof Number) { - return containsKey(((Number)o).longValue()); - } else { - return false; - } - } - @Override - public boolean remove(Object o) { - if (o instanceof Number) { - return LongKeyMap.this.removeEntryForKey(((Number)o).longValue()) != null; - } else { - return false; - } - } - @Override - public void clear() { - LongKeyMap.this.clear(); - } - } - - /** - * Returns a collection view of the values contained in this map. The - * collection is backed by the map, so changes to the map are reflected in - * the collection, and vice-versa. The collection supports element - * removal, which removes the corresponding mapping from this map, via the - * Iterator.remove, Collection.remove, - * removeAll, retainAll, and clear operations. - * It does not support the add or addAll operations. - * - * @return a collection view of the values contained in this map. - */ - @Override - public Collection values() { - Collection vs = values; - return (vs != null ? vs : (values = new Values())); - } - - private class Values extends AbstractCollection { - @Override - public Iterator iterator() { - return newValueIterator(); - } - @Override - public int size() { - return size; - } - @Override - public boolean contains(Object o) { - return containsValue(o); - } - @Override - public void clear() { - LongKeyMap.this.clear(); - } - } - - @Override - public Set entrySet() - { - Set> es = entrySet; - return (es != null ? es : (entrySet = new EntrySet())); - } - - private class EntrySet extends AbstractSet> { - @Override - public Iterator> iterator() { - return newEntryIterator(); - } - @Override - public boolean contains(Object o) { - if (!(o instanceof LongEntry)) - return false; - LongEntry e = (LongEntry)o; - LongEntry candidate = getEntry(e.key); - return candidate != null && candidate.equals(e); - } - @Override - public boolean remove(Object o) { - return removeMapping(o) != null; - } - @Override - public int size() { - return size; - } - @Override - public void clear() { - LongKeyMap.this.clear(); - } - } - - // These methods are used when serializing HashSets - int capacity() { return table.length; } - float loadFactor() { return loadFactor; } -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/MimeType.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/MimeType.java deleted file mode 100644 index 8732a66eafd0d..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/MimeType.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jkiss.utils; - -import java.util.Locale; - -/** - * MIME type parser - */ -public class MimeType { - - private String primaryType; - private String subType; - - public MimeType() { - primaryType = "application"; - subType = "*"; - } - - public MimeType(String rawdata) throws IllegalArgumentException { - parse(rawdata); - } - - public MimeType(String primary, String sub) { - primaryType = primary.toLowerCase(Locale.ENGLISH); - subType = sub.toLowerCase(Locale.ENGLISH); - } - - private void parse(String rawdata) throws IllegalArgumentException { - int slashIndex = rawdata.indexOf('/'); - int semIndex = rawdata.indexOf(';'); - if ((slashIndex < 0) && (semIndex < 0)) { - primaryType = rawdata; - subType = "*"; - } else if ((slashIndex < 0) && (semIndex >= 0)) { - primaryType = rawdata.substring(0, semIndex); - subType = "*"; - } else if ((slashIndex >= 0) && (semIndex < 0)) { - primaryType = rawdata.substring(0, slashIndex).trim().toLowerCase(Locale.ENGLISH); - subType = rawdata.substring(slashIndex + 1).trim().toLowerCase(Locale.ENGLISH); - } else if (slashIndex < semIndex) { - primaryType = rawdata.substring(0, slashIndex).trim().toLowerCase(Locale.ENGLISH); - subType = rawdata.substring(slashIndex + 1, semIndex).trim().toLowerCase(Locale.ENGLISH); - } else { - // we have a ';' lexically before a '/' which means we - // have a primary type and a parameter list but no sub type - throw new IllegalArgumentException("Unable to find a sub type."); - } - } - - public String getPrimaryType() { - return primaryType; - } - - public String getSubType() { - return subType; - } - - public String toString() { - return getBaseType(); - } - - public String getBaseType() { - return primaryType + "/" + subType; - } - - public boolean match(MimeType type) { - return primaryType.equals(type.getPrimaryType()) && - (subType.equals("*") || type.getSubType().equals("*") || (subType.equals(type.getSubType()))); - } - - public boolean match(String rawdata) throws IllegalArgumentException { - return match(new MimeType(rawdata)); - } - -} \ No newline at end of file diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/Pair.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/Pair.java deleted file mode 100644 index 44435f0687846..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/Pair.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jkiss.utils; - -import java.util.Objects; - -/** - * Pair - */ -public class Pair { - private T1 first; - private T2 second; - - public Pair(T1 first, T2 second) - { - this.first = first; - this.second = second; - } - - public T1 getFirst() - { - return first; - } - - public void setFirst(T1 first) { - this.first = first; - } - - public T2 getSecond() - { - return second; - } - - public void setSecond(T2 second) { - this.second = second; - } - - @Override - public String toString() { - return first + "=" + second; - } - - /** - * Checks the two objects for equality by delegating to their respective - * {@link Object#equals(Object)} methods. - * - * @param o the {@link Pair} to which this one is to be checked for equality - * @return true if the underlying objects of the Pair are both considered - * equal - */ - @Override - public boolean equals(Object o) { - if (!(o instanceof Pair)) { - return false; - } - Pair p = (Pair) o; - return Objects.deepEquals(p.first, first) && Objects.deepEquals(p.second, second); - } - - /** - * Compute a hash code using the hash codes of the underlying objects - * @return a hashcode of the Pair - */ - @Override - public int hashCode() { - return (first == null ? 0 : first.hashCode()) ^ (second == null ? 0 : second.hashCode()); - } - - public static Pair of(T1 t1, T2 t2) { - return new Pair<>(t1, t2); - } - -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/ReaderWriterLock.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/ReaderWriterLock.java deleted file mode 100644 index 5209d637cab1c..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/ReaderWriterLock.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jkiss.utils; - -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantReadWriteLock; -import java.util.function.Supplier; - -public class ReaderWriterLock { - - private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(); - private final Supplier mutatorSupplier; - - public ReaderWriterLock(Supplier mutatorSupplier) { - this.mutatorSupplier = mutatorSupplier; - } - - /** - * Represents an operation that accepts a single input argument and returns no result possibly throwing an exception. - */ - public interface ExceptableConsumer { - /** - * Performs the operation on the given argument. - */ - void accept(T t) throws EXCEPTION; - } - - /** - * Represents an operation that accepts a single input argument and produces a result possibly throwing an exception. - */ - public interface ExceptableFunction { - /** - * Performs the operation on the given argument and returns the result. - */ - RESULT apply(T t) throws EXCEPTION; - } - - /** - * Acquires the reader or writer lock, executes given operation and releases the lock returning the operation result. - */ - public RESULT compute( - boolean writing, - ExceptableFunction action - ) throws EXCEPTION { - Lock lock = writing ? rwLock.writeLock() : rwLock.readLock(); - lock.lock(); - try { - return action.apply(mutatorSupplier.get()); - } finally { - lock.unlock(); - } - } - - /** - * Acquires the reader lock, executes given operation and releases the lock returning the operation result. - */ - public RESULT computeReading( - ExceptableFunction action - ) throws EXCEPTION { - return this.compute(false, action); - } - - /** - * Acquires the writer lock, executes given operation and releases the lock returning the operation result. - */ - public RESULT computeWriting( - ExceptableFunction action - ) throws EXCEPTION { - return this.compute(true, action); - } - - /** - * Acquires the reader or writer lock, executes given operation and releases the lock. - */ - public void exec( - boolean writing, - ExceptableConsumer action - ) throws EXCEPTION { - this.compute(writing, m -> { - action.accept(m); - return null; - }); - } - - /** - * Acquires the reader lock, executes given operation and releases the lock. - */ - public void execReading(ExceptableConsumer action) throws EXCEPTION { - this.exec(false, action); - } - - /** - * Acquires the writer lock, executes given operation and releases the lock. - */ - public void execWriting(ExceptableConsumer action) throws EXCEPTION { - this.exec(true, action); - } -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/SecurityUtils.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/SecurityUtils.java deleted file mode 100644 index c33a5ab9b83d1..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/SecurityUtils.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jkiss.utils; - -import java.nio.charset.StandardCharsets; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.util.Random; - -/** - * Come security-related functions. - */ -public class SecurityUtils { - - public static String ECRYPTION_ALGORYTHM = "MD5"; - - private static java.util.Random random; - private static java.util.Random secureRand; - - static { - secureRand = new java.util.Random(System.currentTimeMillis()); - long secureInitializer = secureRand.nextLong(); - random = new java.util.Random(secureInitializer); - } - - /** - * Generate the random GUID - */ - public static String generateGUID(boolean secure) { - String localHostAddr; - { - java.net.InetAddress id; - try { - id = java.net.InetAddress.getLocalHost(); - localHostAddr = id.toString(); - } catch (java.net.UnknownHostException e) { - localHostAddr = "localhost"; - } - } - - long time = System.currentTimeMillis(); - long rand; - - if (secure) { - rand = secureRand.nextLong(); - } else { - rand = SecurityUtils.random.nextLong(); - } - - // This StringBuilder can be a long as you need; the MD5 - // hash will always return 128 bits. You can change - // the seed to include anything you want here. - // You could even stream a file through the MD5 making - // the odds of guessing it at least as great as that - // of guessing the contents of the file! - StringBuilder sb = new StringBuilder(32); - sb.append(localHostAddr) - .append(":") - .append(Long.toString(time)) - .append(":") - .append(Long.toString(rand)); - - - byte[] array; - try { - MessageDigest md5 = MessageDigest.getInstance(ECRYPTION_ALGORYTHM); - md5.update(sb.toString().getBytes(StandardCharsets.UTF_8)); - array = md5.digest(); - } catch (NoSuchAlgorithmException e) { - // Too bad. Lets get simple random numbers - array = new byte[16]; - random.nextBytes(array); - } - sb.setLength(0); - for (int j = 0; j < array.length; ++j) { - int b = array[j] & 0xFF; - if (b < 0x10) { - sb.append('0'); - } - sb.append(Integer.toHexString(b)); - } - - String raw = sb.toString().toUpperCase(); - sb.setLength(0); - sb.append(raw.substring(0, 8)); - sb.append("-"); - sb.append(raw.substring(8, 12)); - sb.append("-"); - sb.append(raw.substring(12, 16)); - sb.append("-"); - sb.append(raw.substring(16, 20)); - sb.append("-"); - sb.append(raw.substring(20)); - - return sb.toString(); - } - - public static String generateUniqueId() { - long curTime = System.currentTimeMillis(); - int random = secureRand.nextInt(); - if (random < 0) { - random = -random; - } - - return - Long.toString(curTime, Character.MAX_RADIX) + - Integer.toString(random, Character.MAX_RADIX); - } - - public static String makeDigest( - String userAlias, - String userPassword) { - try { - if (userPassword == null) { - userPassword = ""; - } - MessageDigest md5 = - MessageDigest.getInstance(ECRYPTION_ALGORYTHM); - md5.update(userAlias.getBytes(StandardCharsets.UTF_8)); - - return CommonUtils.toHexString(md5.digest(userPassword.getBytes(StandardCharsets.UTF_8))); - } catch (NoSuchAlgorithmException toCatch) { - return "*"; - } - } - - public static String makeDigest( - String userPassword) { - try { - MessageDigest md5 = - MessageDigest.getInstance(ECRYPTION_ALGORYTHM); - - return CommonUtils.toHexString(md5.digest(userPassword.getBytes(StandardCharsets.UTF_8))); - } catch (NoSuchAlgorithmException toCatch) { - return "*"; - } - } - - /** - * Generate a random password of the given length. - */ - public static String generatePassword(int length) { - SecureRandom random = new SecureRandom(); - StringBuilder pass = new StringBuilder(length); - for (int i = 0; i < length; i++) { - pass.append( - PASSWORD_ALPHABET[random.nextInt(PASSWORD_ALPHABET.length)] - ); - } - return (pass.toString()); - } - - public static long generateRandomLong() { - SecureRandom random = new SecureRandom(); - return random.nextLong(); - } - - public static byte[] generateRandomBytes(int length) { - SecureRandom random = new SecureRandom(); - byte[] bytes = new byte[length]; - random.nextBytes(bytes); - return bytes; - } - - /** - * Generate a random password of the default length (8). - */ - public static String generatePassword() { - return generatePassword(DEFAULT_PASSWORD_LENGTH); - } - - public static Random getRandom() { - return random; - } - - /** - * Default length for passwords - */ - public static final int DEFAULT_PASSWORD_LENGTH = 8; - - /** - * Alphabet consisting of upper and lowercase letters A-Z and - * the digits 0-9. - */ - public static final char[] PASSWORD_ALPHABET = { - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', - 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', - 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', - 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', - 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', - 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', - 'w', 'x', 'y', 'z', '0', '1', '2', '3', - '4', '5', '6', '7', '8', '9', - }; - -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/StandardConstants.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/StandardConstants.java deleted file mode 100644 index 58a017d674dbf..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/StandardConstants.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jkiss.utils; - -/** - * Standard Java constants - */ -public abstract class StandardConstants { - - public static final String ENV_LINE_SEPARATOR = "line.separator"; - public static final String ENV_PATH_SEPARATOR = "path.separator"; - - public static final String ENV_TMP_DIR = "java.io.tmpdir"; - public static final String ENV_FILE_ENCODING = "file.encoding"; - public static final String ENV_CONSOLE_ENCODING = "console.encoding"; - - public static final String ENV_USER_HOME = "user.home"; - public static final String ENV_USER_NAME = "user.name"; - public static final String ENV_USER_TIMEZONE = "user.timezone"; - public static final String ENV_OS_NAME = "os.name"; - public static final String ENV_OS_VERSION = "os.version"; - public static final String ENV_OS_ARCH = "os.arch"; - - public static final String ENV_JAVA_VERSION = "java.version"; - public static final String ENV_JAVA_VENDOR = "java.vendor"; - public static final String ENV_JAVA_ARCH = "sun.arch.data.model"; - public static final String ENV_JAVA_CLASSPATH = "java.class.path"; - - public static final int MIN_PORT_VALUE = 0; - public static final int MAX_PORT_VALUE = 65535; -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/csv/CSVParser.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/csv/CSVParser.java deleted file mode 100644 index 55d8f2ea2f4db..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/csv/CSVParser.java +++ /dev/null @@ -1,562 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * This package contains a slightly modified version of opencsv library - * without unwanted functionality and dependencies, licensed under Apache 2.0. - * - * See https://search.maven.org/artifact/com.opencsv/opencsv/3.4/bundle - * See http://opencsv.sf.net/ - */ -package org.jkiss.utils.csv; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -/** - * A very simple CSV parser released under a commercial-friendly license. - * This just implements splitting a single line into fields. - * - * @author Glen Smith - * @author Rainer Pruy - */ - -public class CSVParser { - - /** - * The default separator to use if none is supplied to the constructor. - */ - public static final char DEFAULT_SEPARATOR = ','; - /** - * The average size of a line read by openCSV (used for setting the size of StringBuilders). - */ - public static final int INITIAL_READ_SIZE = 128; - /** - * The default quote character to use if none is supplied to the - * constructor. - */ - public static final char DEFAULT_QUOTE_CHARACTER = '"'; - /** - * The default escape character to use if none is supplied to the - * constructor. - */ - public static final char DEFAULT_ESCAPE_CHARACTER = '\\'; - /** - * The default strict quote behavior to use if none is supplied to the - * constructor. - */ - public static final boolean DEFAULT_STRICT_QUOTES = false; - /** - * The default leading whitespace behavior to use if none is supplied to the - * constructor. - */ - public static final boolean DEFAULT_IGNORE_LEADING_WHITESPACE = true; - /** - * If the quote character is set to null then there is no quote character. - */ - public static final boolean DEFAULT_IGNORE_QUOTATIONS = false; - /** - * This is the "null" character - if a value is set to this then it is ignored. - */ - public static final char NULL_CHARACTER = '\0'; - /** - * Denotes what field contents will cause the parser to return null: EMPTY_SEPARATORS, EMPTY_QUOTES, BOTH, NEITHER (default) - */ - public static final CSVReaderNullFieldIndicator DEFAULT_NULL_FIELD_INDICATOR = CSVReaderNullFieldIndicator.NEITHER; - - /** - * This is the character that the CSVParser will treat as the separator. - */ - private final char separator; - /** - * This is the character that the CSVParser will treat as the quotation character. - */ - private final char quotechar; - /** - * This is the character that the CSVParser will treat as the escape character. - */ - private final char escape; - /** - * Determines if the field is between quotes (true) or between separators (false). - */ - private final boolean strictQuotes; - /** - * Ignore any leading white space at the start of the field. - */ - private final boolean ignoreLeadingWhiteSpace; - /** - * Skip over quotation characters when parsing. - */ - private final boolean ignoreQuotations; - private final CSVReaderNullFieldIndicator nullFieldIndicator; - private String pending; - private boolean inField = false; - - /** - * Constructs CSVParser using a comma for the separator. - */ - public CSVParser() { - this(DEFAULT_SEPARATOR, DEFAULT_QUOTE_CHARACTER, DEFAULT_ESCAPE_CHARACTER); - } - - /** - * Constructs CSVParser with supplied separator. - * - * @param separator the delimiter to use for separating entries. - */ - public CSVParser(char separator) { - this(separator, DEFAULT_QUOTE_CHARACTER, DEFAULT_ESCAPE_CHARACTER); - } - - - /** - * Constructs CSVParser with supplied separator and quote char. - * - * @param separator the delimiter to use for separating entries - * @param quotechar the character to use for quoted elements - */ - public CSVParser(char separator, char quotechar) { - this(separator, quotechar, DEFAULT_ESCAPE_CHARACTER); - } - - /** - * Constructs CSVReader with supplied separator and quote char. - * - * @param separator the delimiter to use for separating entries - * @param quotechar the character to use for quoted elements - * @param escape the character to use for escaping a separator or quote - */ - public CSVParser(char separator, char quotechar, char escape) { - this(separator, quotechar, escape, DEFAULT_STRICT_QUOTES); - } - - /** - * Constructs CSVParser with supplied separator and quote char. - * Allows setting the "strict quotes" flag - * - * @param separator the delimiter to use for separating entries - * @param quotechar the character to use for quoted elements - * @param escape the character to use for escaping a separator or quote - * @param strictQuotes if true, characters outside the quotes are ignored - */ - public CSVParser(char separator, char quotechar, char escape, boolean strictQuotes) { - this(separator, quotechar, escape, strictQuotes, DEFAULT_IGNORE_LEADING_WHITESPACE); - } - - /** - * Constructs CSVParser with supplied separator and quote char. - * Allows setting the "strict quotes" and "ignore leading whitespace" flags - * - * @param separator the delimiter to use for separating entries - * @param quotechar the character to use for quoted elements - * @param escape the character to use for escaping a separator or quote - * @param strictQuotes if true, characters outside the quotes are ignored - * @param ignoreLeadingWhiteSpace if true, white space in front of a quote in a field is ignored - */ - public CSVParser(char separator, char quotechar, char escape, boolean strictQuotes, boolean ignoreLeadingWhiteSpace) { - this(separator, quotechar, escape, strictQuotes, ignoreLeadingWhiteSpace, DEFAULT_IGNORE_QUOTATIONS); - } - - /** - * Constructs CSVParser with supplied separator and quote char. - * Allows setting the "strict quotes" and "ignore leading whitespace" flags - * - * @param separator the delimiter to use for separating entries - * @param quotechar the character to use for quoted elements - * @param escape the character to use for escaping a separator or quote - * @param strictQuotes if true, characters outside the quotes are ignored - * @param ignoreLeadingWhiteSpace if true, white space in front of a quote in a field is ignored - * @param ignoreQuotations if true, treat quotations like any other character. - */ - public CSVParser(char separator, char quotechar, char escape, boolean strictQuotes, boolean ignoreLeadingWhiteSpace, - boolean ignoreQuotations) { - this(separator, quotechar, escape, strictQuotes, ignoreLeadingWhiteSpace, ignoreQuotations, DEFAULT_NULL_FIELD_INDICATOR); - } - - /** - * Constructs CSVParser with supplied separator and quote char. - * Allows setting the "strict quotes" and "ignore leading whitespace" flags - * - * @param separator the delimiter to use for separating entries - * @param quotechar the character to use for quoted elements - * @param escape the character to use for escaping a separator or quote - * @param strictQuotes if true, characters outside the quotes are ignored - * @param ignoreLeadingWhiteSpace if true, white space in front of a quote in a field is ignored - * @param ignoreQuotations if true, treat quotations like any other character. - * @param nullFieldIndicator which field content will be returned as null: EMPTY_SEPARATORS, EMPTY_QUOTES, - * BOTH, NEITHER (default) - */ - CSVParser(char separator, char quotechar, char escape, boolean strictQuotes, boolean ignoreLeadingWhiteSpace, - boolean ignoreQuotations, CSVReaderNullFieldIndicator nullFieldIndicator) { - if (anyCharactersAreTheSame(separator, quotechar, escape)) { - throw new UnsupportedOperationException("The separator, quote, and escape characters must be different!"); - } - if (separator == NULL_CHARACTER) { - throw new UnsupportedOperationException("The separator character must be defined!"); - } - this.separator = separator; - this.quotechar = quotechar; - this.escape = escape; - this.strictQuotes = strictQuotes; - this.ignoreLeadingWhiteSpace = ignoreLeadingWhiteSpace; - this.ignoreQuotations = ignoreQuotations; - this.nullFieldIndicator = nullFieldIndicator; - } - - - /** - * @return The default separator for this parser. - */ - public char getSeparator() { - return separator; - } - - /** - * @return The default quotation character for this parser. - */ - public char getQuotechar() { - return quotechar; - } - - /** - * @return The default escape character for this parser. - */ - public char getEscape() { - return escape; - } - - /** - * @return The default strictQuotes setting for this parser. - */ - public boolean isStrictQuotes() { - return strictQuotes; - } - - /** - * @return The default ignoreLeadingWhiteSpace setting for this parser. - */ - public boolean isIgnoreLeadingWhiteSpace() { - return ignoreLeadingWhiteSpace; - } - - /** - * @return the default ignoreQuotation setting for this parser. - */ - public boolean isIgnoreQuotations() { - return ignoreQuotations; - } - - /** - * checks to see if any two of the three characters are the same. This is because in openCSV the - * separator, quote, and escape characters must the different. - * - * @param separator the defined separator character - * @param quotechar the defined quotation cahracter - * @param escape the defined escape character - * @return true if any two of the three are the same. - */ - private boolean anyCharactersAreTheSame(char separator, char quotechar, char escape) { - return isSameCharacter(separator, quotechar) || isSameCharacter(separator, escape) || isSameCharacter(quotechar, escape); - } - - /** - * checks that the two characters are the same and are not the defined NULL_CHARACTER. - * - * @param c1 first character - * @param c2 second character - * @return true if both characters are the same and are not the defined NULL_CHARACTER - */ - private boolean isSameCharacter(char c1, char c2) { - return c1 != NULL_CHARACTER && c1 == c2; - } - - /** - * @return true if something was left over from last call(s) - */ - public boolean isPending() { - return pending != null; - } - - /** - * Parses an incoming String and returns an array of elements. This method is used when the - * data spans multiple lines. - * - * @param nextLine current line to be processed - * @return the comma-tokenized list of elements, or null if nextLine is null - * @throws IOException if bad things happen during the read - */ - public String[] parseLineMulti(String nextLine) throws IOException { - return parseLine(nextLine, true); - } - - /** - * Parses an incoming String and returns an array of elements. This method is used when all data is contained - * in a single line. - * - * @param nextLine Line to be parsed. - * @return the comma-tokenized list of elements, or null if nextLine is null - * @throws IOException if bad things happen during the read - */ - public String[] parseLine(String nextLine) throws IOException { - return parseLine(nextLine, false); - } - - /** - * Parses an incoming String and returns an array of elements. - * - * @param nextLine the string to parse - * @param multi Does it take multiple lines to form a single record. - * @return the comma-tokenized list of elements, or null if nextLine is null - * @throws IOException if bad things happen during the read - */ - private String[] parseLine(String nextLine, boolean multi) throws IOException { - - if (!multi && pending != null) { - pending = null; - } - - if (nextLine == null) { - if (pending != null) { - String s = pending; - pending = null; - return new String[]{s}; - } else { - return null; - } - } - - List tokensOnThisLine = new ArrayList<>(); - StringBuilder sb = new StringBuilder(INITIAL_READ_SIZE); - boolean inQuotes = false; - boolean fromQuotedField = false; - if (pending != null) { - sb.append(pending); - pending = null; - inQuotes = !this.ignoreQuotations;//true; - } - for (int i = 0; i < nextLine.length(); i++) { - - char c = nextLine.charAt(i); - if (c == this.escape) { - if (isNextCharacterEscapable(nextLine, inQuotes(inQuotes), i)) { - i = appendNextCharacterAndAdvanceLoop(nextLine, sb, i); - } - } else if (c == quotechar) { - if (isNextCharacterEscapedQuote(nextLine, inQuotes(inQuotes), i)) { - i = appendNextCharacterAndAdvanceLoop(nextLine, sb, i); - } else { - - inQuotes = !inQuotes; - if (atStartOfField(sb)) { - fromQuotedField = true; - } - - // the tricky case of an embedded quote in the middle: a,bc"d"ef,g - if (!strictQuotes) { - if (i > 2 //not on the beginning of the line - && nextLine.charAt(i - 1) != this.separator //not at the beginning of an escape sequence - && nextLine.length() > (i + 1) && - nextLine.charAt(i + 1) != this.separator //not at the end of an escape sequence - ) { - - if (ignoreLeadingWhiteSpace && sb.length() > 0 && isAllWhiteSpace(sb)) { - sb.setLength(0); - } else { - sb.append(c); - } - - } - } - } - inField = !inField; - } else if (c == separator && !(inQuotes && !ignoreQuotations)) { - tokensOnThisLine.add(convertEmptyToNullIfNeeded(sb.toString(), fromQuotedField)); - fromQuotedField = false; - sb.setLength(0); - inField = false; - } else { - if (!strictQuotes || (inQuotes && !ignoreQuotations)) { - sb.append(c); - inField = true; - fromQuotedField = true; - } - } - - } - // line is done - check status - if ((inQuotes && !ignoreQuotations)) { - if (multi) { - // continuing a quoted section, re-append newline - sb.append('\n'); - pending = sb.toString(); - sb = null; // this partial content is not to be added to field list yet - } else { - throw new IOException("Un-terminated quoted field at end of CSV line"); - } - if (inField) { - fromQuotedField = true; - } - } else { - inField = false; - } - - if (sb != null) { - tokensOnThisLine.add(convertEmptyToNullIfNeeded(sb.toString(), fromQuotedField)); - fromQuotedField = false; - } - return tokensOnThisLine.toArray(new String[tokensOnThisLine.size()]); - - } - - private boolean atStartOfField(StringBuilder sb) { - return sb.length() == 0; - } - - private String convertEmptyToNullIfNeeded(String s, boolean fromQuotedField) { - if (s.isEmpty() && shouldConvertEmptyToNull(fromQuotedField)) { - return null; - } - return s; - } - - private boolean shouldConvertEmptyToNull(boolean fromQuotedField) { - switch (nullFieldIndicator) { - case BOTH: - return true; - case EMPTY_SEPARATORS: - return !fromQuotedField; - case EMPTY_QUOTES: - return fromQuotedField; - default: - return false; - } - } - - /** - * Appends the next character in the line to the stringbuffer. - * - * @param line - line to process - * @param sb - contains the processed character - * @param i - current position in the line. - * @return new position in the line. - */ - private int appendNextCharacterAndAdvanceLoop(String line, StringBuilder sb, int i) { - sb.append(line.charAt(i + 1)); - i++; - return i; - } - - /** - * Determines if we can process as if we were in quotes. - * - * @param inQuotes - are we currently in quotes. - * @return - true if we should process as if we are inside quotes. - */ - private boolean inQuotes(boolean inQuotes) { - return (inQuotes && !ignoreQuotations) || inField; - } - - /** - * Checks to see if the character after the index is a quotation character. - *

- * precondition: the current character is a quote or an escape - * - * @param nextLine the current line - * @param inQuotes true if the current context is quoted - * @param i current index in line - * @return true if the following character is a quote - */ - private boolean isNextCharacterEscapedQuote(String nextLine, boolean inQuotes, int i) { - return inQuotes // we are in quotes, therefore there can be escaped quotes in here. - && nextLine.length() > (i + 1) // there is indeed another character to check. - && isCharacterQuoteCharacter(nextLine.charAt(i + 1)); - } - - /** - * Checks to see if the passed in character is the defined quotation character. - * - * @param c source character - * @return true if c is the defined quotation character - */ - private boolean isCharacterQuoteCharacter(char c) { - return c == quotechar; - } - - /** - * checks to see if the character is the defined escape character. - * - * @param c source character - * @return true if the character is the defined escape character - */ - private boolean isCharacterEscapeCharacter(char c) { - return c == escape; - } - - /** - * Checks to see if the character passed in could be escapable. Escapable characters for openCSV are the - * quotation character or the escape character. - * - * @param c source character - * @return true if the character could be escapable. - */ - private boolean isCharacterEscapable(char c) { - return isCharacterQuoteCharacter(c) || isCharacterEscapeCharacter(c); - } - - /** - * Checks to see if the character after the current index in a String is an escapable character. - * Meaning the next character is either a quotation character or the escape char and you are inside - * quotes. - *

- * precondition: the current character is an escape - * - * @param nextLine the current line - * @param inQuotes true if the current context is quoted - * @param i current index in line - * @return true if the following character is a quote - */ - protected boolean isNextCharacterEscapable(String nextLine, boolean inQuotes, int i) { - return inQuotes // we are in quotes, therefore there can be escaped quotes in here. - && nextLine.length() > (i + 1) // there is indeed another character to check. - && isCharacterEscapable(nextLine.charAt(i + 1)); - } - - /** - * Checks if every element is the character sequence is whitespace. - *

- * precondition: sb.length() is greater than 0 - * - * @param sb A sequence of characters to examine - * @return true if every character in the sequence is whitespace - */ - protected boolean isAllWhiteSpace(CharSequence sb) { - for (int i = 0; i < sb.length(); i++) { - if (Character.isWhitespace(sb.charAt(i))) { - return true; - } - } - return false; - } - - /** - * @return - the null field indicator. - */ - public CSVReaderNullFieldIndicator nullFieldIndicator() { - return nullFieldIndicator; - } -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/csv/CSVParserBuilder.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/csv/CSVParserBuilder.java deleted file mode 100644 index b60a0bfec257c..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/csv/CSVParserBuilder.java +++ /dev/null @@ -1,209 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * This package contains a slightly modified version of opencsv library - * without unwanted functionality and dependencies, licensed under Apache 2.0. - * - * See https://search.maven.org/artifact/com.opencsv/opencsv/3.4/bundle - * See http://opencsv.sf.net/ - */ -package org.jkiss.utils.csv; - - -/** - * Builder for creating a CSVParser. - * - * - * final CSVParser parser = - * new CSVParserBuilder() - * .withSeparator('\t') - * .withIgnoreQuotations(true) - * .build(); - * - * - * @see CSVParser - */ -public class CSVParserBuilder { - - private char separator = CSVParser.DEFAULT_SEPARATOR; - private char quoteChar = CSVParser.DEFAULT_QUOTE_CHARACTER; - private char escapeChar = CSVParser.DEFAULT_ESCAPE_CHARACTER; - private boolean strictQuotes = CSVParser.DEFAULT_STRICT_QUOTES; - private boolean ignoreLeadingWhiteSpace = CSVParser.DEFAULT_IGNORE_LEADING_WHITESPACE; - private boolean ignoreQuotations = CSVParser.DEFAULT_IGNORE_QUOTATIONS; - private CSVReaderNullFieldIndicator nullFieldIndicator = CSVReaderNullFieldIndicator.NEITHER; - - /** - * Default constructor. - */ - public CSVParserBuilder() { - } - - /** - * Sets the delimiter to use for separating entries. - * - * @param separator the delimiter to use for separating entries - * @return The CSVParserBuilder - */ - public CSVParserBuilder withSeparator( - final char separator) { - this.separator = separator; - return this; - } - - - /** - * Sets the character to use for quoted elements. - * - * @param quoteChar the character to use for quoted element. - * @return The CSVParserBuilder - */ - public CSVParserBuilder withQuoteChar( - final char quoteChar) { - this.quoteChar = quoteChar; - return this; - } - - - /** - * Sets the character to use for escaping a separator or quote. - * - * @param escapeChar the character to use for escaping a separator or quote. - * @return The CSVParserBuilder - */ - public CSVParserBuilder withEscapeChar( - final char escapeChar) { - this.escapeChar = escapeChar; - return this; - } - - - /** - * Sets the strict quotes setting - if true, characters - * outside the quotes are ignored. - * - * @param strictQuotes if true, characters outside the quotes are ignored - * @return The CSVParserBuilder - */ - public CSVParserBuilder withStrictQuotes( - final boolean strictQuotes) { - this.strictQuotes = strictQuotes; - return this; - } - - /** - * Sets the ignore leading whitespace setting - if true, white space - * in front of a quote in a field is ignored. - * - * @param ignoreLeadingWhiteSpace if true, white space in front of a quote in a field is ignored - * @return The CSVParserBuilder - */ - public CSVParserBuilder withIgnoreLeadingWhiteSpace( - final boolean ignoreLeadingWhiteSpace) { - this.ignoreLeadingWhiteSpace = ignoreLeadingWhiteSpace; - return this; - } - - /** - * Sets the ignore quotations mode - if true, quotations are ignored. - * - * @param ignoreQuotations if true, quotations are ignored - * @return The CSVParserBuilder - */ - public CSVParserBuilder withIgnoreQuotations( - final boolean ignoreQuotations) { - this.ignoreQuotations = ignoreQuotations; - return this; - } - - /** - * Constructs CSVParser. - * - * @return a new CSVParser with defined settings. - */ - public CSVParser build() { - return new CSVParser( - separator, - quoteChar, - escapeChar, - strictQuotes, - ignoreLeadingWhiteSpace, - ignoreQuotations, - nullFieldIndicator); - } - - /** - * @return the defined separator. - */ - public char getSeparator() { - return separator; - } - - /** - * @return the defined quotation character. - */ - public char getQuoteChar() { - return quoteChar; - } - - /** - * @return the defined escape character. - */ - public char getEscapeChar() { - return escapeChar; - } - - /** - * @return the defined strict quotation setting. - */ - public boolean isStrictQuotes() { - return strictQuotes; - } - - /** - * @return the defined ignoreLeadingWhiteSpace setting. - */ - public boolean isIgnoreLeadingWhiteSpace() { - return ignoreLeadingWhiteSpace; - } - - /** - * @return the defined ignoreQuotation setting. - */ - public boolean isIgnoreQuotations() { - return ignoreQuotations; - } - - /** - * Sets the NullFieldIndicator. - * - * @param fieldIndicator - CSVReaderNullFieldIndicator set to what should be considered a null field. - * @return - The CSVParserBuilder - */ - public CSVParserBuilder withFieldAsNull(final CSVReaderNullFieldIndicator fieldIndicator) { - this.nullFieldIndicator = fieldIndicator; - return this; - } - - /** - * @return - the null field indicator. - */ - public CSVReaderNullFieldIndicator nullFieldIndicator() { - return nullFieldIndicator; - } -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/csv/CSVReader.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/csv/CSVReader.java deleted file mode 100644 index f16f4583259e3..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/csv/CSVReader.java +++ /dev/null @@ -1,377 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * This package contains a slightly modified version of opencsv library - * without unwanted functionality and dependencies, licensed under Apache 2.0. - * - * See https://search.maven.org/artifact/com.opencsv/opencsv/3.4/bundle - * See http://opencsv.sf.net/ - */ -package org.jkiss.utils.csv; - -import java.io.BufferedReader; -import java.io.Closeable; -import java.io.IOException; -import java.io.Reader; -import java.util.ArrayList; -import java.util.List; - -/** - * A very simple CSV reader released under a commercial-friendly license. - * - * @author Glen Smith - */ -public class CSVReader implements Closeable { - - public static final boolean DEFAULT_KEEP_CR = false; - public static final boolean DEFAULT_VERIFY_READER = false; - /** - * The default line to start reading. - */ - public static final int DEFAULT_SKIP_LINES = 0; - private CSVParser parser; - private int skipLines; - private BufferedReader br; - private LineReader lineReader; - private boolean hasNext = true; - private boolean linesSkiped; - private boolean keepCR; - private boolean verifyReader; - - /** - * Constructs CSVReader using a comma for the separator. - * - * @param reader the reader to an underlying CSV source. - */ - public CSVReader(Reader reader) { - this(reader, CSVParser.DEFAULT_SEPARATOR, CSVParser.DEFAULT_QUOTE_CHARACTER, CSVParser.DEFAULT_ESCAPE_CHARACTER); - } - - /** - * Constructs CSVReader with supplied separator. - * - * @param reader the reader to an underlying CSV source. - * @param separator the delimiter to use for separating entries. - */ - public CSVReader(Reader reader, char separator) { - this(reader, separator, CSVParser.DEFAULT_QUOTE_CHARACTER, CSVParser.DEFAULT_ESCAPE_CHARACTER); - } - - /** - * Constructs CSVReader with supplied separator and quote char. - * - * @param reader the reader to an underlying CSV source. - * @param separator the delimiter to use for separating entries - * @param quotechar the character to use for quoted elements - */ - public CSVReader(Reader reader, char separator, char quotechar) { - this(reader, separator, quotechar, CSVParser.DEFAULT_ESCAPE_CHARACTER, DEFAULT_SKIP_LINES, CSVParser.DEFAULT_STRICT_QUOTES); - } - - /** - * Constructs CSVReader with supplied separator, quote char and quote handling - * behavior. - * - * @param reader the reader to an underlying CSV source. - * @param separator the delimiter to use for separating entries - * @param quotechar the character to use for quoted elements - * @param strictQuotes sets if characters outside the quotes are ignored - */ - public CSVReader(Reader reader, char separator, char quotechar, boolean strictQuotes) { - this(reader, separator, quotechar, CSVParser.DEFAULT_ESCAPE_CHARACTER, DEFAULT_SKIP_LINES, strictQuotes); - } - - /** - * Constructs CSVReader. - * - * @param reader the reader to an underlying CSV source. - * @param separator the delimiter to use for separating entries - * @param quotechar the character to use for quoted elements - * @param escape the character to use for escaping a separator or quote - */ - - public CSVReader(Reader reader, char separator, - char quotechar, char escape) { - this(reader, separator, quotechar, escape, DEFAULT_SKIP_LINES, CSVParser.DEFAULT_STRICT_QUOTES); - } - - /** - * Constructs CSVReader. - * - * @param reader the reader to an underlying CSV source. - * @param separator the delimiter to use for separating entries - * @param quotechar the character to use for quoted elements - * @param line the line number to skip for start reading - */ - public CSVReader(Reader reader, char separator, char quotechar, int line) { - this(reader, separator, quotechar, CSVParser.DEFAULT_ESCAPE_CHARACTER, line, CSVParser.DEFAULT_STRICT_QUOTES); - } - - /** - * Constructs CSVReader. - * - * @param reader the reader to an underlying CSV source. - * @param separator the delimiter to use for separating entries - * @param quotechar the character to use for quoted elements - * @param escape the character to use for escaping a separator or quote - * @param line the line number to skip for start reading - */ - public CSVReader(Reader reader, char separator, char quotechar, char escape, int line) { - this(reader, separator, quotechar, escape, line, CSVParser.DEFAULT_STRICT_QUOTES); - } - - /** - * Constructs CSVReader. - * - * @param reader the reader to an underlying CSV source. - * @param separator the delimiter to use for separating entries - * @param quotechar the character to use for quoted elements - * @param escape the character to use for escaping a separator or quote - * @param line the line number to skip for start reading - * @param strictQuotes sets if characters outside the quotes are ignored - */ - public CSVReader(Reader reader, char separator, char quotechar, char escape, int line, boolean strictQuotes) { - this(reader, separator, quotechar, escape, line, strictQuotes, CSVParser.DEFAULT_IGNORE_LEADING_WHITESPACE); - } - - /** - * Constructs CSVReader with all data entered. - * - * @param reader the reader to an underlying CSV source. - * @param separator the delimiter to use for separating entries - * @param quotechar the character to use for quoted elements - * @param escape the character to use for escaping a separator or quote - * @param line the line number to skip for start reading - * @param strictQuotes sets if characters outside the quotes are ignored - * @param ignoreLeadingWhiteSpace it true, parser should ignore white space before a quote in a field - */ - public CSVReader(Reader reader, char separator, char quotechar, char escape, int line, boolean strictQuotes, boolean ignoreLeadingWhiteSpace) { - this(reader, - line, - new CSVParser(separator, quotechar, escape, strictQuotes, ignoreLeadingWhiteSpace)); - } - - /** - * Constructs CSVReader with all data entered. - * - * @param reader the reader to an underlying CSV source. - * @param separator the delimiter to use for separating entries - * @param quotechar the character to use for quoted elements - * @param escape the character to use for escaping a separator or quote - * @param line the line number to skip for start reading - * @param strictQuotes sets if characters outside the quotes are ignored - * @param ignoreLeadingWhiteSpace if true, parser should ignore white space before a quote in a field - * @param keepCR if true the reader will keep carriage returns, otherwise it will discard them. - */ - public CSVReader(Reader reader, char separator, char quotechar, char escape, int line, boolean strictQuotes, - boolean ignoreLeadingWhiteSpace, boolean keepCR) { - this(reader, line, - new CSVParser(separator, quotechar, escape, strictQuotes, ignoreLeadingWhiteSpace), keepCR, DEFAULT_VERIFY_READER); - } - - /** - * Constructs CSVReader with supplied CSVParser. - * - * @param reader the reader to an underlying CSV source. - * @param line the line number to skip for start reading - * @param csvParser the parser to use to parse input - */ - public CSVReader(Reader reader, int line, CSVParser csvParser) { - this(reader, line, csvParser, DEFAULT_KEEP_CR, DEFAULT_VERIFY_READER); - } - - /** - * Constructs CSVReader with supplied CSVParser. - * - * @param reader the reader to an underlying CSV source. - * @param line the line number to skip for start reading - * @param csvParser the parser to use to parse input - * @param keepCR true to keep carriage returns in data read, false otherwise - * @param verifyReader true to verify reader before each read, false otherwise - */ - CSVReader(Reader reader, int line, CSVParser csvParser, boolean keepCR, boolean verifyReader) { - this.br = - (reader instanceof BufferedReader ? - (BufferedReader) reader : - new BufferedReader(reader)); - this.lineReader = new LineReader(br, keepCR); - this.skipLines = line; - this.parser = csvParser; - this.keepCR = keepCR; - this.verifyReader = verifyReader; - } - - /** - * @return the CSVParser used by the reader. - */ - public CSVParser getParser() { - return parser; - } - - /** - * Returns the number of lines in the csv file to skip before processing. This is - * useful when there is miscellaneous data at the beginning of a file. - * - * @return the number of lines in the csv file to skip before processing. - */ - public int getSkipLines() { - return skipLines; - } - - /** - * Returns if the reader will keep carriage returns found in data or remove them. - * - * @return true if reader will keep carriage returns, false otherwise. - */ - public boolean keepCarriageReturns() { - return keepCR; - } - - /** - * Reads the entire file into a List with each element being a String[] of - * tokens. - * - * @return a List of String[], with each String[] representing a line of the - * file. - * @throws IOException if bad things happen during the read - */ - public List readAll() throws IOException { - - List allElements = new ArrayList<>(); - while (hasNext) { - String[] nextLineAsTokens = readNext(); - if (nextLineAsTokens != null) { - allElements.add(nextLineAsTokens); - } - } - return allElements; - - } - - /** - * Reads the next line from the buffer and converts to a string array. - * - * @return a string array with each comma-separated element as a separate - * entry. - * @throws IOException if bad things happen during the read - */ - public String[] readNext() throws IOException { - - String[] result = null; - do { - String nextLine = getNextLine(); - if (!hasNext) { - return result; // should throw if still pending? - } - String[] r = parser.parseLineMulti(nextLine); - if (r.length > 0) { - if (result == null) { - result = r; - } else { - result = combineResultsFromMultipleReads(result, r); - } - } - } while (parser.isPending()); - return result; - } - - /** - * For multi line records this method combines the current result with the result from previous read(s). - * - * @param buffer - previous data read for this record - * @param lastRead - latest data read for this record. - * @return String array with union of the buffer and lastRead arrays. - */ - private String[] combineResultsFromMultipleReads(String[] buffer, String[] lastRead) { - String[] t = new String[buffer.length + lastRead.length]; - System.arraycopy(buffer, 0, t, 0, buffer.length); - System.arraycopy(lastRead, 0, t, buffer.length, lastRead.length); - return t; - } - - /** - * Reads the next line from the file. - * - * @return the next line from the file without trailing newline - * @throws IOException if bad things happen during the read - */ - private String getNextLine() throws IOException { - if (isClosed()) { - hasNext = false; - return null; - } - - if (!this.linesSkiped) { - for (int i = 0; i < skipLines; i++) { - lineReader.readLine(); - } - this.linesSkiped = true; - } - String nextLine = lineReader.readLine(); - if (nextLine == null) { - hasNext = false; - } - return hasNext ? nextLine : null; - } - - /** - * Checks to see if the file is closed. - * - * @return true if the reader can no longer be read from. - */ - private boolean isClosed() { - if (!verifyReader) { - return false; - } - try { - br.mark(1); - int nextByte = br.read(); - br.reset(); // resets stream position, possible because its buffered - return nextByte == -1; // read() returns -1 at end of stream - } catch (IOException e) { - return true; - } - } - - /** - * Closes the underlying reader. - * - * @throws IOException if the close fails - */ - public void close() throws IOException { - br.close(); - } - - /** - * Returns if the CSVReader will verify the reader before each read. - *

- * By default the value is true which is the functionality for version 3.0. - * If set to false the reader is always assumed ready to read - this is the functionality - * for version 2.4 and before. - *

- * The reason this method was needed was that certain types of Readers would return - * false for its ready() method until a read was done (namely readers created using Channels). - * This caused opencsv not to read from those readers. - * - * @return true if CSVReader will verify the reader before reads. False otherwise. - * @link https://sourceforge.net/p/opencsv/bugs/108/ - */ - public boolean verifyReader() { - return this.verifyReader; - } -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/csv/CSVReaderBuilder.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/csv/CSVReaderBuilder.java deleted file mode 100644 index e576f6e047053..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/csv/CSVReaderBuilder.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * This package contains a slightly modified version of opencsv library - * without unwanted functionality and dependencies, licensed under Apache 2.0. - * - * See https://search.maven.org/artifact/com.opencsv/opencsv/3.4/bundle - * See http://opencsv.sf.net/ - */ -package org.jkiss.utils.csv; - - -import java.io.Reader; - -/** - * Builder for creating a CSVReader. This should be the preferred method of - * creating a Reader as there are so many possible values to be set it is - * impossible to have constructors for all of them and keep backwards - * compatibility with previous constructors. - * - * - * final CSVParser parser = - * new CSVParserBuilder() - * .withSeparator('\t') - * .withIgnoreQuotations(true) - * .build(); - * final CSVReader reader = - * new CSVReaderBuilder(new StringReader(csv)) - * .withSkipLines(1) - * .withCSVParser(parser) - * .build(); - * - * - * @see CSVReader - */ -public class CSVReaderBuilder { - - private final CSVParserBuilder parserBuilder = new CSVParserBuilder(); - private final Reader reader; - private int skipLines = CSVReader.DEFAULT_SKIP_LINES; - /*@Nullable*/private CSVParser csvParser = null; - private boolean keepCR; - private boolean verifyReader = CSVReader.DEFAULT_VERIFY_READER; - private CSVReaderNullFieldIndicator nullFieldIndicator = CSVReaderNullFieldIndicator.NEITHER; - - /** - * Sets the reader to an underlying CSV source. - * - * @param reader the reader to an underlying CSV source. - */ - public CSVReaderBuilder( - final Reader reader) { - if (reader == null) { - throw new IllegalArgumentException("Reader may not be null"); - } - this.reader = reader; - } - - /** - * Used by unit tests. - * - * @return the reader. - */ - protected Reader getReader() { - return reader; - } - - /** - * used by unit tests. - * - * @return The set number of lines to skip - */ - protected int getSkipLines() { - return skipLines; - } - - /** - * used by unit tests. - * - * @return the csvParser used by the builder. - */ - protected CSVParser getCsvParser() { - return csvParser; - } - - /** - * Sets the line number to skip for start reading. - * - * @param skipLines the line number to skip for start reading. - * @return the CSVReaderBuilder with skipLines set. - */ - public CSVReaderBuilder withSkipLines( - final int skipLines) { - this.skipLines = (skipLines <= 0 ? 0 : skipLines); - return this; - } - - - /** - * Sets the parser to use to parse the input. - * - * @param csvParser the parser to use to parse the input. - * @return the CSVReaderBuilder with the CSVParser set. - */ - public CSVReaderBuilder withCSVParser( - final /*@Nullable*/ CSVParser csvParser) { - this.csvParser = csvParser; - return this; - } - - - /** - * Creates the CSVReader. - * @return the CSVReader based on the set criteria. - */ - public CSVReader build() { - final CSVParser parser = - (csvParser != null ? csvParser : parserBuilder.withFieldAsNull(nullFieldIndicator).build()); - return new CSVReader(reader, skipLines, parser, keepCR, verifyReader); - } - - /** - * Sets if the reader will keep or discard carriage returns. - * - * @param keepCR - true to keep carriage returns, false to discard. - * @return the CSVReaderBuilder based on the set criteria. - */ - public CSVReaderBuilder withKeepCarriageReturn(boolean keepCR) { - this.keepCR = keepCR; - return this; - } - - /** - * Returns if the reader built will keep or discard carriage returns. - * - * @return true if the reader built will keep carriage returns, false otherwise. - */ - protected boolean keepCarriageReturn() { - return this.keepCR; - } - - /** - * Checks to see if the CSVReader should verify the reader state before reads or not. - * - * This should be set to false if you are using some form of asynchronous reader (like readers created - * by the java.nio.* classes). - * - * The default value is true. - * - * @param verifyReader true if CSVReader should verify reader before each read, false otherwise. - * @return The CSVReaderBuilder based on this criteria. - */ - public CSVReaderBuilder withVerifyReader(boolean verifyReader) { - this.verifyReader = verifyReader; - return this; - } - - /** - * Checks to see if it should treat an field with two separators, two quotes, or both as a null field. - * - * @param indicator - CSVReaderNullFieldIndicator set to what should be considered a null field. - * @return The CSVReaderBuilder based on this criteria. - */ - public CSVReaderBuilder withFieldAsNull(CSVReaderNullFieldIndicator indicator) { - this.nullFieldIndicator = indicator; - return this; - } -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/csv/CSVReaderNullFieldIndicator.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/csv/CSVReaderNullFieldIndicator.java deleted file mode 100644 index 426d01a96119c..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/csv/CSVReaderNullFieldIndicator.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * This package contains a slightly modified version of opencsv library - * without unwanted functionality and dependencies, licensed under Apache 2.0. - * - * See https://search.maven.org/artifact/com.opencsv/opencsv/3.4/bundle - * See http://opencsv.sf.net/ - */ -package org.jkiss.utils.csv; - -/** - * Enumeration used to tell the CSVParser what to consider null. - *

- * EMPTY_SEPARATORS - two sequential separators are null. - * EMPTY_QUOTES - two sequential quotes are null - * BOTH - both are null - * NEITHER - default. Both are considered empty string. - */ -public enum CSVReaderNullFieldIndicator { - EMPTY_SEPARATORS, - EMPTY_QUOTES, - BOTH, - NEITHER; -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/csv/CSVWriter.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/csv/CSVWriter.java deleted file mode 100644 index 0afb172d239ad..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/csv/CSVWriter.java +++ /dev/null @@ -1,314 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * This package contains a slightly modified version of opencsv library - * without unwanted functionality and dependencies, licensed under Apache 2.0. - * - * See https://search.maven.org/artifact/com.opencsv/opencsv/3.4/bundle - * See http://opencsv.sf.net/ - */ -package org.jkiss.utils.csv; - -import java.io.*; -import java.util.List; - -/** - * A very simple CSV writer released under a commercial-friendly license. - * - * @author Glen Smith - */ -public class CSVWriter implements Closeable, Flushable { - - public static final int INITIAL_STRING_SIZE = 128; - /** - * The character used for escaping quotes. - */ - public static final char DEFAULT_ESCAPE_CHARACTER = '"'; - /** - * The default separator to use if none is supplied to the constructor. - */ - public static final char DEFAULT_SEPARATOR = ','; - /** - * The default quote character to use if none is supplied to the - * constructor. - */ - public static final char DEFAULT_QUOTE_CHARACTER = '"'; - /** - * The quote constant to use when you wish to suppress all quoting. - */ - public static final char NO_QUOTE_CHARACTER = '\u0000'; - /** - * The escape constant to use when you wish to suppress all escaping. - */ - public static final char NO_ESCAPE_CHARACTER = '\u0000'; - /** - * Default line terminator uses platform encoding. - */ - public static final String DEFAULT_LINE_END = "\n"; - private Writer rawWriter; - private PrintWriter pw; - private char separator; - private char quotechar; - private char escapechar; - private String lineEnd; - - /** - * Constructs CSVWriter using a comma for the separator. - * - * @param writer the writer to an underlying CSV source. - */ - public CSVWriter(Writer writer) { - this(writer, DEFAULT_SEPARATOR); - } - - /** - * Constructs CSVWriter with supplied separator. - * - * @param writer the writer to an underlying CSV source. - * @param separator the delimiter to use for separating entries. - */ - public CSVWriter(Writer writer, char separator) { - this(writer, separator, DEFAULT_QUOTE_CHARACTER); - } - - /** - * Constructs CSVWriter with supplied separator and quote char. - * - * @param writer the writer to an underlying CSV source. - * @param separator the delimiter to use for separating entries - * @param quotechar the character to use for quoted elements - */ - public CSVWriter(Writer writer, char separator, char quotechar) { - this(writer, separator, quotechar, DEFAULT_ESCAPE_CHARACTER); - } - - /** - * Constructs CSVWriter with supplied separator and quote char. - * - * @param writer the writer to an underlying CSV source. - * @param separator the delimiter to use for separating entries - * @param quotechar the character to use for quoted elements - * @param escapechar the character to use for escaping quotechars or escapechars - */ - public CSVWriter(Writer writer, char separator, char quotechar, char escapechar) { - this(writer, separator, quotechar, escapechar, DEFAULT_LINE_END); - } - - - /** - * Constructs CSVWriter with supplied separator and quote char. - * - * @param writer the writer to an underlying CSV source. - * @param separator the delimiter to use for separating entries - * @param quotechar the character to use for quoted elements - * @param lineEnd the line feed terminator to use - */ - public CSVWriter(Writer writer, char separator, char quotechar, String lineEnd) { - this(writer, separator, quotechar, DEFAULT_ESCAPE_CHARACTER, lineEnd); - } - - - /** - * Constructs CSVWriter with supplied separator, quote char, escape char and line ending. - * - * @param writer the writer to an underlying CSV source. - * @param separator the delimiter to use for separating entries - * @param quotechar the character to use for quoted elements - * @param escapechar the character to use for escaping quotechars or escapechars - * @param lineEnd the line feed terminator to use - */ - public CSVWriter(Writer writer, char separator, char quotechar, char escapechar, String lineEnd) { - this.rawWriter = writer; - this.pw = new PrintWriter(writer); - this.separator = separator; - this.quotechar = quotechar; - this.escapechar = escapechar; - this.lineEnd = lineEnd; - } - - /** - * Writes the entire list to a CSV file. The list is assumed to be a - * String[] - * - * @param allLines a List of String[], with each String[] representing a line of - * the file. - * @param applyQuotesToAll true if all values are to be quoted. false if quotes only - * to be applied to values which contain the separator, escape, - * quote or new line characters. - */ - public void writeAll(List allLines, boolean applyQuotesToAll) { - for (String[] line : allLines) { - writeNext(line, applyQuotesToAll); - } - } - - /** - * Writes the entire list to a CSV file. The list is assumed to be a - * String[] - * - * @param allLines a List of String[], with each String[] representing a line of - * the file. - */ - public void writeAll(List allLines) { - for (String[] line : allLines) { - writeNext(line); - } - } - - /** - * Writes the next line to the file. - * - * @param nextLine a string array with each comma-separated element as a separate - * entry. - * @param applyQuotesToAll true if all values are to be quoted. false applies quotes only - * to values which contain the separator, escape, quote or new line characters. - */ - public void writeNext(String[] nextLine, boolean applyQuotesToAll) { - - if (nextLine == null) { - return; - } - - StringBuilder sb = new StringBuilder(INITIAL_STRING_SIZE); - for (int i = 0; i < nextLine.length; i++) { - - if (i != 0) { - sb.append(separator); - } - - String nextElement = nextLine[i]; - - if (nextElement == null) { - continue; - } - - Boolean stringContainsSpecialCharacters = stringContainsSpecialCharacters(nextElement); - - if ((applyQuotesToAll || stringContainsSpecialCharacters) && quotechar != NO_QUOTE_CHARACTER) { - sb.append(quotechar); - } - - if (stringContainsSpecialCharacters) { - sb.append(processLine(nextElement)); - } else { - sb.append(nextElement); - } - - if ((applyQuotesToAll || stringContainsSpecialCharacters) && quotechar != NO_QUOTE_CHARACTER) { - sb.append(quotechar); - } - } - - sb.append(lineEnd); - pw.write(sb.toString()); - } - - /** - * Writes the next line to the file. - * - * @param nextLine a string array with each comma-separated element as a separate - * entry. - */ - public void writeNext(String[] nextLine) { - writeNext(nextLine, true); - } - - /** - * checks to see if the line contains special characters. - * - * @param line - element of data to check for special characters. - * @return true if the line contains the quote, escape, separator, newline or return. - */ - private boolean stringContainsSpecialCharacters(String line) { - return line.indexOf(quotechar) != -1 || line.indexOf(escapechar) != -1 || line.indexOf(separator) != -1 || line.contains(DEFAULT_LINE_END) || line.contains("\r"); - } - - /** - * Processes all the characters in a line. - * - * @param nextElement - element to process. - * @return a StringBuilder with the elements data. - */ - protected StringBuilder processLine(String nextElement) { - StringBuilder sb = new StringBuilder(INITIAL_STRING_SIZE); - for (int j = 0; j < nextElement.length(); j++) { - char nextChar = nextElement.charAt(j); - processCharacter(sb, nextChar); - } - - return sb; - } - - /** - * Appends the character to the StringBuilder adding the escape character if needed. - * - * @param sb - StringBuffer holding the processed character. - * @param nextChar - character to process - */ - private void processCharacter(StringBuilder sb, char nextChar) { - if (escapechar != NO_ESCAPE_CHARACTER && (nextChar == quotechar || nextChar == escapechar)) { - sb.append(escapechar).append(nextChar); - } else { - sb.append(nextChar); - } - } - - /** - * Flush underlying stream to writer. - * - * @throws IOException if bad things happen - */ - public void flush() throws IOException { - - pw.flush(); - - } - - /** - * Close the underlying stream writer flushing any buffered content. - * - * @throws IOException if bad things happen - */ - public void close() throws IOException { - flush(); - pw.close(); - rawWriter.close(); - } - - /** - * Checks to see if the there has been an error in the printstream. - * - * @return true if the print stream has encountered an error, - * either on the underlying output stream or during a format - * conversion. - */ - public boolean checkError() { - return pw.checkError(); - } - - /** - * flushes the writer without throwing any exceptions. - */ - public void flushQuietly() { - try { - flush(); - } catch (IOException e) { - // catch exception and ignore. - } - } -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/csv/LineReader.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/csv/LineReader.java deleted file mode 100644 index f0231a75bf936..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/csv/LineReader.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * This package contains a slightly modified version of opencsv library - * without unwanted functionality and dependencies, licensed under Apache 2.0. - * - * See https://search.maven.org/artifact/com.opencsv/opencsv/3.4/bundle - * See http://opencsv.sf.net/ - */ -package org.jkiss.utils.csv; - -import java.io.BufferedReader; -import java.io.IOException; - -/** - * This class was created for issue #106 (https://sourceforge.net/p/opencsv/bugs/106/) where - * carriage returns were being removed. This class allows the user to determine if they wish to keep or - * remove them from the data being read. - *

- * Created by scott on 2/19/15. - */ - -public class LineReader { - private final BufferedReader reader; - private final boolean keepCarriageReturns; - - /** - * LineReader constructor. - * - * @param reader - Reader that data will be read from. - * @param keepCarriageReturns - true if carriage returns should remain in the data, false to remove them. - */ - public LineReader(BufferedReader reader, boolean keepCarriageReturns) { - this.reader = reader; - this.keepCarriageReturns = keepCarriageReturns; - } - - /** - * Reads the next line from the Reader. - * - * @return - Line read from reader. - * @throws IOException - on error from BufferedReader - */ - public String readLine() throws IOException { - return keepCarriageReturns ? readUntilNewline() : reader.readLine(); - } - - private String readUntilNewline() throws IOException { - StringBuilder sb = new StringBuilder(CSVParser.INITIAL_READ_SIZE); - for (int c = reader.read(); c > -1 && c != '\n'; c = reader.read()) { - sb.append((char) c); - } - - return sb.length() > 0 ? sb.toString() : null; - } -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/io/BOMInputStream.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/io/BOMInputStream.java deleted file mode 100644 index 84b398f490bce..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/io/BOMInputStream.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jkiss.utils.io; - -import org.jkiss.code.NotNull; -import org.jkiss.code.Nullable; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.Charset; -import java.util.Arrays; -import java.util.Comparator; -import java.util.List; - -/** - * This class wraps a stream that includes an - * encoded {@link ByteOrderMark} as its first bytes. - *

- * This class detects these bytes and skips them and - * return the subsequent byte as the first byte in the stream. - *

- * This class is highly inspired by the BOMInputStream - * class from the Apache Commons library. - * - * @see Wikipedia - Byte Order Mark - */ -public class BOMInputStream extends InputStream { - private static final Comparator BOM_LENGTH_COMPARATOR = Comparator.comparing(ByteOrderMark::length).reversed(); - - private final InputStream in; - private final List boms; - private ByteOrderMark bom; - private int[] firstBytes; - private int fbLength; - private int fbIndex; - private int markFbIndex; - private boolean markedAtStart; - - public BOMInputStream(@NotNull InputStream delegate, @NotNull ByteOrderMark... boms) { - if (boms.length == 0) { - throw new IllegalArgumentException("No BOMs specified"); - } - - this.in = delegate; - this.boms = Arrays.asList(boms); - this.boms.sort(BOM_LENGTH_COMPARATOR); - } - - public BOMInputStream(@NotNull InputStream delegate, @NotNull Charset charset) { - this(delegate, ByteOrderMark.fromCharset(charset)); - } - - public BOMInputStream(@NotNull InputStream delegate) { - this(delegate, ByteOrderMark.UTF_8); - } - - @Override - public int read() throws IOException { - getBOM(); - return fbIndex < fbLength ? firstBytes[fbIndex++] : in.read(); - } - - @Override - public synchronized void mark(int limit) { - markFbIndex = fbIndex; - markedAtStart = firstBytes == null; - in.mark(limit); - } - - @Override - public synchronized void reset() throws IOException { - fbIndex = markFbIndex; - if (markedAtStart) { - firstBytes = null; - } - in.reset(); - } - - @Nullable - public ByteOrderMark getBOM() throws IOException { - if (firstBytes == null) { - fbLength = 0; - firstBytes = new int[boms.get(0).length()]; - for (int i = 0; i < firstBytes.length; i++) { - firstBytes[i] = in.read(); - fbLength++; - if (firstBytes[i] < 0) { - break; - } - } - bom = find(); - if (bom != null) { - if (bom.length() < firstBytes.length) { - fbIndex = bom.length(); - } else { - fbLength = 0; - } - } - } - return bom; - } - - public boolean hasBOM() throws IOException { - return getBOM() != null; - } - - public boolean hasBOM(@NotNull ByteOrderMark bom) throws IOException { - if (!boms.contains(bom)) { - throw new IllegalArgumentException("Stream is not configured to detect " + bom); - } - getBOM(); - return this.bom != null && this.bom.equals(bom); - } - - @Nullable - private ByteOrderMark find() { - for (ByteOrderMark bom : boms) { - if (matches(bom)) { - return bom; - } - } - return null; - } - - private boolean matches(@NotNull ByteOrderMark bom) { - for (int i = 0; i < bom.length(); i++) { - if (bom.get(i) != firstBytes[i]) { - return false; - } - } - return true; - } -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/io/ByteOrderMark.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/io/ByteOrderMark.java deleted file mode 100644 index 5f69fcd88bcb9..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/io/ByteOrderMark.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jkiss.utils.io; - -import org.jkiss.code.NotNull; - -import java.nio.charset.Charset; - -public enum ByteOrderMark implements Comparable { - /** - * UTF-8 BOM - */ - UTF_8("UTF-8", new int[]{0xEF, 0xBB, 0xBF}), - - /** - * UTF-16BE BOM (Big-Endian) - */ - UTF_16BE("UTF-16BE", new int[]{0xFE, 0xFF}), - - /** - * UTF-16LE BOM (Little-Endian) - */ - UTF_16LE("UTF-16LE", new int[]{0xFF, 0xFE}), - - /** - * UTF-32BE BOM (Big-Endian) - */ - UTF_32BE("UTF-32BE", new int[]{0x00, 0x00, 0xFE, 0xFF}), - - /** - * UTF-32LE BOM (Little-Endian) - */ - UTF_32LE("UTF-32LE", new int[]{0xFF, 0xFE, 0x00, 0x00}); - - private final String charsetName; - private final int[] bytes; - - ByteOrderMark(@NotNull String charsetName, @NotNull int[] bytes) { - this.charsetName = charsetName; - this.bytes = bytes; - } - - @NotNull - public String getCharsetName() { - return charsetName; - } - - @NotNull - public byte[] getBytes() { - final byte[] buffer = new byte[bytes.length]; - for (int index = 0; index < bytes.length; index++) { - buffer[index] = (byte) (bytes[index] & 0xFF); - } - return buffer; - } - - public int get(int position) { - return bytes[position]; - } - - public int length() { - return bytes.length; - } - - @NotNull - public static ByteOrderMark fromCharset(@NotNull Charset charset) { - return fromCharset(charset.name()); - } - - @NotNull - public static ByteOrderMark fromCharset(@NotNull String charsetName) { - for (ByteOrderMark bom : values()) { - if (bom.charsetName.equalsIgnoreCase(charsetName)) { - return bom; - } - } - throw new IllegalArgumentException("Can't find BOM for charset " + charsetName); - } -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/rest/RequestMapping.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/rest/RequestMapping.java deleted file mode 100644 index 669deb6c94a6a..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/rest/RequestMapping.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jkiss.utils.rest; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.METHOD) -public @interface RequestMapping { - /** - * Mapping for the annotated method. - */ - String value() default ""; - - /** - * Timeout (in seconds) for this mapping. - */ - int timeout() default 0; -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/rest/RequestParameter.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/rest/RequestParameter.java deleted file mode 100644 index f80642d86c5b9..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/rest/RequestParameter.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jkiss.utils.rest; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.PARAMETER) -public @interface RequestParameter { - /** - * Name of the parameter. - */ - String value(); -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/rest/RestClient.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/rest/RestClient.java deleted file mode 100644 index c68d7f138ff95..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/rest/RestClient.java +++ /dev/null @@ -1,258 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jkiss.utils.rest; - -import com.google.gson.Gson; -import com.google.gson.JsonElement; -import org.jkiss.code.NotNull; -import org.jkiss.utils.BeanUtils; -import org.jkiss.utils.CommonUtils; - -import java.lang.reflect.*; -import java.net.URI; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpRequest.BodyPublishers; -import java.net.http.HttpResponse; -import java.net.http.HttpResponse.BodySubscribers; -import java.nio.charset.StandardCharsets; -import java.time.Duration; -import java.util.*; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class RestClient { - - private static final Pattern ST_LINE_PATTERN = Pattern.compile("\\s*at\\s+([\\w/.$]+)\\((.+)\\)"); - - private RestClient() { - // prevents instantiation - } - - @NotNull - public static T create(@NotNull URI uri, @NotNull Class cls, @NotNull Gson gson) { - final Object proxy = Proxy.newProxyInstance( - cls.getClassLoader(), - new Class[]{cls, RestProxy.class}, - new ClientInvocationHandler(cls, uri, gson) - ); - - return cls.cast(proxy); - } - - @NotNull - public static Builder builder(@NotNull URI uri, @NotNull Class cls) { - return new Builder<>(uri, cls); - } - - public static final class Builder { - private final URI uri; - private final Class cls; - private Gson gson; - - private Builder(@NotNull URI uri, @NotNull Class cls) { - this.uri = uri; - this.cls = cls; - this.gson = RestConstants.DEFAULT_GSON; - } - - @NotNull - public Builder setGson(@NotNull Gson gson) { - this.gson = gson; - return this; - } - - @NotNull - public T create() { - return RestClient.create(uri, cls, gson); - } - } - - private static class ClientInvocationHandler implements InvocationHandler, RestProxy { - @NotNull - private final Class clientClass; - private final URI uri; - private final Gson gson; - private final ExecutorService httpExecutor; - private final HttpClient client; - private final ThreadLocal resultType = new ThreadLocal<>(); - - private ClientInvocationHandler(@NotNull Class clientClass, @NotNull URI uri, @NotNull Gson gson) { - this.clientClass = clientClass; - this.uri = uri; - this.gson = gson; - this.httpExecutor = Executors.newSingleThreadExecutor(); - this.client = HttpClient.newBuilder() - .executor(httpExecutor) - .build(); - } - - @Override - public synchronized Object invoke(Object proxy, Method method, Object[] args) throws RestException { - Class declaringClass = method.getDeclaringClass(); - if (declaringClass == Object.class) { - return BeanUtils.handleObjectMethod(proxy, method, args); - } else if (declaringClass == RestProxy.class) { - setNextCallResultType((Type) args[0]); - return null; - } else if (method.getName().equals("close") && (declaringClass == AutoCloseable.class || declaringClass == clientClass)) { - closeClient(); - return null; - } - if (httpExecutor.isShutdown() || httpExecutor.isTerminated()) { - throw new RestException("Rest client has been terminated"); - } - - final RequestMapping mapping = method.getDeclaredAnnotation(RequestMapping.class); - - if (mapping == null) { - throw createException(method, "it's not annotated with @RequestMapping"); - } - - final Parameter[] parameters = method.getParameters(); - final Map values = new LinkedHashMap<>(parameters.length); - - for (int i = 0; i < parameters.length; i++) { - final Parameter p = parameters[i]; - final RequestParameter param = p.getDeclaredAnnotation(RequestParameter.class); - - if (param == null) { - throw createException(method, "one or more of its parameters are not annotated with @RequestParameter"); - } - - if (CommonUtils.isEmptyTrimmed(param.value())) { - throw createException(method, "one or more of its parameters has empty name specified in @RequestParameter"); - } - - if (values.put(param.value(), gson.toJsonTree(args[i])) != null) { - throw createException(method, "one or more of its parameters share the same name specified in @RequestParameter"); - } - } - - try { - String endpoint = mapping.value(); - if (CommonUtils.isEmpty(endpoint)) { - endpoint = method.getName(); - } - StringBuilder url = new StringBuilder(); - url.append(uri); - if (url.charAt(url.length() - 1) != '/') url.append('/'); - url.append(endpoint); - HttpResponse.BodyHandler readerBodyHandler = - info -> BodySubscribers.ofString(StandardCharsets.UTF_8); - String requestString = gson.toJson(values); - - final HttpRequest.Builder builder = HttpRequest.newBuilder() - .uri(URI.create(url.toString())) - .header("Content-Type", "application/json") - .POST(BodyPublishers.ofString(requestString)); - - if (mapping.timeout() > 0) { - builder.timeout(Duration.ofSeconds(mapping.timeout())); - } - - final HttpResponse response = client.send( - builder.build(), - readerBodyHandler - ); - - String contents = response.body(); - if (response.statusCode() != RestConstants.SC_OK) { - handleError(contents); - } - - Type returnType = resultType.get(); - if (returnType == null) { - returnType = method.getReturnType(); - } else { - resultType.remove(); - } - if (returnType == void.class) { - return null; - } - if (returnType instanceof TypeVariable) { - Type[] bounds = ((TypeVariable) returnType).getBounds(); - if (bounds.length > 0) { - returnType = bounds[0]; - } - } - if (returnType instanceof ParameterizedType && ((ParameterizedType) returnType).getRawType() == Class.class) { - // Convert to raw class type to force our serializer to work - returnType = Class.class; - } - - return gson.fromJson(contents, returnType); - } catch (RuntimeException e) { - throw e; - } catch (Exception e) { - throw new RestException(e); - } - } - - private void closeClient() { - if (!httpExecutor.isShutdown()) { - httpExecutor.shutdown(); - } - } - - @NotNull - private static RestException createException(@NotNull Method method, @NotNull String reason) { - return new RestException("Unable to invoke the method " + method + " because " + reason); - } - - @Override - public void setNextCallResultType(Type type) { - this.resultType.set(type); - } - } - - private static void handleError(String contents) throws RestException { - String[] stackTraceRows = contents.split("\n"); - String errorLine = stackTraceRows[0]; - List stackTraceElements = new ArrayList<>(); - for (int i = 1; i < stackTraceRows.length; i++) { - Matcher matcher = ST_LINE_PATTERN.matcher(stackTraceRows[i]); - if (matcher.find()) { - String methodRef = matcher.group(1); - int divPos = methodRef.lastIndexOf('.'); - String className = methodRef.substring(0, divPos); - String methodName = methodRef.substring(divPos + 1); - - String classRef = matcher.group(2); - divPos = classRef.indexOf(':'); - String fileName; - int fileLine; - if (divPos == -1) { - fileName = classRef; - fileLine = -1; - } else { - fileName = classRef.substring(0, divPos).trim(); - fileLine = CommonUtils.toInt(classRef.substring(divPos + 1).trim()); - } - stackTraceElements.add( - new StackTraceElement(className, methodName, fileName, fileLine)); - } - } - RestException runtimeException = new RestException(errorLine); - Collections.addAll(stackTraceElements, runtimeException.getStackTrace()); - runtimeException.setStackTrace(stackTraceElements.toArray(new StackTraceElement[0])); - - throw runtimeException; - } -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/rest/RestConstants.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/rest/RestConstants.java deleted file mode 100644 index eadf0fe31ec0a..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/rest/RestConstants.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jkiss.utils.rest; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -public class RestConstants { - public static final int SC_OK = 200; - public static final int SC_FORBIDDEN = 403; - public static final int SC_UNSUPPORTED = 405; - public static final int SC_NOT_FOUND = 404; - public static final int SC_SERVER_ERROR = 500; - - static final Gson DEFAULT_GSON = new GsonBuilder() - .setLenient() - .disableHtmlEscaping() - .serializeNulls() - .create(); -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/rest/RestException.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/rest/RestException.java deleted file mode 100644 index 2b98b27bbd6a7..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/rest/RestException.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jkiss.utils.rest; - -public class RestException extends RuntimeException { - public RestException(String message) { - super(message); - } - - public RestException(String message, Throwable cause) { - super(message, cause); - } - - public RestException(Throwable cause) { - super(cause); - } - - public RestException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { - super(message, cause, enableSuppression, writableStackTrace); - } -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/rest/RestProxy.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/rest/RestProxy.java deleted file mode 100644 index 097f598867fcb..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/rest/RestProxy.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jkiss.utils.rest; - -import java.lang.reflect.Type; - -public interface RestProxy { - - void setNextCallResultType(Type resultType); -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/rest/RestServer.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/rest/RestServer.java deleted file mode 100644 index ceb9f19c10a06..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/rest/RestServer.java +++ /dev/null @@ -1,340 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jkiss.utils.rest; - -import com.google.gson.Gson; -import com.google.gson.JsonElement; -import com.google.gson.JsonNull; -import com.google.gson.reflect.TypeToken; -import com.sun.net.httpserver.HttpExchange; -import com.sun.net.httpserver.HttpHandler; -import com.sun.net.httpserver.HttpServer; -import org.jkiss.code.NotNull; -import org.jkiss.code.Nullable; -import org.jkiss.utils.CommonUtils; - -import java.io.*; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Parameter; -import java.lang.reflect.Type; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.*; -import java.util.function.Predicate; -import java.util.logging.Level; -import java.util.logging.Logger; - -public class RestServer { - private static final Logger log = Logger.getLogger(RestServer.class.getName()); - private HttpServer server; - - public RestServer( - @NotNull Class cls, - @NotNull T object, - @NotNull Gson gson, - @NotNull Predicate filter, - int port, - int backlog - ) throws IOException { - InetSocketAddress listenAddr = new InetSocketAddress(InetAddress.getLoopbackAddress(), port); - server = HttpServer.create(listenAddr, backlog); - server.createContext("/", createHandler(cls, object, gson, filter)); - server.setExecutor(createExecutor()); - server.start(); - } - - @NotNull - public static Builder builder(@NotNull Class cls, @NotNull T object) { - return new Builder<>(object, cls); - } - - public boolean isRunning() { - return server != null; - } - - public void stop() { - stop(1); - } - - public void stop(int delay) { - try { - server.stop(delay); - - final Executor executor = server.getExecutor(); - if (executor instanceof ExecutorService) { - ((ExecutorService) executor).shutdown(); - } - } finally { - server = null; - } - } - - @NotNull - public InetSocketAddress getAddress() { - return server.getAddress(); - } - - @NotNull - protected Executor createExecutor() { - return new ThreadPoolExecutor(1, 10, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>()); - } - - @NotNull - protected RequestHandler createHandler( - @NotNull Class cls, - @NotNull T object, - @NotNull Gson gson, - @NotNull Predicate filter - ) { - return new RequestHandler<>(cls, object, gson, filter); - } - - protected static class RequestHandler implements HttpHandler { - private static final Type REQUEST_TYPE = new TypeToken>() {}.getType(); - - private final T object; - private final Gson gson; - private final Map mappings; - private final Predicate filter; - - protected RequestHandler( - @NotNull Class cls, - @NotNull T object, - @NotNull Gson gson, - @NotNull Predicate filter - ) { - this.object = object; - this.gson = gson; - this.mappings = createMappings(cls); - this.filter = filter; - } - - @SuppressWarnings("TryFinallyCanBeTryWithResources") - @Override - public void handle(HttpExchange exchange) throws IOException { - Response response; - - try { - response = createResponse(exchange); - } catch (IOException e) { - log.log(Level.SEVERE, "IO error", e); - response = new Response<>(e.getMessage(), String.class, 500); - } - - try { - Object responseObject = response.object; - if (responseObject == null) { - responseObject = "Internal error"; - } - if (response.code == RestConstants.SC_OK) { - String responseText; - if (response.type == void.class) { - responseText = CommonUtils.toString(response.object); - exchange.getResponseHeaders().add("Content-Type", "text/plain"); - } else { - try { - responseText = gson.toJson(response.object, response.type); - } catch (Throwable e) { - // Serialization error - StringWriter buf = new StringWriter(); - new RestException("JSON serialization error: " + e.getMessage(), e).printStackTrace(new PrintWriter(buf, true)); - - sendError(exchange, RestConstants.SC_SERVER_ERROR, buf.toString()); - return; - } - exchange.getResponseHeaders().add("Content-Type", "application/json"); - } - byte[] responseBytes = responseText.getBytes(StandardCharsets.UTF_8); - - exchange.sendResponseHeaders(RestConstants.SC_OK, responseBytes.length); - try (OutputStream responseBody = exchange.getResponseBody()) { - responseBody.write(responseBytes); - } - } else { - sendError(exchange, response.code, responseObject); - } - } catch (Throwable e) { - log.log(Level.SEVERE, "Internal IO error", e); - throw e; - } finally { - exchange.close(); - } - } - - private void sendError(HttpExchange exchange, int resultCode, Object responseObject) throws IOException { - String responseText = responseObject.toString(); - byte[] result = responseText.getBytes(StandardCharsets.UTF_8); - - exchange.getResponseHeaders().add("Content-Type", "text/plain"); - exchange.sendResponseHeaders(resultCode, result.length); - try (OutputStream responseBody = exchange.getResponseBody()) { - responseBody.write(result); - } - } - - @NotNull - protected Response createResponse(@NotNull HttpExchange exchange) throws IOException { - if (!filter.test(exchange.getRemoteAddress())) { - return new Response<>("Access is forbidden", String.class, RestConstants.SC_FORBIDDEN); - } - - if (!exchange.getRequestMethod().equalsIgnoreCase("POST")) { - return new Response<>("Unsupported method", String.class, RestConstants.SC_UNSUPPORTED); - } - - final URI uri = exchange.getRequestURI(); - final String path = uri.getPath().replaceAll("^/+", ""); - final Method method = mappings.get(path); - - if (method == null) { - return new Response<>("Mapping " + path + " not found", String.class, RestConstants.SC_NOT_FOUND); - } - - final Map request; - - try (Reader reader = new BufferedReader(new InputStreamReader(exchange.getRequestBody()))) { - request = gson.fromJson(reader, REQUEST_TYPE); - } - - final Parameter[] parameters = method.getParameters(); - final Object[] values = new Object[parameters.length]; - - for (int i = 0; i < parameters.length; i++) { - final Parameter p = parameters[i]; - final RequestParameter param = p.getDeclaredAnnotation(RequestParameter.class); - final JsonElement element = request.getOrDefault(param.value(), JsonNull.INSTANCE); - values[i] = gson.fromJson(element, p.getParameterizedType()); - } - - try { - final Object result = method.invoke(object, values); - final Type type = method.getGenericReturnType(); - return new Response<>(result, type, RestConstants.SC_OK); - } catch (Throwable e) { - if (e instanceof InvocationTargetException) { - e = ((InvocationTargetException) e).getTargetException(); - } - log.log(Level.SEVERE, "RPC call '" + uri + "' failed: " + e.getMessage()); - StringWriter buf = new StringWriter(); - e.printStackTrace(new PrintWriter(buf, true)); - return new Response<>(buf.toString(), String.class, RestConstants.SC_SERVER_ERROR); - } - } - - @NotNull - protected Map createMappings(@NotNull Class cls) { - final Map mappings = new HashMap<>(); - - for (Method method : cls.getDeclaredMethods()) { - if (method.getDeclaringClass() == Object.class) { - continue; - } - - final RequestMapping mapping = method.getDeclaredAnnotation(RequestMapping.class); - - if (mapping == null) { - continue; - } - - String methodEndpoint = mapping.value(); - if (CommonUtils.isEmptyTrimmed(mapping.value())) { - methodEndpoint = method.getName(); - } - - if (mappings.containsKey(methodEndpoint)) { - log.warning("Method " + method + " has duplicate mapping, skipping"); - continue; - } - - method.setAccessible(true); - mappings.put(methodEndpoint, method); - } - - return Collections.unmodifiableMap(mappings); - } - } - - public static final class Builder { - private static final Predicate DEFAULT_PREDICATE = address -> true; - - private final T object; - private final Class cls; - private Gson gson; - private int port; - private int backlog; - private Predicate filter = DEFAULT_PREDICATE; - - private Builder(@NotNull T object, @NotNull Class cls) { - this.object = object; - this.cls = cls; - this.gson = RestConstants.DEFAULT_GSON; - this.port = 0; - this.backlog = 0; - } - - @NotNull - public Builder setGson(@NotNull Gson gson) { - this.gson = gson; - return this; - } - - @NotNull - public Builder setPort(int port) { - this.port = port; - return this; - } - - @NotNull - public Builder setBacklog(int backlog) { - this.backlog = backlog; - return this; - } - - @NotNull - public Builder setFilter(@NotNull Predicate filter) { - this.filter = filter; - return this; - } - - @NotNull - public RestServer create() { - try { - return new RestServer<>(cls, object, gson, filter, port, backlog); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - } - - private static class Response { - private final T object; - private final Type type; - private final int code; - - public Response(@Nullable T object, @NotNull Type type, int code) { - this.object = object; - this.type = type; - this.code = code; - } - } -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/time/ExtendedDateFormat.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/time/ExtendedDateFormat.java deleted file mode 100644 index 36d734d8e8cbf..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/time/ExtendedDateFormat.java +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jkiss.utils.time; - -import org.jkiss.code.NotNull; - -import java.sql.Timestamp; -import java.text.FieldPosition; -import java.text.ParsePosition; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Locale; - -/** - * Formatter adapted to support nanoseconds from java.sql.Timestanp. - */ -public class ExtendedDateFormat extends SimpleDateFormat { - - private static final String NINE_ZEROES = "000000000"; - private static final int MAX_NANO_LENGTH = 8; - - private int nanoStart = -1, nanoLength; - private boolean nanoOptional; - private String nanoPrefix, nanoPostfix; - - public ExtendedDateFormat(String pattern) - { - this(pattern, Locale.getDefault()); - } - - public ExtendedDateFormat(String pattern, Locale locale) - { - super(stripNanos(pattern), locale); - - int quoteCount = 0; - for (int i = 0; i < pattern.length(); i++) { - char c = pattern.charAt(i); - if (c == '\'') { - quoteCount++; - for (int k = i + 1; k < pattern.length(); k++) { - if (pattern.charAt(k) == '\'') { - if (k != i + 1) { - quoteCount++; - } - i = k; - break; - } - } - } else if (c == '[') { - nanoStart = i; - nanoOptional = true; - for (int k = i + 1; k < pattern.length(); k++) { - if (pattern.charAt(k) == 'f' || pattern.charAt(k) == 'S') { - nanoLength++; - if (nanoPrefix == null) { - nanoPrefix = pattern.substring(i + 1, k); - } - } - if (pattern.charAt(k) == ']') { - if (nanoPrefix == null){ - break; - } - nanoPostfix = pattern.substring(i + 1 + nanoPrefix.length() + nanoLength, k); - i = k + 1; - break; - } - } - } else if (c == 'f' || c == 'S') { - nanoStart = i - quoteCount; - nanoOptional = false; - for (int k = i + 1; k < pattern.length(); k++) { - if (pattern.charAt(k) != 'f' && pattern.charAt(k) != 'S') { - break; - } - nanoLength++; - } - nanoLength++; - i = i + nanoLength; - } - } - } - - @Override - public StringBuffer format(@NotNull Date date, @NotNull StringBuffer toAppendTo, @NotNull FieldPosition pos) - { - StringBuffer result = super.format(date, toAppendTo, pos); - if (nanoStart >= 0) { - long nanos = 0; - if (date instanceof Timestamp) { - nanos = ((Timestamp) date).getNanos(); - } - if (!nanoOptional || nanos > 0) { - StringBuilder nanosRes = new StringBuilder(nanoLength); - // Append nanos value in the end - if (nanoPrefix != null) { - nanosRes.append(nanoPrefix); - } - String nanoStr = String.valueOf(nanos); - - // nanoStr must be a string of exactly 9 chars in length. Pad with leading "0" if not - int nbZeroesToPad = 9 - nanoStr.length(); - if (nbZeroesToPad > 0) { - nanoStr = NINE_ZEROES.substring(0, nbZeroesToPad) + nanoStr; - } - - if (nanoLength < nanoStr.length()) { - // Truncate nanos string to fit in the pattern - nanoStr = nanoStr.substring(0, nanoLength); - } else { - // Pad with 0s - for (int i = 0; i < nanoLength - nanoStr.length(); i++) { - nanosRes.append("0"); - } - } - nanosRes.append(nanoStr); - if (nanoPostfix != null) { - nanosRes.append(nanoPostfix); - } - result.insert(nanoStart, nanosRes.toString()); - } - } - return result; - } - - @Override - public Date parse(@NotNull String text, @NotNull ParsePosition pos) - { - Date date = super.parse(text, pos); - if (date == null) { - return null; - } - int index = pos.getIndex(); - if (index < text.length() && nanoStart > 0) { - long nanos = 0; - if (nanoPrefix != null) { - index += nanoPrefix.length(); - } - for (int i = 0; i < nanoLength; i++) { - int digitPos = index + i; - if (digitPos == text.length()) { - break; - } - char c = text.charAt(digitPos); - if (!Character.isDigit(c)) { - pos.setErrorIndex(index); - pos.setIndex(index); - //throw new ParseException("Invalid nanosecond character at pos " + digitPos + ": " + c, index); - return null; - } - long digit = ((int)c - (int)'0'); - for (int k = MAX_NANO_LENGTH - i; k > 0; k--) { - digit *= 10; - } - nanos += digit; - } - if (nanos > 0) { - Timestamp ts = new Timestamp(date.getTime()); - ts.setNanos((int)nanos); - return ts; - } - } - return date; - } - - private static String stripNanos(String pattern) - { - for (int i = 0; i < pattern.length(); i++) { - char c = pattern.charAt(i); - if (c == '\'') { - for (int k = i + 1; k < pattern.length(); k++) { - if (pattern.charAt(k) == '\'') { - i = k; - break; - } - } - } else if (c == '[') { - for (int k = i + 1; k < pattern.length(); k++) { - if (pattern.charAt(k) == ']') { - return pattern.substring(0, i) + pattern.substring(k + 1); - } - } - } else if (c == 'f' || c == 'S') { - for (int k = i + 1; k < pattern.length(); k++) { - if (pattern.charAt(k) != 'f' && pattern.charAt(k) != 'S') { - return pattern.substring(0, i) + pattern.substring(k); - } - } - return pattern.substring(0, i); - } - } - return pattern; - } - - public static void main(String[] args) - { - test("'TIMESTAMP '''yyyy-MM-dd HH:mm:ss.ffffff''"); - test("yyyy-MM-dd Z hh:mm:ss[.fffffffff]"); - test("yyyy-MM-dd Z hh:mm:ss.fffffffff"); - test("yyyy-MM-dd Z hh:mm:ss"); - test("yyyy-MM-dd Z hh:mm:ss[.fffffffff nanos]"); - test("yyyy-MM-dd Z hh:mm:ss[.ffffff micros]"); - test("yyyy-MM-dd Z hh:mm:ss.ffffff"); - test("yyyy-MM-dd Z hh:mm:ss.f"); // 1/10 secs = 'S' - } - - private static void test(String pattern) - { - ExtendedDateFormat edf = new ExtendedDateFormat(pattern); - Timestamp date = new Timestamp(System.currentTimeMillis()); - System.out.println(edf.format(date)); - date.setNanos(0); - System.out.println(edf.format(date)); - } - -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/xml/SAXListener.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/xml/SAXListener.java deleted file mode 100644 index b3a134cb83c29..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/xml/SAXListener.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jkiss.utils.xml; - -import org.xml.sax.Attributes; - -/** - SAX document listener -*/ -public interface SAXListener { - - void saxStartElement( - SAXReader reader, - String namespaceURI, - String localName, - org.xml.sax.Attributes atts) - throws XMLException; - - void saxText( - SAXReader reader, - String data) - throws XMLException; - - void saxEndElement( - SAXReader reader, - String namespaceURI, - String localName) - throws XMLException; - - - /** - * Empty listener supposed to skip element subtrees - */ - class BaseListener implements SAXListener { - - @Override - public void saxStartElement(SAXReader reader, String namespaceURI, String localName, Attributes atts) throws XMLException { - } - - @Override - public void saxText(SAXReader reader, String data) throws XMLException { - } - - @Override - public void saxEndElement(SAXReader reader, String namespaceURI, String localName) throws XMLException { - } - } - SAXListener EMPTY_LISTENER = new BaseListener(); - -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/xml/SAXReader.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/xml/SAXReader.java deleted file mode 100644 index 831b4a9a50095..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/xml/SAXReader.java +++ /dev/null @@ -1,385 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jkiss.utils.xml; - -import org.xml.sax.*; - -import javax.xml.parsers.FactoryConfigurationError; -import javax.xml.parsers.ParserConfigurationException; -import java.io.IOException; -import java.io.InputStream; -import java.io.Reader; -import java.io.StringReader; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * SAX document reader - */ -public final class SAXReader implements ContentHandler, EntityResolver, DTDHandler { - - public static final int DEFAULT_POOL_SIZE = 10; - - private static javax.xml.parsers.SAXParserFactory saxParserFactory = null; - private static List parsersPool = new ArrayList<>(); - - private org.xml.sax.InputSource inputSource; - private Locator locator; - - private Map attributes = new HashMap<>(); - private List elementLayers = new ArrayList<>(); - private SAXListener curListener; - private StringBuilder textValue = new StringBuilder(); - private int depth = 0; - private boolean handleWhiteSpaces = false; - - /** - * Private constructor. - * Initialize parser. - */ - private SAXReader() { - } - - /** - * Standard constructor. - * Initialize parser and prepare input stream for reading. - */ - public SAXReader(InputStream stream) { - this(); - inputSource = new org.xml.sax.InputSource(stream); - } - - /** - * Standard constructor. - * Initialize parser and prepare input stream for reading. - */ - public SAXReader(Reader reader) { - this(); - inputSource = new org.xml.sax.InputSource(reader); - } - - public boolean isHandleWhiteSpaces() { - return handleWhiteSpaces; - } - - public void setHandleWhiteSpaces( - boolean flag) { - handleWhiteSpaces = flag; - } - - public Locator getLocator() { - return locator; - } - - /** - * Parse input stream and handle XML tags. - */ - public void parse(SAXListener listener) throws IOException, XMLException { - // Initialize SAX parser - Parser parser = acquireParser(); - - // Get reader and parse using SAX2 API - try { - XMLReader saxReader = parser.getSAXParser().getXMLReader(); - saxReader.setFeature(javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING, true ); - saxReader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); - - saxReader.setErrorHandler(new ParseErrorHandler()); - saxReader.setContentHandler(this); - saxReader.setEntityResolver(this); - saxReader.setDTDHandler(this); - - curListener = listener; - - elementLayers.add(listener); - - saxReader.parse(inputSource); - } catch (SAXParseException toCatch) { - throw new XMLException( - "Document parse error (line " + toCatch.getLineNumber() + ", pos " + toCatch.getColumnNumber() + ")", - toCatch); - } catch (SAXException toCatch) { - throw new XMLException( - "Document reading SAX exception", - XMLUtils.adaptSAXException(toCatch)); - } finally { - parser.close(); - } - } - - public synchronized static Parser acquireParser() throws XMLException { - try { - if (saxParserFactory == null) { - try { - saxParserFactory = javax.xml.parsers.SAXParserFactory.newInstance(); - saxParserFactory.setNamespaceAware(true); - saxParserFactory.setValidating(false); - } catch (FactoryConfigurationError toCatch) { - throw new XMLException( - "SAX factory configuration error", - toCatch); - } - } - - for (int i = 0; i < parsersPool.size(); i++) { - Parser parser = parsersPool.get(i); - if (parser != null) { - if (!parser.isAcquired()) { - parser.acquire(); - return parser; - } - } else { - parsersPool.remove(i); - parser = new Parser(saxParserFactory.newSAXParser(), true); - parsersPool.add(parser); - return parser; - } - } - if (parsersPool.size() == DEFAULT_POOL_SIZE) { - throw new XMLException( - "Maximum SAX Parsers Number Exceeded (" + DEFAULT_POOL_SIZE + ")"); - } - Parser parser = new Parser(saxParserFactory.newSAXParser(), true); - parsersPool.add(parser); - return parser; - } catch (ParserConfigurationException toCatch) { - throw new XMLException( - "SAX Parser Configuration error", - toCatch); - } catch (SAXException toCatch) { - throw new XMLException( - "SAX Parser error", - toCatch); - } - } - - /** - * Closes parser and frees all resources. - */ - public void close() { - if (elementLayers != null) { - elementLayers.clear(); - elementLayers = null; - } - inputSource = null; - curListener = null; - } - - /** - * Set listener for next event. - */ - public void setListener( - SAXListener listener) { - curListener = listener; - } - - public boolean hasAttribute( - String name) { - return attributes.get(name) != null; - } - - public Object getAttribute( - String name) { - return attributes.get(name); - } - - public void setAttribute( - String name, - Object value) { - attributes.put(name, value); - } - - public Object removeAttribute( - String name) { - return attributes.remove(name); - } - - private void handleText() - throws SAXException { - curListener = elementLayers.get(elementLayers.size() - 1); - try { - String value = textValue.toString(); - - curListener.saxText(this, value); - } catch (Exception toCatch) { - throw new SAXException(toCatch); - } finally { - textValue.setLength(0); - } - } - - /////////////////////////////////////////////////////////////// - // SAX Context Handler overrides - /////////////////////////////////////////////////////////////// - - @Override - public void startDocument() { - // just do-nothing - } - - @Override - public void endDocument() { - this.close(); - } - - @Override - public void startElement( - String namespaceURI, - String localName, - String qName, - org.xml.sax.Attributes attributes) - throws SAXException { - if (depth++ > 0) { - this.handleText(); - } - - curListener = elementLayers.get(elementLayers.size() - 1); - - try { - curListener.saxStartElement(this, namespaceURI, localName, attributes); - } catch (XMLException toCatch) { - throw new SAXException(toCatch); - } - - elementLayers.add(curListener); - } - - @Override - public void endElement( - String namespaceURI, - String localName, - String qName) - throws SAXException { - this.handleText(); - - elementLayers.remove(elementLayers.size() - 1); - - curListener = elementLayers.get(elementLayers.size() - 1); - try { - curListener.saxEndElement(this, namespaceURI, localName); - } catch (XMLException toCatch) { - throw new SAXException(toCatch); - } - depth--; - } - - @Override - public void startPrefixMapping(String prefix, String uri) { - // just do-nothing - } - - @Override - public void endPrefixMapping(String prefix) { - // just do-nothing - } - - @Override - public void characters(char[] ch, int start, int length) { - textValue.append(ch, start, length); - } - - @Override - public void ignorableWhitespace(char[] ch, int start, int length) { - if (handleWhiteSpaces) { - textValue.append(ch, start, length); - } - } - - @Override - public void processingInstruction(String target, String data) { - // just do-nothing - } - - @Override - public void setDocumentLocator(Locator locator) { - this.locator = locator; - } - - @Override - public void skippedEntity(String name) { - // just do-nothing - } - - @Override - public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { - // Return empty stream - we don't need entities by default - return new InputSource(new StringReader("")); - } - - @Override - public void notationDecl(String name, String publicId, String systemId) throws SAXException { - // do nothing - } - - @Override - public void unparsedEntityDecl(String name, String publicId, String systemId, String notationName) throws SAXException { - // do nothing - } - - static public class Parser { - private javax.xml.parsers.SAXParser saxParser; - private boolean isAcquired; - - public Parser(javax.xml.parsers.SAXParser saxParser, boolean isAcquired) { - this.saxParser = saxParser; - this.isAcquired = isAcquired; - } - - public void setSAXParser(javax.xml.parsers.SAXParser saxParser) { - this.saxParser = saxParser; - } - - public void acquire() { - isAcquired = true; - } - - public void close() { - isAcquired = false; - } - - public javax.xml.parsers.SAXParser getSAXParser() { - return saxParser; - } - - public boolean isAcquired() { - return isAcquired; - } - } - - static class ParseErrorHandler implements org.xml.sax.ErrorHandler { - - @Override - public void error(SAXParseException exception) { - - } - - @Override - public void fatalError(SAXParseException exception) { - - } - - @Override - public void warning(SAXParseException exception) { - - } - - } - - -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/xml/XMLBuilder.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/xml/XMLBuilder.java deleted file mode 100644 index fedec3aec6d3c..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/xml/XMLBuilder.java +++ /dev/null @@ -1,634 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jkiss.utils.xml; - -import org.jkiss.utils.Base64; - -import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Stream oriented XML document builder. - */ -public class XMLBuilder -{ - - public final class Element implements AutoCloseable - { - - private Element parent; - private String name; - private Map nsStack = null; - private int level; - - Element( - Element parent, - String name) - { - this.init(parent, name); - } - - void init( - Element parent, - String name) - { - this.parent = parent; - this.name = name; - this.nsStack = null; - this.level = parent == null ? 0 : parent.level + 1; - } - - public String getName() - { - return name; - } - - public int getLevel() - { - return level; - } - - public void addNamespace(String nsURI, String nsPrefix) - { - if (nsStack == null) { - nsStack = new HashMap<>(); - } - nsStack.put(nsURI, nsPrefix); - } - - public String getNamespacePrefix(String nsURI) - { - if (nsURI.equals(XMLConstants.NS_XML)) { - return XMLConstants.PREFIX_XML; - } - String prefix = (nsStack == null ? null : nsStack.get(nsURI)); - return prefix != null ? - prefix : - (parent != null ? parent.getNamespacePrefix(nsURI) : null); - } - - @Override - public void close() throws IOException { - XMLBuilder.this.endElement(); - } - } - - // At the beginning and after tag closing - private static final int STATE_NOTHING = 0; - // After tag opening - private static final int STATE_ELEM_OPENED = 1; - // After text added - private static final int STATE_TEXT_ADDED = 2; - - private static final int IO_BUFFER_SIZE = 8192; - - private java.io.Writer writer; - - private int state = STATE_NOTHING; - - private Element element = null; - private boolean butify = false; - - private List trashElements = new java.util.ArrayList<>(); - - public XMLBuilder( - java.io.OutputStream stream, - String documentEncoding) - throws java.io.IOException - { - this(stream, documentEncoding, true); - } - - public XMLBuilder( - java.io.OutputStream stream, - String documentEncoding, - boolean printHeader) - throws java.io.IOException - { - if (documentEncoding == null) { - this.init(new java.io.OutputStreamWriter(stream), null, printHeader); - } else { - this.init( - new java.io.OutputStreamWriter(stream, documentEncoding), - documentEncoding, - printHeader); - } - } - - public XMLBuilder( - java.io.Writer writer, - String documentEncoding) - throws java.io.IOException - { - this(writer, documentEncoding, true); - } - - public XMLBuilder( - java.io.Writer writer, - String documentEncoding, - boolean printHeader) - throws java.io.IOException - { - this.init(writer, documentEncoding, printHeader); - } - - private Element createElement( - Element parent, - String name) - { - if (trashElements.isEmpty()) { - return new Element(parent, name); - } else { - Element element = trashElements.remove(trashElements.size() - 1); - element.init(parent, name); - return element; - } - } - - private void deleteElement( - Element element) - { - trashElements.add(element); - } - - private void init( - java.io.Writer writer, - String documentEncoding, - boolean printHeader) - throws java.io.IOException - { - this.writer = new java.io.BufferedWriter(writer, IO_BUFFER_SIZE); - - if (printHeader) { - if (documentEncoding != null) { - this.writer.write(XMLConstants.XML_HEADER(documentEncoding)); - } else { - this.writer.write(XMLConstants.XML_HEADER()); - } - } - } - - public boolean isButify() - { - return butify; - } - - public void setButify(boolean butify) - { - this.butify = butify; - } - - public Element startElement( - String elementName) - throws java.io.IOException - { - return this.startElement(null, null, elementName); - } - - public Element startElement( - String nsURI, - String elementName) - throws java.io.IOException - { - return this.startElement(nsURI, null, elementName); - } - - /* - NS prefix will be used in element name if its directly specified - as nsPrefix parameter or if nsURI has been declared above - */ - public Element startElement( - String nsURI, - String nsPrefix, - String elementName) - throws java.io.IOException - { - switch (state) { - case STATE_ELEM_OPENED: - writer.write('>'); - case STATE_NOTHING: - if (butify) { - writer.write('\n'); - } - break; - default: - break; - } - if (butify) { - if (element != null) { - for (int i = 0; i <= element.getLevel(); i++) { - writer.write('\t'); - } - } - } - writer.write('<'); - - boolean addNamespace = (nsURI != null); - - // If old nsURI specified - use prefix - if (nsURI != null) { - if (nsPrefix == null && element != null) { - nsPrefix = element.getNamespacePrefix(nsURI); - if (nsPrefix != null) { - // Do not add NS declaration - it was declared somewhere above - addNamespace = false; - } - } - } - - // If we have prefix - use it in tag name - if (nsPrefix != null) { - elementName = nsPrefix + ':' + elementName; - } - - writer.write(elementName); - state = STATE_ELEM_OPENED; - - element = this.createElement(element, elementName); - - if (addNamespace) { - this.addNamespace(nsURI, nsPrefix); - element.addNamespace(nsURI, nsPrefix); - } - - return element; - } - - public XMLBuilder endElement() - throws java.io.IOException, IllegalStateException - { - if (element == null) { - throw new IllegalStateException("Close tag without open"); - } - - switch (state) { - case STATE_ELEM_OPENED: - writer.write("/>"); - break; - case STATE_NOTHING: - if (butify) { - writer.write('\n'); - for (int i = 0; i < element.getLevel(); i++) { - writer.write('\t'); - } - } - case STATE_TEXT_ADDED: - writer.write("'); - default: - break; - } - - this.deleteElement(element); - element = element.parent; - state = STATE_NOTHING; - - return this; - } - - public XMLBuilder addNamespace(String nsURI) - throws java.io.IOException - { - return this.addNamespace(nsURI, null); - } - - public XMLBuilder addNamespace( - String nsURI, - String nsPrefix) - throws java.io.IOException, IllegalStateException - { - if (element == null) { - throw new IllegalStateException("Namespace outside of element"); - } - String attrName = XMLConstants.XMLNS; - if (nsPrefix != null) { - attrName = attrName + ':' + nsPrefix; - element.addNamespace(nsURI, nsPrefix); - } - this.addAttribute(null, attrName, nsURI, true); - - return this; - } - - public XMLBuilder addAttribute( - String attributeName, - String attributeValue) - throws java.io.IOException - { - return this.addAttribute(null, attributeName, attributeValue, true); - } - - public XMLBuilder addAttribute( - String attributeName, - int attributeValue) - throws java.io.IOException - { - return this.addAttribute(null, attributeName, String.valueOf(attributeValue), false); - } - - public XMLBuilder addAttribute( - String attributeName, - long attributeValue) - throws java.io.IOException - { - return this.addAttribute(null, attributeName, String.valueOf(attributeValue), false); - } - - public XMLBuilder addAttribute( - String attributeName, - boolean attributeValue) - throws java.io.IOException - { - return this.addAttribute(null, attributeName, String.valueOf(attributeValue), false); - } - - public XMLBuilder addAttribute( - String attributeName, - float attributeValue) - throws java.io.IOException - { - return this.addAttribute(null, attributeName, String.valueOf(attributeValue), false); - } - - public XMLBuilder addAttribute( - String attributeName, - double attributeValue) - throws java.io.IOException - { - return this.addAttribute(null, attributeName, String.valueOf(attributeValue), false); - } - - public XMLBuilder addAttribute( - String nsURI, - String attributeName, - String attributeValue) - throws java.io.IOException - { - return this.addAttribute(nsURI, attributeName, attributeValue, true); - } - - private XMLBuilder addAttribute( - String nsURI, - String attributeName, - String attributeValue, - boolean escape) - throws java.io.IOException, IllegalStateException - { - switch (state) { - case STATE_ELEM_OPENED: { - if (nsURI != null) { - String nsPrefix = element.getNamespacePrefix(nsURI); - if (nsPrefix == null) { - throw new IllegalStateException( - "Unknown attribute '" + attributeName + "' namespace URI '" + nsURI + "' in element '" + element.getName() + "'"); - } - attributeName = nsPrefix + ':' + attributeName; - } - writer.write(' '); - writer.write(attributeName); - writer.write("=\""); - writer.write(escape ? XMLUtils.escapeXml(attributeValue) : attributeValue); - writer.write('"'); - break; - } - case STATE_TEXT_ADDED: - case STATE_NOTHING: - throw new IllegalStateException( - "Attribute ouside of element"); - default: - break; - } - - return this; - } - - public XMLBuilder addText( - CharSequence textValue) - throws java.io.IOException - { - return addText(textValue, true); - } - - public XMLBuilder addText( - CharSequence textValue, - boolean escape) - throws java.io.IOException - { - switch (state) { - case STATE_ELEM_OPENED: - writer.write('>'); - case STATE_TEXT_ADDED: - case STATE_NOTHING: - break; - default: - break; - } - this.writeText(textValue, escape); - - state = STATE_TEXT_ADDED; - - return this; - } - - /** - * Adds entire content of specified reader as text - * - * @param reader text reader - * @return self reference - * @throws java.io.IOException on IO error - */ - public XMLBuilder addText( - java.io.Reader reader) - throws java.io.IOException - { - switch (state) { - case STATE_ELEM_OPENED: - writer.write('>'); - case STATE_TEXT_ADDED: - case STATE_NOTHING: - break; - default: - break; - } - - writer.write(""); - - state = STATE_TEXT_ADDED; - - return this; - } - - public XMLBuilder addTextData( - String text) - throws java.io.IOException - { - switch (state) { - case STATE_ELEM_OPENED: - writer.write('>'); - case STATE_TEXT_ADDED: - case STATE_NOTHING: - break; - default: - break; - } - - writer.write(""); - - state = STATE_TEXT_ADDED; - - return this; - } - - /** - * Adds content of specified stream as Base64 encoded text - * - * @param stream Input content stream - * @param length Content length (this parameter must be correctly specified) - * @return self reference - * @throws java.io.IOException on IO error - */ - public XMLBuilder addBinary( - java.io.InputStream stream, - int length) - throws java.io.IOException - { - switch (state) { - case STATE_ELEM_OPENED: - writer.write('>'); - case STATE_TEXT_ADDED: - case STATE_NOTHING: - break; - default: - break; - } - - Base64.encode(stream, length, writer); - state = STATE_TEXT_ADDED; - - return this; - } - - public XMLBuilder addBinary( - byte[] buffer) - throws java.io.IOException - { - switch (state) { - case STATE_ELEM_OPENED: - writer.write('>'); - case STATE_TEXT_ADDED: - case STATE_NOTHING: - break; - default: - break; - } - - Base64.encode(buffer, 0, buffer.length, writer); - state = STATE_TEXT_ADDED; - - return this; - } - - /** - * Adds character content as is without any escaping or validation - * @param textValue content - * @return self reference - * @throws java.io.IOException - */ - public XMLBuilder addContent( - CharSequence textValue) - throws java.io.IOException - { - writer.write(textValue.toString()); - return this; - } - - public XMLBuilder addComment( - String commentValue) - throws java.io.IOException - { - switch (state) { - case STATE_ELEM_OPENED: - writer.write('>'); - case STATE_NOTHING: - if (butify) { - writer.write('\n'); - } - break; - default: - break; - } - writer.write(""); - if (butify) { - writer.write('\n'); - } - state = STATE_TEXT_ADDED; - - return this; - } - - public XMLBuilder addElement( - String elementName, - String elementValue) - throws java.io.IOException - { - this.startElement(elementName); - this.addText(elementValue); - this.endElement(); - return this; - } - - public XMLBuilder addElementText( - String elementName, - String elementValue) - throws java.io.IOException - { - this.startElement(elementName); - this.addTextData(elementValue); - this.endElement(); - return this; - } - - public XMLBuilder flush() - throws java.io.IOException - { - writer.flush(); - return this; - } - - private XMLBuilder writeText(CharSequence textValue, boolean escape) - throws java.io.IOException - { - if (textValue != null) { - writer.write(escape ? XMLUtils.escapeXml(textValue) : textValue.toString()); - } - return this; - } - -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/xml/XMLConstants.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/xml/XMLConstants.java deleted file mode 100644 index b5ffebc211af0..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/xml/XMLConstants.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jkiss.utils.xml; - -/** - XML Constants -*/ -public class XMLConstants { - - public static final String XMLNS = "xmlns"; - public static final String NS_XML = "http://www.w3.org/TR/REC-xml"; - public static final String PREFIX_XML = "xml"; - public static final String ATTR_LANG = "lang"; - - public static String XML_HEADER() - { - return ""; - } - - public static String XML_HEADER(String encoding) - { - return ""; - } - -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/xml/XMLException.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/xml/XMLException.java deleted file mode 100644 index 4a7fd19099673..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/xml/XMLException.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jkiss.utils.xml; - -/** - * XMLException - */ -public class XMLException extends Exception -{ - public XMLException(String message) - { - super(message); - } - - public XMLException(String message, Throwable cause) - { - super(message, cause); - } - -} diff --git a/bundles/org.jkiss.utils/src/org/jkiss/utils/xml/XMLUtils.java b/bundles/org.jkiss.utils/src/org/jkiss/utils/xml/XMLUtils.java deleted file mode 100644 index 6aa88c4bf15bd..0000000000000 --- a/bundles/org.jkiss.utils/src/org/jkiss/utils/xml/XMLUtils.java +++ /dev/null @@ -1,285 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jkiss.utils.xml; - -import org.jkiss.code.NotNull; -import org.jkiss.code.Nullable; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.xml.sax.InputSource; - -import javax.xml.XMLConstants; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -/** - * Common XML utils - */ -public class XMLUtils { - - public static Document parseDocument(String fileName) - throws XMLException { - return parseDocument(new java.io.File(fileName)); - } - - public static Document parseDocument(java.io.File file) throws XMLException { - try (InputStream is = new FileInputStream(file)) { - return parseDocument(new InputSource(is)); - } catch (IOException e) { - throw new XMLException("Error opening file '" + file + "'", e); - } - } - - public static Document parseDocument(java.io.InputStream is) throws XMLException { - return parseDocument(new InputSource(is)); - } - - public static Document parseDocument(java.io.Reader is) throws XMLException { - return parseDocument(new InputSource(is)); - } - - public static Document parseDocument(InputSource source) throws XMLException { - try { - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); - dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); - DocumentBuilder xmlBuilder = dbf.newDocumentBuilder(); - return xmlBuilder.parse(source); - } catch (Exception er) { - throw new XMLException("Error parsing XML document", er); - } - } - - public static Document createDocument() - throws XMLException { - try { - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - DocumentBuilder xmlBuilder = dbf.newDocumentBuilder(); - return xmlBuilder.newDocument(); - } catch (Exception er) { - throw new XMLException("Error creating XML document", er); - } - } - - public static Element getChildElement(Element element, @NotNull String childName) { - if (element == null) { - return null; - } - for (Node node = element.getFirstChild(); node != null; node = node.getNextSibling()) { - if (node.getNodeType() == Node.ELEMENT_NODE && - ((Element) node).getTagName().equals(childName)) { - return (Element) node; - } - } - return null; - } - - @Nullable - public static String getChildElementBody(Element element, @NotNull String childName) { - if (element == null) { - return null; - } - for (Node node = element.getFirstChild(); node != null; node = node.getNextSibling()) { - if (node.getNodeType() == Node.ELEMENT_NODE && - ((Element) node).getTagName().equals(childName)) { - return getElementBody((Element) node); - } - } - return null; - } - - @Nullable - public static String getElementBody(@NotNull Element element) { - return element.getTextContent(); - } - - // Get list of all child elements of specified node - @NotNull - public static List getChildElementList( - Element parent, - String nodeName) { - List list = new ArrayList<>(); - if (parent != null) { - for (Node node = parent.getFirstChild(); node != null; node = node.getNextSibling()) { - if (node.getNodeType() == Node.ELEMENT_NODE && - nodeName.equals(node.getNodeName())) { - list.add((Element) node); - } - } - } - return list; - } - - // Get list of all child elements of specified node - @NotNull - public static Collection getChildElementListNS( - Element parent, - String nsURI) { - List list = new ArrayList<>(); - if (parent != null) { - for (Node node = parent.getFirstChild(); node != null; node = node.getNextSibling()) { - if (node.getNodeType() == Node.ELEMENT_NODE && - node.getNamespaceURI().equals(nsURI)) { - list.add((Element) node); - } - } - } - return list; - } - - // Get list of all child elements of specified node - public static Collection getChildElementListNS( - Element parent, - String nodeName, - String nsURI) { - List list = new ArrayList<>(); - for (Node node = parent.getFirstChild(); node != null; node = node.getNextSibling()) { - if (node.getNodeType() == Node.ELEMENT_NODE && - node.getLocalName().equals(nodeName) && - node.getNamespaceURI().equals(nsURI)) { - list.add((Element) node); - } - } - return list; - } - - // Get list of all child elements of specified node - @NotNull - public static Collection getChildElementList( - Element parent, - String[] nodeNameList) { - List list = new ArrayList<>(); - for (Node node = parent.getFirstChild(); node != null; node = node.getNextSibling()) { - if (node.getNodeType() == Node.ELEMENT_NODE) { - for (String s : nodeNameList) { - if (node.getNodeName().equals(s)) { - list.add((Element) node); - } - } - } - } - return list; - } - - // Find one child element with specified name - @Nullable - public static Element findChildElement( - Element parent) { - for (Node node = parent.getFirstChild(); node != null; node = node.getNextSibling()) { - if (node.getNodeType() == Node.ELEMENT_NODE) { - return (Element) node; - } - } - return null; - } - - public static Object escapeXml(Object obj) { - if (obj == null) { - return null; - } else if (obj instanceof CharSequence) { - return escapeXml((CharSequence) obj); - } else { - return obj; - } - } - - public static String escapeXml(CharSequence str) { - if (str == null) { - return null; - } - StringBuilder res = null; - int strLength = str.length(); - for (int i = 0; i < strLength; i++) { - char c = str.charAt(i); - String repl = encodeXMLChar(c); - if (repl == null) { - if (res != null) { - res.append(c); - } - } else { - if (res == null) { - res = new StringBuilder(str.length() + 5); - for (int k = 0; k < i; k++) { - res.append(str.charAt(k)); - } - } - res.append(repl); - } - } - return res == null ? str.toString() : res.toString(); - } - - public static boolean isValidXMLChar(char c) { - return (c >= 32 || c == '\n' || c == '\r' || c == '\t'); - } - - /** - * Encodes a char to XML-valid form replacing &,',",<,> with special XML encoding. - * - * @param ch char to convert - * @return XML-encoded text - */ - public static String encodeXMLChar(char ch) { - return switch (ch) { - case '&' -> "&"; - case '\"' -> """; - case '\'' -> "'"; - case '<' -> "<"; - case '>' -> ">"; - default -> null; - }; - } - - public static XMLException adaptSAXException(Exception toCatch) { - if (toCatch instanceof XMLException) { - return (XMLException) toCatch; - } else if (toCatch instanceof org.xml.sax.SAXException) { - String message = toCatch.getMessage(); - Exception embedded = ((org.xml.sax.SAXException) toCatch).getException(); - if (embedded != null && embedded.getMessage() != null && embedded.getMessage().equals(message)) { - // Just SAX wrapper - skip it - return adaptSAXException(embedded); - } else { - return new XMLException( - message, - embedded != null ? adaptSAXException(embedded) : null); - } - } else { - return new XMLException(toCatch.getMessage(), toCatch); - } - } - - public static Collection getChildElementList(Element element) { - List children = new ArrayList<>(); - if (element != null) { - for (Node node = element.getFirstChild(); node != null; node = node.getNextSibling()) { - if (node.getNodeType() == Node.ELEMENT_NODE) { - children.add((Element) node); - } - } - } - return children; - } -} diff --git a/bundles/org.jkiss.wmi/META-INF/MANIFEST.MF b/bundles/org.jkiss.wmi/META-INF/MANIFEST.MF deleted file mode 100644 index ab5ab31700b50..0000000000000 --- a/bundles/org.jkiss.wmi/META-INF/MANIFEST.MF +++ /dev/null @@ -1,11 +0,0 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: WMI native interface -Bundle-SymbolicName: org.jkiss.wmi -Bundle-Version: 2.0.217.qualifier -Bundle-Release-Date: 20240205 -Bundle-RequiredExecutionEnvironment: JavaSE-17 -Bundle-Vendor: DBeaver Corp -Bundle-ActivationPolicy: lazy -Export-Package: org.jkiss.wmi.service -Automatic-Module-Name: org.jkiss.wmi diff --git a/bundles/org.jkiss.wmi/build.properties b/bundles/org.jkiss.wmi/build.properties deleted file mode 100644 index 4a21684e60077..0000000000000 --- a/bundles/org.jkiss.wmi/build.properties +++ /dev/null @@ -1,5 +0,0 @@ -source.. = src/java -output.. = target/classes/ -bin.includes = META-INF/,\ - .,\ - native/ diff --git a/bundles/org.jkiss.wmi/copy_contrib.cmd b/bundles/org.jkiss.wmi/copy_contrib.cmd deleted file mode 100644 index e12c14486d121..0000000000000 --- a/bundles/org.jkiss.wmi/copy_contrib.cmd +++ /dev/null @@ -1,2 +0,0 @@ -copy .\lib\jkiss_wmi_x86.dll ..\..\contrib\drivers\wmi\x86\jkiss_wmi.dll -copy .\lib\jkiss_wmi_x64.dll ..\..\contrib\drivers\wmi\x64\jkiss_wmi.dll \ No newline at end of file diff --git a/bundles/org.jkiss.wmi/native/x86/jkiss_wmi.dll b/bundles/org.jkiss.wmi/native/x86/jkiss_wmi.dll deleted file mode 100644 index 44ef5b99bc066..0000000000000 Binary files a/bundles/org.jkiss.wmi/native/x86/jkiss_wmi.dll and /dev/null differ diff --git a/bundles/org.jkiss.wmi/pom.xml b/bundles/org.jkiss.wmi/pom.xml deleted file mode 100644 index 059aaf840cb96..0000000000000 --- a/bundles/org.jkiss.wmi/pom.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - 4.0.0 - - org.jkiss.dbeaver - bundles - 1.0.0-SNAPSHOT - ../ - - org.jkiss.wmi - 2.0.217-SNAPSHOT - eclipse-plugin - - - ${project.basedir}/src/java - - - diff --git a/bundles/pom.xml b/bundles/pom.xml deleted file mode 100644 index f29f2c9fddaf8..0000000000000 --- a/bundles/pom.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - 4.0.0 - - org.jkiss.dbeaver - dbeaver - 1.0.0-SNAPSHOT - ../ - - bundles - pom - - - org.jkiss.utils - org.jkiss.wmi - - - diff --git a/features/org.jkiss.dbeaver.db.feature/feature.xml b/features/org.jkiss.dbeaver.db.feature/feature.xml index e0b2b97542b5a..52541584cf610 100644 --- a/features/org.jkiss.dbeaver.db.feature/feature.xml +++ b/features/org.jkiss.dbeaver.db.feature/feature.xml @@ -51,7 +51,6 @@ - diff --git a/plugins/org.jkiss.dbeaver.ext.wmi/META-INF/MANIFEST.MF b/plugins/org.jkiss.dbeaver.ext.wmi/META-INF/MANIFEST.MF index 44d6f016fb23e..b8164748ed17a 100644 --- a/plugins/org.jkiss.dbeaver.ext.wmi/META-INF/MANIFEST.MF +++ b/plugins/org.jkiss.dbeaver.ext.wmi/META-INF/MANIFEST.MF @@ -12,8 +12,7 @@ Require-Bundle: org.eclipse.ui, org.eclipse.jface.text, org.jkiss.dbeaver.core, org.jkiss.dbeaver.model, - org.eclipse.ui.workbench.texteditor, - org.jkiss.wmi;visibility:=reexport + org.eclipse.ui.workbench.texteditor Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: JavaSE-17 Bundle-Vendor: DBeaver Corp diff --git a/plugins/org.jkiss.dbeaver.ext.wmi/build.properties b/plugins/org.jkiss.dbeaver.ext.wmi/build.properties index 13a8aa73a6175..6b83020b11ae9 100644 --- a/plugins/org.jkiss.dbeaver.ext.wmi/build.properties +++ b/plugins/org.jkiss.dbeaver.ext.wmi/build.properties @@ -1,7 +1,8 @@ source.. = src/ output.. = target/classes/ bin.includes = .,\ - META-INF/,\ - OSGI-INF/,\ - icons/,\ - plugin.xml + META-INF/,\ + OSGI-INF/,\ + icons/,\ + native/,\ + plugin.xml diff --git a/bundles/org.jkiss.wmi/native/x64/jkiss_wmi.dll b/plugins/org.jkiss.dbeaver.ext.wmi/native/x64/jkiss_wmi.dll similarity index 100% rename from bundles/org.jkiss.wmi/native/x64/jkiss_wmi.dll rename to plugins/org.jkiss.dbeaver.ext.wmi/native/x64/jkiss_wmi.dll diff --git a/bundles/org.jkiss.wmi/src/native/JNIMetaData.cpp b/plugins/org.jkiss.dbeaver.ext.wmi/src-native/JNIMetaData.cpp similarity index 100% rename from bundles/org.jkiss.wmi/src/native/JNIMetaData.cpp rename to plugins/org.jkiss.dbeaver.ext.wmi/src-native/JNIMetaData.cpp diff --git a/bundles/org.jkiss.wmi/src/native/JNIMetaData.h b/plugins/org.jkiss.dbeaver.ext.wmi/src-native/JNIMetaData.h similarity index 100% rename from bundles/org.jkiss.wmi/src/native/JNIMetaData.h rename to plugins/org.jkiss.dbeaver.ext.wmi/src-native/JNIMetaData.h diff --git a/bundles/org.jkiss.wmi/src/native/WMIObject.cpp b/plugins/org.jkiss.dbeaver.ext.wmi/src-native/WMIObject.cpp similarity index 100% rename from bundles/org.jkiss.wmi/src/native/WMIObject.cpp rename to plugins/org.jkiss.dbeaver.ext.wmi/src-native/WMIObject.cpp diff --git a/bundles/org.jkiss.wmi/src/native/WMIObject.h b/plugins/org.jkiss.dbeaver.ext.wmi/src-native/WMIObject.h similarity index 100% rename from bundles/org.jkiss.wmi/src/native/WMIObject.h rename to plugins/org.jkiss.dbeaver.ext.wmi/src-native/WMIObject.h diff --git a/bundles/org.jkiss.wmi/src/native/WMIObjectJNI.cpp b/plugins/org.jkiss.dbeaver.ext.wmi/src-native/WMIObjectJNI.cpp similarity index 100% rename from bundles/org.jkiss.wmi/src/native/WMIObjectJNI.cpp rename to plugins/org.jkiss.dbeaver.ext.wmi/src-native/WMIObjectJNI.cpp diff --git a/bundles/org.jkiss.wmi/src/native/WMIObjectJNI.h b/plugins/org.jkiss.dbeaver.ext.wmi/src-native/WMIObjectJNI.h similarity index 100% rename from bundles/org.jkiss.wmi/src/native/WMIObjectJNI.h rename to plugins/org.jkiss.dbeaver.ext.wmi/src-native/WMIObjectJNI.h diff --git a/bundles/org.jkiss.wmi/src/native/WMIObjectSink.cpp b/plugins/org.jkiss.dbeaver.ext.wmi/src-native/WMIObjectSink.cpp similarity index 100% rename from bundles/org.jkiss.wmi/src/native/WMIObjectSink.cpp rename to plugins/org.jkiss.dbeaver.ext.wmi/src-native/WMIObjectSink.cpp diff --git a/bundles/org.jkiss.wmi/src/native/WMIObjectSink.h b/plugins/org.jkiss.dbeaver.ext.wmi/src-native/WMIObjectSink.h similarity index 100% rename from bundles/org.jkiss.wmi/src/native/WMIObjectSink.h rename to plugins/org.jkiss.dbeaver.ext.wmi/src-native/WMIObjectSink.h diff --git a/bundles/org.jkiss.wmi/src/native/WMIService.cpp b/plugins/org.jkiss.dbeaver.ext.wmi/src-native/WMIService.cpp similarity index 100% rename from bundles/org.jkiss.wmi/src/native/WMIService.cpp rename to plugins/org.jkiss.dbeaver.ext.wmi/src-native/WMIService.cpp diff --git a/bundles/org.jkiss.wmi/src/native/WMIService.h b/plugins/org.jkiss.dbeaver.ext.wmi/src-native/WMIService.h similarity index 100% rename from bundles/org.jkiss.wmi/src/native/WMIService.h rename to plugins/org.jkiss.dbeaver.ext.wmi/src-native/WMIService.h diff --git a/bundles/org.jkiss.wmi/src/native/WMIService.sln b/plugins/org.jkiss.dbeaver.ext.wmi/src-native/WMIService.sln similarity index 100% rename from bundles/org.jkiss.wmi/src/native/WMIService.sln rename to plugins/org.jkiss.dbeaver.ext.wmi/src-native/WMIService.sln diff --git a/bundles/org.jkiss.wmi/src/native/WMIService.vcproj b/plugins/org.jkiss.dbeaver.ext.wmi/src-native/WMIService.vcproj similarity index 100% rename from bundles/org.jkiss.wmi/src/native/WMIService.vcproj rename to plugins/org.jkiss.dbeaver.ext.wmi/src-native/WMIService.vcproj diff --git a/bundles/org.jkiss.wmi/src/native/WMIServiceJNI.cpp b/plugins/org.jkiss.dbeaver.ext.wmi/src-native/WMIServiceJNI.cpp similarity index 100% rename from bundles/org.jkiss.wmi/src/native/WMIServiceJNI.cpp rename to plugins/org.jkiss.dbeaver.ext.wmi/src-native/WMIServiceJNI.cpp diff --git a/bundles/org.jkiss.wmi/src/native/WMIServiceJNI.h b/plugins/org.jkiss.dbeaver.ext.wmi/src-native/WMIServiceJNI.h similarity index 100% rename from bundles/org.jkiss.wmi/src/native/WMIServiceJNI.h rename to plugins/org.jkiss.dbeaver.ext.wmi/src-native/WMIServiceJNI.h diff --git a/bundles/org.jkiss.wmi/src/native/WMIServiceModule.cpp b/plugins/org.jkiss.dbeaver.ext.wmi/src-native/WMIServiceModule.cpp similarity index 100% rename from bundles/org.jkiss.wmi/src/native/WMIServiceModule.cpp rename to plugins/org.jkiss.dbeaver.ext.wmi/src-native/WMIServiceModule.cpp diff --git a/bundles/org.jkiss.wmi/src/native/WMIUtils.cpp b/plugins/org.jkiss.dbeaver.ext.wmi/src-native/WMIUtils.cpp similarity index 100% rename from bundles/org.jkiss.wmi/src/native/WMIUtils.cpp rename to plugins/org.jkiss.dbeaver.ext.wmi/src-native/WMIUtils.cpp diff --git a/bundles/org.jkiss.wmi/src/native/WMIUtils.h b/plugins/org.jkiss.dbeaver.ext.wmi/src-native/WMIUtils.h similarity index 100% rename from bundles/org.jkiss.wmi/src/native/WMIUtils.h rename to plugins/org.jkiss.dbeaver.ext.wmi/src-native/WMIUtils.h diff --git a/bundles/org.jkiss.wmi/src/native/gen_headers.cmd b/plugins/org.jkiss.dbeaver.ext.wmi/src-native/gen_headers.cmd similarity index 100% rename from bundles/org.jkiss.wmi/src/native/gen_headers.cmd rename to plugins/org.jkiss.dbeaver.ext.wmi/src-native/gen_headers.cmd diff --git a/bundles/org.jkiss.wmi/src/native/show_sigs.cmd b/plugins/org.jkiss.dbeaver.ext.wmi/src-native/show_sigs.cmd similarity index 100% rename from bundles/org.jkiss.wmi/src/native/show_sigs.cmd rename to plugins/org.jkiss.dbeaver.ext.wmi/src-native/show_sigs.cmd diff --git a/bundles/org.jkiss.wmi/src/native/stdafx.cpp b/plugins/org.jkiss.dbeaver.ext.wmi/src-native/stdafx.cpp similarity index 100% rename from bundles/org.jkiss.wmi/src/native/stdafx.cpp rename to plugins/org.jkiss.dbeaver.ext.wmi/src-native/stdafx.cpp diff --git a/bundles/org.jkiss.wmi/src/native/stdafx.h b/plugins/org.jkiss.dbeaver.ext.wmi/src-native/stdafx.h similarity index 100% rename from bundles/org.jkiss.wmi/src/native/stdafx.h rename to plugins/org.jkiss.dbeaver.ext.wmi/src-native/stdafx.h diff --git a/bundles/org.jkiss.wmi/src/java/org/jkiss/wmi/service/WMIConstants.java b/plugins/org.jkiss.dbeaver.ext.wmi/src/org/jkiss/wmi/service/WMIConstants.java similarity index 100% rename from bundles/org.jkiss.wmi/src/java/org/jkiss/wmi/service/WMIConstants.java rename to plugins/org.jkiss.dbeaver.ext.wmi/src/org/jkiss/wmi/service/WMIConstants.java diff --git a/bundles/org.jkiss.wmi/src/java/org/jkiss/wmi/service/WMIDataType.java b/plugins/org.jkiss.dbeaver.ext.wmi/src/org/jkiss/wmi/service/WMIDataType.java similarity index 100% rename from bundles/org.jkiss.wmi/src/java/org/jkiss/wmi/service/WMIDataType.java rename to plugins/org.jkiss.dbeaver.ext.wmi/src/org/jkiss/wmi/service/WMIDataType.java diff --git a/bundles/org.jkiss.wmi/src/java/org/jkiss/wmi/service/WMIException.java b/plugins/org.jkiss.dbeaver.ext.wmi/src/org/jkiss/wmi/service/WMIException.java similarity index 100% rename from bundles/org.jkiss.wmi/src/java/org/jkiss/wmi/service/WMIException.java rename to plugins/org.jkiss.dbeaver.ext.wmi/src/org/jkiss/wmi/service/WMIException.java diff --git a/bundles/org.jkiss.wmi/src/java/org/jkiss/wmi/service/WMIObject.java b/plugins/org.jkiss.dbeaver.ext.wmi/src/org/jkiss/wmi/service/WMIObject.java similarity index 100% rename from bundles/org.jkiss.wmi/src/java/org/jkiss/wmi/service/WMIObject.java rename to plugins/org.jkiss.dbeaver.ext.wmi/src/org/jkiss/wmi/service/WMIObject.java diff --git a/bundles/org.jkiss.wmi/src/java/org/jkiss/wmi/service/WMIObjectAttribute.java b/plugins/org.jkiss.dbeaver.ext.wmi/src/org/jkiss/wmi/service/WMIObjectAttribute.java similarity index 100% rename from bundles/org.jkiss.wmi/src/java/org/jkiss/wmi/service/WMIObjectAttribute.java rename to plugins/org.jkiss.dbeaver.ext.wmi/src/org/jkiss/wmi/service/WMIObjectAttribute.java diff --git a/bundles/org.jkiss.wmi/src/java/org/jkiss/wmi/service/WMIObjectElement.java b/plugins/org.jkiss.dbeaver.ext.wmi/src/org/jkiss/wmi/service/WMIObjectElement.java similarity index 100% rename from bundles/org.jkiss.wmi/src/java/org/jkiss/wmi/service/WMIObjectElement.java rename to plugins/org.jkiss.dbeaver.ext.wmi/src/org/jkiss/wmi/service/WMIObjectElement.java diff --git a/bundles/org.jkiss.wmi/src/java/org/jkiss/wmi/service/WMIObjectMethod.java b/plugins/org.jkiss.dbeaver.ext.wmi/src/org/jkiss/wmi/service/WMIObjectMethod.java similarity index 100% rename from bundles/org.jkiss.wmi/src/java/org/jkiss/wmi/service/WMIObjectMethod.java rename to plugins/org.jkiss.dbeaver.ext.wmi/src/org/jkiss/wmi/service/WMIObjectMethod.java diff --git a/bundles/org.jkiss.wmi/src/java/org/jkiss/wmi/service/WMIObjectSink.java b/plugins/org.jkiss.dbeaver.ext.wmi/src/org/jkiss/wmi/service/WMIObjectSink.java similarity index 100% rename from bundles/org.jkiss.wmi/src/java/org/jkiss/wmi/service/WMIObjectSink.java rename to plugins/org.jkiss.dbeaver.ext.wmi/src/org/jkiss/wmi/service/WMIObjectSink.java diff --git a/bundles/org.jkiss.wmi/src/java/org/jkiss/wmi/service/WMIObjectSinkStatus.java b/plugins/org.jkiss.dbeaver.ext.wmi/src/org/jkiss/wmi/service/WMIObjectSinkStatus.java similarity index 100% rename from bundles/org.jkiss.wmi/src/java/org/jkiss/wmi/service/WMIObjectSinkStatus.java rename to plugins/org.jkiss.dbeaver.ext.wmi/src/org/jkiss/wmi/service/WMIObjectSinkStatus.java diff --git a/bundles/org.jkiss.wmi/src/java/org/jkiss/wmi/service/WMIQualifiedObject.java b/plugins/org.jkiss.dbeaver.ext.wmi/src/org/jkiss/wmi/service/WMIQualifiedObject.java similarity index 100% rename from bundles/org.jkiss.wmi/src/java/org/jkiss/wmi/service/WMIQualifiedObject.java rename to plugins/org.jkiss.dbeaver.ext.wmi/src/org/jkiss/wmi/service/WMIQualifiedObject.java diff --git a/bundles/org.jkiss.wmi/src/java/org/jkiss/wmi/service/WMIQualifier.java b/plugins/org.jkiss.dbeaver.ext.wmi/src/org/jkiss/wmi/service/WMIQualifier.java similarity index 100% rename from bundles/org.jkiss.wmi/src/java/org/jkiss/wmi/service/WMIQualifier.java rename to plugins/org.jkiss.dbeaver.ext.wmi/src/org/jkiss/wmi/service/WMIQualifier.java diff --git a/bundles/org.jkiss.wmi/src/java/org/jkiss/wmi/service/WMIService.java b/plugins/org.jkiss.dbeaver.ext.wmi/src/org/jkiss/wmi/service/WMIService.java similarity index 100% rename from bundles/org.jkiss.wmi/src/java/org/jkiss/wmi/service/WMIService.java rename to plugins/org.jkiss.dbeaver.ext.wmi/src/org/jkiss/wmi/service/WMIService.java diff --git a/bundles/org.jkiss.wmi/src/java/org/jkiss/wmi/service/WMISinkStatus.java b/plugins/org.jkiss.dbeaver.ext.wmi/src/org/jkiss/wmi/service/WMISinkStatus.java similarity index 100% rename from bundles/org.jkiss.wmi/src/java/org/jkiss/wmi/service/WMISinkStatus.java rename to plugins/org.jkiss.dbeaver.ext.wmi/src/org/jkiss/wmi/service/WMISinkStatus.java diff --git a/bundles/org.jkiss.wmi/src/java/org/jkiss/wmi/test/TestService.java b/plugins/org.jkiss.dbeaver.ext.wmi/src/org/jkiss/wmi/test/TestService.java similarity index 100% rename from bundles/org.jkiss.wmi/src/java/org/jkiss/wmi/test/TestService.java rename to plugins/org.jkiss.dbeaver.ext.wmi/src/org/jkiss/wmi/test/TestService.java diff --git a/pom.xml b/pom.xml index 08ee5b219140a..49a16b7bc4948 100644 --- a/pom.xml +++ b/pom.xml @@ -3,6 +3,14 @@ xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 4.0.0 + + + com.dbeaver.common + com.dbeaver.common.main + 1.0.0-SNAPSHOT + ../dbeaver-common/pom.xml + + org.jkiss.dbeaver dbeaver 1.0.0-SNAPSHOT @@ -11,19 +19,10 @@ 23.3.4 DBeaver - 4.0.4 - 2023-12 - https://download.eclipse.org/releases - UTF-8 - yyyyMMddHHmm - - 17 - 17 ${dbeaver-version} https://p2.dev.dbeaver.com/eclipse-repo/${local-p2-repo.version} - ${eclipse-repo-url}/${eclipse-version}/ https://download.eclipse.org/tools/orbit/downloads/drops/R20230531010532/repository @@ -32,7 +31,6 @@ - bundles plugins features @@ -43,11 +41,6 @@ ${local-p2-repo.url} p2 - - eclipse-p2-repo - ${eclipse-p2-repo.url} - p2 - orbit-repo ${orbit-repo.url} diff --git a/project.deps b/project.deps new file mode 100644 index 0000000000000..400e936c9701e --- /dev/null +++ b/project.deps @@ -0,0 +1 @@ +dbeaver-common \ No newline at end of file