| /* |
| * Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others. |
| * This program and the accompanying materials are made |
| * available under the terms of the Eclipse Public License 2.0 |
| * which is available at https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Eike Stepper - initial API and implementation |
| */ |
| package org.eclipse.userstorage.internal.util; |
| |
| import java.io.UnsupportedEncodingException; |
| import java.net.URI; |
| import java.net.URISyntaxException; |
| import java.net.URLDecoder; |
| import java.net.URLEncoder; |
| import java.nio.ByteBuffer; |
| import java.nio.charset.Charset; |
| import java.util.Locale; |
| import java.util.Random; |
| |
| /** |
| * @author Eike Stepper |
| */ |
| public final class StringUtil |
| { |
| public static final String EMPTY = ""; //$NON-NLS-1$ |
| |
| public static final String UTF8 = "UTF-8"; //$NON-NLS-1$ |
| |
| private static final byte[] NO_BYTES = {}; |
| |
| private static final byte[] KEY = new byte[256]; |
| |
| private static Random random; |
| |
| private StringUtil() |
| { |
| } |
| |
| public static boolean isEmpty(String str) |
| { |
| return str == null || str.length() == 0; |
| } |
| |
| public static String safe(String str) |
| { |
| return safe(str, EMPTY); |
| } |
| |
| public static String safe(String str, String def) |
| { |
| if (str == null) |
| { |
| return def; |
| } |
| |
| return str; |
| } |
| |
| public static String charToHex(char ch) |
| { |
| return Integer.toHexString(ch).toUpperCase(Locale.ENGLISH); |
| } |
| |
| public static char hexToChar(String s) throws NumberFormatException |
| { |
| return (char)Integer.parseInt(s, 16); |
| } |
| |
| public static byte[] toUTF(String str) throws RuntimeException |
| { |
| if (str == null) |
| { |
| return null; |
| } |
| |
| if (str.length() == 0) |
| { |
| return NO_BYTES; |
| } |
| |
| try |
| { |
| return str.getBytes(UTF8); |
| } |
| catch (UnsupportedEncodingException ex) |
| { |
| throw new RuntimeException(ex); |
| } |
| } |
| |
| public static String fromUTF(byte[] bytes) throws RuntimeException |
| { |
| if (bytes == null) |
| { |
| return null; |
| } |
| |
| if (bytes.length == 0) |
| { |
| return EMPTY; |
| } |
| |
| try |
| { |
| return new String(bytes, UTF8); |
| } |
| catch (UnsupportedEncodingException ex) |
| { |
| throw new RuntimeException(ex); |
| } |
| } |
| |
| public static URI newURI(String uri) throws RuntimeException |
| { |
| if (isEmpty(uri)) |
| { |
| return null; |
| } |
| |
| try |
| { |
| return new URI(uri); |
| } |
| catch (URISyntaxException ex) |
| { |
| throw new RuntimeException(ex); |
| } |
| } |
| |
| public static URI newURI(URI uri, String path) throws RuntimeException |
| { |
| if (isEmpty(path)) |
| { |
| return uri; |
| } |
| |
| String result = uri.toString(); |
| if (!result.endsWith("/")) |
| { |
| result += "/"; |
| } |
| |
| if (path.startsWith("/")) |
| { |
| result += path.substring(1); |
| } |
| else |
| { |
| result += path; |
| } |
| |
| return newURI(result); |
| } |
| |
| public static String encodeURI(URI uri) |
| { |
| return encodeURI(uri.toString()); |
| } |
| |
| public static String decodeURI(String encoded) |
| { |
| try |
| { |
| return URLDecoder.decode(encoded, UTF8); |
| } |
| catch (UnsupportedEncodingException ex) |
| { |
| // UTF-8 should always be available. |
| return encoded; |
| } |
| } |
| |
| public static String encodeURI(String uri) |
| { |
| try |
| { |
| uri = URLEncoder.encode(uri, UTF8); |
| } |
| catch (UnsupportedEncodingException ex) |
| { |
| // UTF-8 should always be available. |
| } |
| |
| return uri; |
| } |
| |
| public static byte[] encrypt(String str) throws RuntimeException |
| { |
| if (str == null) |
| { |
| return null; |
| } |
| |
| if (str.length() == 0) |
| { |
| return NO_BYTES; |
| } |
| |
| byte[] bytes = toUTF(str); |
| byte[] result = new byte[bytes.length + 1]; |
| |
| synchronized (KEY) |
| { |
| if (random == null) |
| { |
| random = new Random(System.currentTimeMillis()); |
| random.nextBytes(KEY); |
| } |
| } |
| |
| int j = random.nextInt(KEY.length); |
| result[bytes.length] = (byte)(j + Byte.MIN_VALUE); |
| crypt(bytes, result, bytes.length, j); |
| return result; |
| } |
| |
| public static String decrypt(byte[] bytes) throws RuntimeException |
| { |
| if (bytes == null) |
| { |
| return null; |
| } |
| |
| if (bytes.length == 0) |
| { |
| return EMPTY; |
| } |
| |
| byte[] result = new byte[bytes.length - 1]; |
| int j = bytes[result.length] - Byte.MIN_VALUE; |
| crypt(bytes, result, result.length, j); |
| return fromUTF(result); |
| } |
| |
| private static void crypt(byte[] bytes, byte[] result, int length, int j) |
| { |
| for (int i = 0; i < length; i++) |
| { |
| result[i] = (byte)(bytes[i] ^ KEY[j++ % KEY.length]); |
| } |
| } |
| |
| public static String join(String joiner, String... values) |
| { |
| if (values.length < 0) |
| { |
| return ""; |
| } |
| else if (values.length == 1) |
| { |
| return values[0]; |
| } |
| |
| StringBuilder sb = new StringBuilder(); |
| for (int i = 0; i < values.length; i++) |
| { |
| sb.append(values[i]); |
| if (i + 1 < values.length) |
| { |
| sb.append(joiner); |
| } |
| } |
| return sb.toString(); |
| } |
| |
| public static char[] decryptAsChars(byte[] bytes) |
| { |
| if (bytes == null) |
| { |
| return null; |
| } |
| |
| if (bytes.length == 0) |
| { |
| return new char[0]; |
| } |
| |
| byte[] result = new byte[bytes.length - 1]; |
| int j = bytes[result.length] - Byte.MIN_VALUE; |
| crypt(bytes, result, result.length, j); |
| return Charset.forName(UTF8).decode(ByteBuffer.wrap(result)).array(); |
| } |
| } |