001/* 002 * (C) Copyright 2006-2017 Nuxeo (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * bstefanescu 018 * jcarsique 019 * Kevin Leturc <kleturc@nuxeo.com> 020 */ 021package org.nuxeo.common; 022 023import java.io.File; 024import java.net.URL; 025import java.util.Properties; 026 027import org.apache.commons.lang3.StringUtils; 028import org.apache.commons.lang3.builder.ToStringBuilder; 029import org.apache.commons.logging.Log; 030import org.apache.commons.logging.LogFactory; 031 032/** 033 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> 034 */ 035public class Environment { 036 037 private static Log logger = LogFactory.getLog(Environment.class); 038 039 /** 040 * Constants that identifies possible hosts for the framework. 041 */ 042 public static final String JBOSS_HOST = "JBoss"; 043 044 // Jetty or GF3 embedded 045 public static final String NXSERVER_HOST = "NXServer"; 046 047 public static final String TOMCAT_HOST = "Tomcat"; 048 049 public static final String NUXEO_HOME_DIR = "nuxeo.home.dir"; 050 051 /** 052 * @since 5.6 053 */ 054 public static final String NUXEO_HOME = "nuxeo.home"; 055 056 /** 057 * @since 5.4.2 058 */ 059 public static final String NUXEO_RUNTIME_HOME = "nuxeo.runtime.home"; 060 061 public static final String NUXEO_DATA_DIR = "nuxeo.data.dir"; 062 063 /** 064 * @since 5.9.4 065 */ 066 public static final String DEFAULT_DATA_DIR = "data"; 067 068 public static final String NUXEO_LOG_DIR = "nuxeo.log.dir"; 069 070 /** 071 * @since 5.9.4 072 */ 073 public static final String DEFAULT_LOG_DIR = "log"; 074 075 public static final String NUXEO_PID_DIR = "nuxeo.pid.dir"; 076 077 public static final String NUXEO_TMP_DIR = "nuxeo.tmp.dir"; 078 079 /** 080 * @since 5.9.4 081 */ 082 public static final String DEFAULT_TMP_DIR = "tmp"; 083 084 public static final String NUXEO_CONFIG_DIR = "nuxeo.config.dir"; 085 086 /** 087 * @since 5.9.4 088 */ 089 public static final String DEFAULT_CONFIG_DIR = "config"; 090 091 public static final String NUXEO_WEB_DIR = "nuxeo.web.dir"; 092 093 /** 094 * @since 5.9.4 095 */ 096 public static final String DEFAULT_WEB_DIR = "web"; 097 098 /** 099 * @since 5.9.4 100 */ 101 public static final String NUXEO_MP_DIR = "nuxeo.mp.dir"; 102 103 /** 104 * @since 5.9.4 105 */ 106 public static final String DEFAULT_MP_DIR = "packages"; 107 108 /** 109 * @since 5.6 110 */ 111 public static final String NUXEO_CONTEXT_PATH = "org.nuxeo.ecm.contextPath"; 112 113 /** 114 * The application layout (optional): directory containing nuxeo runtime osgi bundles. 115 */ 116 public static final String BUNDLES_DIR = "nuxeo.osgi.app.bundles"; 117 118 public static final String BUNDLES = "nuxeo.osgi.bundles"; 119 120 private static volatile Environment DEFAULT; 121 122 protected final File home; 123 124 protected File data; 125 126 protected File log; 127 128 protected File config; 129 130 protected File web; 131 132 protected File temp; 133 134 protected final Properties properties; 135 136 protected String[] args; 137 138 protected boolean isAppServer; 139 140 protected String hostAppName; 141 142 protected String hostAppVersion; 143 144 protected Iterable<URL> configProvider; 145 146 // Handy parameter to distinguish from (Runtime)home 147 private File serverHome = null; 148 149 // Handy parameter to distinguish from (Server)home 150 private File runtimeHome = null; 151 152 public static final String SERVER_STATUS_KEY = "server.status.key"; 153 154 public static final String DISTRIBUTION_NAME = "org.nuxeo.distribution.name"; 155 156 public static final String DISTRIBUTION_VERSION = "org.nuxeo.distribution.version"; 157 158 /** 159 * @since 7.10 160 */ 161 public static final String DISTRIBUTION_SERVER = "org.nuxeo.distribution.server"; 162 163 /** 164 * @since 7.10 165 */ 166 public static final String DISTRIBUTION_DATE = "org.nuxeo.distribution.date"; 167 168 /** 169 * @since 7.10 170 */ 171 public static final String DISTRIBUTION_PACKAGE = "org.nuxeo.distribution.package"; 172 173 /** 174 * @since 7.10 175 */ 176 public static final String PRODUCT_NAME = "org.nuxeo.ecm.product.name"; 177 178 /** 179 * @since 7.10 180 */ 181 public static final String PRODUCT_VERSION = "org.nuxeo.ecm.product.version"; 182 183 // proxy 184 /** 185 * @since 6.0 186 */ 187 public static final String NUXEO_HTTP_PROXY_HOST = "nuxeo.http.proxy.host"; 188 189 /** 190 * @since 6.0 191 */ 192 public static final String NUXEO_HTTP_PROXY_PORT = "nuxeo.http.proxy.port"; 193 194 /** 195 * @since 6.0 196 */ 197 public static final String NUXEO_HTTP_PROXY_LOGIN = "nuxeo.http.proxy.login"; 198 199 /** 200 * @since 6.0 201 */ 202 public static final String NUXEO_HTTP_PROXY_PASSWORD = "nuxeo.http.proxy.password"; 203 204 /** 205 * @since 7.4 206 */ 207 public static final String CRYPT_ALGO = "server.crypt.algorithm"; 208 209 /** 210 * @since 7.4 211 */ 212 public static final String CRYPT_KEY = "server.crypt.secretkey"; 213 214 /** 215 * @since 7.4 216 */ 217 public static final String CRYPT_KEYALIAS = "server.crypt.keyalias"; 218 219 /** 220 * @since 7.4 221 */ 222 public static final String CRYPT_KEYSTORE_PATH = "server.crypt.keystore.path"; 223 224 /** 225 * @since 7.4 226 */ 227 public static final String CRYPT_KEYSTORE_PASS = "server.crypt.keystore.pass"; 228 229 /** 230 * @since 7.4 231 */ 232 public static final String JAVA_DEFAULT_KEYSTORE = "javax.net.ssl.keyStore"; 233 234 /** 235 * @since 7.4 236 */ 237 public static final String JAVA_DEFAULT_KEYSTORE_PASS = "javax.net.ssl.keyStorePassword"; 238 239 /** 240 * Call to that constructor should be followed by a call to {@link #init()}. Depending on the available System 241 * properties, you may want to also call {@link #loadProperties(Properties)} or {@link #setServerHome(File)} methods 242 * before {@link #init()}; here is the recommended order: 243 * 244 * <pre> 245 * Environment env = new Environment(home); 246 * Environment.setDefault(env); 247 * env.loadProperties(properties); 248 * env.setServerHome(home); 249 * env.init(); 250 * </pre> 251 * 252 * @param home Root path used for most defaults. It is recommended to make it match the server home rather than the 253 * runtime home. 254 * @see #init() 255 */ 256 public Environment(File home) { 257 this(home, null); 258 } 259 260 /** 261 * Call to that constructor should be followed by a call to {@link #init()}. Depending on the available System 262 * properties, you may want to also call {@link #setServerHome(File)} method before {@link #init()}; here is the 263 * recommended order: 264 * 265 * <pre> 266 * Environment env = new Environment(home, properties); 267 * Environment.setDefault(env); 268 * env.setServerHome(home); 269 * env.init(); 270 * </pre> 271 * 272 * @param home Root path used for most defaults. It is recommended to make it match the server home rather than the 273 * runtime home. 274 * @param properties Source properties for initialization. It is used as an {@code Hashtable}: ie only the custom 275 * values are read, the properties default values are ignored if any. 276 * @see #init() 277 */ 278 public Environment(File home, Properties properties) { 279 this.home = home.getAbsoluteFile(); 280 this.properties = new Properties(); 281 if (properties != null) { 282 loadProperties(properties); 283 } 284 } 285 286 public static synchronized void setDefault(Environment env) { 287 DEFAULT = env; 288 } 289 290 public static Environment getDefault() { 291 if (DEFAULT == null) { 292 tryInitEnvironment(); 293 } 294 return DEFAULT; 295 } 296 297 private static synchronized void tryInitEnvironment() { 298 String homeDir = System.getProperty(NUXEO_HOME); 299 if (homeDir != null) { 300 File home = new File(homeDir); 301 if (home.isDirectory()) { 302 DEFAULT = new Environment(home); 303 DEFAULT.init(); 304 } 305 } 306 } 307 308 public File getHome() { 309 return home; 310 } 311 312 public boolean isApplicationServer() { 313 return isAppServer; 314 } 315 316 public void setIsApplicationServer(boolean isAppServer) { 317 this.isAppServer = isAppServer; 318 } 319 320 public String getHostApplicationName() { 321 return hostAppName; 322 } 323 324 public String getHostApplicationVersion() { 325 return hostAppVersion; 326 } 327 328 public void setHostApplicationName(String name) { 329 hostAppName = name; 330 } 331 332 public void setHostApplicationVersion(String version) { 333 hostAppVersion = version; 334 } 335 336 public File getTemp() { 337 if (temp == null) { 338 setTemp(properties.getProperty(NUXEO_TMP_DIR, DEFAULT_TMP_DIR)); 339 } 340 return temp; 341 } 342 343 /** 344 * Resolve the path against {@link Environment#serverHome} if not absolute. 345 * 346 * @since 8.1 347 */ 348 public void setTemp(String temp) { 349 setTemp(getServerHome().toPath().resolve(temp).toFile()); 350 } 351 352 public void setTemp(File temp) { 353 this.temp = temp.getAbsoluteFile(); 354 setProperty(NUXEO_TMP_DIR, temp.getAbsolutePath()); 355 temp.mkdirs(); 356 } 357 358 public File getConfig() { 359 if (config == null) { 360 setConfig(properties.getProperty(NUXEO_CONFIG_DIR, DEFAULT_CONFIG_DIR)); 361 } 362 return config; 363 } 364 365 /** 366 * Resolve the path against {@link Environment#runtimeHome} if not absolute. 367 * 368 * @since 8.1 369 */ 370 public void setConfig(String config) { 371 File configFile = getRuntimeHome().toPath().resolve(config).toFile(); 372 setConfig(configFile); 373 } 374 375 public void setConfig(File config) { 376 this.config = config.getAbsoluteFile(); 377 setProperty(NUXEO_CONFIG_DIR, config.getAbsolutePath()); 378 config.mkdirs(); 379 } 380 381 public File getLog() { 382 if (log == null) { 383 setLog(properties.getProperty(NUXEO_LOG_DIR, DEFAULT_LOG_DIR)); 384 } 385 return log; 386 } 387 388 /** 389 * Resolve the path against {@link Environment#serverHome} if not absolute. 390 * 391 * @since 8.1 392 */ 393 public void setLog(String log) { 394 setLog(getServerHome().toPath().resolve(log).toFile()); 395 } 396 397 public void setLog(File log) { 398 this.log = log.getAbsoluteFile(); 399 setProperty(NUXEO_LOG_DIR, log.getAbsolutePath()); 400 log.mkdirs(); 401 } 402 403 public File getData() { 404 if (data == null) { 405 setData(properties.getProperty(NUXEO_DATA_DIR, DEFAULT_DATA_DIR)); 406 } 407 return data; 408 } 409 410 /** 411 * Resolve the path against {@link Environment#runtimeHome} if not absolute. 412 * 413 * @since 8.1 414 */ 415 public void setData(String data) { 416 setData(getRuntimeHome().toPath().resolve(data).toFile()); 417 } 418 419 public void setData(File data) { 420 this.data = data.getAbsoluteFile(); 421 setProperty(NUXEO_DATA_DIR, data.getAbsolutePath()); 422 data.mkdirs(); 423 } 424 425 public File getWeb() { 426 if (web == null) { 427 setWeb(properties.getProperty(NUXEO_WEB_DIR, DEFAULT_WEB_DIR)); 428 } 429 return web; 430 } 431 432 /** 433 * Resolve the path against {@link Environment#runtimeHome} if not absolute. 434 * 435 * @since 8.1 436 */ 437 public void setWeb(String web) { 438 setWeb(getRuntimeHome().toPath().resolve(web).toFile()); 439 } 440 441 public void setWeb(File web) { 442 this.web = web; 443 setProperty(NUXEO_WEB_DIR, web.getAbsolutePath()); 444 } 445 446 /** 447 * @since 5.4.2 448 */ 449 public File getRuntimeHome() { 450 initRuntimeHome(); 451 return runtimeHome; 452 } 453 454 /** 455 * @since 5.4.2 456 */ 457 public void setRuntimeHome(File runtimeHome) { 458 this.runtimeHome = runtimeHome.getAbsoluteFile(); 459 setProperty(NUXEO_RUNTIME_HOME, runtimeHome.getAbsolutePath()); 460 } 461 462 public String[] getCommandLineArguments() { 463 return args; 464 } 465 466 public void setCommandLineArguments(String[] args) { 467 this.args = args; 468 } 469 470 public String getProperty(String key) { 471 return properties.getProperty(key); 472 } 473 474 public String getProperty(String key, String defaultValue) { 475 String val = properties.getProperty(key); 476 return val == null ? defaultValue : val; 477 } 478 479 /** 480 * If setting a path property, consider using {@link #setPath(String, String)} 481 */ 482 public void setProperty(String key, String value) { 483 properties.setProperty(key, value); 484 } 485 486 public Properties getProperties() { 487 return properties; 488 } 489 490 public void loadProperties(Properties props) { 491 properties.putAll(props); 492 } 493 494 public boolean isJBoss() { 495 return JBOSS_HOST.equals(hostAppName); 496 } 497 498 public boolean isJetty() { 499 return NXSERVER_HOST.equals(hostAppName); 500 } 501 502 public boolean isTomcat() { 503 return TOMCAT_HOST.equals(hostAppName); 504 } 505 506 /** 507 * Initialization with System properties to avoid issues due to home set with runtime home instead of server home. 508 * If {@link #NUXEO_HOME} System property is not set, or if you want to set a custom server home, then you should 509 * call {@link #setServerHome(File)} before. 510 * 511 * @since 5.4.1 512 */ 513 public void init() { 514 initServerHome(); 515 initRuntimeHome(); 516 517 String dataDir = System.getProperty(NUXEO_DATA_DIR); 518 if (StringUtils.isNotEmpty(dataDir)) { 519 setData(new File(dataDir)); 520 } 521 522 String configDir = System.getProperty(NUXEO_CONFIG_DIR); 523 if (StringUtils.isNotEmpty(configDir)) { 524 setConfig(new File(configDir)); 525 } 526 527 String logDir = System.getProperty(NUXEO_LOG_DIR); 528 if (StringUtils.isNotEmpty(logDir)) { 529 setLog(new File(logDir)); 530 } 531 532 String tmpDir = System.getProperty(NUXEO_TMP_DIR); 533 if (StringUtils.isNotEmpty(tmpDir)) { 534 setTemp(new File(tmpDir)); 535 } 536 537 String mpDir = System.getProperty(NUXEO_MP_DIR); 538 setPath(NUXEO_MP_DIR, StringUtils.isNotEmpty(mpDir) ? mpDir : DEFAULT_MP_DIR, getServerHome()); 539 } 540 541 private void initRuntimeHome() { 542 if (runtimeHome != null) { 543 return; 544 } 545 String runtimeDir = System.getProperty(NUXEO_RUNTIME_HOME); 546 if (runtimeDir != null && !runtimeDir.isEmpty()) { 547 setRuntimeHome(new File(runtimeDir)); 548 } else { 549 setRuntimeHome(home); 550 } 551 } 552 553 /** 554 * This method always returns the server home (or {@link #getHome()} if {@link #NUXEO_HOME_DIR} is not set). 555 * 556 * @since 5.4.2 557 * @return Server home 558 */ 559 public File getServerHome() { 560 initServerHome(); 561 return serverHome; 562 } 563 564 /** 565 * @since 5.4.2 566 */ 567 public void setServerHome(File serverHome) { 568 this.serverHome = serverHome.getAbsoluteFile(); 569 setProperty(NUXEO_HOME_DIR, serverHome.getAbsolutePath()); 570 } 571 572 private void initServerHome() { 573 if (serverHome != null) { 574 return; 575 } 576 String homeDir = System.getProperty(NUXEO_HOME, System.getProperty(NUXEO_HOME_DIR)); 577 if (homeDir != null && !homeDir.isEmpty()) { 578 setServerHome(new File(homeDir)); 579 } else { 580 logger.warn(String.format("Could not set the server home from %s or %s system properties, will use %s", 581 NUXEO_HOME, NUXEO_HOME_DIR, home)); 582 setServerHome(home); 583 } 584 logger.debug(this); 585 } 586 587 public void setConfigurationProvider(Iterable<URL> configProvider) { 588 this.configProvider = configProvider; 589 } 590 591 public Iterable<URL> getConfigurationProvider() { 592 return configProvider; 593 } 594 595 @Override 596 public String toString() { 597 return ToStringBuilder.reflectionToString(this); 598 } 599 600 /** 601 * Add a file path as a property 602 * 603 * @param key Property key 604 * @param value Property value: an absolute or relative file 605 * @param baseDir The directory against which the file will be resolved if not absolute 606 * @since 8.1 607 * @see #setProperty(String, String) 608 * @see #setPath(String, String, File) 609 * @see #setPath(String, File) 610 */ 611 public void setPath(String key, File value, File baseDir) { 612 setProperty(key, baseDir.toPath().resolve(value.toPath()).toFile().getAbsolutePath()); 613 } 614 615 /** 616 * Add a file path as a property 617 * 618 * @param key Property key 619 * @param value Property value: an absolute or relative file path 620 * @param baseDir The directory against which the file will be resolved if not absolute 621 * @since 8.1 622 * @see #setProperty(String, String) 623 * @see #setPath(String, File, File) 624 * @see #setPath(String, File) 625 */ 626 public void setPath(String key, String value, File baseDir) { 627 setProperty(key, baseDir.toPath().resolve(value).toFile().getAbsolutePath()); 628 } 629 630 /** 631 * Add a file path as a property 632 * 633 * @param key Property key 634 * @param value Property value: an absolute or relative file; if relative, it will be resolved against {@link #home} 635 * @since 8.1 636 * @see #setProperty(String, String) 637 * @see #setPath(String, File, File) 638 */ 639 public void setPath(String key, File value) { 640 setPath(key, value, home); 641 } 642 643 /** 644 * Add a file path as a property 645 * 646 * @param key Property key 647 * @param value Property value: an absolute or relative file path; if relative, it will be resolved against 648 * {@link #home} 649 * @since 8.1 650 * @see #setProperty(String, String) 651 * @see #setPath(String, String, File) 652 */ 653 public void setPath(String key, String value) { 654 setPath(key, value, home); 655 } 656 657 /** 658 * @return the file which path is associated with the given key. The file is guaranteed to be absolute if it has 659 * been set with {@link #setPath(String, File)} 660 * @since 8.1 661 */ 662 public File getPath(String key) { 663 return getPath(key, null); 664 } 665 666 /** 667 * @param key the property key 668 * @param defaultValue the default path, absolute or relative to server home 669 * @return the file which path is associated with the given key. The file is guaranteed to be absolute if it has 670 * been set with {@link #setPath(String, File)} 671 * @since 8.1 672 */ 673 public File getPath(String key, String defaultValue) { 674 String path = properties.getProperty(key); 675 if (path != null) { 676 return new File(path); 677 } else if (defaultValue != null) { 678 return getServerHome().toPath().resolve(defaultValue).toFile(); 679 } 680 return null; 681 } 682}