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 // volatile for double-checked locking 121 private static volatile Environment defaultEnvironment; 122 123 protected final File home; 124 125 protected File data; 126 127 protected File log; 128 129 protected File config; 130 131 protected File web; 132 133 protected File temp; 134 135 protected final Properties properties; 136 137 protected String[] args; 138 139 protected boolean isAppServer; 140 141 protected String hostAppName; 142 143 protected String hostAppVersion; 144 145 protected Iterable<URL> configProvider; 146 147 // Handy parameter to distinguish from (Runtime)home 148 private File serverHome = null; 149 150 // Handy parameter to distinguish from (Server)home 151 private File runtimeHome = null; 152 153 public static final String SERVER_STATUS_KEY = "server.status.key"; 154 155 public static final String DISTRIBUTION_NAME = "org.nuxeo.distribution.name"; 156 157 public static final String DISTRIBUTION_VERSION = "org.nuxeo.distribution.version"; 158 159 /** 160 * @since 7.10 161 */ 162 public static final String DISTRIBUTION_SERVER = "org.nuxeo.distribution.server"; 163 164 /** 165 * @since 7.10 166 */ 167 public static final String DISTRIBUTION_DATE = "org.nuxeo.distribution.date"; 168 169 /** 170 * @since 7.10 171 */ 172 public static final String DISTRIBUTION_PACKAGE = "org.nuxeo.distribution.package"; 173 174 /** 175 * @since 11.5 176 */ 177 public static final String DISTRIBUTION_HOTFIX = "org.nuxeo.distribution.hotfix"; 178 179 /** 180 * @since 7.10 181 */ 182 public static final String PRODUCT_NAME = "org.nuxeo.ecm.product.name"; 183 184 /** 185 * @since 7.10 186 */ 187 public static final String PRODUCT_VERSION = "org.nuxeo.ecm.product.version"; 188 189 // proxy 190 /** 191 * @since 6.0 192 */ 193 public static final String NUXEO_HTTP_PROXY_HOST = "nuxeo.http.proxy.host"; 194 195 /** 196 * @since 6.0 197 */ 198 public static final String NUXEO_HTTP_PROXY_PORT = "nuxeo.http.proxy.port"; 199 200 /** 201 * @since 6.0 202 */ 203 public static final String NUXEO_HTTP_PROXY_LOGIN = "nuxeo.http.proxy.login"; 204 205 /** 206 * @since 6.0 207 */ 208 public static final String NUXEO_HTTP_PROXY_PASSWORD = "nuxeo.http.proxy.password"; 209 210 /** 211 * @since 7.4 212 */ 213 public static final String CRYPT_ALGO = "server.crypt.algorithm"; 214 215 /** 216 * @since 7.4 217 */ 218 public static final String CRYPT_KEY = "server.crypt.secretkey"; 219 220 /** 221 * @since 7.4 222 */ 223 public static final String CRYPT_KEYALIAS = "server.crypt.keyalias"; 224 225 /** 226 * @since 7.4 227 */ 228 public static final String CRYPT_KEYSTORE_PATH = "server.crypt.keystore.path"; 229 230 /** 231 * @since 7.4 232 */ 233 public static final String CRYPT_KEYSTORE_PASS = "server.crypt.keystore.pass"; 234 235 /** 236 * @since 7.4 237 */ 238 public static final String JAVA_DEFAULT_KEYSTORE = "javax.net.ssl.keyStore"; 239 240 /** 241 * @since 7.4 242 */ 243 public static final String JAVA_DEFAULT_KEYSTORE_PASS = "javax.net.ssl.keyStorePassword"; 244 245 /** 246 * Call to that constructor should be followed by a call to {@link #init()}. Depending on the available System 247 * properties, you may want to also call {@link #loadProperties(Properties)} or {@link #setServerHome(File)} methods 248 * before {@link #init()}; here is the recommended order: 249 * 250 * <pre> 251 * Environment env = new Environment(home); 252 * Environment.setDefault(env); 253 * env.loadProperties(properties); 254 * env.setServerHome(home); 255 * env.init(); 256 * </pre> 257 * 258 * @param home Root path used for most defaults. It is recommended to make it match the server home rather than the 259 * runtime home. 260 * @see #init() 261 */ 262 public Environment(File home) { 263 this(home, null); 264 } 265 266 /** 267 * Call to that constructor should be followed by a call to {@link #init()}. Depending on the available System 268 * properties, you may want to also call {@link #setServerHome(File)} method before {@link #init()}; here is the 269 * recommended order: 270 * 271 * <pre> 272 * Environment env = new Environment(home, properties); 273 * Environment.setDefault(env); 274 * env.setServerHome(home); 275 * env.init(); 276 * </pre> 277 * 278 * @param home Root path used for most defaults. It is recommended to make it match the server home rather than the 279 * runtime home. 280 * @param properties Source properties for initialization. It is used as an {@code Hashtable}: ie only the custom 281 * values are read, the properties default values are ignored if any. 282 * @see #init() 283 */ 284 public Environment(File home, Properties properties) { 285 this.home = home.getAbsoluteFile(); 286 this.properties = new Properties(); 287 if (properties != null) { 288 loadProperties(properties); 289 } 290 } 291 292 public static void setDefault(Environment env) { 293 synchronized (Environment.class) { 294 defaultEnvironment = env; 295 } 296 } 297 298 public static Environment getDefault() { 299 if (defaultEnvironment == null) { 300 synchronized (Environment.class) { 301 if (defaultEnvironment == null) { 302 String homeDir = System.getProperty(NUXEO_HOME); 303 if (homeDir != null) { 304 File home = new File(homeDir); 305 if (home.isDirectory()) { 306 Environment env = new Environment(home); 307 env.init(); 308 defaultEnvironment = env; 309 } 310 } 311 } 312 } 313 } 314 return defaultEnvironment; 315 } 316 317 public File getHome() { 318 return home; 319 } 320 321 public boolean isApplicationServer() { 322 return isAppServer; 323 } 324 325 public void setIsApplicationServer(boolean isAppServer) { 326 this.isAppServer = isAppServer; 327 } 328 329 public String getHostApplicationName() { 330 return hostAppName; 331 } 332 333 public String getHostApplicationVersion() { 334 return hostAppVersion; 335 } 336 337 public void setHostApplicationName(String name) { 338 hostAppName = name; 339 } 340 341 public void setHostApplicationVersion(String version) { 342 hostAppVersion = version; 343 } 344 345 public File getTemp() { 346 if (temp == null) { 347 setTemp(properties.getProperty(NUXEO_TMP_DIR, DEFAULT_TMP_DIR)); 348 } 349 return temp; 350 } 351 352 /** 353 * Resolve the path against {@link Environment#serverHome} if not absolute. 354 * 355 * @since 8.1 356 */ 357 public void setTemp(String temp) { 358 setTemp(getServerHome().toPath().resolve(temp).toFile()); 359 } 360 361 public void setTemp(File temp) { 362 this.temp = temp.getAbsoluteFile(); 363 setProperty(NUXEO_TMP_DIR, temp.getAbsolutePath()); 364 temp.mkdirs(); 365 } 366 367 public File getConfig() { 368 if (config == null) { 369 setConfig(properties.getProperty(NUXEO_CONFIG_DIR, DEFAULT_CONFIG_DIR)); 370 } 371 return config; 372 } 373 374 /** 375 * Resolve the path against {@link Environment#runtimeHome} if not absolute. 376 * 377 * @since 8.1 378 */ 379 public void setConfig(String config) { 380 File configFile = getRuntimeHome().toPath().resolve(config).toFile(); 381 setConfig(configFile); 382 } 383 384 public void setConfig(File config) { 385 this.config = config.getAbsoluteFile(); 386 setProperty(NUXEO_CONFIG_DIR, config.getAbsolutePath()); 387 config.mkdirs(); 388 } 389 390 public File getLog() { 391 if (log == null) { 392 setLog(properties.getProperty(NUXEO_LOG_DIR, DEFAULT_LOG_DIR)); 393 } 394 return log; 395 } 396 397 /** 398 * Resolve the path against {@link Environment#serverHome} if not absolute. 399 * 400 * @since 8.1 401 */ 402 public void setLog(String log) { 403 setLog(getServerHome().toPath().resolve(log).toFile()); 404 } 405 406 public void setLog(File log) { 407 this.log = log.getAbsoluteFile(); 408 setProperty(NUXEO_LOG_DIR, log.getAbsolutePath()); 409 log.mkdirs(); 410 } 411 412 public File getData() { 413 if (data == null) { 414 setData(properties.getProperty(NUXEO_DATA_DIR, DEFAULT_DATA_DIR)); 415 } 416 return data; 417 } 418 419 /** 420 * Resolve the path against {@link Environment#runtimeHome} if not absolute. 421 * 422 * @since 8.1 423 */ 424 public void setData(String data) { 425 setData(getRuntimeHome().toPath().resolve(data).toFile()); 426 } 427 428 public void setData(File data) { 429 this.data = data.getAbsoluteFile(); 430 setProperty(NUXEO_DATA_DIR, data.getAbsolutePath()); 431 data.mkdirs(); 432 } 433 434 public File getWeb() { 435 if (web == null) { 436 setWeb(properties.getProperty(NUXEO_WEB_DIR, DEFAULT_WEB_DIR)); 437 } 438 return web; 439 } 440 441 /** 442 * Resolve the path against {@link Environment#runtimeHome} if not absolute. 443 * 444 * @since 8.1 445 */ 446 public void setWeb(String web) { 447 setWeb(getRuntimeHome().toPath().resolve(web).toFile()); 448 } 449 450 public void setWeb(File web) { 451 this.web = web; 452 setProperty(NUXEO_WEB_DIR, web.getAbsolutePath()); 453 } 454 455 /** 456 * @since 5.4.2 457 */ 458 public File getRuntimeHome() { 459 initRuntimeHome(); 460 return runtimeHome; 461 } 462 463 /** 464 * @since 5.4.2 465 */ 466 public void setRuntimeHome(File runtimeHome) { 467 this.runtimeHome = runtimeHome.getAbsoluteFile(); 468 setProperty(NUXEO_RUNTIME_HOME, runtimeHome.getAbsolutePath()); 469 } 470 471 public String[] getCommandLineArguments() { 472 return args; 473 } 474 475 public void setCommandLineArguments(String[] args) { 476 this.args = args; 477 } 478 479 public String getProperty(String key) { 480 return properties.getProperty(key); 481 } 482 483 public String getProperty(String key, String defaultValue) { 484 String val = properties.getProperty(key); 485 return val == null ? defaultValue : val; 486 } 487 488 /** 489 * If setting a path property, consider using {@link #setPath(String, String)} 490 */ 491 public void setProperty(String key, String value) { 492 properties.setProperty(key, value); 493 } 494 495 public Properties getProperties() { 496 return properties; 497 } 498 499 public void loadProperties(Properties props) { 500 properties.putAll(props); 501 } 502 503 public boolean isJBoss() { 504 return JBOSS_HOST.equals(hostAppName); 505 } 506 507 public boolean isJetty() { 508 return NXSERVER_HOST.equals(hostAppName); 509 } 510 511 public boolean isTomcat() { 512 return TOMCAT_HOST.equals(hostAppName); 513 } 514 515 /** 516 * Initialization with System properties to avoid issues due to home set with runtime home instead of server home. 517 * If {@link #NUXEO_HOME} System property is not set, or if you want to set a custom server home, then you should 518 * call {@link #setServerHome(File)} before. 519 * 520 * @since 5.4.1 521 */ 522 public void init() { 523 initServerHome(); 524 initRuntimeHome(); 525 526 String dataDir = System.getProperty(NUXEO_DATA_DIR); 527 if (StringUtils.isNotEmpty(dataDir)) { 528 setData(new File(dataDir)); 529 } 530 531 String configDir = System.getProperty(NUXEO_CONFIG_DIR); 532 if (StringUtils.isNotEmpty(configDir)) { 533 setConfig(new File(configDir)); 534 } 535 536 String logDir = System.getProperty(NUXEO_LOG_DIR); 537 if (StringUtils.isNotEmpty(logDir)) { 538 setLog(new File(logDir)); 539 } 540 541 String tmpDir = System.getProperty(NUXEO_TMP_DIR); 542 if (StringUtils.isNotEmpty(tmpDir)) { 543 setTemp(new File(tmpDir)); 544 } 545 546 String mpDir = System.getProperty(NUXEO_MP_DIR); 547 setPath(NUXEO_MP_DIR, StringUtils.isNotEmpty(mpDir) ? mpDir : DEFAULT_MP_DIR, getServerHome()); 548 } 549 550 private void initRuntimeHome() { 551 if (runtimeHome != null) { 552 return; 553 } 554 String runtimeDir = System.getProperty(NUXEO_RUNTIME_HOME); 555 if (runtimeDir != null && !runtimeDir.isEmpty()) { 556 setRuntimeHome(new File(runtimeDir)); 557 } else { 558 setRuntimeHome(home); 559 } 560 } 561 562 /** 563 * This method always returns the server home (or {@link #getHome()} if {@link #NUXEO_HOME_DIR} is not set). 564 * 565 * @since 5.4.2 566 * @return Server home 567 */ 568 public File getServerHome() { 569 initServerHome(); 570 return serverHome; 571 } 572 573 /** 574 * @since 5.4.2 575 */ 576 public void setServerHome(File serverHome) { 577 this.serverHome = serverHome.getAbsoluteFile(); 578 setProperty(NUXEO_HOME_DIR, serverHome.getAbsolutePath()); 579 } 580 581 private void initServerHome() { 582 if (serverHome != null) { 583 return; 584 } 585 String homeDir = System.getProperty(NUXEO_HOME, System.getProperty(NUXEO_HOME_DIR)); 586 if (homeDir != null && !homeDir.isEmpty()) { 587 setServerHome(new File(homeDir)); 588 } else { 589 logger.warn(String.format("Could not set the server home from %s or %s system properties, will use %s", 590 NUXEO_HOME, NUXEO_HOME_DIR, home)); 591 setServerHome(home); 592 } 593 logger.debug(this); 594 } 595 596 public void setConfigurationProvider(Iterable<URL> configProvider) { 597 this.configProvider = configProvider; 598 } 599 600 public Iterable<URL> getConfigurationProvider() { 601 return configProvider; 602 } 603 604 @Override 605 public String toString() { 606 return ToStringBuilder.reflectionToString(this); 607 } 608 609 /** 610 * Add a file path as a property 611 * 612 * @param key Property key 613 * @param value Property value: an absolute or relative file 614 * @param baseDir The directory against which the file will be resolved if not absolute 615 * @since 8.1 616 * @see #setProperty(String, String) 617 * @see #setPath(String, String, File) 618 * @see #setPath(String, File) 619 */ 620 public void setPath(String key, File value, File baseDir) { 621 setProperty(key, baseDir.toPath().resolve(value.toPath()).toFile().getAbsolutePath()); 622 } 623 624 /** 625 * Add a file path as a property 626 * 627 * @param key Property key 628 * @param value Property value: an absolute or relative file path 629 * @param baseDir The directory against which the file will be resolved if not absolute 630 * @since 8.1 631 * @see #setProperty(String, String) 632 * @see #setPath(String, File, File) 633 * @see #setPath(String, File) 634 */ 635 public void setPath(String key, String value, File baseDir) { 636 setProperty(key, baseDir.toPath().resolve(value).toFile().getAbsolutePath()); 637 } 638 639 /** 640 * Add a file path as a property 641 * 642 * @param key Property key 643 * @param value Property value: an absolute or relative file; if relative, it will be resolved against {@link #home} 644 * @since 8.1 645 * @see #setProperty(String, String) 646 * @see #setPath(String, File, File) 647 */ 648 public void setPath(String key, File value) { 649 setPath(key, value, home); 650 } 651 652 /** 653 * Add a file path as a property 654 * 655 * @param key Property key 656 * @param value Property value: an absolute or relative file path; if relative, it will be resolved against 657 * {@link #home} 658 * @since 8.1 659 * @see #setProperty(String, String) 660 * @see #setPath(String, String, File) 661 */ 662 public void setPath(String key, String value) { 663 setPath(key, value, home); 664 } 665 666 /** 667 * @return the file which path is associated with the given key. The file is guaranteed to be absolute if it has 668 * been set with {@link #setPath(String, File)} 669 * @since 8.1 670 */ 671 public File getPath(String key) { 672 return getPath(key, null); 673 } 674 675 /** 676 * @param key the property key 677 * @param defaultValue the default path, absolute or relative to server home 678 * @return the file which path is associated with the given key. The file is guaranteed to be absolute if it has 679 * been set with {@link #setPath(String, File)} 680 * @since 8.1 681 */ 682 public File getPath(String key, String defaultValue) { 683 String path = properties.getProperty(key); 684 if (path != null) { 685 return new File(path); 686 } else if (defaultValue != null) { 687 return getServerHome().toPath().resolve(defaultValue).toFile(); 688 } 689 return null; 690 } 691}