blob: 0ba665bac5323955ba1d0f844009787581d8f102 [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2009, 2022 Stephan Wahlbrink 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, or the Apache License, Version 2.0
# which is available at https://www.apache.org/licenses/LICENSE-2.0.
#
# SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
#
# Contributors:
# Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
#=============================================================================*/
package org.eclipse.statet.internal.rj.servi;
import static org.eclipse.statet.jcommons.lang.SystemUtils.OS_WIN;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.jcommons.lang.Nullable;
import org.eclipse.statet.jcommons.lang.SystemUtils;
import org.eclipse.statet.jcommons.runtime.CommonsRuntime;
import org.eclipse.statet.jcommons.status.ErrorStatus;
import org.eclipse.statet.jcommons.status.InfoStatus;
import org.eclipse.statet.rj.servi.RServiUtils;
@NonNullByDefault
public class Utils {
public static void preLoad() {
// Load class for errors
new InfoStatus(RServiUtils.RJ_SERVI_ID, Messages.StartNode_error_message);
}
/**
* Utility class to parse command line arguments.
*/
private static class ArgumentParser {
private final String args;
private int index= 0;
private int ch= -1;
public ArgumentParser(final String args) {
this.args= args;
}
public List<String> parseArguments() {
final List<String> v= new ArrayList<>();
this.ch= getNext();
while (this.ch > 0) {
if (Character.isWhitespace((char) this.ch)) {
this.ch= getNext();
}
else {
if (this.ch == '"') {
final StringBuffer buf= new StringBuffer();
buf.append(parseString());
if (buf.length() == 0 && SystemUtils.getLocalOs() == OS_WIN) {
// empty string on windows platform
buf.append("\"\""); //$NON-NLS-1$
}
v.add(buf.toString());
}
else {
v.add(parseToken());
}
}
}
return v;
}
private int getNext() {
if (this.index < this.args.length()) {
return this.args.charAt(this.index++);
}
return -1;
}
private String parseString() {
this.ch= getNext();
if (this.ch == '"') {
this.ch= getNext();
return ""; //$NON-NLS-1$
}
final StringBuffer buf= new StringBuffer();
while (this.ch > 0 && this.ch != '"') {
if (this.ch == '\\') {
this.ch= getNext();
if (this.ch != '"') { // Only escape double quotes
buf.append('\\');
}
else {
if (SystemUtils.getLocalOs() == OS_WIN) {
buf.append('\\');
}
}
}
if (this.ch > 0) {
buf.append((char) this.ch);
this.ch= getNext();
}
}
this.ch= getNext();
return buf.toString();
}
private String parseToken() {
final StringBuffer buf= new StringBuffer();
while (this.ch > 0 && !Character.isWhitespace((char) this.ch)) {
if (this.ch == '\\') {
this.ch= getNext();
if (Character.isWhitespace((char) this.ch)) {
// end of token, don't lose trailing backslash
buf.append('\\');
return buf.toString();
}
if (this.ch > 0) {
if (this.ch != '"') { // Only escape double quotes
buf.append('\\');
}
else {
if (SystemUtils.getLocalOs() == OS_WIN) {
buf.append('\\');
}
}
buf.append((char) this.ch);
this.ch= getNext();
}
else if (this.ch == -1) { // Don't lose a trailing backslash
buf.append('\\');
}
}
else if (this.ch == '"') {
buf.append(parseString());
}
else {
buf.append((char) this.ch);
this.ch= getNext();
}
}
return buf.toString();
}
}
public static List<String> parseArguments(final @Nullable String args) {
if (args == null) {
return new ArrayList<>(0);
}
else {
final ArgumentParser parser= new ArgumentParser(args);
return parser.parseArguments();
}
}
public static void logInfo(final String message) {
CommonsRuntime.log(new InfoStatus(RServiUtils.RJ_SERVI_ID, message));
}
public static void logError(final String message, final Throwable e) {
CommonsRuntime.log(new ErrorStatus(RServiUtils.RJ_SERVI_ID, message, e));
}
public static @Nullable String getProperty(final Properties properties,
final String key, final @Nullable String altKey) {
String s= properties.getProperty(key);
if (s == null && altKey != null) {
s= properties.getProperty(altKey);
}
return s;
}
public static void setProperty(final Properties properties,
final String key, final @Nullable String value) {
if (value != null) {
properties.setProperty(key, value);
}
else {
properties.remove(key);
}
}
public static boolean isNegative(final @Nullable Duration duration) {
return (duration != null && duration.isNegative());
}
private static boolean isSign(final char c) {
return (c == '+' || c == '-');
}
private static boolean isDigit(final char c) {
return (c >= '0' && c <= '9');
}
public static Duration parseDuration(final String s) {
if (!s.isEmpty()
&& (isSign(s.charAt(0)) ?
s.length() >= 2 && isDigit(s.charAt(1)) :
isDigit(s.charAt(0)) )) {
final long millis= Long.parseLong(s);
return Duration.ofMillis(millis);
}
return Duration.parse(s);
}
public static Duration parseDuration(final @Nullable String s,
final Duration defaultValue) {
if (s == null) {
return defaultValue;
}
return parseDuration(s);
}
public static String serDuration(final Duration duration) {
return Long.toString(duration.toMillis());
}
public static @Nullable Duration parseNullableDuration(final String s) {
if (s.isEmpty()) {
return null;
}
if ((isSign(s.charAt(0)) ?
s.length() >= 2 && isDigit(s.charAt(1)) :
isDigit(s.charAt(0)) )) {
final long millis= Long.parseLong(s);
if (millis == -1) {
return null;
}
return Duration.ofMillis(millis);
}
return Duration.parse(s);
}
public static @Nullable Duration parseNullableDuration(final @Nullable String s,
final Duration defaultValue) {
if (s == null) {
return defaultValue;
}
return parseNullableDuration(s);
}
public static String serNullableDuration(final @Nullable Duration duration) {
if (duration == null) {
return "-1"; // for backward compatibility //$NON-NLS-1$
}
return Long.toString(duration.toMillis());
}
private Utils() {
}
}