001/* 002 * (C) Copyright 2010-2016 Nuxeo SA (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 * Julien Carsique 018 * 019 */ 020 021package org.nuxeo.launcher.config; 022 023import java.io.BufferedReader; 024import java.io.BufferedWriter; 025import java.io.File; 026import java.io.FileInputStream; 027import java.io.FileNotFoundException; 028import java.io.FileReader; 029import java.io.FileWriter; 030import java.io.IOException; 031import java.io.InputStream; 032import java.net.Inet6Address; 033import java.net.InetAddress; 034import java.net.MalformedURLException; 035import java.net.ServerSocket; 036import java.net.URL; 037import java.net.URLClassLoader; 038import java.net.UnknownHostException; 039import java.sql.Connection; 040import java.sql.Driver; 041import java.sql.DriverManager; 042import java.sql.SQLException; 043import java.util.ArrayList; 044import java.util.Arrays; 045import java.util.Date; 046import java.util.Enumeration; 047import java.util.HashMap; 048import java.util.HashSet; 049import java.util.Hashtable; 050import java.util.List; 051import java.util.Map; 052import java.util.Properties; 053import java.util.Set; 054import java.util.StringTokenizer; 055import java.util.TreeSet; 056import java.util.UUID; 057 058import javax.naming.NamingException; 059import javax.naming.directory.DirContext; 060import javax.naming.directory.InitialDirContext; 061 062import org.apache.commons.lang.ArrayUtils; 063import org.apache.commons.lang.StringUtils; 064import org.apache.commons.lang3.SystemUtils; 065import org.apache.commons.logging.Log; 066import org.apache.commons.logging.LogFactory; 067import org.apache.log4j.Logger; 068import org.apache.log4j.helpers.NullEnumeration; 069 070import org.nuxeo.common.Environment; 071import org.nuxeo.common.codec.Crypto; 072import org.nuxeo.common.codec.CryptoProperties; 073import org.nuxeo.common.utils.TextTemplate; 074import org.nuxeo.launcher.commons.DatabaseDriverException; 075import org.nuxeo.log4j.Log4JHelper; 076 077import freemarker.core.ParseException; 078import freemarker.template.TemplateException; 079 080/** 081 * Builder for server configuration and datasource files from templates and properties. 082 * 083 * @author jcarsique 084 */ 085public class ConfigurationGenerator { 086 087 /** 088 * @since 6.0 089 */ 090 public static final String TEMPLATE_SEPARATOR = ","; 091 092 /** 093 * Accurate but not used internally. NXP-18023: Java 8 update 40+ required 094 * 095 * @since 5.7 096 */ 097 public static final String[] COMPLIANT_JAVA_VERSIONS = new String[] { "1.8.0_40" }; 098 099 /** 100 * @since 5.6 101 */ 102 protected static final String CONFIGURATION_PROPERTIES = "configuration.properties"; 103 104 private static final Log log = LogFactory.getLog(ConfigurationGenerator.class); 105 106 /** 107 * @deprecated Since 5.6, use {@link Environment#NUXEO_HOME} instead 108 */ 109 @Deprecated 110 public static final String NUXEO_HOME = Environment.NUXEO_HOME; 111 112 public static final String NUXEO_CONF = "nuxeo.conf"; 113 114 public static final String TEMPLATES = "templates"; 115 116 public static final String NUXEO_DEFAULT_CONF = "nuxeo.defaults"; 117 118 /** 119 * Absolute or relative PATH to the user chosen template 120 * 121 * @deprecated use {@link #PARAM_TEMPLATES_NAME} instead 122 */ 123 @Deprecated 124 public static final String PARAM_TEMPLATE_NAME = "nuxeo.template"; 125 126 /** 127 * Absolute or relative PATH to the user chosen templates (comma separated list) 128 */ 129 public static final String PARAM_TEMPLATES_NAME = "nuxeo.templates"; 130 131 public static final String PARAM_TEMPLATE_DBNAME = "nuxeo.dbtemplate"; 132 133 /** 134 * @since 8.1 135 */ 136 public static final String PARAM_TEMPLATE_DBNOSQL_NAME = "nuxeo.dbnosqltemplate"; 137 138 public static final String PARAM_TEMPLATE_DBTYPE = "nuxeo.db.type"; 139 140 /** 141 * @since 8.1 142 */ 143 public static final String PARAM_TEMPLATE_DBNOSQL_TYPE = "nuxeo.dbnosql.type"; 144 145 /** 146 * @deprecated since 5.7 147 */ 148 @Deprecated 149 public static final String PARAM_TEMPLATES_NODB = "nuxeo.nodbtemplates"; 150 151 public static final String OLD_PARAM_TEMPLATES_PARSING_EXTENSIONS = "nuxeo.templates.parsing.extensions"; 152 153 public static final String PARAM_TEMPLATES_PARSING_EXTENSIONS = "nuxeo.plaintext_parsing_extensions"; 154 155 public static final String PARAM_TEMPLATES_FREEMARKER_EXTENSIONS = "nuxeo.freemarker_parsing_extensions"; 156 157 /** 158 * Absolute or relative PATH to the included templates (comma separated list) 159 */ 160 protected static final String PARAM_INCLUDED_TEMPLATES = "nuxeo.template.includes"; 161 162 public static final String PARAM_FORCE_GENERATION = "nuxeo.force.generation"; 163 164 public static final String BOUNDARY_BEGIN = "### BEGIN - DO NOT EDIT BETWEEN BEGIN AND END ###"; 165 166 public static final String BOUNDARY_END = "### END - DO NOT EDIT BETWEEN BEGIN AND END ###"; 167 168 public static final List<String> DB_LIST = Arrays.asList("default", "postgresql", "oracle", "mysql", "mssql", "db2"); 169 170 public static final List<String> DB_NOSQL_LIST = Arrays.asList("none", "mongodb"); 171 172 public static final List<String> DB_EXCLUDE_CHECK_LIST = Arrays.asList("default", "none"); 173 174 public static final String PARAM_WIZARD_DONE = "nuxeo.wizard.done"; 175 176 public static final String PARAM_WIZARD_RESTART_PARAMS = "wizard.restart.params"; 177 178 public static final String PARAM_FAKE_WINDOWS = "org.nuxeo.fake.vindoz"; 179 180 public static final String PARAM_LOOPBACK_URL = "nuxeo.loopback.url"; 181 182 public static final int MIN_PORT = 1; 183 184 public static final int MAX_PORT = 65535; 185 186 public static final int ADDRESS_PING_TIMEOUT = 1000; 187 188 public static final String PARAM_BIND_ADDRESS = "nuxeo.bind.address"; 189 190 public static final String PARAM_HTTP_PORT = "nuxeo.server.http.port"; 191 192 /** 193 * @deprecated Since 7.4. Use {@link Environment#SERVER_STATUS_KEY} instead 194 */ 195 @Deprecated 196 public static final String PARAM_STATUS_KEY = Environment.SERVER_STATUS_KEY; 197 198 public static final String PARAM_CONTEXT_PATH = "org.nuxeo.ecm.contextPath"; 199 200 public static final String PARAM_MP_DIR = "nuxeo.distribution.marketplace.dir"; 201 202 public static final String DISTRIBUTION_MP_DIR = "setupWizardDownloads"; 203 204 public static final String INSTALL_AFTER_RESTART = "installAfterRestart.log"; 205 206 public static final String PARAM_DB_DRIVER = "nuxeo.db.driver"; 207 208 public static final String PARAM_DB_JDBC_URL = "nuxeo.db.jdbc.url"; 209 210 public static final String PARAM_DB_HOST = "nuxeo.db.host"; 211 212 public static final String PARAM_DB_PORT = "nuxeo.db.port"; 213 214 public static final String PARAM_DB_NAME = "nuxeo.db.name"; 215 216 public static final String PARAM_DB_USER = "nuxeo.db.user"; 217 218 public static final String PARAM_DB_PWD = "nuxeo.db.password"; 219 220 /** 221 * @since 8.1 222 */ 223 public static final String PARAM_MONGODB_NAME = "nuxeo.mongodb.dbname"; 224 225 /** 226 * @since 8.1 227 */ 228 public static final String PARAM_MONGODB_SERVER = "nuxeo.mongodb.server"; 229 230 /** 231 * Keys which value must be displayed thoughtfully 232 * 233 * @since 8.1 234 */ 235 public static final List<String> SECRET_KEYS = Arrays.asList(PARAM_DB_PWD, "mailservice.password", 236 "mail.transport.password", "nuxeo.http.proxy.password", "nuxeo.ldap.bindpassword", 237 "nuxeo.user.emergency.password"); 238 239 /** 240 * @deprecated Since 7.10. Use {@link Environment#PRODUCT_NAME} 241 */ 242 @Deprecated 243 public static final String PARAM_PRODUCT_NAME = Environment.PRODUCT_NAME; 244 245 /** 246 * @deprecated Since 7.10. Use {@link Environment#PRODUCT_VERSION} 247 */ 248 @Deprecated 249 public static final String PARAM_PRODUCT_VERSION = Environment.PRODUCT_VERSION; 250 251 /** 252 * @since 5.6 253 */ 254 public static final String PARAM_NUXEO_URL = "nuxeo.url"; 255 256 /** 257 * Global dev property, duplicated from runtime framework 258 * 259 * @since 5.6 260 */ 261 public static final String NUXEO_DEV_SYSTEM_PROP = "org.nuxeo.dev"; 262 263 /** 264 * Seam hot reload property, also controlled by {@link #NUXEO_DEV_SYSTEM_PROP} 265 * 266 * @since 5.6 267 */ 268 public static final String SEAM_DEBUG_SYSTEM_PROP = "org.nuxeo.seam.debug"; 269 270 /** 271 * Old way of detecting if seam debug should be enabled, by looking for the presence of this file. Setting property 272 * {@link #SEAM_DEBUG_SYSTEM_PROP} in nuxeo.conf is enough now. 273 * 274 * @deprecated since 5.6 275 * @since 5.6 276 */ 277 @Deprecated 278 public static final String SEAM_HOT_RELOAD_GLOBAL_CONFIG_FILE = "seam-debug.properties"; 279 280 private final File nuxeoHome; 281 282 // User configuration file 283 private final File nuxeoConf; 284 285 // Chosen templates 286 private final List<File> includedTemplates = new ArrayList<>(); 287 288 // Common default configuration file 289 private File nuxeoDefaultConf; 290 291 public boolean isJBoss; 292 293 public boolean isJetty; 294 295 public boolean isTomcat; 296 297 private ServerConfigurator serverConfigurator; 298 299 private boolean forceGeneration; 300 301 private Properties defaultConfig; 302 303 private CryptoProperties userConfig; 304 305 private boolean configurable = false; 306 307 private boolean onceGeneration = false; 308 309 private String templates; 310 311 // if PARAM_FORCE_GENERATION=once, set to false; else keep current value 312 private boolean setOnceToFalse = true; 313 314 // if PARAM_FORCE_GENERATION=false, set to once; else keep the current 315 // value 316 private boolean setFalseToOnce = false; 317 318 public boolean isConfigurable() { 319 return configurable; 320 } 321 322 public ConfigurationGenerator() { 323 this(true, false); 324 } 325 326 private boolean quiet = false; 327 328 @SuppressWarnings("unused") 329 private boolean debug = false; 330 331 private static boolean hideDeprecationWarnings = false; 332 333 private Environment env; 334 335 private Properties storedConfig; 336 337 /** 338 * @since 5.7 339 */ 340 protected Properties getStoredConfig() { 341 if (storedConfig == null) { 342 updateStoredConfig(); 343 } 344 return storedConfig; 345 } 346 347 protected static final Map<String, String> parametersMigration = new HashMap<String, String>() { 348 private static final long serialVersionUID = 1L; 349 { 350 put(OLD_PARAM_TEMPLATES_PARSING_EXTENSIONS, PARAM_TEMPLATES_PARSING_EXTENSIONS); 351 put("nuxeo.db.user.separator.key", "nuxeo.db.user_separator_key"); 352 put("mail.pop3.host", "mail.store.host"); 353 put("mail.pop3.port", "mail.store.port"); 354 put("mail.smtp.host", "mail.transport.host"); 355 put("mail.smtp.port", "mail.transport.port"); 356 put("mail.smtp.username", "mail.transport.username"); 357 put("mail.transport.username", "mail.transport.user"); 358 put("mail.smtp.password", "mail.transport.password"); 359 put("mail.smtp.usetls", "mail.transport.usetls"); 360 put("mail.smtp.auth", "mail.transport.auth"); 361 } 362 }; 363 364 /** 365 * @param quiet Suppress info level messages from the console output 366 * @param debug Activate debug level logging 367 * @since 5.6 368 */ 369 public ConfigurationGenerator(boolean quiet, boolean debug) { 370 this.quiet = quiet; 371 this.debug = debug; 372 File serverHome = Environment.getDefault().getServerHome(); 373 if (serverHome != null) { 374 nuxeoHome = serverHome.getAbsoluteFile(); 375 } else { 376 File userDir = new File(System.getProperty("user.dir")); 377 if ("bin".equalsIgnoreCase(userDir.getName())) { 378 nuxeoHome = userDir.getParentFile().getAbsoluteFile(); 379 } else { 380 nuxeoHome = userDir.getAbsoluteFile(); 381 } 382 } 383 String nuxeoConfPath = System.getProperty(NUXEO_CONF); 384 if (nuxeoConfPath != null) { 385 nuxeoConf = new File(nuxeoConfPath).getAbsoluteFile(); 386 } else { 387 nuxeoConf = new File(nuxeoHome, "bin" + File.separator + "nuxeo.conf").getAbsoluteFile(); 388 } 389 System.setProperty(NUXEO_CONF, nuxeoConf.getPath()); 390 391 nuxeoDefaultConf = new File(nuxeoHome, TEMPLATES + File.separator + NUXEO_DEFAULT_CONF); 392 393 // detect server type based on System properties 394 isJetty = System.getProperty(JettyConfigurator.JETTY_HOME) != null; 395 isTomcat = System.getProperty(TomcatConfigurator.TOMCAT_HOME) != null; 396 if (!isJBoss && !isJetty && !isTomcat) { 397 // fallback on jar detection 398 isJBoss = new File(nuxeoHome, "bin/run.jar").exists(); 399 isTomcat = new File(nuxeoHome, "bin/bootstrap.jar").exists(); 400 String[] files = nuxeoHome.list(); 401 for (String file : files) { 402 if (file.startsWith("nuxeo-runtime-launcher")) { 403 isJetty = true; 404 break; 405 } 406 } 407 } 408 if (isTomcat) { 409 serverConfigurator = new TomcatConfigurator(this); 410 } else if (isJetty) { 411 serverConfigurator = new JettyConfigurator(this); 412 } else { 413 serverConfigurator = new UnknownServerConfigurator(this); 414 } 415 if (Logger.getRootLogger().getAllAppenders() instanceof NullEnumeration) { 416 serverConfigurator.initLogs(); 417 } 418 String homeInfo = "Nuxeo home: " + nuxeoHome.getPath(); 419 String confInfo = "Nuxeo configuration: " + nuxeoConf.getPath(); 420 if (quiet) { 421 log.debug(homeInfo); 422 log.debug(confInfo); 423 } else { 424 log.info(homeInfo); 425 log.info(confInfo); 426 } 427 } 428 429 public void hideDeprecationWarnings(boolean hide) { 430 hideDeprecationWarnings = hide; 431 } 432 433 /** 434 * @see #PARAM_FORCE_GENERATION 435 * @param forceGeneration 436 */ 437 public void setForceGeneration(boolean forceGeneration) { 438 this.forceGeneration = forceGeneration; 439 } 440 441 /** 442 * @see #PARAM_FORCE_GENERATION 443 * @return true if configuration will be generated from templates 444 * @since 5.4.2 445 */ 446 public boolean isForceGeneration() { 447 return forceGeneration; 448 } 449 450 public CryptoProperties getUserConfig() { 451 return userConfig; 452 } 453 454 /** 455 * @since 5.4.2 456 */ 457 public final ServerConfigurator getServerConfigurator() { 458 return serverConfigurator; 459 } 460 461 /** 462 * Runs the configuration files generation. 463 */ 464 public void run() throws ConfigurationException { 465 if (init()) { 466 if (!serverConfigurator.isConfigured()) { 467 log.info("No current configuration, generating files..."); 468 generateFiles(); 469 } else if (forceGeneration) { 470 log.info("Configuration files generation (nuxeo.force.generation=" 471 + userConfig.getProperty(PARAM_FORCE_GENERATION) + ")..."); 472 generateFiles(); 473 } else { 474 log.info("Server already configured (set nuxeo.force.generation=true to force configuration files generation)."); 475 } 476 } 477 } 478 479 /** 480 * Initialize configurator, check requirements and load current configuration 481 * 482 * @return returns true if current install is configurable, else returns false 483 */ 484 public boolean init() { 485 return init(false); 486 } 487 488 /** 489 * Initialize configurator, check requirements and load current configuration 490 * 491 * @since 5.6 492 * @param forceReload If true, forces configuration reload. 493 * @return returns true if current install is configurable, else returns false 494 */ 495 public boolean init(boolean forceReload) { 496 if (serverConfigurator instanceof UnknownServerConfigurator) { 497 configurable = false; 498 forceGeneration = false; 499 log.warn("Server will be considered as not configurable."); 500 } 501 if (!nuxeoConf.exists()) { 502 log.info("Missing " + nuxeoConf); 503 configurable = false; 504 userConfig = new CryptoProperties(); 505 } else if (userConfig == null || userConfig.size() == 0 || forceReload) { 506 try { 507 setBasicConfiguration(); 508 configurable = true; 509 } catch (ConfigurationException e) { 510 log.warn("Error reading basic configuration.", e); 511 configurable = false; 512 } 513 } else { 514 configurable = true; 515 } 516 return configurable; 517 } 518 519 /** 520 * @param newTemplates 521 * @return Old templates 522 */ 523 public String changeTemplates(String newTemplates) { 524 String oldTemplates = templates; 525 templates = newTemplates; 526 try { 527 setBasicConfiguration(false); 528 configurable = true; 529 } catch (ConfigurationException e) { 530 log.warn("Error reading basic configuration.", e); 531 configurable = false; 532 } 533 return oldTemplates; 534 } 535 536 /** 537 * Change templates using given database template 538 * 539 * @param dbTemplate new database template 540 * @since 5.4.2 541 */ 542 public void changeDBTemplate(String dbTemplate) { 543 changeTemplates(rebuildTemplatesStr(dbTemplate)); 544 } 545 546 private void setBasicConfiguration() throws ConfigurationException { 547 setBasicConfiguration(true); 548 } 549 550 private void setBasicConfiguration(boolean save) throws ConfigurationException { 551 try { 552 // Load default configuration 553 defaultConfig = loadTrimmedProperties(nuxeoDefaultConf); 554 // Add System properties 555 defaultConfig.putAll(System.getProperties()); 556 userConfig = new CryptoProperties(defaultConfig); 557 558 // If Windows, replace backslashes in paths in nuxeo.conf 559 if (SystemUtils.IS_OS_WINDOWS) { 560 replaceBackslashes(); 561 } 562 // Load user configuration 563 userConfig.putAll(loadTrimmedProperties(nuxeoConf)); 564 onceGeneration = "once".equals(userConfig.getProperty(PARAM_FORCE_GENERATION)); 565 forceGeneration = onceGeneration 566 || Boolean.parseBoolean(userConfig.getProperty(PARAM_FORCE_GENERATION, "false")); 567 checkForDeprecatedParameters(userConfig); 568 569 // Synchronize directories between serverConfigurator and 570 // userConfig/defaultConfig 571 setDirectoryWithProperty(org.nuxeo.common.Environment.NUXEO_DATA_DIR); 572 setDirectoryWithProperty(org.nuxeo.common.Environment.NUXEO_LOG_DIR); 573 setDirectoryWithProperty(org.nuxeo.common.Environment.NUXEO_PID_DIR); 574 setDirectoryWithProperty(org.nuxeo.common.Environment.NUXEO_TMP_DIR); 575 setDirectoryWithProperty(org.nuxeo.common.Environment.NUXEO_MP_DIR); 576 } catch (NullPointerException e) { 577 throw new ConfigurationException("Missing file", e); 578 } catch (FileNotFoundException e) { 579 throw new ConfigurationException("Missing file: " + nuxeoDefaultConf + " or " + nuxeoConf, e); 580 } catch (IOException e) { 581 throw new ConfigurationException("Error reading " + nuxeoConf, e); 582 } 583 584 // Override default configuration with specific configuration(s) of 585 // the chosen template(s) which can be outside of server filesystem 586 try { 587 includeTemplates(); 588 checkForDeprecatedParameters(defaultConfig); 589 extractDatabaseTemplateName(); 590 extractNoSqlDatabaseTemplateName(); 591 } catch (FileNotFoundException e) { 592 throw new ConfigurationException("Missing file", e); 593 } catch (IOException e) { 594 throw new ConfigurationException("Error reading " + nuxeoConf, e); 595 } 596 597 Map<String, String> newParametersToSave = evalDynamicProperties(); 598 if (save && newParametersToSave != null && !newParametersToSave.isEmpty()) { 599 saveConfiguration(newParametersToSave, false, false); 600 } 601 602 logDebugInformation(); 603 604 // Could be useful to initialize DEFAULT env... 605 // initEnv(); 606 } 607 608 /** 609 * @since 5.7 610 * @throws IOException 611 */ 612 protected void includeTemplates() throws IOException { 613 includedTemplates.clear(); 614 List<File> orderedTemplates = includeTemplates(getUserTemplates()); 615 includedTemplates.clear(); 616 includedTemplates.addAll(orderedTemplates); 617 log.debug(includedTemplates); 618 } 619 620 /** 621 * Old way of detecting if seam debug is set, by checking for the presence of a file. 622 * <p> 623 * On 5.6, using the config generator to get the info from the nuxeo.conf file makes it possible to get the property 624 * value this early, so adding an empty file at {@link #SEAM_HOT_RELOAD_GLOBAL_CONFIG_FILE} is no longer needed. 625 * 626 * @deprecated since 5.6 627 */ 628 @Deprecated 629 protected boolean hasSeamDebugFile() { 630 File f = new File(getServerConfigurator().getConfigDir(), SEAM_HOT_RELOAD_GLOBAL_CONFIG_FILE); 631 if (!f.exists()) { 632 return false; 633 } 634 return true; 635 } 636 637 private void logDebugInformation() { 638 String debugPropValue = userConfig.getProperty(NUXEO_DEV_SYSTEM_PROP); 639 if (Boolean.parseBoolean(debugPropValue)) { 640 log.debug("Nuxeo Dev mode enabled"); 641 } else { 642 log.debug("Nuxeo Dev mode is not enabled"); 643 } 644 645 // XXX: cannot init seam debug mode when global debug mode is set, as 646 // it needs to be activated at startup, and requires the seam-debug jar 647 // to be in the classpath anyway 648 String seamDebugPropValue = userConfig.getProperty(SEAM_DEBUG_SYSTEM_PROP); 649 if (Boolean.parseBoolean(seamDebugPropValue) || hasSeamDebugFile()) { 650 log.debug("Nuxeo Seam HotReload is enabled"); 651 // add it to the system props for compat, in case this mode was 652 // detected because of presence of the file in the config dir, and 653 // because it's checked there on code that relies on it 654 System.setProperty(SEAM_DEBUG_SYSTEM_PROP, "true"); 655 } else { 656 log.debug("Nuxeo Seam HotReload is not enabled"); 657 } 658 } 659 660 /** 661 * Generate properties which values are based on others 662 * 663 * @return Map with new parameters to save in {@code nuxeoConf} 664 * @throws ConfigurationException 665 * @since 5.5 666 */ 667 protected HashMap<String, String> evalDynamicProperties() throws ConfigurationException { 668 HashMap<String, String> newParametersToSave = new HashMap<>(); 669 evalLoopbackURL(); 670 evalServerStatusKey(newParametersToSave); 671 return newParametersToSave; 672 } 673 674 /** 675 * Generate a server status key if not already set 676 * 677 * @param newParametersToSave 678 * @throws ConfigurationException 679 * @see Environment#SERVER_STATUS_KEY 680 * @since 5.5 681 */ 682 private void evalServerStatusKey(Map<String, String> newParametersToSave) throws ConfigurationException { 683 if (userConfig.getProperty(Environment.SERVER_STATUS_KEY) == null) { 684 newParametersToSave.put(Environment.SERVER_STATUS_KEY, UUID.randomUUID().toString().substring(0, 8)); 685 } 686 } 687 688 private void evalLoopbackURL() throws ConfigurationException { 689 String loopbackURL = userConfig.getProperty(PARAM_LOOPBACK_URL); 690 if (loopbackURL != null) { 691 log.debug("Using configured loop back url: " + loopbackURL); 692 return; 693 } 694 InetAddress bindAddress = getBindAddress(); 695 // Address and ports already checked by #checkAddressesAndPorts 696 try { 697 if (bindAddress.isAnyLocalAddress()) { 698 boolean preferIPv6 = "false".equals(System.getProperty("java.net.preferIPv4Stack")) 699 && "true".equals(System.getProperty("java.net.preferIPv6Addresses")); 700 bindAddress = preferIPv6 ? InetAddress.getByName("::1") : InetAddress.getByName("127.0.0.1"); 701 log.debug("Bind address is \"ANY\", using local address instead: " + bindAddress); 702 } 703 } catch (UnknownHostException e) { 704 log.debug(e, e); 705 log.error(e.getMessage()); 706 } 707 708 String httpPort = userConfig.getProperty(PARAM_HTTP_PORT); 709 String contextPath = userConfig.getProperty(PARAM_CONTEXT_PATH); 710 // Is IPv6 or IPv4 ? 711 if (bindAddress instanceof Inet6Address) { 712 loopbackURL = "http://[" + bindAddress.getHostAddress() + "]:" + httpPort + contextPath; 713 } else { 714 loopbackURL = "http://" + bindAddress.getHostAddress() + ":" + httpPort + contextPath; 715 } 716 log.debug("Set as loop back URL: " + loopbackURL); 717 defaultConfig.setProperty(PARAM_LOOPBACK_URL, loopbackURL); 718 } 719 720 /** 721 * Read nuxeo.conf, replace backslashes in paths and write new nuxeo.conf 722 * 723 * @throws ConfigurationException if any error reading or writing nuxeo.conf 724 * @since 5.4.1 725 */ 726 protected void replaceBackslashes() throws ConfigurationException { 727 StringBuffer sb = new StringBuffer(); 728 BufferedReader reader = null; 729 try { 730 reader = new BufferedReader(new FileReader(nuxeoConf)); 731 String line; 732 while ((line = reader.readLine()) != null) { 733 if (line.matches(".*:\\\\.*")) { 734 line = line.replaceAll("\\\\", "/"); 735 } 736 sb.append(line + System.getProperty("line.separator")); 737 } 738 reader.close(); 739 } catch (IOException e) { 740 throw new ConfigurationException("Error reading " + nuxeoConf, e); 741 } finally { 742 if (reader != null) { 743 try { 744 reader.close(); 745 } catch (IOException e) { 746 throw new ConfigurationException(e); 747 } 748 } 749 } 750 FileWriter writer = null; 751 try { 752 writer = new FileWriter(nuxeoConf, false); 753 // Copy back file content 754 writer.append(sb.toString()); 755 } catch (IOException e) { 756 throw new ConfigurationException("Error writing in " + nuxeoConf, e); 757 } finally { 758 if (writer != null) { 759 try { 760 writer.close(); 761 } catch (IOException e) { 762 throw new ConfigurationException(e); 763 } 764 } 765 } 766 } 767 768 /** 769 * @since 5.4.2 770 * @param key Directory system key 771 * @see Environment 772 */ 773 public void setDirectoryWithProperty(String key) { 774 String directory = userConfig.getProperty(key); 775 if (directory == null) { 776 defaultConfig.setProperty(key, serverConfigurator.getDirectory(key).getPath()); 777 } else { 778 serverConfigurator.setDirectory(key, directory); 779 } 780 } 781 782 public String getUserTemplates() { 783 if (templates == null) { 784 templates = userConfig.getProperty(PARAM_TEMPLATES_NAME); 785 } 786 if (templates == null) { 787 // backward compliance: manage parameter for a single template 788 templates = userConfig.getProperty(PARAM_TEMPLATE_NAME); 789 } 790 if (templates == null) { 791 log.warn("No template found in configuration! Fallback on 'default'."); 792 templates = "default"; 793 } 794 userConfig.setProperty(PARAM_TEMPLATES_NAME, templates); 795 return templates; 796 } 797 798 protected void generateFiles() throws ConfigurationException { 799 try { 800 serverConfigurator.parseAndCopy(userConfig); 801 serverConfigurator.dumpProperties(userConfig); 802 log.info("Configuration files generated."); 803 // keep true or false, switch once to false 804 if (onceGeneration) { 805 setOnceToFalse = true; 806 writeConfiguration(); 807 } 808 } catch (FileNotFoundException e) { 809 throw new ConfigurationException("Missing file: " + e.getMessage(), e); 810 } catch (TemplateException | ParseException e) { 811 throw new ConfigurationException("Could not process FreeMarker template: " + e.getMessage(), e); 812 } catch (IOException e) { 813 throw new ConfigurationException("Configuration failure: " + e.getMessage(), e); 814 } 815 } 816 817 private List<File> includeTemplates(String templatesList) throws IOException { 818 List<File> orderedTemplates = new ArrayList<>(); 819 StringTokenizer st = new StringTokenizer(templatesList, TEMPLATE_SEPARATOR); 820 while (st.hasMoreTokens()) { 821 String nextToken = st.nextToken(); 822 File chosenTemplate = new File(nextToken); 823 // is it absolute and existing or relative path ? 824 if (!chosenTemplate.exists() || !chosenTemplate.getPath().equals(chosenTemplate.getAbsolutePath())) { 825 chosenTemplate = new File(nuxeoDefaultConf.getParentFile(), nextToken); 826 } 827 if (includedTemplates.contains(chosenTemplate)) { 828 log.debug("Already included " + nextToken); 829 continue; 830 } 831 if (!chosenTemplate.exists()) { 832 log.error(String.format("Template '%s' not found with relative or absolute path (%s). " 833 + "Check your %s parameter, and %s for included files.", nextToken, chosenTemplate, 834 PARAM_TEMPLATES_NAME, PARAM_INCLUDED_TEMPLATES)); 835 continue; 836 } 837 File chosenTemplateConf = new File(chosenTemplate, NUXEO_DEFAULT_CONF); 838 includedTemplates.add(chosenTemplate); 839 if (!chosenTemplateConf.exists()) { 840 log.warn("Ignore template (no default configuration): " + nextToken); 841 continue; 842 } 843 844 Properties subTemplateConf = loadTrimmedProperties(chosenTemplateConf); 845 String subTemplatesList = subTemplateConf.getProperty(PARAM_INCLUDED_TEMPLATES); 846 if (subTemplatesList != null && subTemplatesList.length() > 0) { 847 orderedTemplates.addAll(includeTemplates(subTemplatesList)); 848 } 849 // Load configuration from chosen templates 850 defaultConfig.putAll(subTemplateConf); 851 orderedTemplates.add(chosenTemplate); 852 String templateInfo = "Include template: " + chosenTemplate.getPath(); 853 if (quiet) { 854 log.debug(templateInfo); 855 } else { 856 log.info(templateInfo); 857 } 858 } 859 return orderedTemplates; 860 } 861 862 /** 863 * Check for deprecated parameters 864 * 865 * @param properties 866 * @since 5.6 867 */ 868 protected void checkForDeprecatedParameters(Properties properties) { 869 serverConfigurator.addServerSpecificParameters(parametersMigration); 870 @SuppressWarnings("rawtypes") 871 Enumeration userEnum = properties.propertyNames(); 872 while (userEnum.hasMoreElements()) { 873 String key = (String) userEnum.nextElement(); 874 if (parametersMigration.containsKey(key)) { 875 String value = properties.getProperty(key); 876 properties.setProperty(parametersMigration.get(key), value); 877 // Don't remove the deprecated key yet - more 878 // warnings but old things should keep working 879 // properties.remove(key); 880 if (!hideDeprecationWarnings) { 881 log.warn("Parameter " + key + " is deprecated - please use " + parametersMigration.get(key) 882 + " instead"); 883 } 884 } 885 } 886 } 887 888 public File getNuxeoHome() { 889 return nuxeoHome; 890 } 891 892 public File getNuxeoDefaultConf() { 893 return nuxeoDefaultConf; 894 } 895 896 public List<File> getIncludedTemplates() { 897 return includedTemplates; 898 } 899 900 public static void main(String[] args) throws ConfigurationException { 901 new ConfigurationGenerator().run(); 902 } 903 904 /** 905 * Save changed parameters in {@code nuxeo.conf}. This method does not check values in map. Use 906 * {@link #saveFilteredConfiguration(Map)} for parameters filtering. 907 * 908 * @param changedParameters Map of modified parameters 909 * @see #saveFilteredConfiguration(Map) 910 */ 911 public void saveConfiguration(Map<String, String> changedParameters) throws ConfigurationException { 912 // Keep generation true or once; switch false to once 913 saveConfiguration(changedParameters, false, true); 914 } 915 916 /** 917 * Save changed parameters in {@code nuxeo.conf} calculating templates if changedParameters contains a value for 918 * {@link #PARAM_TEMPLATE_DBNAME}. If a parameter value is empty ("" or null), then the property is unset. 919 * {@link #PARAM_WIZARD_DONE}, {@link #PARAM_TEMPLATES_NAME} and {@link #PARAM_FORCE_GENERATION} cannot be unset, 920 * but their value can be changed.<br/> 921 * This method does not check values in map: use {@link #saveFilteredConfiguration(Map)} for parameters filtering. 922 * 923 * @param changedParameters Map of modified parameters 924 * @param setGenerationOnceToFalse If generation was on (true or once), then set it to false or not? 925 * @param setGenerationFalseToOnce If generation was off (false), then set it to once? 926 * @see #saveFilteredConfiguration(Map) 927 * @since 5.5 928 */ 929 public void saveConfiguration(Map<String, String> changedParameters, boolean setGenerationOnceToFalse, 930 boolean setGenerationFalseToOnce) throws ConfigurationException { 931 setOnceToFalse = setGenerationOnceToFalse; 932 setFalseToOnce = setGenerationFalseToOnce; 933 updateStoredConfig(); 934 String newDbTemplate = changedParameters.remove(PARAM_TEMPLATE_DBNAME); 935 if (newDbTemplate != null) { 936 changedParameters.put(PARAM_TEMPLATES_NAME, rebuildTemplatesStr(newDbTemplate)); 937 } 938 newDbTemplate = changedParameters.remove(PARAM_TEMPLATE_DBNOSQL_NAME); 939 if (newDbTemplate != null) { 940 changedParameters.put(PARAM_TEMPLATES_NAME, rebuildTemplatesStr(newDbTemplate)); 941 } 942 if (changedParameters.containsValue(null) || changedParameters.containsValue("")) { 943 // There are properties to unset 944 Set<String> propertiesToUnset = new HashSet<>(); 945 for (String key : changedParameters.keySet()) { 946 if (StringUtils.isEmpty(changedParameters.get(key))) { 947 propertiesToUnset.add(key); 948 } 949 } 950 for (String key : propertiesToUnset) { 951 changedParameters.remove(key); 952 userConfig.remove(key); 953 } 954 } 955 userConfig.putAll(changedParameters); 956 writeConfiguration(); 957 updateStoredConfig(); 958 } 959 960 private void updateStoredConfig() { 961 if (storedConfig == null) { 962 storedConfig = new Properties(defaultConfig); 963 } else { 964 storedConfig.clear(); 965 } 966 storedConfig.putAll(userConfig); 967 } 968 969 /** 970 * Save changed parameters in {@code nuxeo.conf}, filtering parameters with {@link #getChangedParameters(Map)} 971 * 972 * @param changedParameters Maps of modified parameters 973 * @since 5.4.2 974 * @see #saveConfiguration(Map) 975 * @see #getChangedParameters(Map) 976 */ 977 public void saveFilteredConfiguration(Map<String, String> changedParameters) throws ConfigurationException { 978 Map<String, String> filteredParameters = getChangedParameters(changedParameters); 979 saveConfiguration(filteredParameters); 980 } 981 982 /** 983 * Filters given parameters including them only if (there was no previous value and new value is not empty/null) or 984 * (there was a previous value and it differs from the new value) 985 * 986 * @param changedParameters parameters to be filtered 987 * @return filtered map 988 * @since 5.4.2 989 */ 990 public Map<String, String> getChangedParameters(Map<String, String> changedParameters) { 991 Map<String, String> filteredChangedParameters = new HashMap<>(); 992 for (String key : changedParameters.keySet()) { 993 String oldParam = getStoredConfig().getProperty(key); 994 String newParam = changedParameters.get(key); 995 if (newParam != null) { 996 newParam = newParam.trim(); 997 } 998 if (oldParam == null && StringUtils.isNotEmpty(newParam) || oldParam != null 999 && !oldParam.trim().equals(newParam)) { 1000 filteredChangedParameters.put(key, newParam); 1001 } 1002 } 1003 return filteredChangedParameters; 1004 } 1005 1006 private void writeConfiguration() throws ConfigurationException { 1007 StringBuffer newContent = readConfiguration(); 1008 FileWriter writer = null; 1009 try { 1010 writer = new FileWriter(nuxeoConf, false); 1011 // Copy back file content 1012 writer.append(newContent.toString()); 1013 // Write changed parameters 1014 writer.write(BOUNDARY_BEGIN + " " + new Date().toString() + System.getProperty("line.separator")); 1015 for (Object o : new TreeSet<>(userConfig.keySet())) { 1016 String key = (String) o; 1017 // Ignore parameters already stored in newContent 1018 if (PARAM_FORCE_GENERATION.equals(key) || PARAM_WIZARD_DONE.equals(key) 1019 || PARAM_TEMPLATES_NAME.equals(key)) { 1020 continue; 1021 } 1022 String oldValue = storedConfig.getProperty(key, ""); 1023 String newValue = userConfig.getRawProperty(key, ""); 1024 if (!newValue.equals(oldValue)) { 1025 writer.write("#" + key + "=" + oldValue + System.getProperty("line.separator")); 1026 writer.write(key + "=" + newValue + System.getProperty("line.separator")); 1027 } 1028 } 1029 writer.write(BOUNDARY_END + System.getProperty("line.separator")); 1030 } catch (IOException e) { 1031 throw new ConfigurationException("Error writing in " + nuxeoConf, e); 1032 } finally { 1033 if (writer != null) { 1034 try { 1035 writer.close(); 1036 } catch (IOException e) { 1037 throw new ConfigurationException(e); 1038 } 1039 } 1040 } 1041 } 1042 1043 private StringBuffer readConfiguration() throws ConfigurationException { 1044 String wizardParam = null, templatesParam = null; 1045 Integer generationIndex = null, wizardIndex = null, templatesIndex = null; 1046 // Will change wizardParam value instead of appending it 1047 wizardParam = userConfig.getProperty(PARAM_WIZARD_DONE); 1048 // Will change templatesParam value instead of appending it 1049 templatesParam = userConfig.getProperty(PARAM_TEMPLATES_NAME); 1050 ArrayList<String> newLines = new ArrayList<>(); 1051 BufferedReader reader = null; 1052 try { 1053 reader = new BufferedReader(new FileReader(nuxeoConf)); 1054 String line; 1055 boolean onConfiguratorContent = false; 1056 while ((line = reader.readLine()) != null) { 1057 if (!onConfiguratorContent) { 1058 if (!line.startsWith(BOUNDARY_BEGIN)) { 1059 if (line.startsWith(PARAM_FORCE_GENERATION)) { 1060 if (setOnceToFalse && onceGeneration) { 1061 line = PARAM_FORCE_GENERATION + "=false"; 1062 } 1063 if (setFalseToOnce && !forceGeneration) { 1064 line = PARAM_FORCE_GENERATION + "=once"; 1065 } 1066 if (generationIndex == null) { 1067 newLines.add(line); 1068 generationIndex = newLines.size() - 1; 1069 } else { 1070 newLines.set(generationIndex, line); 1071 } 1072 } else if (line.startsWith(PARAM_WIZARD_DONE)) { 1073 if (wizardParam != null) { 1074 line = PARAM_WIZARD_DONE + "=" + wizardParam; 1075 } 1076 if (wizardIndex == null) { 1077 newLines.add(line); 1078 wizardIndex = newLines.size() - 1; 1079 } else { 1080 newLines.set(wizardIndex, line); 1081 } 1082 } else if (line.startsWith(PARAM_TEMPLATES_NAME)) { 1083 if (templatesParam != null) { 1084 line = PARAM_TEMPLATES_NAME + "=" + templatesParam; 1085 } 1086 if (templatesIndex == null) { 1087 newLines.add(line); 1088 templatesIndex = newLines.size() - 1; 1089 } else { 1090 newLines.set(templatesIndex, line); 1091 } 1092 } else { 1093 int equalIdx = line.indexOf("="); 1094 if (equalIdx < 1 || line.trim().startsWith("#")) { 1095 newLines.add(line); 1096 } else { 1097 String key = line.substring(0, equalIdx).trim(); 1098 if (userConfig.getProperty(key) != null) { 1099 newLines.add(line); 1100 } else { 1101 newLines.add("#" + line); 1102 } 1103 } 1104 } 1105 } else { 1106 // What must be written just before the BOUNDARY_BEGIN 1107 if (templatesIndex == null && templatesParam != null) { 1108 newLines.add(PARAM_TEMPLATES_NAME + "=" + templatesParam); 1109 templatesIndex = newLines.size() - 1; 1110 } 1111 if (wizardIndex == null && wizardParam != null) { 1112 newLines.add(PARAM_WIZARD_DONE + "=" + wizardParam); 1113 wizardIndex = newLines.size() - 1; 1114 } 1115 onConfiguratorContent = true; 1116 } 1117 } else { 1118 if (!line.startsWith(BOUNDARY_END)) { 1119 int equalIdx = line.indexOf("="); 1120 if (line.startsWith("#" + PARAM_TEMPLATES_NAME) || line.startsWith(PARAM_TEMPLATES_NAME)) { 1121 // Backward compliance, it must be ignored 1122 continue; 1123 } 1124 if (equalIdx < 1) { // Ignore non-readable lines 1125 continue; 1126 } 1127 if (line.trim().startsWith("#")) { 1128 String key = line.substring(1, equalIdx).trim(); 1129 String value = line.substring(equalIdx + 1).trim(); 1130 getStoredConfig().setProperty(key, value); 1131 } else { 1132 String key = line.substring(0, equalIdx).trim(); 1133 String value = line.substring(equalIdx + 1).trim(); 1134 if (!value.equals(userConfig.getRawProperty(key))) { 1135 getStoredConfig().setProperty(key, value); 1136 } 1137 } 1138 } else { 1139 onConfiguratorContent = false; 1140 } 1141 } 1142 } 1143 reader.close(); 1144 } catch (IOException e) { 1145 throw new ConfigurationException("Error reading " + nuxeoConf, e); 1146 } finally { 1147 if (reader != null) { 1148 try { 1149 reader.close(); 1150 } catch (IOException e) { 1151 throw new ConfigurationException(e); 1152 } 1153 } 1154 } 1155 StringBuffer newContent = new StringBuffer(); 1156 for (int i = 0; i < newLines.size(); i++) { 1157 newContent.append(newLines.get(i).trim() + System.getProperty("line.separator")); 1158 } 1159 return newContent; 1160 } 1161 1162 /** 1163 * Extract a database template from the current list of templates. Return the last one if there are multiples. 1164 * 1165 * @see #rebuildTemplatesStr(String) 1166 */ 1167 public String extractDatabaseTemplateName() { 1168 return extractDbTemplateName(DB_LIST, PARAM_TEMPLATE_DBTYPE, PARAM_TEMPLATE_DBNAME, "unknown"); 1169 } 1170 1171 /** 1172 * Extract a NoSQL database template from the current list of templates. Return the last one if there are multiples. 1173 * 1174 * @see #rebuildTemplatesStr(String) 1175 * @since 8.1 1176 */ 1177 public String extractNoSqlDatabaseTemplateName() { 1178 return extractDbTemplateName(DB_NOSQL_LIST, PARAM_TEMPLATE_DBNOSQL_TYPE, PARAM_TEMPLATE_DBNOSQL_NAME, null); 1179 } 1180 1181 private String extractDbTemplateName(List<String> knownDbList, String paramTemplateDbType, 1182 String paramTemplateDbName, String defaultTemplate) { 1183 String dbTemplate = defaultTemplate; 1184 boolean found = false; 1185 for (File templateFile : includedTemplates) { 1186 String template = templateFile.getName(); 1187 if (knownDbList.contains(template)) { 1188 dbTemplate = template; 1189 found = true; 1190 } 1191 } 1192 String dbType = userConfig.getProperty(paramTemplateDbType); 1193 if (!found && dbType != null) { 1194 log.warn(String.format("Didn't find a known database template in the list but " 1195 + "some template contributed a value for %s.", paramTemplateDbType)); 1196 dbTemplate = dbType; 1197 } 1198 if (dbTemplate != null && !dbTemplate.equals(dbType)) { 1199 if (dbType == null) { 1200 log.warn(String.format("Missing value for %s, using %s", paramTemplateDbType, dbTemplate)); 1201 userConfig.setProperty(paramTemplateDbType, dbTemplate); 1202 } else { 1203 log.error(String.format("Inconsistent values between %s (%s) and %s (%s)", paramTemplateDbName, 1204 dbTemplate, paramTemplateDbType, dbType)); 1205 } 1206 } 1207 if (dbTemplate == null) { 1208 defaultConfig.remove(paramTemplateDbName); 1209 } else { 1210 defaultConfig.setProperty(paramTemplateDbName, dbTemplate); 1211 } 1212 return dbTemplate; 1213 } 1214 1215 /** 1216 * @return nuxeo.conf file used 1217 */ 1218 public File getNuxeoConf() { 1219 return nuxeoConf; 1220 } 1221 1222 /** 1223 * Delegate logs initialization to serverConfigurator instance 1224 * 1225 * @since 5.4.2 1226 */ 1227 public void initLogs() { 1228 serverConfigurator.initLogs(); 1229 } 1230 1231 /** 1232 * @return log directory 1233 * @since 5.4.2 1234 */ 1235 public File getLogDir() { 1236 return serverConfigurator.getLogDir(); 1237 } 1238 1239 /** 1240 * @return pid directory 1241 * @since 5.4.2 1242 */ 1243 public File getPidDir() { 1244 return serverConfigurator.getPidDir(); 1245 } 1246 1247 /** 1248 * @return Data directory 1249 * @since 5.4.2 1250 */ 1251 public File getDataDir() { 1252 return serverConfigurator.getDataDir(); 1253 } 1254 1255 /** 1256 * Create needed directories. Check existence of old paths. If old paths have been found and they cannot be upgraded 1257 * automatically, then upgrading message is logged and error thrown. 1258 * 1259 * @throws ConfigurationException If a deprecated directory has been detected. 1260 * @since 5.4.2 1261 * @see ServerConfigurator#verifyInstallation() 1262 */ 1263 public void verifyInstallation() throws ConfigurationException { 1264 checkJavaVersion(); 1265 ifNotExistsAndIsDirectoryThenCreate(getLogDir()); 1266 ifNotExistsAndIsDirectoryThenCreate(getPidDir()); 1267 ifNotExistsAndIsDirectoryThenCreate(getDataDir()); 1268 ifNotExistsAndIsDirectoryThenCreate(getTmpDir()); 1269 ifNotExistsAndIsDirectoryThenCreate(getPackagesDir()); 1270 checkAddressesAndPorts(); 1271 serverConfigurator.verifyInstallation(); 1272 if (!DB_EXCLUDE_CHECK_LIST.contains(userConfig.getProperty(PARAM_TEMPLATE_DBTYPE))) { 1273 try { 1274 checkDatabaseConnection(userConfig.getProperty(PARAM_TEMPLATE_DBNAME), 1275 userConfig.getProperty(PARAM_DB_NAME), userConfig.getProperty(PARAM_DB_USER), 1276 userConfig.getProperty(PARAM_DB_PWD), userConfig.getProperty(PARAM_DB_HOST), 1277 userConfig.getProperty(PARAM_DB_PORT)); 1278 } catch (IOException e) { 1279 throw new ConfigurationException(e); 1280 } catch (DatabaseDriverException e) { 1281 log.debug(e, e); 1282 log.error(e.getMessage()); 1283 throw new ConfigurationException("Could not find database driver: " + e.getMessage()); 1284 } catch (SQLException e) { 1285 log.debug(e, e); 1286 log.error(e.getMessage()); 1287 throw new ConfigurationException("Failed to connect on database: " + e.getMessage()); 1288 } 1289 } 1290 // TODO NXP-18773: check NoSQL database 1291 } 1292 1293 /** 1294 * @return Marketplace packages directory 1295 * @since 5.9.4 1296 */ 1297 private File getPackagesDir() { 1298 return serverConfigurator.getPackagesDir(); 1299 } 1300 1301 /** 1302 * Check that the process is executed with a supported Java version. See <a 1303 * href="http://www.oracle.com/technetwork/java/javase/versioning-naming-139433.html">J2SE SDK/JRE Version String 1304 * Naming Convention</a> 1305 * 1306 * @throws ConfigurationException 1307 * @since 5.6 1308 */ 1309 public void checkJavaVersion() throws ConfigurationException { 1310 String[] requiredVersion = COMPLIANT_JAVA_VERSIONS[0].split("_"); 1311 String version = System.getProperty("java.version"); 1312 String[] versionSplit = version.split("_"); 1313 boolean isCompliant = requiredVersion[0].equals(versionSplit[0]) 1314 && requiredVersion[1].compareTo(versionSplit[1]) <= 0; 1315 boolean isGreater = requiredVersion[0].compareTo(versionSplit[0]) < 0; 1316 if (!isCompliant) { 1317 String message = String.format("Nuxeo requires Java %s+ (detected %s).", COMPLIANT_JAVA_VERSIONS[0], 1318 version); 1319 if (isGreater || "nofail".equalsIgnoreCase(System.getProperty("jvmcheck", "fail"))) { 1320 log.warn(message); 1321 } else { 1322 throw new ConfigurationException(message + " See 'jvmcheck' option to bypass version check."); 1323 } 1324 } 1325 } 1326 1327 /** 1328 * Will check the configured addresses are reachable and Nuxeo required ports are available on those addresses. 1329 * Server specific implementations should override this method in order to check for server specific ports. 1330 * {@link #PARAM_BIND_ADDRESS} must be set before. 1331 * 1332 * @throws ConfigurationException 1333 * @since 5.5 1334 * @see ServerConfigurator#verifyInstallation() 1335 */ 1336 public void checkAddressesAndPorts() throws ConfigurationException { 1337 InetAddress bindAddress = getBindAddress(); 1338 // Sanity check 1339 if (bindAddress.isMulticastAddress()) { 1340 throw new ConfigurationException("Multicast address won't work: " + bindAddress); 1341 } 1342 checkAddressReachable(bindAddress); 1343 checkPortAvailable(bindAddress, Integer.parseInt(userConfig.getProperty(PARAM_HTTP_PORT))); 1344 } 1345 1346 public InetAddress getBindAddress() throws ConfigurationException { 1347 InetAddress bindAddress; 1348 try { 1349 bindAddress = InetAddress.getByName(userConfig.getProperty(PARAM_BIND_ADDRESS)); 1350 log.debug("Configured bind address: " + bindAddress); 1351 } catch (UnknownHostException e) { 1352 throw new ConfigurationException(e); 1353 } 1354 return bindAddress; 1355 } 1356 1357 /** 1358 * @param address address to check for availability 1359 * @throws ConfigurationException 1360 * @since 5.5 1361 */ 1362 public static void checkAddressReachable(InetAddress address) throws ConfigurationException { 1363 try { 1364 log.debug("Checking availability of " + address); 1365 address.isReachable(ADDRESS_PING_TIMEOUT); 1366 } catch (IOException e) { 1367 throw new ConfigurationException("Unreachable bind address " + address); 1368 } 1369 } 1370 1371 /** 1372 * Checks if port is available on given address. 1373 * 1374 * @param port port to check for availability 1375 * @throws ConfigurationException Throws an exception if address is unavailable. 1376 * @since 5.5 1377 */ 1378 public static void checkPortAvailable(InetAddress address, int port) throws ConfigurationException { 1379 if ((port == 0) || (port == -1)) { 1380 log.warn("Port is set to " + Integer.toString(port) 1381 + " - assuming it is disabled - skipping availability check"); 1382 return; 1383 } 1384 if (port < MIN_PORT || port > MAX_PORT) { 1385 throw new IllegalArgumentException("Invalid port: " + port); 1386 } 1387 ServerSocket socketTCP = null; 1388 // DatagramSocket socketUDP = null; 1389 try { 1390 log.debug("Checking availability of port " + port + " on address " + address); 1391 socketTCP = new ServerSocket(port, 0, address); 1392 socketTCP.setReuseAddress(true); 1393 // socketUDP = new DatagramSocket(port, address); 1394 // socketUDP.setReuseAddress(true); 1395 // return true; 1396 } catch (IOException e) { 1397 throw new ConfigurationException(e.getMessage() + ": " + address + ":" + port, e); 1398 } finally { 1399 // if (socketUDP != null) { 1400 // socketUDP.close(); 1401 // } 1402 if (socketTCP != null) { 1403 try { 1404 socketTCP.close(); 1405 } catch (IOException e) { 1406 // Do not throw 1407 } 1408 } 1409 } 1410 } 1411 1412 /** 1413 * @return Temporary directory 1414 */ 1415 public File getTmpDir() { 1416 return serverConfigurator.getTmpDir(); 1417 } 1418 1419 private void ifNotExistsAndIsDirectoryThenCreate(File directory) { 1420 if (!directory.isDirectory()) { 1421 directory.mkdirs(); 1422 } 1423 } 1424 1425 /** 1426 * @return Log files produced by Log4J configuration without loading this configuration instead of current active 1427 * one. 1428 * @since 5.4.2 1429 */ 1430 public ArrayList<String> getLogFiles() { 1431 File log4jConfFile = serverConfigurator.getLogConfFile(); 1432 System.setProperty(org.nuxeo.common.Environment.NUXEO_LOG_DIR, getLogDir().getPath()); 1433 return Log4JHelper.getFileAppendersFiles(log4jConfFile); 1434 } 1435 1436 /** 1437 * Check if wizard must and can be ran 1438 * 1439 * @return true if configuration wizard is required before starting Nuxeo 1440 * @since 5.4.2 1441 */ 1442 public boolean isWizardRequired() { 1443 return !"true".equalsIgnoreCase(getUserConfig().getProperty(PARAM_WIZARD_DONE, "true")) 1444 && serverConfigurator.isWizardAvailable(); 1445 } 1446 1447 /** 1448 * Rebuild a templates string for use in nuxeo.conf 1449 * 1450 * @param dbTemplate database template to use instead of current one 1451 * @return new templates string using given dbTemplate 1452 * @since 5.4.2 1453 * @see #extractDatabaseTemplateName() 1454 * @see #changeDBTemplate(String) 1455 * @see #changeTemplates(String) 1456 */ 1457 public String rebuildTemplatesStr(String dbTemplate) { 1458 List<String> templatesList = new ArrayList<>(); 1459 templatesList.addAll(Arrays.asList(templates.split(TEMPLATE_SEPARATOR))); 1460 String currentDBTemplate = null; 1461 if (DB_LIST.contains(dbTemplate)) { 1462 currentDBTemplate = userConfig.getProperty(PARAM_TEMPLATE_DBNAME); 1463 if (currentDBTemplate == null) { 1464 currentDBTemplate = extractDatabaseTemplateName(); 1465 } 1466 } else if (DB_NOSQL_LIST.contains(dbTemplate)) { 1467 currentDBTemplate = userConfig.getProperty(PARAM_TEMPLATE_DBNOSQL_NAME); 1468 if (currentDBTemplate == null) { 1469 currentDBTemplate = extractNoSqlDatabaseTemplateName(); 1470 } 1471 if ("none".equals(dbTemplate)) { 1472 dbTemplate = null; 1473 } 1474 } 1475 int dbIdx = templatesList.indexOf(currentDBTemplate); 1476 if (dbIdx < 0) { 1477 if (dbTemplate == null) { 1478 return templates; 1479 } 1480 // current db template is implicit => set the new one 1481 templatesList.add(dbTemplate); 1482 } else if (dbTemplate == null) { 1483 // current db template is explicit => remove it 1484 templatesList.remove(dbIdx); 1485 } else { 1486 // current db template is explicit => replace it 1487 templatesList.set(dbIdx, dbTemplate); 1488 } 1489 return StringUtils.join(templatesList, TEMPLATE_SEPARATOR); 1490 } 1491 1492 /** 1493 * @return Nuxeo config directory 1494 * @since 5.4.2 1495 */ 1496 public File getConfigDir() { 1497 return serverConfigurator.getConfigDir(); 1498 } 1499 1500 /** 1501 * Ensure the server will start only wizard application, not Nuxeo 1502 * 1503 * @since 5.4.2 1504 */ 1505 public void prepareWizardStart() { 1506 serverConfigurator.prepareWizardStart(); 1507 } 1508 1509 /** 1510 * Ensure the wizard won't be started and nuxeo is ready for use 1511 * 1512 * @since 5.4.2 1513 */ 1514 public void cleanupPostWizard() { 1515 serverConfigurator.cleanupPostWizard(); 1516 } 1517 1518 /** 1519 * @return Nuxeo runtime home 1520 */ 1521 public File getRuntimeHome() { 1522 return serverConfigurator.getRuntimeHome(); 1523 } 1524 1525 /** 1526 * @since 5.4.2 1527 * @return true if there's an install in progress 1528 */ 1529 public boolean isInstallInProgress() { 1530 return getInstallFile().exists(); 1531 } 1532 1533 /** 1534 * @return File pointing to the directory containing the marketplace packages included in the distribution 1535 * @since 5.6 1536 */ 1537 public File getDistributionMPDir() { 1538 String mpDir = userConfig.getProperty(PARAM_MP_DIR, DISTRIBUTION_MP_DIR); 1539 return new File(getNuxeoHome(), mpDir); 1540 } 1541 1542 /** 1543 * @return Install/upgrade file 1544 * @since 5.4.1 1545 */ 1546 public File getInstallFile() { 1547 return new File(serverConfigurator.getDataDir(), INSTALL_AFTER_RESTART); 1548 } 1549 1550 /** 1551 * Add template(s) to the {@link #PARAM_TEMPLATES_NAME} list if not already present 1552 * 1553 * @param templatesToAdd Comma separated templates to add 1554 * @throws ConfigurationException 1555 * @since 5.5 1556 */ 1557 public void addTemplate(String templatesToAdd) throws ConfigurationException { 1558 String currentTemplatesStr = userConfig.getProperty(PARAM_TEMPLATES_NAME); 1559 List<String> templatesList = new ArrayList<>(); 1560 templatesList.addAll(Arrays.asList(currentTemplatesStr.split(TEMPLATE_SEPARATOR))); 1561 List<String> templatesToAddList = Arrays.asList(templatesToAdd.split(TEMPLATE_SEPARATOR)); 1562 if (templatesList.addAll(templatesToAddList)) { 1563 String newTemplatesStr = StringUtils.join(templatesList, TEMPLATE_SEPARATOR); 1564 HashMap<String, String> parametersToSave = new HashMap<>(); 1565 parametersToSave.put(PARAM_TEMPLATES_NAME, newTemplatesStr); 1566 saveFilteredConfiguration(parametersToSave); 1567 changeTemplates(newTemplatesStr); 1568 } 1569 } 1570 1571 /** 1572 * Remove template(s) from the {@link #PARAM_TEMPLATES_NAME} list 1573 * 1574 * @param templatesToRm Comma separated templates to remove 1575 * @throws ConfigurationException 1576 * @since 5.5 1577 */ 1578 public void rmTemplate(String templatesToRm) throws ConfigurationException { 1579 String currentTemplatesStr = userConfig.getProperty(PARAM_TEMPLATES_NAME); 1580 List<String> templatesList = new ArrayList<>(); 1581 templatesList.addAll(Arrays.asList(currentTemplatesStr.split(TEMPLATE_SEPARATOR))); 1582 List<String> templatesToRmList = Arrays.asList(templatesToRm.split(TEMPLATE_SEPARATOR)); 1583 if (templatesList.removeAll(templatesToRmList)) { 1584 String newTemplatesStr = StringUtils.join(templatesList, TEMPLATE_SEPARATOR); 1585 HashMap<String, String> parametersToSave = new HashMap<>(); 1586 parametersToSave.put(PARAM_TEMPLATES_NAME, newTemplatesStr); 1587 saveFilteredConfiguration(parametersToSave); 1588 changeTemplates(newTemplatesStr); 1589 } 1590 } 1591 1592 /** 1593 * Set a property in nuxeo configuration 1594 * 1595 * @param key 1596 * @param value 1597 * @throws ConfigurationException 1598 * @return The old value 1599 * @since 5.5 1600 */ 1601 public String setProperty(String key, String value) throws ConfigurationException { 1602 String oldValue = getStoredConfig().getProperty(key); 1603 if (PARAM_TEMPLATES_NAME.equals(key)) { 1604 templates = StringUtils.isBlank(value) ? null : value; 1605 } 1606 HashMap<String, String> newParametersToSave = new HashMap<>(); 1607 newParametersToSave.put(key, value); 1608 saveFilteredConfiguration(newParametersToSave); 1609 setBasicConfiguration(); 1610 return oldValue; 1611 } 1612 1613 /** 1614 * Set properties in nuxeo configuration 1615 * 1616 * @param newParametersToSave 1617 * @return The old values 1618 * @throws ConfigurationException 1619 * @since 7.4 1620 */ 1621 public Map<String, String> setProperties(Map<String, String> newParametersToSave) throws ConfigurationException { 1622 Map<String, String> oldValues = new HashMap<>(); 1623 for (String key : newParametersToSave.keySet()) { 1624 oldValues.put(key, getStoredConfig().getProperty(key)); 1625 if (PARAM_TEMPLATES_NAME.equals(key)) { 1626 String value = newParametersToSave.get(key); 1627 templates = StringUtils.isBlank(value) ? null : value; 1628 } 1629 } 1630 saveFilteredConfiguration(newParametersToSave); 1631 setBasicConfiguration(); 1632 return oldValues; 1633 } 1634 1635 /** 1636 * Set properties in the given template, if it exists 1637 * 1638 * @param newParametersToSave 1639 * @return The old values 1640 * @throws ConfigurationException 1641 * @throws IOException 1642 * @since 7.4 1643 */ 1644 public Map<String, String> setProperties(String template, Map<String, String> newParametersToSave) 1645 throws ConfigurationException, IOException { 1646 File templateConf = getTemplateConf(template); 1647 Properties templateProperties = loadTrimmedProperties(templateConf); 1648 Map<String, String> oldValues = new HashMap<>(); 1649 StringBuffer newContent = new StringBuffer(); 1650 try (BufferedReader reader = new BufferedReader(new FileReader(templateConf))) { 1651 String line = reader.readLine(); 1652 if (line != null && line.startsWith("## DO NOT EDIT THIS FILE")) { 1653 throw new ConfigurationException("The template states in its header that it must not be modified."); 1654 } 1655 while (line != null) { 1656 int equalIdx = line.indexOf("="); 1657 if (equalIdx < 1 || line.trim().startsWith("#")) { 1658 newContent.append(line + System.getProperty("line.separator")); 1659 } else { 1660 String key = line.substring(0, equalIdx).trim(); 1661 if (newParametersToSave.containsKey(key)) { 1662 newContent.append(key + "=" + newParametersToSave.get(key) 1663 + System.getProperty("line.separator")); 1664 } else { 1665 newContent.append(line + System.getProperty("line.separator")); 1666 } 1667 } 1668 line = reader.readLine(); 1669 } 1670 } 1671 for (String key : newParametersToSave.keySet()) { 1672 if (templateProperties.containsKey(key)) { 1673 oldValues.put(key, templateProperties.getProperty(key)); 1674 } else { 1675 newContent.append(key + "=" + newParametersToSave.get(key) + System.getProperty("line.separator")); 1676 } 1677 } 1678 try (BufferedWriter writer = new BufferedWriter(new FileWriter(templateConf))) { 1679 writer.append(newContent.toString()); 1680 } 1681 setBasicConfiguration(); 1682 return oldValues; 1683 } 1684 1685 /** 1686 * Check driver availability and database connection 1687 * 1688 * @param databaseTemplate Nuxeo database template 1689 * @param dbName nuxeo.db.name parameter in nuxeo.conf 1690 * @param dbUser nuxeo.db.user parameter in nuxeo.conf 1691 * @param dbPassword nuxeo.db.password parameter in nuxeo.conf 1692 * @param dbHost nuxeo.db.host parameter in nuxeo.conf 1693 * @param dbPort nuxeo.db.port parameter in nuxeo.conf 1694 * @throws DatabaseDriverException 1695 * @throws IOException 1696 * @throws FileNotFoundException 1697 * @throws SQLException 1698 * @since 5.6 1699 */ 1700 public void checkDatabaseConnection(String databaseTemplate, String dbName, String dbUser, String dbPassword, 1701 String dbHost, String dbPort) throws FileNotFoundException, IOException, DatabaseDriverException, 1702 SQLException { 1703 File databaseTemplateDir = new File(nuxeoHome, TEMPLATES + File.separator + databaseTemplate); 1704 Properties templateProperties = loadTrimmedProperties(new File(databaseTemplateDir, NUXEO_DEFAULT_CONF)); 1705 String classname, connectionUrl; 1706 if (userConfig.getProperty(PARAM_TEMPLATE_DBNAME).equals(databaseTemplateDir)) { 1707 // userConfig already includes databaseTemplate 1708 classname = userConfig.getProperty(PARAM_DB_DRIVER); 1709 connectionUrl = userConfig.getProperty(PARAM_DB_JDBC_URL); 1710 } else { // testing a databaseTemplate not included in userConfig 1711 // check if value is set in nuxeo.conf 1712 if (userConfig.containsKey(PARAM_DB_DRIVER)) { 1713 classname = (String) userConfig.get(PARAM_DB_DRIVER); 1714 } else { 1715 classname = templateProperties.getProperty(PARAM_DB_DRIVER); 1716 } 1717 if (userConfig.containsKey(PARAM_DB_JDBC_URL)) { 1718 connectionUrl = (String) userConfig.get(PARAM_DB_JDBC_URL); 1719 } else { 1720 connectionUrl = templateProperties.getProperty(PARAM_DB_JDBC_URL); 1721 } 1722 } 1723 // Load driver class from template or default lib directory 1724 Driver driver = lookupDriver(databaseTemplate, databaseTemplateDir, classname); 1725 // Test db connection 1726 DriverManager.registerDriver(driver); 1727 Properties ttProps = new Properties(userConfig); 1728 ttProps.put(PARAM_DB_HOST, dbHost); 1729 ttProps.put(PARAM_DB_PORT, dbPort); 1730 ttProps.put(PARAM_DB_NAME, dbName); 1731 ttProps.put(PARAM_DB_USER, dbUser); 1732 ttProps.put(PARAM_DB_PWD, dbPassword); 1733 TextTemplate tt = new TextTemplate(ttProps); 1734 String url = tt.processText(connectionUrl); 1735 Properties conProps = new Properties(); 1736 conProps.put("user", dbUser); 1737 conProps.put("password", dbPassword); 1738 log.debug("Testing URL " + url + " with " + conProps); 1739 Connection con = driver.connect(url, conProps); 1740 con.close(); 1741 } 1742 1743 /** 1744 * Build an {@link URLClassLoader} for the given databaseTemplate looking in the templates directory and in the 1745 * server lib directory, then looks for a driver 1746 * 1747 * @param databaseTemplate 1748 * @param databaseTemplateDir 1749 * @param classname Driver class name, defined by {@link #PARAM_DB_DRIVER} 1750 * @return Driver driver if found, else an Exception must have been raised. 1751 * @throws IOException 1752 * @throws FileNotFoundException 1753 * @throws DatabaseDriverException If there was an error when trying to instantiate the driver. 1754 * @since 5.6 1755 */ 1756 private Driver lookupDriver(String databaseTemplate, File databaseTemplateDir, String classname) 1757 throws FileNotFoundException, IOException, DatabaseDriverException { 1758 File[] files = (File[]) ArrayUtils.addAll( // 1759 new File(databaseTemplateDir, "lib").listFiles(), // 1760 serverConfigurator.getServerLibDir().listFiles()); 1761 List<URL> urlsList = new ArrayList<>(); 1762 if (files != null) { 1763 for (File file : files) { 1764 if (file.getName().endsWith("jar")) { 1765 try { 1766 urlsList.add(new URL("jar:file:" + file.getPath() + "!/")); 1767 log.debug("Added " + file.getPath()); 1768 } catch (MalformedURLException e) { 1769 log.error(e); 1770 } 1771 } 1772 } 1773 } 1774 URLClassLoader ucl = new URLClassLoader(urlsList.toArray(new URL[0])); 1775 try { 1776 return (Driver) Class.forName(classname, true, ucl).newInstance(); 1777 } catch (InstantiationException e) { 1778 throw new DatabaseDriverException(e); 1779 } catch (IllegalAccessException e) { 1780 throw new DatabaseDriverException(e); 1781 } catch (ClassNotFoundException e) { 1782 throw new DatabaseDriverException(e); 1783 } 1784 } 1785 1786 /** 1787 * @since 5.6 1788 * @return an {@link Environment} initialized with a few basics 1789 */ 1790 public Environment getEnv() { 1791 /* 1792 * It could be useful to initialize DEFAULT env in {@link #setBasicConfiguration()}... For now, the generated 1793 * {@link Environment} is not static. 1794 */ 1795 if (env == null) { 1796 env = new Environment(getRuntimeHome()); 1797 File distribFile = new File(new File(nuxeoHome, TEMPLATES), "common/config/distribution.properties"); 1798 if (distribFile.exists()) { 1799 try { 1800 env.loadProperties(loadTrimmedProperties(distribFile)); 1801 } catch (FileNotFoundException e) { 1802 log.error(e); 1803 } catch (IOException e) { 1804 log.error(e); 1805 } 1806 } 1807 env.loadProperties(userConfig); 1808 env.setServerHome(getNuxeoHome()); 1809 env.init(); 1810 env.setData(userConfig.getProperty(Environment.NUXEO_DATA_DIR)); 1811 env.setLog(userConfig.getProperty(Environment.NUXEO_LOG_DIR)); 1812 env.setTemp(userConfig.getProperty(Environment.NUXEO_TMP_DIR)); 1813 env.setPath(PARAM_MP_DIR, getDistributionMPDir(), env.getServerHome()); 1814 env.setPath(Environment.NUXEO_MP_DIR, getPackagesDir(), env.getServerHome()); 1815 } 1816 return env; 1817 } 1818 1819 /** 1820 * @since 5.6 1821 * @param propsFile Properties file 1822 * @return new Properties containing trimmed keys and values read in {@code propsFile} 1823 * @throws IOException 1824 */ 1825 public static Properties loadTrimmedProperties(File propsFile) throws IOException { 1826 Properties props = new Properties(); 1827 FileInputStream propsIS = new FileInputStream(propsFile); 1828 try { 1829 loadTrimmedProperties(props, propsIS); 1830 } finally { 1831 propsIS.close(); 1832 } 1833 return props; 1834 } 1835 1836 /** 1837 * @since 5.6 1838 * @param props Properties object to be filled 1839 * @param propsIS Properties InputStream 1840 * @throws IOException 1841 */ 1842 public static void loadTrimmedProperties(Properties props, InputStream propsIS) throws IOException { 1843 if (props == null) { 1844 return; 1845 } 1846 Properties p = new Properties(); 1847 p.load(propsIS); 1848 @SuppressWarnings("unchecked") 1849 Enumeration<String> pEnum = (Enumeration<String>) p.propertyNames(); 1850 while (pEnum.hasMoreElements()) { 1851 String key = pEnum.nextElement(); 1852 String value = p.getProperty(key); 1853 props.put(key.trim(), value.trim()); 1854 } 1855 } 1856 1857 /** 1858 * @return The generated properties file with dumped configuration. 1859 * @since 5.6 1860 */ 1861 public File getDumpedConfig() { 1862 return new File(getConfigDir(), CONFIGURATION_PROPERTIES); 1863 } 1864 1865 /** 1866 * Build a {@link Hashtable} which contains environment properties to instantiate a {@link InitialDirContext} 1867 * 1868 * @since 6.0 1869 */ 1870 public Hashtable<Object, Object> getContextEnv(String ldapUrl, String bindDn, String bindPassword, 1871 boolean checkAuthentication) { 1872 Hashtable<Object, Object> contextEnv = new Hashtable<>(); 1873 contextEnv.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); 1874 contextEnv.put("com.sun.jndi.ldap.connect.timeout", "10000"); 1875 contextEnv.put(javax.naming.Context.PROVIDER_URL, ldapUrl); 1876 if (checkAuthentication) { 1877 contextEnv.put(javax.naming.Context.SECURITY_AUTHENTICATION, "simple"); 1878 contextEnv.put(javax.naming.Context.SECURITY_PRINCIPAL, bindDn); 1879 contextEnv.put(javax.naming.Context.SECURITY_CREDENTIALS, bindPassword); 1880 } 1881 return contextEnv; 1882 } 1883 1884 /** 1885 * Check if the LDAP parameters are correct to bind to a LDAP server. if authenticate argument is true, it will also 1886 * check if the authentication against the LDAP server succeeds 1887 * 1888 * @param ldapUrl 1889 * @param ldapBindDn 1890 * @param ldapBindPwd 1891 * @param authenticate Indicates if authentication against LDAP should be checked. 1892 * @since 6.0 1893 */ 1894 public void checkLdapConnection(String ldapUrl, String ldapBindDn, String ldapBindPwd, boolean authenticate) 1895 throws NamingException { 1896 checkLdapConnection(getContextEnv(ldapUrl, ldapBindDn, ldapBindPwd, authenticate)); 1897 } 1898 1899 /** 1900 * @param contextEnv Environment properties to build a {@link InitialDirContext} 1901 * @since 6.0 1902 */ 1903 public void checkLdapConnection(Hashtable<Object, Object> contextEnv) throws NamingException { 1904 DirContext dirContext = new InitialDirContext(contextEnv); 1905 dirContext.close(); 1906 } 1907 1908 /** 1909 * @return a {@link Crypto} instance initialized with the configuration parameters 1910 * @since 7.4 1911 * @see Crypto 1912 */ 1913 public Crypto getCrypto() { 1914 return userConfig.getCrypto(); 1915 } 1916 1917 /** 1918 * @param template path to configuration template directory 1919 * @return A {@code nuxeo.defaults} file if it exists. 1920 * @throws ConfigurationException if the template file is not found. 1921 * @since 7.4 1922 */ 1923 public File getTemplateConf(String template) throws ConfigurationException { 1924 File templateDir = new File(template); 1925 if (!templateDir.isAbsolute()) { 1926 templateDir = new File(System.getProperty("user.dir"), template); 1927 if (!templateDir.exists() || !new File(templateDir, NUXEO_DEFAULT_CONF).exists()) { 1928 templateDir = new File(nuxeoDefaultConf.getParentFile(), template); 1929 } 1930 } 1931 if (!templateDir.exists() || !new File(templateDir, NUXEO_DEFAULT_CONF).exists()) { 1932 throw new ConfigurationException("Template not found: " + template); 1933 } 1934 return new File(templateDir, NUXEO_DEFAULT_CONF); 1935 } 1936 1937}