package org.basex.util;
import java.io.*;
import java.net.*;
import java.nio.file.*;
import java.security.*;
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.*;
import org.basex.core.*;
import org.basex.io.*;
import org.basex.util.options.*;
/**
* This class contains constants and system properties which are used all around the project.
*
* @author BaseX Team 2005-17, BSD License
* @author Christian Gruen
*/
public final class Prop {
/** Global options, assigned by the starter classes and the web.xml context parameters. */
private static final Map<String, String> OPTIONS = new ConcurrentHashMap<>();
/** User's home directory. */
public static final String USERHOME;
/** Application URL. */
public static final URL LOCATION;
static {
// linux: check HOME variable (#773)
final String home = System.getenv("HOME");
USERHOME = dir(home != null ? home : System.getProperty("user.home"));
// retrieve application URL
URL loc = null;
final ProtectionDomain pd = MainOptions.class.getProtectionDomain();
if(pd != null) {
final CodeSource cs = pd.getCodeSource();
if(cs != null) loc = cs.getLocation();
}
LOCATION = loc;
}
/** Project name. */
public static final String NAME = "BaseX";
/** Code version (may contain major, minor and optional patch number). */
public static final String VERSION = version("8.6.4 beta");
/** Main author. */
public static final String AUTHOR = "Christian Gr\u00FCn";
/** Co-authors (1). */
public static final String TEAM1 = "Michael Seiferle, Alexander Holupirek";
/** Co-authors (2). */
public static final String TEAM2 = "Dirk Kirsten, Sabine Teubner, Jagrut Kosti";
/** Entity. */
public static final String ENTITY = NAME + " Team";
/** Project namespace. */
public static final String PROJECT_NAME = NAME.toLowerCase(Locale.ENGLISH);
/** URL. */
public static final String URL = "http://" + PROJECT_NAME + ".org";
/** URL of the community page. */
public static final String COMMUNITY_URL = URL + "/community";
/** URL of the documentation. */
public static final String DOC_URL = "http://docs." + PROJECT_NAME + ".org";
/** URL of the update page. */
public static final String UPDATE_URL = URL + "/products/download/all-downloads/";
/** Version URL. */
public static final String VERSION_URL = "http://files." + PROJECT_NAME + ".org/version.txt";
/** Repository URL. */
public static final String REPO_URL = "http://files." + PROJECT_NAME + ".org/modules";
/** Mail. */
public static final String MAILING_LIST = PROJECT_NAME + "-talk@mailman.uni-konstanz.de";
/** Title and version. */
public static final String TITLE = NAME + ' ' + VERSION;
/** System-specific newline string. */
public static final String NL = System.getProperty("line.separator");
/** Returns the system's default encoding. */
public static final String ENCODING = System.getProperty("file.encoding");
/** System's temporary directory. */
public static final String TMP = dir(System.getProperty("java.io.tmpdir"));
/** OS flag (source: {@code http://lopica.sourceforge.net/os.html}). */
private static final String OS = System.getProperty("os.name");
/** Flag denoting if OS belongs to Mac family. */
public static final boolean MAC = OS.startsWith("Mac");
/** Flag denoting if OS belongs to Windows family. */
public static final boolean WIN = OS.startsWith("Windows");
/** Respect lower/upper case when doing file comparisons. */
public static final boolean CASE = !(MAC || WIN);
/** Prefix for project specific options. */
public static final String DBPREFIX = "org.basex.";
/** System property for specifying database home directory. */
public static final String PATH = DBPREFIX + "path";
/** Directory for storing the property files, database directory, etc. */
public static final String HOME = dir(homeDir());
// STATIC OPTIONS =====================================================================
/** Language (applied after restart). */
public static String language = "English";
/** Flag for prefixing texts with their keys (helps while translating texts). */
public static boolean langkeys;
/** Language direction (right vs. left). */
public static boolean langright;
/** Debug mode. */
public static boolean debug;
/** GUI mode. */
public static boolean gui;
/** Private constructor. */
private Prop() { }
// STATIC METHODS =====================================================================
/**
* <p>Determines the project's home directory for storing property files
* and directories. The directory is chosen as follows:</p>
* <ol>
* <li> First, the <b>system property</b> {@code "org.basex.path"} is checked.
* If it contains a value, it is adopted as home directory.</li>
* <li> If not, the <b>current working directory</b> (defined by the system
* property {@code "user.dir"}) is chosen if the file {@code .basex} or
* {@code .basexhome} is found in this directory.</li>
* <li> Otherwise, the files are searched in the <b>application directory</b>
* (the folder in which the application code is located).</li>
* <li> Otherwise, the <b>user's home directory</b> (defined in
* {@code "user.home"}) is chosen.</li>
* </ol>
* @return path to home directory
*/
private static String homeDir() {
// check for system property
String dir = System.getProperty(PATH);
if(dir != null) return dir;
// not found; check working directory for property file
dir = System.getProperty("user.dir");
final String home = IO.BASEXSUFFIX + "home";
IOFile file = new IOFile(dir, home);
if(!file.exists()) file = new IOFile(dir, IO.BASEXSUFFIX);
if(file.exists()) return file.dir();
// not found; check application directory
if(LOCATION != null) {
try {
dir = new IOFile(Paths.get(LOCATION.toURI()).toString()).dir();
file = new IOFile(dir, home);
if(!file.exists()) file = new IOFile(dir, IO.BASEXSUFFIX);
if(file.exists()) return file.dir();
} catch(final Exception ex) {
Util.stack(ex);
}
}
// not found; choose user home directory as default
return USERHOME;
}
/**
* Attaches a directory separator to the specified directory string.
* @param dir input string
* @return directory string
*/
private static String dir(final String dir) {
return dir.endsWith("\\") || dir.endsWith("/") ? dir : dir + File.separator;
}
/**
* Build version string using data from the JAR manifest.
* @param devVersion version used during development;
* returned if there is no implementation version or no manifest.
* @return version string
*/
private static String version(final String devVersion) {
final String version = Prop.class.getPackage().getImplementationVersion();
if(version == null) return devVersion;
if(!version.contains("-SNAPSHOT")) return version;
final StringBuilder result = new StringBuilder(version.replace("-SNAPSHOT", " beta"));
final Object revision = JarManifest.get("Implementation-Build");
if(revision != null) result.append(' ').append(revision);
return result.toString();
}
/**
* Sets a global option.
* @param option option
* @param value value
*/
public static void put(final Option<?> option, final String value) {
put(key(option), value);
}
/**
* Sets a global option.
* @param name name of the option
* @param value value
*/
public static void put(final String name, final String value) {
OPTIONS.put(name, value);
}
/**
* Removes all global options.
*/
public static void clear() {
OPTIONS.clear();
}
/**
* Returns a system property or global option. System properties override global options.
* @param name name of the option
* @return global option
*/
public static String get(final String name) {
final String value = System.getProperty(name);
return value != null ? value : OPTIONS.get(name);
}
/**
* Returns a system property or global option. System properties override global options.
* @param option option
* @return value, or {@code null}
*/
public static String get(final Option<?> option) {
return get(key(option));
}
/**
* Returns all global options and system properties.
* System properties override global options.
* @return entry set
*/
public static Set<Entry<String, String>> entries() {
// properties from starter classes and web.xml context parameters
final HashMap<String, String> entries = new HashMap<>(OPTIONS);
// override with system properties
for(final Entry<Object, Object> entry : System.getProperties().entrySet()) {
entries.put(entry.getKey().toString(), entry.getValue().toString());
}
return entries.entrySet();
}
/**
* Sets a system property if it has not been set before.
* @param name name of the property
* @param value value
*/
public static void setSystem(final String name, final String value) {
if(System.getProperty(name) == null) System.setProperty(name, value);
}
/**
* Returns the key of an option. The returned key is prefixed with {@link #DBPREFIX}.
* @param option option
* @return key
*/
private static String key(final Option<?> option) {
return DBPREFIX + option.name().toLowerCase(Locale.ENGLISH);
}
}