Java tutorial
/* * Copyright 2019 ThoughtWorks, Inc. * * 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 com.thoughtworks.go.util; import ch.qos.logback.classic.Level; import com.thoughtworks.go.utils.Timeout; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.io.InputStream; import java.io.Serializable; import java.nio.charset.Charset; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Properties; import static org.apache.commons.lang3.StringUtils.isBlank; public class SystemEnvironment implements Serializable, ConfigDirProvider { private static final Logger LOG = LoggerFactory.getLogger(SystemEnvironment.class); private static final long ONE_YEAR = 60 * 60 * 24 * 365; public static final String CRUISE_LISTEN_HOST = "cruise.listen.host"; private static final String CRUISE_DATABASE_PORT = "cruise.database.port"; public static final String CRUISE_SERVER_PORT = "cruise.server.port"; public static final String CRUISE_SERVER_SSL_PORT = "cruise.server.ssl.port"; static final String AGENT_CONNECTION_TIMEOUT_IN_SECONDS = "agent.connection.timeout"; private static final String JETTY_XML = "jetty.xml"; public static final String CRUISE_SERVER_WAR_PROPERTY = "cruise.server.war"; public static final String CRUISE_CONFIG_REPO_DIR = "cruise.config.repo.dir"; private static final String DB_BASE_DIR = "db/"; private static final String DB_DEFAULT_PATH = DB_BASE_DIR + "h2db"; private static final String CONFIG_REPO_DEFAULT_PATH = DB_BASE_DIR + "config.git"; public static final String CRUISE_DB_CACHE_SIZE = "cruise.db.cache.size"; public static final String CRUISE_DB_CACHE_SIZE_DEFAULT = String.valueOf(128 * 1024); // 128MB Cache Size by default public static final String ACTIVEMQ_USE_JMX = "activemq.use.jmx"; public static final String ACTIVEMQ_QUEUE_PREFETCH = "activemq.queue.prefetch"; private static final String ACTIVEMQ_CONNECTOR_PORT = "activemq.conn.port"; public static final String PARENT_LOADER_PRIORITY = "parent.loader.priority"; public static final String AGENT_CONTENT_MD5_HEADER = "Agent-Content-MD5"; public static final String AGENT_LAUNCHER_CONTENT_MD5_HEADER = "Agent-Launcher-Content-MD5"; public static final String AGENT_PLUGINS_ZIP_MD5_HEADER = "Agent-Plugins-Content-MD5"; public static final String AGENT_TFS_SDK_MD5_HEADER = "TFS-SDK-Content-MD5"; public static final String AGENT_EXTRA_PROPERTIES_HEADER = "GoCD-Agent-Extra-Properties"; public static final String EMPTY_STRING = ""; public static final String BLANK_STRING = EMPTY_STRING; public static final String ENFORCE_SERVER_IMMUTABILITY = "go.enforce.server.immutability"; public static final String CONFIGURATION_YES = "Y"; public static final String CONFIGURATION_NO = "N"; public static final String RESOLVE_FANIN_REVISIONS = "resolve.fanin.revisions"; private String hsqlPath = null; public static final String ENABLE_CONFIG_MERGE_PROPERTY = "enable.config.merge"; public static final GoSystemProperty<Boolean> ENABLE_CONFIG_MERGE_FEATURE = new CachedProperty<>( new GoBooleanSystemProperty(ENABLE_CONFIG_MERGE_PROPERTY, Boolean.TRUE)); private String defaultDbPort = "9153"; private static final String DB_UPGRADE_H2_DELTAS_FOLDER = "h2deltas"; private boolean debug; public static final String CRUISE_PROPERTIES = "/cruise.properties"; private Properties properties; public static final String CRUISE_EXPERIMENTAL_ENABLE_ALL = "cruise.experimental.enable-all"; public static final String ARTIFACT_FULL_SIZE_LIMIT = "artifact.full.size.limit"; public static final String DATABASE_FULL_SIZE_LIMIT = "db.full.size.limit"; public static final String ARTIFACT_WARNING_SIZE_LIMIT = "artifact.warning.size.limit"; public static final String DATABASE_WARNING_SIZE_LIMIT = "db.warning.size.limit"; public static final String AGENT_SIZE_LIMIT = "agent.size.limit"; private static final String DISK_SPACE_CACHE_REFRESHER_INTERVAL = "disk.space.cache.refresher.interval"; private static final String COMMAND_REPOSITORY_WARNING_TIMEOUT = "command.repo.warning.timeout"; public static final String AGENT_SOCKET_TYPE_NIO = "nio"; private static final String AGENT_SOCKET_TYPE_PROPERTY = "agent.socket.type"; public static final String CONFIG_FILE_PROPERTY = "cruise.config.file"; public static final String INTERVAL = "cruise.console.publish.interval"; public static final String SERVICE_URL = "serviceUrl"; public static final String AGENT_SSL_VERIFICATION_MODE = "sslVerificationMode"; public static final String AGENT_ROOT_CERT_FILE = "rootCertFile"; public static final String CONFIG_DIR_PROPERTY = "cruise.config.dir"; public static final String DES_CONFIG_CIPHER = "cipher"; public static final String AES_CONFIG_CIPHER = "cipher.aes"; public static final int TFS_SOCKET_TIMEOUT_IN_MILLISECONDS = 20 * 60 * 1000; public static final String TFS_SOCKET_TIMEOUT_PROPERTY = "tfs.socket.block.timeout"; public static GoSystemProperty<Integer> RESOLVE_FANIN_MAX_BACK_TRACK_LIMIT = new CachedProperty<>( new GoIntSystemProperty("resolve.fanin.max.backtrack.limit", 100)); public static GoSystemProperty<Integer> MATERIAL_UPDATE_INACTIVE_TIMEOUT = new CachedProperty<>( new GoIntSystemProperty("material.update.inactive.timeout", 15)); public static GoSystemProperty<Integer> H2_DB_TRACE_LEVEL = new GoIntSystemProperty("h2.trace.level", 1); public static GoSystemProperty<Integer> H2_DB_TRACE_FILE_SIZE_MB = new GoIntSystemProperty( "h2.trace.file.size.mb", 16); private static GoSystemProperty<String> CRUISE_DATABASE_DIR = new GoStringSystemProperty("cruise.database.dir", DB_DEFAULT_PATH); public static final String MATERIAL_UPDATE_IDLE_INTERVAL_PROPERTY = "material.update.idle.interval"; private static GoSystemProperty<Long> MATERIAL_UPDATE_IDLE_INTERVAL = new GoLongSystemProperty( MATERIAL_UPDATE_IDLE_INTERVAL_PROPERTY, 60000L); public static GoSystemProperty<Integer> PLUGIN_LOCATION_MONITOR_INTERVAL_IN_SECONDS = new GoIntSystemProperty( "pluginLocationMonitor.sleepTimeInSecs", -1); public static final String PLUGINS_PATH = "plugins"; public static GoSystemProperty<String> PLUGIN_GO_PROVIDED_PATH = new GoStringSystemProperty( "plugins.go.provided.path", PLUGINS_PATH + System.getProperty("file.separator") + "bundled"); public static GoSystemProperty<String> PLUGIN_EXTERNAL_PROVIDED_PATH = new GoStringSystemProperty( "plugins.external.provided.path", PLUGINS_PATH + System.getProperty("file.separator") + "external"); public static GoSystemProperty<String> PLUGIN_BUNDLE_PATH = new CachedProperty<>( new GoStringSystemProperty("plugins.work.path", "plugins_work")); public static GoSystemProperty<String> PLUGIN_ACTIVATOR_JAR_PATH = new CachedProperty<>( new GoStringSystemProperty("plugins.activator.jar.path", "lib/go-plugin-activator.jar")); public static GoSystemProperty<String> ALL_PLUGINS_ZIP_PATH = new GoStringSystemProperty("plugins.all.zip.path", new File(PLUGINS_PATH, "go-plugins-all.zip").getAbsolutePath()); public static GoSystemProperty<String> ADDONS_PATH = new GoStringSystemProperty("addons.path", "addons"); public static GoSystemProperty<String> AVAILABLE_FEATURE_TOGGLES_FILE_PATH = new GoStringSystemProperty( "available.toggles.path", "/available.toggles"); public static GoSystemProperty<String> USER_FEATURE_TOGGLES_FILE_PATH_RELATIVE_TO_CONFIG_DIR = new GoStringSystemProperty( "user.toggles.path", "go.feature.toggles"); public static GoSystemProperty<String> DEFAULT_COMMAND_SNIPPETS_ZIP = new CachedProperty<>( new GoStringSystemProperty("default.command.snippets.zip.location", "/defaultFiles/defaultCommandSnippets.zip")); public static GoSystemProperty<String> DEFAULT_PLUGINS_ZIP = new CachedProperty<>( new GoStringSystemProperty("default.plugins.zip.location", "/defaultFiles/plugins.zip")); public static final GoSystemProperty<String> AGENT_PLUGINS_PATH = new CachedProperty<>( new GoStringSystemProperty("agent.plugins.path", PLUGINS_PATH)); public static GoSystemProperty<String> VERSION_FILE_IN_DEFAULT_COMMAND_REPOSITORY = new CachedProperty<>( new GoStringSystemProperty("version.file.in.command.repository", "version.txt")); public static GoSystemProperty<Integer> COMMAND_REPOSITORY_CACHE_TIME_IN_SECONDS = new CachedProperty<>( new GoIntSystemProperty("command.repo.cache.timeout.in.secs", 30 * 60)); public static GoSystemProperty<String> COMMAND_REPOSITORY_DIRECTORY = new CachedProperty<>( new GoStringSystemProperty("command.repo.dir", DB_BASE_DIR + "command_repository")); public static GoSystemProperty<Integer> IDLE_TIMEOUT = new GoIntSystemProperty("idle.timeout", 30000); public static GoSystemProperty<Integer> RESPONSE_BUFFER_SIZE = new GoIntSystemProperty("response.buffer.size", 32768); public static final GoSystemProperty<Integer> API_REQUEST_IDLE_TIMEOUT_IN_SECONDS = new GoIntSystemProperty( "api.request.idle.timeout.seconds", 300); public static final GoSystemProperty<Integer> AGENT_REQUEST_IDLE_TIMEOUT_IN_SECONDS = new GoIntSystemProperty( "agent.request.idle.timeout.seconds", 30); public static final GoSystemProperty<Integer> GO_SERVER_SESSION_TIMEOUT_IN_SECONDS = new GoIntSystemProperty( "go.server.session.timeout.seconds", 60 * 60 * 24 * 14); public static final GoSystemProperty<Integer> GO_SERVER_SESSION_COOKIE_MAX_AGE_IN_SECONDS = new GoIntSystemProperty( "go.sessioncookie.maxage.seconds", 60 * 60 * 24 * 14); public static final GoSystemProperty<Boolean> GO_SERVER_SESSION_COOKIE_SECURE = new GoBooleanSystemProperty( "go.sessioncookie.secure", false); public static final GoSystemProperty<String> AGENT_EXTRA_PROPERTIES = new GoStringSystemProperty( "gocd.agent.extra.properties", ""); public static final GoSystemProperty<Integer> JMS_LISTENER_BACKOFF_TIME = new GoIntSystemProperty( "go.jms.listener.backoff.time.in.milliseconds", 5000); public static final GoSystemProperty<Integer> GO_SERVER_AUTHORIZATION_EXTENSION_CALLS_CACHE_TIMEOUT_IN_SECONDS = new GoIntSystemProperty( "go.server.authorization.extension.calls.cache.timeout.in.secs", 60 * 30); /* DATABASE CONFIGURATION - Defaults are of H2 */ public static GoSystemProperty<String> GO_DATABASE_HOST = new GoStringSystemProperty("db.host", "localhost"); public static GoSystemProperty<String> GO_DATABASE_PORT = new GoStringSystemProperty("db.port", ""); public static GoSystemProperty<String> GO_DATABASE_NAME = new GoStringSystemProperty("db.name", "cruise"); public static GoSystemProperty<String> GO_DATABASE_USER = new GoStringSystemProperty("db.user", "sa"); public static GoSystemProperty<String> GO_DATABASE_PASSWORD = new GoStringSystemProperty("db.password", ""); public static GoIntSystemProperty GO_DATABASE_MAX_ACTIVE = new GoIntSystemProperty("db.maxActive", 32); public static GoIntSystemProperty GO_DATABASE_MAX_IDLE = new GoIntSystemProperty("db.maxIdle", 32); public static final String H2_DATABASE = "com.thoughtworks.go.server.database.H2Database"; public static GoStringSystemProperty GO_DATABASE_PROVIDER = new GoStringSystemProperty("go.database.provider", H2_DATABASE); public static GoSystemProperty<String> JETTY_XML_FILE_NAME = new GoStringSystemProperty("jetty.xml.file.name", JETTY_XML); public static final String JETTY9 = "com.thoughtworks.go.server.Jetty9Server"; public static GoSystemProperty<String> APP_SERVER = new CachedProperty<>( new GoStringSystemProperty("app.server", JETTY9)); public static GoSystemProperty<String> GO_SERVER_STATE = new GoStringSystemProperty("go.server.state", "active"); public static GoSystemProperty<String> GO_LANDING_PAGE = new GoStringSystemProperty("go.landing.page", "/pipelines"); public static GoSystemProperty<Boolean> FETCH_ARTIFACT_AUTO_SUGGEST = new GoBooleanSystemProperty( "go.fetch-artifact.auto-suggest", true); public static GoSystemProperty<Boolean> GO_FETCH_ARTIFACT_TEMPLATE_AUTO_SUGGEST = new GoBooleanSystemProperty( "go.fetch-artifact.template.auto-suggest", true); public static GoSystemProperty<String> GO_SSL_TRANSPORT_PROTOCOL_TO_BE_USED_BY_AGENT = new GoStringSystemProperty( "go.ssl.agent.protocol", "TLSv1.2"); public static GoSystemProperty<String> GO_SSL_CERTS_ALGORITHM = new GoStringSystemProperty( "go.ssl.cert.algorithm", "SHA512WITHRSA"); public static GoSystemProperty<String> GO_SSL_CERTS_PUBLIC_KEY_ALGORITHM = new GoStringSystemProperty( "go.ssl.cert.public-key.algorithm", "SHA256WithRSAEncryption"); public static GoSystemProperty<Boolean> GO_SSL_CONFIG_CLEAR_JETTY_DEFAULT_EXCLUSIONS = new GoBooleanSystemProperty( "go.ssl.config.clear.default.exclusions", true); public static GoSystemProperty<String[]> GO_SSL_INCLUDE_CIPHERS = new GoStringArraySystemProperty( "go.ssl.ciphers.include", null); public static GoSystemProperty<String[]> GO_SSL_EXCLUDE_CIPHERS = new GoStringArraySystemProperty( "go.ssl.ciphers.exclude", null); public static GoSystemProperty<String[]> GO_SSL_INCLUDE_PROTOCOLS = new GoStringArraySystemProperty( "go.ssl.protocols.include", null); public static GoSystemProperty<String[]> GO_SSL_EXCLUDE_PROTOCOLS = new GoStringArraySystemProperty( "go.ssl.protocols.exclude", null); public static GoSystemProperty<Boolean> GO_SSL_RENEGOTIATION_ALLOWED = new GoBooleanSystemProperty( "go.ssl.renegotiation.allowed", true); public static GoSystemProperty<Boolean> GO_CONFIG_REPO_GC_AGGRESSIVE = new GoBooleanSystemProperty( "go.config.repo.gc.aggressive", true); public static GoSystemProperty<Long> GO_CONFIG_REPO_GC_EXPIRE = new GoLongSystemProperty( "go.config.repo.gc.expire", 24L); public static GoSystemProperty<Long> GO_CONFIG_REPO_GC_LOOSE_OBJECT_WARNING_THRESHOLD = new GoLongSystemProperty( "go.config.repo.gc.warning.looseobject.threshold", 10000L); public static GoSystemProperty<Boolean> GO_CONFIG_REPO_PERIODIC_GC = new GoBooleanSystemProperty( "go.config.repo.gc.periodic", false); public static GoSystemProperty<String> GO_UPDATE_SERVER_PUBLIC_KEY_FILE_NAME = new GoStringSystemProperty( "go.update.server.public.key.file.name", "go_update_server.pub"); public static GoSystemProperty<String> GO_UPDATE_SERVER_URL = new GoStringSystemProperty("go.update.server.url", "https://update.gocd.org/channels/supported/latest.json"); public static GoSystemProperty<Boolean> GO_CHECK_UPDATES = new GoBooleanSystemProperty("go.check.updates", true); public static GoSystemProperty<String> GO_DATA_SHARING_POST_USAGE_DATA_SERVER_URL = new GoStringSystemProperty( "go.datasharing.server.url", "https://datasharing.gocd.org/v2/usagedata"); public static GoSystemProperty<String> GO_DATA_SHARING_GET_ENCRYPTION_KEYS_URL = new GoStringSystemProperty( "go.datasharing.get.encryption.keys.url", "https://datasharing.gocd.org/encryption_keys"); public static GoSystemProperty<Integer> GO_ELASTIC_PLUGIN_CREATE_AGENT_THREADS = new GoIntSystemProperty( "go.elasticplugin.createagent.threads", 5); public static GoSystemProperty<Integer> GO_ELASTIC_PLUGIN_SERVER_PING_THREADS = new GoIntSystemProperty( "go.elasticplugin.serverping.threads", 1); public static GoSystemProperty<Integer> GO_ENCRYPTION_API_MAX_REQUESTS = new GoIntSystemProperty( "go.encryption.api.max.requests", 30); public static GoSystemProperty<Boolean> AUTO_REGISTER_LOCAL_AGENT_ENABLED = new GoBooleanSystemProperty( "go.auto.register.local.agent.enabled", true); public static GoSystemProperty<Boolean> GO_SERVER_SHALLOW_CLONE = new GoBooleanSystemProperty( "go.server.shallowClone", false); public static GoSystemProperty<Boolean> GO_SERVER_SCHEDULED_PIPELINE_LOADER_GLOBAL_MATERIAL_LOOKUP = new GoBooleanSystemProperty( "go.server.scheduledPipelineLoader.globalMaterialLookup", false); public static GoSystemProperty<Boolean> GO_API_WITH_SAFE_MODE = new GoBooleanSystemProperty( "go.api.with.safe.mode", true); public static GoSystemProperty<Integer> MAX_PENDING_AGENTS_ALLOWED = new GoIntSystemProperty( "max.pending.agents.allowed", 100); public static GoSystemProperty<Boolean> CHECK_AND_REMOVE_DUPLICATE_MODIFICATIONS = new GoBooleanSystemProperty( "go.modifications.removeDuplicates", true); public static GoSystemProperty<String> GO_AGENT_KEYSTORE_PASSWORD = new GoStringSystemProperty( "go.agent.keystore.password", "agent5s0repa55w0rd"); public static GoSystemProperty<String> GO_SERVER_KEYSTORE_PASSWORD = new GoStringSystemProperty( "go.server.keystore.password", "serverKeystorepa55w0rd"); private static final GoSystemProperty<Boolean> GO_AGENT_USE_SSL_CONTEXT = new GoBooleanSystemProperty( "go.agent.reuse.ssl.context", true); public static final GoSystemProperty<Boolean> ENABLE_BUILD_COMMAND_PROTOCOL = new GoBooleanSystemProperty( "go.agent.enableBuildCommandProtocol", false); public static final GoSystemProperty<Boolean> GO_DIAGNOSTICS_MODE = new GoBooleanSystemProperty( "go.diagnostics.mode", false); public static GoIntSystemProperty DEPENDENCY_MATERIAL_UPDATE_LISTENERS = new GoIntSystemProperty( "dependency.material.check.threads", 3); public static GoIntSystemProperty CONFIG_MATERIAL_POST_UPDATE_LISTENERS = new GoIntSystemProperty( "config.material.post.update.threads", 2); public static GoSystemProperty<String> GO_SERVER_MODE = new GoStringSystemProperty("go.server.mode", "production"); public static GoBooleanSystemProperty REAUTHENTICATION_ENABLED = new GoBooleanSystemProperty( "go.security.reauthentication.enabled", true); public static GoSystemProperty<Long> REAUTHENTICATION_TIME_INTERVAL = new GoLongSystemProperty( "go.security.reauthentication.interval", 1800 * 1000L); public static GoSystemProperty<Boolean> CONSOLE_OUT_TO_STDOUT = new GoBooleanSystemProperty("go.console.stdout", false); private static GoSystemProperty<String> CONSOLE_LOG_CHARSET = new GoStringSystemProperty( "go.console.log.charset", "utf-8"); private static GoSystemProperty<Boolean> AGENT_STATUS_API_ENABLED = new GoBooleanSystemProperty( "go.agent.status.api.enabled", true); private static GoSystemProperty<String> AGENT_STATUS_API_BIND_HOST = new GoStringSystemProperty( "go.agent.status.api.bind.host", "localhost"); private static GoSystemProperty<Integer> AGENT_STATUS_API_BIND_PORT = new GoIntSystemProperty( "go.agent.status.api.bind.port", 8152); private static GoSystemProperty<Integer> GO_SPA_TIMEOUT = new GoIntSystemProperty("go.spa.timeout", 60000); private static GoSystemProperty<Integer> GO_SPA_REFRESH_INTERVAL = new GoIntSystemProperty( "go.spa.refresh.interval", 10000); private static GoSystemProperty<Boolean> ENABLE_ANALYTICS_ONLY_FOR_ADMINS = new GoBooleanSystemProperty( "go.enable.analytics.only.for.admins", false); public static final GoSystemProperty<Boolean> FAIL_STARTUP_ON_DATA_ERROR = new GoBooleanSystemProperty( "gocd.fail.startup.on.data.error", false); private static final GoSystemProperty<Boolean> JOB_DETAILS_USE_IFRAME_SANDBOX = new GoBooleanSystemProperty( "gocd.job.details.sandbox", true); private static GoSystemProperty<Boolean> GO_PLUGIN_CLASSLOADER_OLD = new GoBooleanSystemProperty( "gocd.plugins.classloader.old", false); public static final GoSystemProperty<String> LOADING_PAGE = new GoStringSystemProperty( "loading.page.resource.path", "/loading_pages/new.loading.page.html"); public static GoSystemProperty<Long> NOTIFICATION_PLUGIN_MESSAGES_TTL = new GoLongSystemProperty( "plugins.notification.message.ttl.millis", 2 * 60 * 1000L); public static GoSystemProperty<Boolean> ENABLE_HSTS_HEADER = new GoBooleanSystemProperty( "gocd.enable.hsts.header", false); public static GoSystemProperty<Long> HSTS_HEADER_MAX_AGE = new GoLongSystemProperty("gocd.hsts.header.max.age", ONE_YEAR); public static GoSystemProperty<Boolean> HSTS_HEADER_INCLUDE_SUBDOMAINS = new GoBooleanSystemProperty( "gocd.hsts.header.include.subdomains", false); public static GoSystemProperty<Boolean> HSTS_HEADER_PRELOAD = new GoBooleanSystemProperty( "gocd.hsts.header.preload", false); private final static Map<String, String> GIT_ALLOW_PROTOCOL; static { Map<String, String> map = new HashMap<String, String>() { { put("GIT_ALLOW_PROTOCOL", System.getenv("GIT_ALLOW_PROTOCOL") == null ? "http:https:ssh:git:file:rsync" : System.getenv("GIT_ALLOW_PROTOCOL")); } }; GIT_ALLOW_PROTOCOL = Collections.unmodifiableMap(map); } private volatile static Integer agentConnectionTimeout; private volatile static Integer cruiseSSlPort; private volatile static String cruiseConfigDir; private volatile static Long databaseFullSizeLimit; private volatile static Charset consoleLogCharsetAsCharset; private volatile static Long artifactFullSizeLimit; private volatile static Long diskSpaceCacheRefresherInterval; public static final String UNRESPONSIVE_JOB_WARNING_THRESHOLD = "cruise.unresponsive.job.warning"; private File configDir; private volatile Boolean enforceRevisionCompatibilityWithUpstream; public SystemEnvironment() { } public SystemEnvironment(Properties properties) { this.properties = properties; } public SystemEnvironment(String hsqlPath, String defaultDbPort) { if (defaultDbPort == null) { throw ExceptionUtils.bomb("Default db port cannot be null"); } this.hsqlPath = hsqlPath; this.defaultDbPort = defaultDbPort; debug = getPropertyImpl("DB_DEBUG_MODE") != null && !(getPropertyImpl("DB_DEBUG_MODE").equals("false")); } public <T> T get(GoSystemProperty<T> systemProperty) { return systemProperty.getValue(); } public <T> void set(GoSystemProperty<T> systemProperty, T value) { System.setProperty(systemProperty.propertyName, "" + value); if (systemProperty instanceof CachedProperty) { ((CachedProperty) systemProperty).clear(); } } public void set(GoSystemProperty<Boolean> systemProperty, boolean value) { System.setProperty(systemProperty.propertyName, value ? "Y" : "N"); if (systemProperty instanceof CachedProperty) { ((CachedProperty) systemProperty).clear(); } } public File configDir() { if (configDir == null) { configDir = new File(getPropertyImpl(CONFIG_FILE_PROPERTY, "config/cruise-config.xml")).getParentFile(); } return configDir; } public File keystore() { return new File(configDir(), "keystore"); } public File truststore() { return new File(configDir(), "truststore"); } public File agentkeystore() { return new File(configDir(), "agentkeystore"); } public int getServerPort() { return Integer.parseInt(getPropertyImpl(CRUISE_SERVER_PORT, "8153")); } public String getListenHost() { return getPropertyImpl(CRUISE_LISTEN_HOST); } public long getArtifactReposiotryFullLimit() { if (artifactFullSizeLimit != null) { return artifactFullSizeLimit; } return artifactFullSizeLimit = Long .parseLong(trimMegaFromSize(getPropertyImpl(ARTIFACT_FULL_SIZE_LIMIT, "100M"))); } public long getDatabaseDiskSpaceFullLimit() { if (databaseFullSizeLimit != null) { return databaseFullSizeLimit; } return databaseFullSizeLimit = Long .parseLong(trimMegaFromSize(getPropertyImpl(DATABASE_FULL_SIZE_LIMIT, "100M"))); } public long getDiskSpaceCacheRefresherInterval() { if (diskSpaceCacheRefresherInterval != null) { return diskSpaceCacheRefresherInterval; } return diskSpaceCacheRefresherInterval = Long .parseLong(getPropertyImpl(DISK_SPACE_CACHE_REFRESHER_INTERVAL, "5000")); } public boolean consoleOutToStdout() { return get(CONSOLE_OUT_TO_STDOUT); } //Used in Tests public void setDiskSpaceCacheRefresherInterval(long interval) { diskSpaceCacheRefresherInterval = interval; } public long getAgentSizeLimit() { return Long.parseLong(trimMegaFromSize(getPropertyImpl(AGENT_SIZE_LIMIT, "100M"))) * 1024 * 1024; } public long getArtifactReposiotryWarningLimit() { return Long.parseLong(trimMegaFromSize(getPropertyImpl(ARTIFACT_WARNING_SIZE_LIMIT, "1024M"))); } public long getDatabaseDiskSpaceWarningLimit() { return Long.parseLong(trimMegaFromSize(getPropertyImpl(DATABASE_WARNING_SIZE_LIMIT, "1024M"))); } private String trimMegaFromSize(String sizeInMega) { return StringUtils.removeEndIgnoreCase(sizeInMega, "M"); } public int getSslServerPort() { if (cruiseSSlPort != null) { return cruiseSSlPort; } return cruiseSSlPort = Integer.parseInt(getPropertyImpl(CRUISE_SERVER_SSL_PORT, "8154")); } public String getConfigDir() { if (cruiseConfigDir != null) { return cruiseConfigDir; } return cruiseConfigDir = getPropertyImpl(CONFIG_DIR_PROPERTY, "config"); } public File getJettyConfigFile() { return new File(getConfigDir(), get(JETTY_XML_FILE_NAME)); } /** * @deprecated use <code>new SystemEnvironment().getXXXXX()</code> instead. */ public static String getProperty(String property, String defaultValue) { return new SystemEnvironment().getPropertyImpl(property, defaultValue); } /** * @deprecated use <code>new SystemEnvironment().getXXXXX()</code> instead. */ public static String getProperty(String property) { return new SystemEnvironment().getPropertyImpl(property); } private String getPropertyImpl(String property, String defaultValue) { return System.getProperty(property, defaultValue); } public String getPropertyImpl(String property) { return System.getProperty(property); } public String getOperatingSystemFamilyName() { return OperatingSystem.getFamilyName(); } public String getOperatingSystemCompleteName() { return OperatingSystem.getCompleteName(); } public String getOperatingSystemName() { return getPropertyImpl("os.name"); } public int getDatabaseSeverPort() { String port = getDatabasePort(); try { return Integer.parseInt(port); } catch (NumberFormatException e) { LOG.info("Could not parse port={}", port); } return Integer.parseInt(defaultDbPort); } private String getDatabasePort() { String port = getPropertyImpl(CRUISE_DATABASE_PORT); if (port == null) { port = defaultDbPort; } return port; } public boolean getEnableRequestTimeLogging() { return Boolean.parseBoolean(getPropertyImpl("cruise.request.time.logging", "false")); } public int getActivemqQueuePrefetch() { return Integer.parseInt(getPropertyImpl(ACTIVEMQ_QUEUE_PREFETCH, "0")); } public long getCommandRepoWarningTimeout() { return Long.parseLong( getPropertyImpl(COMMAND_REPOSITORY_WARNING_TIMEOUT, String.valueOf(Timeout.ONE_HOUR.inMillis()))); } public boolean getActivemqUseJmx() { return Boolean.parseBoolean(getPropertyImpl(ACTIVEMQ_USE_JMX, "false")); } public int getActivemqConnectorPort() { return Integer.parseInt(getPropertyImpl(ACTIVEMQ_CONNECTOR_PORT, "1099")); } public String getScriptPath() { return new File(getDbPath(), "cruise").getAbsolutePath(); } public File getDBDeltasPath() { return new File(getDbFolder(), DB_UPGRADE_H2_DELTAS_FOLDER); } public File getDbPath() { if (hsqlPath == null) { hsqlPath = get(CRUISE_DATABASE_DIR); } return new File(hsqlPath); } public File getConfigRepoDir() { return new File(properties().getProperty(CRUISE_CONFIG_REPO_DIR, CONFIG_REPO_DEFAULT_PATH)); } public File getDESCipherFile() { return new File(getConfigDir(), DES_CONFIG_CIPHER); } public File getAESCipherFile() { return new File(getConfigDir(), AES_CONFIG_CIPHER); } public File getDbFolder() { return getDbPath().getParentFile(); } public int getNumberOfMaterialCheckListener() { return Integer.parseInt(getPropertyImpl("material.check.threads", "10")); } public int getNumberOfConfigMaterialCheckListener() { return Integer.parseInt(getPropertyImpl("material.config.check.threads", "2")); } public int getNumberOfDependencyMaterialUpdateListeners() { return DEPENDENCY_MATERIAL_UPDATE_LISTENERS.getValue(); } public int getNumberOfConfigMaterialPostUpdateListeners() { return CONFIG_MATERIAL_POST_UPDATE_LISTENERS.getValue(); } public String getAgentMd5() { return getPropertyImpl(GoConstants.AGENT_JAR_MD5, BLANK_STRING); } public String getTfsImplMd5() { return getPropertyImpl(GoConstants.TFS_IMPL_MD5, BLANK_STRING); } public String getGivenAgentLauncherMd5() { return getPropertyImpl(GoConstants.GIVEN_AGENT_LAUNCHER_JAR_MD5, BLANK_STRING); } public String getAgentPluginsMd5() { return getPropertyImpl(GoConstants.AGENT_PLUGINS_MD5, BLANK_STRING); } public boolean inDbDebugMode() { return debug; } public boolean usingRemoteDb() { return getPropertyImpl("DB_REMOTE") != null && !(getPropertyImpl("DB_REMOTE").equals("false")); } public void setDebugMode(boolean debug) { this.debug = debug; } public boolean isFeatureEnabled(String value) { if (Boolean.parseBoolean(properties().getProperty(CRUISE_EXPERIMENTAL_ENABLE_ALL, "false"))) { return true; } return Boolean.parseBoolean(properties().getProperty(value, "false")); } private Properties properties() { if (properties == null) { properties = new Properties(); try (InputStream is = getClass().getResourceAsStream(CRUISE_PROPERTIES)) { properties.load(is); } catch (Exception e) { LOG.error("Unable to load newProperties file {}", CRUISE_PROPERTIES); } } return properties; } public boolean useNioSslSocket() { String socketType = getPropertyImpl(AGENT_SOCKET_TYPE_PROPERTY, AGENT_SOCKET_TYPE_NIO); return AGENT_SOCKET_TYPE_NIO.equalsIgnoreCase(socketType); } public String getCruiseConfigFile() { return getPropertyImpl(CONFIG_FILE_PROPERTY, getConfigDir() + "/cruise-config.xml"); } public int getAgentConnectionTimeout() { if (agentConnectionTimeout != null) { return agentConnectionTimeout; } return agentConnectionTimeout = Integer .parseInt(getPropertyImpl(AGENT_CONNECTION_TIMEOUT_IN_SECONDS, "300")); } public Integer getConsolePublishInterval() { return Integer.valueOf(getPropertyImpl(INTERVAL, "10")); } public String getServiceUrl() { return getPropertyImpl(SERVICE_URL, defaultRemotingUrl()); } public File getRootCertFile() { if (getPropertyImpl(AGENT_ROOT_CERT_FILE) == null) { return null; } return new File(getPropertyImpl(AGENT_ROOT_CERT_FILE)); } public SslVerificationMode getAgentSslVerificationMode() { if (getPropertyImpl(AGENT_SSL_VERIFICATION_MODE) == null) { return SslVerificationMode.NONE; } return SslVerificationMode.valueOf(getPropertyImpl(AGENT_SSL_VERIFICATION_MODE)); } private String defaultRemotingUrl() { return "https://localhost:8443" + getWebappContextPath(); } public boolean useCompressedJs() { return Boolean.parseBoolean(getPropertyImpl(GoConstants.USE_COMPRESSED_JAVASCRIPT, "true")); } public String getEnvironmentVariable(String key, String defaultValue) { return System.getenv().getOrDefault(key, defaultValue); } public Map<String, String> getGitAllowedProtocols() { return GIT_ALLOW_PROTOCOL; } public void setProperty(String name, String value) { clearCachedSystemEnvironment(); System.setProperty(name, value); } public void clearProperty(String name) { clearCachedSystemEnvironment(); System.clearProperty(name); } private void clearCachedSystemEnvironment() { agentConnectionTimeout = null; cruiseSSlPort = null; cruiseConfigDir = null; databaseFullSizeLimit = null; artifactFullSizeLimit = null; consoleLogCharsetAsCharset = null; } public String getWebappContextPath() { return getPropertyImpl("cruise.server.context", "/go"); } public String pathFor(String appPath) { return (getWebappContextPath() + "/" + appPath).replaceAll("//", "/"); } public String getCruiseWar() { return getPropertyImpl(CRUISE_SERVER_WAR_PROPERTY, "cruise.war"); } public String getCruiseDbCacheSize() { return getPropertyImpl(CRUISE_DB_CACHE_SIZE, CRUISE_DB_CACHE_SIZE_DEFAULT); } public long getUnresponsiveJobWarningThreshold() { return Long.parseLong(getPropertyImpl(UNRESPONSIVE_JOB_WARNING_THRESHOLD, "5")) * 60 * 1000;//mins to mills } public boolean getParentLoaderPriority() { return Boolean.parseBoolean(getPropertyImpl(PARENT_LOADER_PRIORITY, "false")); } public String getUserDirectory() { return getPropertyImpl("user.dir"); } public static final ThreadLocal<Boolean> enforceServerImmutability = ThreadLocal.withInitial(() -> false); public static int getMaxEncryptionAPIRequestsPerMinute() { return GO_ENCRYPTION_API_MAX_REQUESTS.getValue(); } public boolean enforceServerImmutability() { return CONFIGURATION_YES.equals(getPropertyImpl(ENFORCE_SERVER_IMMUTABILITY, CONFIGURATION_YES)) || enforceServerImmutability.get(); } public boolean enforceRevisionCompatibilityWithUpstream() { if (enforceRevisionCompatibilityWithUpstream == null) { enforceRevisionCompatibilityWithUpstream = CONFIGURATION_YES .equals(getPropertyImpl(RESOLVE_FANIN_REVISIONS, CONFIGURATION_YES)); } return enforceRevisionCompatibilityWithUpstream; } public int getTfsSocketTimeout() { return Integer.parseInt( getPropertyImpl(TFS_SOCKET_TIMEOUT_PROPERTY, String.valueOf(TFS_SOCKET_TIMEOUT_IN_MILLISECONDS))); } public int getCruiseDbTraceLevel() { return H2_DB_TRACE_LEVEL.getValue(); } public int getCruiseDbTraceFileSize() { return H2_DB_TRACE_FILE_SIZE_MB.getValue(); } public Level pluginLoggingLevel(String pluginId) { return Level.toLevel(getPropertyImpl("plugin." + pluginId + ".log.level", "INFO"), Level.INFO); } public File getDefaultCommandRepository() { return new File(get(COMMAND_REPOSITORY_DIRECTORY), "default"); } public String consoleLogCharset() { return consoleLogCharsetAsCharset().name(); } public Charset consoleLogCharsetAsCharset() { if (consoleLogCharsetAsCharset == null) { consoleLogCharsetAsCharset = Charset.forName(get(CONSOLE_LOG_CHARSET)); } return consoleLogCharsetAsCharset; } public String getCommandRepositoryRootLocation() { return new File(get(COMMAND_REPOSITORY_DIRECTORY)).getAbsolutePath(); } public String getExternalPluginAbsolutePath() { return new File(get(PLUGIN_EXTERNAL_PROVIDED_PATH)).getAbsolutePath(); } public static Integer getGoServerAuthorizationExtensionCallsCacheTimeoutInSeconds() { return GO_SERVER_AUTHORIZATION_EXTENSION_CALLS_CACHE_TIMEOUT_IN_SECONDS.getValue(); } public String getBundledPluginAbsolutePath() { return new File(get(PLUGIN_GO_PROVIDED_PATH)).getAbsolutePath(); } public <T> void reset(GoSystemProperty<T> systemProperty) { System.clearProperty(systemProperty.propertyName()); if (systemProperty instanceof CachedProperty) { ((CachedProperty) systemProperty).clear(); } } public long getMaterialUpdateIdleInterval() { return MATERIAL_UPDATE_IDLE_INTERVAL.getValue(); } public boolean isDefaultDbProvider() { return GO_DATABASE_PROVIDER.getValue().equals(H2_DATABASE); } public String getDatabaseProvider() { return GO_DATABASE_PROVIDER.getValue(); } public String landingPage() { return GO_LANDING_PAGE.getValue(); } public boolean usingJetty9() { return get(APP_SERVER).equals(JETTY9); } public boolean isServerActive() { return GO_SERVER_STATE.getValue().equalsIgnoreCase("active"); } public void switchToActiveState() { set(GO_SERVER_STATE, "active"); } public void switchToPassiveState() { set(GO_SERVER_STATE, "passive"); } public String getUpdateServerPublicKeyPath() { return String.format("%s/%s", getConfigDir(), GO_UPDATE_SERVER_PUBLIC_KEY_FILE_NAME.getValue()); } public boolean isGOUpdateCheckEnabled() { return GO_CHECK_UPDATES.getValue(); } public boolean isFetchArtifactTemplateAutoSuggestEnabled() { return GO_FETCH_ARTIFACT_TEMPLATE_AUTO_SUGGEST.getValue(); } public String getUpdateServerUrl() { return GO_UPDATE_SERVER_URL.getValue(); } public String getGoDataSharingServerUrl() { return GO_DATA_SHARING_POST_USAGE_DATA_SERVER_URL.getValue(); } public String getGoDataSharingGetEncryptionKeysUrl() { return GO_DATA_SHARING_GET_ENCRYPTION_KEYS_URL.getValue(); } public boolean isAutoRegisterLocalAgentEnabled() { return AUTO_REGISTER_LOCAL_AGENT_ENABLED.getValue(); } public Long getConfigGitGCExpireTime() { Long hour = GO_CONFIG_REPO_GC_EXPIRE.getValue(); return hour * 60 * 60 * 1000; } public boolean isApiSafeModeEnabled() { return GO_API_WITH_SAFE_MODE.getValue(); } public boolean useSslContext() { return GO_AGENT_USE_SSL_CONTEXT.getValue(); } public boolean isBuildCommandProtocolEnabled() { return Boolean.valueOf(get(SystemEnvironment.ENABLE_BUILD_COMMAND_PROTOCOL)); } public String getAgentKeyStorePassword() { return get(SystemEnvironment.GO_AGENT_KEYSTORE_PASSWORD); } public String getServerKeyStorePassword() { return get(SystemEnvironment.GO_SERVER_KEYSTORE_PASSWORD); } public int sessionTimeoutInSeconds() { return GO_SERVER_SESSION_TIMEOUT_IN_SECONDS.getValue(); } public int sessionCookieMaxAgeInSeconds() { return GO_SERVER_SESSION_COOKIE_MAX_AGE_IN_SECONDS.getValue(); } public boolean isSessionCookieSecure() { return GO_SERVER_SESSION_COOKIE_SECURE.getValue(); } public boolean isProductionMode() { return GO_SERVER_MODE.getValue().equalsIgnoreCase("production"); } public boolean isServerInStandbyMode() { return GO_SERVER_MODE.getValue().equalsIgnoreCase("standby"); } public boolean isReAuthenticationEnabled() { return REAUTHENTICATION_ENABLED.getValue(); } public long getReAuthenticationTimeInterval() { return REAUTHENTICATION_TIME_INTERVAL.getValue(); } public Boolean getAgentStatusEnabled() { return AGENT_STATUS_API_ENABLED.getValue(); } public String getAgentStatusHostname() { if (isBlank(AGENT_STATUS_API_BIND_HOST.getValue())) { return null; } else { return AGENT_STATUS_API_BIND_HOST.getValue(); } } public int getAgentStatusPort() { return AGENT_STATUS_API_BIND_PORT.getValue(); } public static Integer goSpaRefreshInterval() { return GO_SPA_REFRESH_INTERVAL.getValue(); } public static Integer goSpaTimeout() { return GO_SPA_TIMEOUT.getValue(); } public Integer getNotificationListenerCountForPlugin(String pluginId) { return Integer.parseInt(getPropertyImpl("plugin." + pluginId + ".notifications.listener.count", "1")); } public boolean enableAnalyticsOnlyForAdmins() { return ENABLE_ANALYTICS_ONLY_FOR_ADMINS.getValue(); } public boolean enableHstsHeader() { return ENABLE_HSTS_HEADER.getValue(); } public long hstsHeaderMaxAge() { return HSTS_HEADER_MAX_AGE.getValue(); } public boolean hstsHeaderIncludeSubdomains() { return HSTS_HEADER_INCLUDE_SUBDOMAINS.getValue(); } public boolean hstsHeaderPreload() { return HSTS_HEADER_PRELOAD.getValue(); } public boolean shouldFailStartupOnDataError() { return get(FAIL_STARTUP_ON_DATA_ERROR); } public boolean useIframeSandbox() { return JOB_DETAILS_USE_IFRAME_SANDBOX.getValue(); } public boolean pluginClassLoaderHasOldBehaviour() { return GO_PLUGIN_CLASSLOADER_OLD.getValue(); } public static abstract class GoSystemProperty<T> { private String propertyName; protected T defaultValue; protected GoSystemProperty(String propertyName, T defaultValue) { this.propertyName = propertyName; this.defaultValue = defaultValue; } T getValue() { String propertyValue = System.getProperty(propertyName); return convertValue(propertyValue, defaultValue); } protected abstract T convertValue(String propertyValueFromSystem, T defaultValue); public String propertyName() { return propertyName; } } private static class GoIntSystemProperty extends GoSystemProperty<Integer> { public GoIntSystemProperty(String propertyName, Integer defaultValue) { super(propertyName, defaultValue); } @Override protected Integer convertValue(String propertyValueFromSystem, Integer defaultValue) { try { return Integer.parseInt(propertyValueFromSystem); } catch (NumberFormatException e) { return defaultValue; } } } private static class GoLongSystemProperty extends GoSystemProperty<Long> { public GoLongSystemProperty(String propertyName, Long defaultValue) { super(propertyName, defaultValue); } @Override protected Long convertValue(String propertyValueFromSystem, Long defaultValue) { try { return Long.parseLong(propertyValueFromSystem); } catch (NumberFormatException e) { return defaultValue; } } } private static class GoStringSystemProperty extends GoSystemProperty<String> { public GoStringSystemProperty(String propertyName, String defaultValue) { super(propertyName, defaultValue); } @Override protected String convertValue(String propertyValueFromSystem, String defaultValue) { return propertyValueFromSystem == null ? defaultValue : propertyValueFromSystem; } } protected static class GoStringArraySystemProperty extends GoSystemProperty<String[]> { public GoStringArraySystemProperty(String propertyName, String[] defaultValue) { super(propertyName, defaultValue); } @Override protected String[] convertValue(String propertyValueFromSystem, String[] defaultValue) { return isBlank(propertyValueFromSystem) ? defaultValue : propertyValueFromSystem.trim().split("(\\s*)?,(\\s*)?"); } } private static class CachedProperty<T> extends GoSystemProperty<T> { private GoSystemProperty<T> wrappedProperty; private T cachedValue; public CachedProperty(GoSystemProperty<T> goSystemProperty) { super(goSystemProperty.propertyName, goSystemProperty.defaultValue); wrappedProperty = goSystemProperty; } @Override protected T convertValue(String propertyValueFromSystem, T defaultValue) { if (cachedValue == null) { cachedValue = wrappedProperty.convertValue(propertyValueFromSystem, defaultValue); } return cachedValue; } public void clear() { cachedValue = null; } } private static class GoBooleanSystemProperty extends GoSystemProperty<Boolean> { public GoBooleanSystemProperty(String propertyName, Boolean defaultValue) { super(propertyName, defaultValue); } @Override protected Boolean convertValue(String propertyValueFromSystem, Boolean defaultValue) { if (propertyValueFromSystem == null) { return defaultValue; } return "Y".equalsIgnoreCase(propertyValueFromSystem) || "true".equalsIgnoreCase(propertyValueFromSystem); } } }