1b5840353SAdam Hornáček /* 2b5840353SAdam Hornáček * CDDL HEADER START 3b5840353SAdam Hornáček * 4b5840353SAdam Hornáček * The contents of this file are subject to the terms of the 5b5840353SAdam Hornáček * Common Development and Distribution License (the "License"). 6b5840353SAdam Hornáček * You may not use this file except in compliance with the License. 7b5840353SAdam Hornáček * 8b5840353SAdam Hornáček * See LICENSE.txt included in this distribution for the specific 9b5840353SAdam Hornáček * language governing permissions and limitations under the License. 10b5840353SAdam Hornáček * 11b5840353SAdam Hornáček * When distributing Covered Code, include this CDDL HEADER in each 12b5840353SAdam Hornáček * file and include the License file at LICENSE.txt. 13b5840353SAdam Hornáček * If applicable, add the following below this CDDL HEADER, with the 14b5840353SAdam Hornáček * fields enclosed by brackets "[]" replaced with your own identifying 15b5840353SAdam Hornáček * information: Portions Copyright [yyyy] [name of copyright owner] 16b5840353SAdam Hornáček * 17b5840353SAdam Hornáček * CDDL HEADER END 18b5840353SAdam Hornáček */ 19b5840353SAdam Hornáček 20b5840353SAdam Hornáček /* 218e5e1036SVladimir Kotal * Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved. 225d9f3aa0SAdam Hornáček * Portions Copyright (c) 2017, 2020, Chris Fraire <cfraire@me.com>. 2368c19b4cSAlexandrSergei4 * Portions Copyright (c) 2020, Aleksandr Kirillov <alexkirillovsamara@gmail.com>. 24b5840353SAdam Hornáček */ 259805b761SAdam Hornáček package org.opengrok.indexer.configuration; 26b5840353SAdam Hornáček 27b5840353SAdam Hornáček import java.beans.ExceptionListener; 28b5840353SAdam Hornáček import java.beans.XMLDecoder; 29b5840353SAdam Hornáček import java.beans.XMLEncoder; 30b5840353SAdam Hornáček import java.io.BufferedInputStream; 31b5840353SAdam Hornáček import java.io.BufferedOutputStream; 32b5840353SAdam Hornáček import java.io.ByteArrayInputStream; 33b5840353SAdam Hornáček import java.io.ByteArrayOutputStream; 34b5840353SAdam Hornáček import java.io.File; 35b5840353SAdam Hornáček import java.io.FileInputStream; 36b5840353SAdam Hornáček import java.io.FileOutputStream; 37b5840353SAdam Hornáček import java.io.IOException; 38b5840353SAdam Hornáček import java.io.InputStream; 39b5840353SAdam Hornáček import java.io.OutputStream; 40f197cd77SVladimir Kotal import java.nio.file.Path; 41f197cd77SVladimir Kotal import java.nio.file.Paths; 42b5840353SAdam Hornáček import java.util.ArrayList; 43b5840353SAdam Hornáček import java.util.Collections; 44b5840353SAdam Hornáček import java.util.HashMap; 45b5840353SAdam Hornáček import java.util.HashSet; 46b5840353SAdam Hornáček import java.util.LinkedList; 47b5840353SAdam Hornáček import java.util.List; 48b5840353SAdam Hornáček import java.util.Map; 49b5840353SAdam Hornáček import java.util.Set; 50b5840353SAdam Hornáček import java.util.TreeSet; 51b5840353SAdam Hornáček import java.util.concurrent.ConcurrentHashMap; 52b5840353SAdam Hornáček import java.util.logging.Level; 53b5840353SAdam Hornáček import java.util.logging.Logger; 54b5840353SAdam Hornáček import java.util.regex.PatternSyntaxException; 55fcbdc96bSChris Fraire import java.util.stream.Collectors; 56fcbdc96bSChris Fraire 579805b761SAdam Hornáček import org.opengrok.indexer.authorization.AuthControlFlag; 589805b761SAdam Hornáček import org.opengrok.indexer.authorization.AuthorizationStack; 599805b761SAdam Hornáček import org.opengrok.indexer.history.RepositoryInfo; 609805b761SAdam Hornáček import org.opengrok.indexer.logger.LoggerFactory; 61b5840353SAdam Hornáček 6264819763SVladimir Kotal import static org.opengrok.indexer.configuration.PatternUtil.compilePattern; 6364819763SVladimir Kotal 642ffbb0cfSVladimir Kotal 65b5840353SAdam Hornáček /** 662ffbb0cfSVladimir Kotal * Placeholder class for all configuration variables. Due to the multi-threaded 67b5840353SAdam Hornáček * nature of the web application, each thread will use the same instance of the 68b5840353SAdam Hornáček * configuration object for each page request. Class and methods should have 69b5840353SAdam Hornáček * package scope, but that didn't work with the XMLDecoder/XMLEncoder. 7029816c3bSChris Fraire * <p> 7129816c3bSChris Fraire * This should be as close to a 7229816c3bSChris Fraire * <a href="https://en.wikipedia.org/wiki/Plain_old_Java_object">POJO</a> as 7329816c3bSChris Fraire * possible. 74b5840353SAdam Hornáček */ 75b5840353SAdam Hornáček public final class Configuration { 76b5840353SAdam Hornáček 77b5840353SAdam Hornáček private static final Logger LOGGER = LoggerFactory.getLogger(Configuration.class); 78b5840353SAdam Hornáček public static final String PLUGIN_DIRECTORY_DEFAULT = "plugins"; 79b5840353SAdam Hornáček 80b5840353SAdam Hornáček /** 81b5840353SAdam Hornáček * Error string for negative numbers (could be int, double, long, ...). 82b5840353SAdam Hornáček * First argument is the name of the property, second argument is the actual 83b5840353SAdam Hornáček * value. 84b5840353SAdam Hornáček */ 85b5840353SAdam Hornáček private static final String NEGATIVE_NUMBER_ERROR = "Invalid value for \"%s\" - \"%s\". Expected value greater or equal than 0"; 86b5840353SAdam Hornáček /** 87b5840353SAdam Hornáček * Error string for non-positive numbers (could be int, double, long, ...). 88b5840353SAdam Hornáček * First argument is the name of the property, second argument is the actual 89b5840353SAdam Hornáček * value. 90b5840353SAdam Hornáček */ 91b5840353SAdam Hornáček private static final String NONPOSITIVE_NUMBER_ERROR = 92b5840353SAdam Hornáček "Invalid value for \"%s\" - \"%s\". Expected value greater than 0"; 93b5840353SAdam Hornáček 942ffbb0cfSVladimir Kotal /** 952ffbb0cfSVladimir Kotal * Path to {@code ctags} binary. 962ffbb0cfSVladimir Kotal */ 97b5840353SAdam Hornáček private String ctags; 98e829566cSChris Fraire private boolean webappCtags; 99b5840353SAdam Hornáček 100b5840353SAdam Hornáček /** 101b5840353SAdam Hornáček * A defined value to specify the mandoc binary or else null so that mandoc 102b5840353SAdam Hornáček * will be cross-referenced using {@code PlainXref}. 103b5840353SAdam Hornáček */ 104b5840353SAdam Hornáček private String mandoc; 105b5840353SAdam Hornáček 106b5840353SAdam Hornáček /** 107b5840353SAdam Hornáček * Should the history log be cached? 108b5840353SAdam Hornáček */ 109b5840353SAdam Hornáček private boolean historyCache; 110b5840353SAdam Hornáček /** 111b5840353SAdam Hornáček * flag to generate history. This is bigger hammer than @{code historyCache} 112b5840353SAdam Hornáček * above. If set to false, no history query will be ever made and the webapp 113b5840353SAdam Hornáček * will not display any history related links/allow any history queries. 114b5840353SAdam Hornáček */ 115b5840353SAdam Hornáček private boolean historyEnabled; 116b5840353SAdam Hornáček /** 117b5840353SAdam Hornáček * maximum number of messages in webapp. 118b5840353SAdam Hornáček */ 119b5840353SAdam Hornáček private int messageLimit; 120b5840353SAdam Hornáček /** 121b5840353SAdam Hornáček * Directory with authorization plug-ins. Default value is 122b5840353SAdam Hornáček * {@code dataRoot/../plugins} (can be {@code /var/opengrok/plugins} if dataRoot is 123b5840353SAdam Hornáček * {@code /var/opengrok/data}). 124b5840353SAdam Hornáček */ 125b5840353SAdam Hornáček private String pluginDirectory; 126b5840353SAdam Hornáček /** 127b5840353SAdam Hornáček * Enable watching the plug-in directory for changes in real time. Suitable 128b5840353SAdam Hornáček * for development. 129b5840353SAdam Hornáček */ 130b5840353SAdam Hornáček private boolean authorizationWatchdogEnabled; 131b5840353SAdam Hornáček private AuthorizationStack pluginStack; 132b5840353SAdam Hornáček private Map<String, Project> projects; // project name -> Project 133b5840353SAdam Hornáček private Set<Group> groups; 134b5840353SAdam Hornáček private String sourceRoot; 135b5840353SAdam Hornáček private String dataRoot; 136a03922c4SAdam Hornáček /** 137ff44f24aSAdam Hornáček * Directory with include files for web application (header, footer, etc.). 138a03922c4SAdam Hornáček */ 139a03922c4SAdam Hornáček private String includeRoot; 140b5840353SAdam Hornáček private List<RepositoryInfo> repositories; 1417d060254SAdam Hornáček 142b5840353SAdam Hornáček private boolean generateHtml; 143b5840353SAdam Hornáček /** 144b5840353SAdam Hornáček * Default projects will be used, when no project is selected and no project 145b5840353SAdam Hornáček * is in cookie, so basically only the first time a page is opened, 146b5840353SAdam Hornáček * or when web cookies are cleared. 147b5840353SAdam Hornáček */ 148b5840353SAdam Hornáček private Set<Project> defaultProjects; 149b5840353SAdam Hornáček /** 150b5840353SAdam Hornáček * Default size of memory to be used for flushing of Lucene docs per thread. 151b5840353SAdam Hornáček * Lucene 4.x uses 16MB and 8 threads, so below is a nice tunable. 152b5840353SAdam Hornáček */ 153b5840353SAdam Hornáček private double ramBufferSize; 154b5840353SAdam Hornáček /** 155b5840353SAdam Hornáček * If below is set, then we count how many files per project we need to 156b5840353SAdam Hornáček * process and print percentage of completion per project. 157b5840353SAdam Hornáček */ 158b5840353SAdam Hornáček private boolean printProgress; 159b5840353SAdam Hornáček private boolean allowLeadingWildcard; 160b5840353SAdam Hornáček private IgnoredNames ignoredNames; 161b5840353SAdam Hornáček private Filter includedNames; 162b5840353SAdam Hornáček private String userPage; 163b5840353SAdam Hornáček private String userPageSuffix; 164b5840353SAdam Hornáček private String bugPage; 165b5840353SAdam Hornáček private String bugPattern; 166b5840353SAdam Hornáček private String reviewPage; 167b5840353SAdam Hornáček private String reviewPattern; 168b5840353SAdam Hornáček private String webappLAF; 169b5840353SAdam Hornáček private RemoteSCM remoteScmSupported; 170b5840353SAdam Hornáček private boolean optimizeDatabase; 17129816c3bSChris Fraire private boolean quickContextScan; 1727d060254SAdam Hornáček 173b5840353SAdam Hornáček private LuceneLockName luceneLocking = LuceneLockName.OFF; 174b5840353SAdam Hornáček private boolean compressXref; 175b5840353SAdam Hornáček private boolean indexVersionedFilesOnly; 176b5840353SAdam Hornáček private int indexingParallelism; 1772123e367SVladimir Kotal private int repositoryInvalidationParallelism; 178b5840353SAdam Hornáček private int historyParallelism; 179dc607a84SVladimir Kotal private int historyFileParallelism; 180b5840353SAdam Hornáček private boolean tagsEnabled; 181b5840353SAdam Hornáček private int hitsPerPage; 182b5840353SAdam Hornáček private int cachePages; 183b5840353SAdam Hornáček private short contextLimit; // initialized non-zero in ctor 184b5840353SAdam Hornáček private short contextSurround; 185b5840353SAdam Hornáček private boolean lastEditedDisplayMode; 186b5840353SAdam Hornáček private String CTagsExtraOptionsFile; 187b5840353SAdam Hornáček private int scanningDepth; 1882402fe1cSChris Fraire private int nestingMaximum; 189b5840353SAdam Hornáček private Set<String> allowedSymlinks; 1900e0ac58dSChris Fraire private Set<String> canonicalRoots; 191b5840353SAdam Hornáček private boolean obfuscatingEMailAddresses; 192b5840353SAdam Hornáček private boolean chattyStatusPage; 193b5840353SAdam Hornáček private final Map<String, String> cmds; // repository type -> command 194b5840353SAdam Hornáček private int tabSize; 195a904b83aSVladimir Kotal private int indexerCommandTimeout; // in seconds 196b5840353SAdam Hornáček private int interactiveCommandTimeout; // in seconds 197a904b83aSVladimir Kotal private int webappStartCommandTimeout; // in seconds 198a904b83aSVladimir Kotal private int restfulCommandTimeout; // in seconds 199b124dbe6SVladimir Kotal private long ctagsTimeout; // in seconds 200e92cec67SVladimir Kotal private long xrefTimeout; // in seconds 201b5840353SAdam Hornáček private boolean scopesEnabled; 202b5840353SAdam Hornáček private boolean projectsEnabled; 203b5840353SAdam Hornáček private boolean foldingEnabled; 204b5840353SAdam Hornáček /* 205b5840353SAdam Hornáček * Set to false if we want to disable fetching history of individual files 206b5840353SAdam Hornáček * (by running appropriate SCM command) when the history is not found 207b5840353SAdam Hornáček * in history cache for repositories capable of fetching history for 208ec5b57ecSVladimir Kotal * directories. 209b5840353SAdam Hornáček */ 210b5840353SAdam Hornáček private boolean fetchHistoryWhenNotInCache; 211b5840353SAdam Hornáček /* 212b5840353SAdam Hornáček * Set to false to disable extended handling of history of files across 213b5840353SAdam Hornáček * renames, i.e. support getting diffs of revisions across renames 214b5840353SAdam Hornáček * for capable repositories. 215b5840353SAdam Hornáček */ 216b5840353SAdam Hornáček private boolean handleHistoryOfRenamedFiles; 217b5840353SAdam Hornáček 2188e5e1036SVladimir Kotal private boolean mergeCommitsEnabled; 2198e5e1036SVladimir Kotal 220b5840353SAdam Hornáček public static final double defaultRamBufferSize = 16; 221b5840353SAdam Hornáček 222b5840353SAdam Hornáček /** 223b5840353SAdam Hornáček * The directory hierarchy depth to limit the scanning for repositories. 224b5840353SAdam Hornáček * E.g. if the /mercurial/ directory (relative to source root) is a repository 225b5840353SAdam Hornáček * and /mercurial/usr/closed/ is sub-repository, the latter will be discovered 2268df660a0SVladimir Kotal * only if the depth is set to 2 or greater. 227b5840353SAdam Hornáček */ 2288df660a0SVladimir Kotal public static final int defaultScanningDepth = 2; 229b5840353SAdam Hornáček 230b5840353SAdam Hornáček /** 231b5840353SAdam Hornáček * The name of the eftar file relative to the <var>DATA_ROOT</var>, which 232b5840353SAdam Hornáček * contains definition tags. 233b5840353SAdam Hornáček */ 234f197cd77SVladimir Kotal public static final String EFTAR_DTAGS_NAME = "dtags.eftar"; 235b5840353SAdam Hornáček 236b5840353SAdam Hornáček /** 237b5840353SAdam Hornáček * Revision messages will be collapsible if they exceed this many number of 238b5840353SAdam Hornáček * characters. Front end enforces an appropriate minimum. 239b5840353SAdam Hornáček */ 240b5840353SAdam Hornáček private int revisionMessageCollapseThreshold; 241b5840353SAdam Hornáček 242b5840353SAdam Hornáček /** 243b5840353SAdam Hornáček * Groups are collapsed if number of repositories is greater than this 244b5840353SAdam Hornáček * threshold. This applies only for non-favorite groups - groups which don't 245b5840353SAdam Hornáček * contain a project which is considered as a favorite project for the user. 246b5840353SAdam Hornáček * Favorite projects are the projects which the user browses and searches 247b5840353SAdam Hornáček * and are stored in a cookie. Favorite groups are always expanded. 248b5840353SAdam Hornáček */ 249b5840353SAdam Hornáček private int groupsCollapseThreshold; 250b5840353SAdam Hornáček 251b5840353SAdam Hornáček /** 252b5840353SAdam Hornáček * Current indexed message will be collapsible if they exceed this many 253b5840353SAdam Hornáček * number of characters. Front end enforces an appropriate minimum. 254b5840353SAdam Hornáček */ 255b5840353SAdam Hornáček private int currentIndexedCollapseThreshold; 256b5840353SAdam Hornáček 257b5840353SAdam Hornáček /** 258b5840353SAdam Hornáček * Upper bound for number of threads used for performing multi-project 259fb531549SVladimir Kotal * searches. This is total for the whole webapp. 260b5840353SAdam Hornáček */ 261b5840353SAdam Hornáček private int MaxSearchThreadCount; 262b5840353SAdam Hornáček 263b5840353SAdam Hornáček /** 264fb531549SVladimir Kotal * Upper bound for number of threads used for getting revision contents. 265fb531549SVladimir Kotal * This is total for the whole webapp. 266fb531549SVladimir Kotal */ 267fb531549SVladimir Kotal private int MaxRevisionThreadCount; 268fb531549SVladimir Kotal 269fb531549SVladimir Kotal /** 270b5840353SAdam Hornáček * If false, do not display listing or projects/repositories on the index page. 271b5840353SAdam Hornáček */ 272b5840353SAdam Hornáček private boolean displayRepositories; 273b5840353SAdam Hornáček 274b5840353SAdam Hornáček /** 275b5840353SAdam Hornáček * If true, list directories first in xref directory listing. 276b5840353SAdam Hornáček */ 277b5840353SAdam Hornáček private boolean listDirsFirst = true; 278b5840353SAdam Hornáček 279326dace0SVladimir Kotal /** 280326dace0SVladimir Kotal * A flag if the navigate window should be opened by default when browsing 281326dace0SVladimir Kotal * the source code of projects. 282326dace0SVladimir Kotal */ 283326dace0SVladimir Kotal private boolean navigateWindowEnabled; 284326dace0SVladimir Kotal 285911e8af0SAdam Hornáček private SuggesterConfig suggesterConfig = new SuggesterConfig(); 286911e8af0SAdam Hornáček 2870d7ace53SVladimir Kotal private StatsdConfig statsdConfig = new StatsdConfig(); 2880d7ace53SVladimir Kotal 28929816c3bSChris Fraire private Set<String> disabledRepositories; 29029816c3bSChris Fraire 291b118f02bSVladimir Kotal private Set<String> authenticationTokens; // for non-localhost API access 2928d34347cSVladimir Kotal private String indexerAuthenticationToken; 29360e45c9fSVladimir Kotal private boolean allowInsecureTokens; 294b0a23e73SVladimir Kotal 295a2f09795SVladimir Kotal private int historyChunkCount; 2965a635a8eSVladimir Kotal private boolean historyCachePerPartesEnabled = true; 297a2f09795SVladimir Kotal 2980516dd21SVladimir Kotal private String serverName; // for reverse proxy environment 2990516dd21SVladimir Kotal 3001c258122SVladimir Kotal private int connectTimeout = -1; // connect timeout in seconds 3011c258122SVladimir Kotal private int apiTimeout = -1; // API timeout in seconds 3021c258122SVladimir Kotal 303f4571972SVladimir Kotal private boolean historyBasedReindex; 30412365fb4SVladimir Kotal 305b5840353SAdam Hornáček /* 306b5840353SAdam Hornáček * types of handling history for remote SCM repositories: 307b5840353SAdam Hornáček * ON - index history and display it in webapp 308b5840353SAdam Hornáček * OFF - do not index or display history in webapp 309b5840353SAdam Hornáček * DIRBASED - index history only for repositories capable 310b5840353SAdam Hornáček * of getting history for directories 311b5840353SAdam Hornáček * UIONLY - display history only in webapp (do not index it) 312b5840353SAdam Hornáček */ 313b5840353SAdam Hornáček public enum RemoteSCM { 314b5840353SAdam Hornáček ON, OFF, DIRBASED, UIONLY 315b5840353SAdam Hornáček } 316b5840353SAdam Hornáček 317b5840353SAdam Hornáček /** 318b5840353SAdam Hornáček * Get the default tab size (number of space characters per tab character) 319b5840353SAdam Hornáček * to use for each project. If {@code <= 0} tabs are read/write as is. 320b5840353SAdam Hornáček * 321b5840353SAdam Hornáček * @return current tab size set. 322b5840353SAdam Hornáček * @see Project#getTabSize() 3239805b761SAdam Hornáček * @see org.opengrok.indexer.analysis.ExpandTabsReader 324b5840353SAdam Hornáček */ getTabSize()325b5840353SAdam Hornáček public int getTabSize() { 326b5840353SAdam Hornáček return tabSize; 327b5840353SAdam Hornáček } 328b5840353SAdam Hornáček 329b5840353SAdam Hornáček /** 330b5840353SAdam Hornáček * Set the default tab size (number of space characters per tab character) 331b5840353SAdam Hornáček * to use for each project. If {@code <= 0} tabs are read/write as is. 332b5840353SAdam Hornáček * 333b5840353SAdam Hornáček * @param tabSize tabsize to set. 334b5840353SAdam Hornáček * @see Project#setTabSize(int) 3359805b761SAdam Hornáček * @see org.opengrok.indexer.analysis.ExpandTabsReader 336b5840353SAdam Hornáček */ setTabSize(int tabSize)337b5840353SAdam Hornáček public void setTabSize(int tabSize) { 338b5840353SAdam Hornáček this.tabSize = tabSize; 339b5840353SAdam Hornáček } 340b5840353SAdam Hornáček getScanningDepth()341b5840353SAdam Hornáček public int getScanningDepth() { 342b5840353SAdam Hornáček return scanningDepth; 343b5840353SAdam Hornáček } 344b5840353SAdam Hornáček 345b5840353SAdam Hornáček /** 346ff44f24aSAdam Hornáček * Set the scanning depth to a new value. 347b5840353SAdam Hornáček * 348b5840353SAdam Hornáček * @param scanningDepth the new value 349b5840353SAdam Hornáček * @throws IllegalArgumentException when the scanningDepth is negative 350b5840353SAdam Hornáček */ setScanningDepth(int scanningDepth)351b5840353SAdam Hornáček public void setScanningDepth(int scanningDepth) throws IllegalArgumentException { 352b5840353SAdam Hornáček if (scanningDepth < 0) { 353b5840353SAdam Hornáček throw new IllegalArgumentException( 354b5840353SAdam Hornáček String.format(NEGATIVE_NUMBER_ERROR, "scanningDepth", scanningDepth)); 355b5840353SAdam Hornáček } 356b5840353SAdam Hornáček this.scanningDepth = scanningDepth; 357b5840353SAdam Hornáček } 358b5840353SAdam Hornáček 3592402fe1cSChris Fraire /** 3602402fe1cSChris Fraire * Gets the nesting maximum of repositories. Default is 1. 3612402fe1cSChris Fraire */ getNestingMaximum()3622402fe1cSChris Fraire public int getNestingMaximum() { 3632402fe1cSChris Fraire return nestingMaximum; 3642402fe1cSChris Fraire } 3652402fe1cSChris Fraire 3662402fe1cSChris Fraire /** 3672402fe1cSChris Fraire * Sets the nesting maximum of repositories to a specified value. 3682402fe1cSChris Fraire * @param nestingMaximum the new value 3692402fe1cSChris Fraire * @throws IllegalArgumentException if {@code nestingMaximum} is negative 3702402fe1cSChris Fraire */ setNestingMaximum(int nestingMaximum)3712402fe1cSChris Fraire public void setNestingMaximum(int nestingMaximum) throws IllegalArgumentException { 3722402fe1cSChris Fraire if (nestingMaximum < 0) { 3732402fe1cSChris Fraire throw new IllegalArgumentException( 3742402fe1cSChris Fraire String.format(NEGATIVE_NUMBER_ERROR, "nestingMaximum", nestingMaximum)); 3752402fe1cSChris Fraire } 3762402fe1cSChris Fraire this.nestingMaximum = nestingMaximum; 3772402fe1cSChris Fraire } 3782402fe1cSChris Fraire getIndexerCommandTimeout()379a904b83aSVladimir Kotal public int getIndexerCommandTimeout() { 380a904b83aSVladimir Kotal return indexerCommandTimeout; 381b5840353SAdam Hornáček } 382b5840353SAdam Hornáček 383b5840353SAdam Hornáček /** 384ff44f24aSAdam Hornáček * Set the command timeout to a new value. 385b5840353SAdam Hornáček * 386a904b83aSVladimir Kotal * @param timeout the new value 387b5840353SAdam Hornáček * @throws IllegalArgumentException when the timeout is negative 388b5840353SAdam Hornáček */ setIndexerCommandTimeout(int timeout)389a904b83aSVladimir Kotal public void setIndexerCommandTimeout(int timeout) throws IllegalArgumentException { 390a904b83aSVladimir Kotal if (timeout < 0) { 391b5840353SAdam Hornáček throw new IllegalArgumentException( 392a904b83aSVladimir Kotal String.format(NEGATIVE_NUMBER_ERROR, "commandTimeout", timeout)); 393b5840353SAdam Hornáček } 394a904b83aSVladimir Kotal this.indexerCommandTimeout = timeout; 395a904b83aSVladimir Kotal } 396a904b83aSVladimir Kotal getRestfulCommandTimeout()397a904b83aSVladimir Kotal public int getRestfulCommandTimeout() { 398a904b83aSVladimir Kotal return restfulCommandTimeout; 399a904b83aSVladimir Kotal } 400a904b83aSVladimir Kotal 401a904b83aSVladimir Kotal /** 402a904b83aSVladimir Kotal * Set the command timeout to a new value. 403a904b83aSVladimir Kotal * 404a904b83aSVladimir Kotal * @param timeout the new value 405a904b83aSVladimir Kotal * @throws IllegalArgumentException when the timeout is negative 406a904b83aSVladimir Kotal */ setRestfulCommandTimeout(int timeout)407a904b83aSVladimir Kotal public void setRestfulCommandTimeout(int timeout) throws IllegalArgumentException { 408a904b83aSVladimir Kotal if (timeout < 0) { 409a904b83aSVladimir Kotal throw new IllegalArgumentException( 410a904b83aSVladimir Kotal String.format(NEGATIVE_NUMBER_ERROR, "restfulCommandTimeout", timeout)); 411a904b83aSVladimir Kotal } 412a904b83aSVladimir Kotal this.restfulCommandTimeout = timeout; 413a904b83aSVladimir Kotal } 414a904b83aSVladimir Kotal getWebappStartCommandTimeout()415a904b83aSVladimir Kotal public int getWebappStartCommandTimeout() { 416a904b83aSVladimir Kotal return webappStartCommandTimeout; 417a904b83aSVladimir Kotal } 418a904b83aSVladimir Kotal 419a904b83aSVladimir Kotal /** 420a904b83aSVladimir Kotal * Set the command timeout to a new value. 421a904b83aSVladimir Kotal * 422a904b83aSVladimir Kotal * @param timeout the new value 423a904b83aSVladimir Kotal * @throws IllegalArgumentException when the timeout is negative 424a904b83aSVladimir Kotal */ setWebappStartCommandTimeout(int timeout)425a904b83aSVladimir Kotal public void setWebappStartCommandTimeout(int timeout) throws IllegalArgumentException { 426a904b83aSVladimir Kotal if (timeout < 0) { 427a904b83aSVladimir Kotal throw new IllegalArgumentException( 428a904b83aSVladimir Kotal String.format(NEGATIVE_NUMBER_ERROR, "webappStartCommandTimeout", timeout)); 429a904b83aSVladimir Kotal } 430a904b83aSVladimir Kotal this.webappStartCommandTimeout = timeout; 431b5840353SAdam Hornáček } 432b5840353SAdam Hornáček getInteractiveCommandTimeout()433b5840353SAdam Hornáček public int getInteractiveCommandTimeout() { 434b5840353SAdam Hornáček return interactiveCommandTimeout; 435b5840353SAdam Hornáček } 436b5840353SAdam Hornáček 437b5840353SAdam Hornáček /** 438b5840353SAdam Hornáček * Set the interactive command timeout to a new value. 439b5840353SAdam Hornáček * 440a904b83aSVladimir Kotal * @param timeout the new value 441b5840353SAdam Hornáček * @throws IllegalArgumentException when the timeout is negative 442b5840353SAdam Hornáček */ setInteractiveCommandTimeout(int timeout)443a904b83aSVladimir Kotal public void setInteractiveCommandTimeout(int timeout) throws IllegalArgumentException { 444a904b83aSVladimir Kotal if (timeout < 0) { 445b5840353SAdam Hornáček throw new IllegalArgumentException( 446a904b83aSVladimir Kotal String.format(NEGATIVE_NUMBER_ERROR, "interactiveCommandTimeout", timeout)); 447b5840353SAdam Hornáček } 448a904b83aSVladimir Kotal this.interactiveCommandTimeout = timeout; 449b5840353SAdam Hornáček } 450b5840353SAdam Hornáček getCtagsTimeout()451b124dbe6SVladimir Kotal public long getCtagsTimeout() { 452b82c5e9dSVladimir Kotal return ctagsTimeout; 453b82c5e9dSVladimir Kotal } 454b82c5e9dSVladimir Kotal 455b82c5e9dSVladimir Kotal /** 456b82c5e9dSVladimir Kotal * Set the ctags timeout to a new value. 457b82c5e9dSVladimir Kotal * 458b82c5e9dSVladimir Kotal * @param timeout the new value 459b82c5e9dSVladimir Kotal * @throws IllegalArgumentException when the timeout is negative 460b82c5e9dSVladimir Kotal */ setCtagsTimeout(long timeout)461b124dbe6SVladimir Kotal public void setCtagsTimeout(long timeout) throws IllegalArgumentException { 462a904b83aSVladimir Kotal if (timeout < 0) { 463b82c5e9dSVladimir Kotal throw new IllegalArgumentException( 464b82c5e9dSVladimir Kotal String.format(NEGATIVE_NUMBER_ERROR, "ctagsTimeout", timeout)); 465b82c5e9dSVladimir Kotal } 466b82c5e9dSVladimir Kotal this.ctagsTimeout = timeout; 467b82c5e9dSVladimir Kotal } 468b82c5e9dSVladimir Kotal getXrefTimeout()469e92cec67SVladimir Kotal public long getXrefTimeout() { 470e92cec67SVladimir Kotal return xrefTimeout; 471e92cec67SVladimir Kotal } 472e92cec67SVladimir Kotal 473e92cec67SVladimir Kotal /** 474e92cec67SVladimir Kotal * Set the timeout for generating xrefs to a new value. 475e92cec67SVladimir Kotal * 476e92cec67SVladimir Kotal * @param timeout the new value 477e92cec67SVladimir Kotal * @throws IllegalArgumentException when the timeout is negative 478e92cec67SVladimir Kotal */ setXrefTimeout(long timeout)479e92cec67SVladimir Kotal public void setXrefTimeout(long timeout) throws IllegalArgumentException { 480e92cec67SVladimir Kotal if (timeout < 0) { 481e92cec67SVladimir Kotal throw new IllegalArgumentException( 482e92cec67SVladimir Kotal String.format(NEGATIVE_NUMBER_ERROR, "xrefTimeout", timeout)); 483e92cec67SVladimir Kotal } 484e92cec67SVladimir Kotal this.xrefTimeout = timeout; 485e92cec67SVladimir Kotal } 486e92cec67SVladimir Kotal isLastEditedDisplayMode()487b5840353SAdam Hornáček public boolean isLastEditedDisplayMode() { 488b5840353SAdam Hornáček return lastEditedDisplayMode; 489b5840353SAdam Hornáček } 490b5840353SAdam Hornáček setLastEditedDisplayMode(boolean lastEditedDisplayMode)491b5840353SAdam Hornáček public void setLastEditedDisplayMode(boolean lastEditedDisplayMode) { 492b5840353SAdam Hornáček this.lastEditedDisplayMode = lastEditedDisplayMode; 493b5840353SAdam Hornáček } 494b5840353SAdam Hornáček getGroupsCollapseThreshold()495b5840353SAdam Hornáček public int getGroupsCollapseThreshold() { 496b5840353SAdam Hornáček return groupsCollapseThreshold; 497b5840353SAdam Hornáček } 498b5840353SAdam Hornáček 499b5840353SAdam Hornáček /** 500ff44f24aSAdam Hornáček * Set the groups collapse threshold to a new value. 501b5840353SAdam Hornáček * 502b5840353SAdam Hornáček * @param groupsCollapseThreshold the new value 503b5840353SAdam Hornáček * @throws IllegalArgumentException when the timeout is negative 504b5840353SAdam Hornáček */ setGroupsCollapseThreshold(int groupsCollapseThreshold)505b5840353SAdam Hornáček public void setGroupsCollapseThreshold(int groupsCollapseThreshold) throws IllegalArgumentException { 506b5840353SAdam Hornáček if (groupsCollapseThreshold < 0) { 507b5840353SAdam Hornáček throw new IllegalArgumentException( 508b5840353SAdam Hornáček String.format(NEGATIVE_NUMBER_ERROR, "groupsCollapseThreshold", groupsCollapseThreshold)); 509b5840353SAdam Hornáček } 510b5840353SAdam Hornáček this.groupsCollapseThreshold = groupsCollapseThreshold; 511b5840353SAdam Hornáček } 512b5840353SAdam Hornáček 513b5840353SAdam Hornáček /** 514b82c5e9dSVladimir Kotal * Creates a new instance of Configuration with default values. 515b5840353SAdam Hornáček */ Configuration()516b5840353SAdam Hornáček public Configuration() { 517b82c5e9dSVladimir Kotal // This list of calls is sorted alphabetically so please keep it. 518b5840353SAdam Hornáček cmds = new HashMap<>(); 5195b7cea89SLubos Kosco setAllowLeadingWildcard(true); 520b5840353SAdam Hornáček setAllowedSymlinks(new HashSet<>()); 521acac8e33SVladimir Kotal setAuthenticationTokens(new HashSet<>()); 522b5840353SAdam Hornáček setAuthorizationWatchdogEnabled(false); 523b5840353SAdam Hornáček //setBugPage("http://bugs.myserver.org/bugdatabase/view_bug.do?bug_id="); 524b5840353SAdam Hornáček setBugPattern("\\b([12456789][0-9]{6})\\b"); 525b5840353SAdam Hornáček setCachePages(5); 5260e0ac58dSChris Fraire setCanonicalRoots(new HashSet<>()); 527a904b83aSVladimir Kotal setIndexerCommandTimeout(600); // 10 minutes 528a904b83aSVladimir Kotal setRestfulCommandTimeout(60); 529b5840353SAdam Hornáček setInteractiveCommandTimeout(30); 530a904b83aSVladimir Kotal setWebappStartCommandTimeout(5); 531b5840353SAdam Hornáček setCompressXref(true); 532b5840353SAdam Hornáček setContextLimit((short) 10); 533b5840353SAdam Hornáček //contextSurround is default(short) 534b5840353SAdam Hornáček //ctags is default(String) 535b124dbe6SVladimir Kotal setCtagsTimeout(10); 536b5840353SAdam Hornáček setCurrentIndexedCollapseThreshold(27); 537b5840353SAdam Hornáček setDataRoot(null); 538b5840353SAdam Hornáček setDisplayRepositories(true); 539b5840353SAdam Hornáček setFetchHistoryWhenNotInCache(true); 540b5840353SAdam Hornáček setFoldingEnabled(true); 541b5840353SAdam Hornáček setGenerateHtml(true); 542b5840353SAdam Hornáček setGroups(new TreeSet<>()); 543b5840353SAdam Hornáček setGroupsCollapseThreshold(4); 544b5840353SAdam Hornáček setHandleHistoryOfRenamedFiles(false); 545b5840353SAdam Hornáček setHistoryCache(true); 546b5840353SAdam Hornáček setHistoryEnabled(true); 547b5840353SAdam Hornáček setHitsPerPage(25); 548b5840353SAdam Hornáček setIgnoredNames(new IgnoredNames()); 549b5840353SAdam Hornáček setIncludedNames(new Filter()); 550b5840353SAdam Hornáček setIndexVersionedFilesOnly(false); 551b5840353SAdam Hornáček setLastEditedDisplayMode(true); 552b5840353SAdam Hornáček //luceneLocking default is OFF 553b5840353SAdam Hornáček //mandoc is default(String) 554b5840353SAdam Hornáček setMaxSearchThreadCount(2 * Runtime.getRuntime().availableProcessors()); 555fb531549SVladimir Kotal setMaxRevisionThreadCount(Runtime.getRuntime().availableProcessors()); 556610d9085SVladimir Kotal setMergeCommitsEnabled(false); 557b5840353SAdam Hornáček setMessageLimit(500); 558326dace0SVladimir Kotal setNavigateWindowEnabled(false); 5592402fe1cSChris Fraire setNestingMaximum(1); 560b5840353SAdam Hornáček setOptimizeDatabase(true); 561b5840353SAdam Hornáček setPluginDirectory(null); 562b5840353SAdam Hornáček setPluginStack(new AuthorizationStack(AuthControlFlag.REQUIRED, "default stack")); 563b5840353SAdam Hornáček setPrintProgress(false); 56429816c3bSChris Fraire setDisabledRepositories(new HashSet<>()); 565b5840353SAdam Hornáček setProjects(new ConcurrentHashMap<>()); 566b5840353SAdam Hornáček setQuickContextScan(true); 567b5840353SAdam Hornáček //below can cause an outofmemory error, since it is defaulting to NO LIMIT 568b5840353SAdam Hornáček setRamBufferSize(defaultRamBufferSize); //MB 569b5840353SAdam Hornáček setRemoteScmSupported(RemoteSCM.OFF); 570b5840353SAdam Hornáček setRepositories(new ArrayList<>()); 571b5840353SAdam Hornáček //setReviewPage("http://arc.myserver.org/caselog/PSARC/"); 572b5840353SAdam Hornáček setReviewPattern("\\b(\\d{4}/\\d{3})\\b"); // in form e.g. PSARC 2008/305 573b5840353SAdam Hornáček setRevisionMessageCollapseThreshold(200); 574b5840353SAdam Hornáček setScanningDepth(defaultScanningDepth); // default depth of scanning for repositories 575b5840353SAdam Hornáček setScopesEnabled(true); 576b5840353SAdam Hornáček setSourceRoot(null); 577b5840353SAdam Hornáček //setTabSize(4); 578b5840353SAdam Hornáček setTagsEnabled(false); 579b5840353SAdam Hornáček //setUserPage("http://www.myserver.org/viewProfile.jspa?username="); 580e92cec67SVladimir Kotal // Set to empty string so we can append it to the URL unconditionally later. 581f4571972SVladimir Kotal setHistoryBasedReindex(true); 582b5840353SAdam Hornáček setUserPageSuffix(""); 583b5840353SAdam Hornáček setWebappLAF("default"); 584e829566cSChris Fraire // webappCtags is default(boolean) 585e92cec67SVladimir Kotal setXrefTimeout(30); 5861c258122SVladimir Kotal setApiTimeout(300); // 5 minutes 5871c258122SVladimir Kotal setConnectTimeout(3); 588b5840353SAdam Hornáček } 589b5840353SAdam Hornáček getRepoCmd(String clazzName)590b5840353SAdam Hornáček public String getRepoCmd(String clazzName) { 591b5840353SAdam Hornáček return cmds.get(clazzName); 592b5840353SAdam Hornáček } 593b5840353SAdam Hornáček setRepoCmd(String clazzName, String cmd)594b5840353SAdam Hornáček public String setRepoCmd(String clazzName, String cmd) { 595b5840353SAdam Hornáček if (clazzName == null) { 596b5840353SAdam Hornáček return null; 597b5840353SAdam Hornáček } 598b5840353SAdam Hornáček if (cmd == null || cmd.length() == 0) { 599b5840353SAdam Hornáček return cmds.remove(clazzName); 600b5840353SAdam Hornáček } 601b5840353SAdam Hornáček return cmds.put(clazzName, cmd); 602b5840353SAdam Hornáček } 603b5840353SAdam Hornáček 604b5840353SAdam Hornáček // just to satisfy bean/de|encoder stuff getCmds()605b5840353SAdam Hornáček public Map<String, String> getCmds() { 606b5840353SAdam Hornáček return Collections.unmodifiableMap(cmds); 607b5840353SAdam Hornáček } 608b5840353SAdam Hornáček 609b5840353SAdam Hornáček /** 6101a2bb6b6SAdam Hornáček * @see org.opengrok.indexer.web.messages.MessagesContainer 611b5840353SAdam Hornáček * 612b5840353SAdam Hornáček * @return int the current message limit 613b5840353SAdam Hornáček */ getMessageLimit()614b5840353SAdam Hornáček public int getMessageLimit() { 615b5840353SAdam Hornáček return messageLimit; 616b5840353SAdam Hornáček } 617b5840353SAdam Hornáček 618b5840353SAdam Hornáček /** 6191a2bb6b6SAdam Hornáček * @see org.opengrok.indexer.web.messages.MessagesContainer 620b5840353SAdam Hornáček * 621b5840353SAdam Hornáček * @param messageLimit the limit 622b5840353SAdam Hornáček * @throws IllegalArgumentException when the limit is negative 623b5840353SAdam Hornáček */ setMessageLimit(int messageLimit)624b5840353SAdam Hornáček public void setMessageLimit(int messageLimit) throws IllegalArgumentException { 625b5840353SAdam Hornáček if (messageLimit < 0) { 626b5840353SAdam Hornáček throw new IllegalArgumentException( 627b5840353SAdam Hornáček String.format(NEGATIVE_NUMBER_ERROR, "messageLimit", messageLimit)); 628b5840353SAdam Hornáček } 629b5840353SAdam Hornáček this.messageLimit = messageLimit; 630b5840353SAdam Hornáček } 631b5840353SAdam Hornáček getPluginDirectory()632b5840353SAdam Hornáček public String getPluginDirectory() { 633b5840353SAdam Hornáček return pluginDirectory; 634b5840353SAdam Hornáček } 635b5840353SAdam Hornáček setPluginDirectory(String pluginDirectory)636b5840353SAdam Hornáček public void setPluginDirectory(String pluginDirectory) { 637b5840353SAdam Hornáček this.pluginDirectory = pluginDirectory; 638b5840353SAdam Hornáček } 639b5840353SAdam Hornáček isAuthorizationWatchdogEnabled()640b5840353SAdam Hornáček public boolean isAuthorizationWatchdogEnabled() { 641b5840353SAdam Hornáček return authorizationWatchdogEnabled; 642b5840353SAdam Hornáček } 643b5840353SAdam Hornáček setAuthorizationWatchdogEnabled(boolean authorizationWatchdogEnabled)644b5840353SAdam Hornáček public void setAuthorizationWatchdogEnabled(boolean authorizationWatchdogEnabled) { 645b5840353SAdam Hornáček this.authorizationWatchdogEnabled = authorizationWatchdogEnabled; 646b5840353SAdam Hornáček } 647b5840353SAdam Hornáček getPluginStack()648b5840353SAdam Hornáček public AuthorizationStack getPluginStack() { 649b5840353SAdam Hornáček return pluginStack; 650b5840353SAdam Hornáček } 651b5840353SAdam Hornáček setPluginStack(AuthorizationStack pluginStack)652b5840353SAdam Hornáček public void setPluginStack(AuthorizationStack pluginStack) { 653b5840353SAdam Hornáček this.pluginStack = pluginStack; 654b5840353SAdam Hornáček } 655b5840353SAdam Hornáček setCmds(Map<String, String> cmds)656b5840353SAdam Hornáček public void setCmds(Map<String, String> cmds) { 657b5840353SAdam Hornáček this.cmds.clear(); 658b5840353SAdam Hornáček this.cmds.putAll(cmds); 659b5840353SAdam Hornáček } 660b5840353SAdam Hornáček 661b5840353SAdam Hornáček /** 662b5840353SAdam Hornáček * Gets the configuration's ctags command. Default is null. 663b5840353SAdam Hornáček * @return the configured value 664b5840353SAdam Hornáček */ getCtags()665b5840353SAdam Hornáček public String getCtags() { 666b5840353SAdam Hornáček return ctags; 667b5840353SAdam Hornáček } 668b5840353SAdam Hornáček 669b5840353SAdam Hornáček /** 670b5840353SAdam Hornáček * Sets the configuration's ctags command. 671b5840353SAdam Hornáček * @param ctags A program name (full-path if necessary) or {@code null} 672b5840353SAdam Hornáček */ setCtags(String ctags)673b5840353SAdam Hornáček public void setCtags(String ctags) { 674b5840353SAdam Hornáček this.ctags = ctags; 675b5840353SAdam Hornáček } 676b5840353SAdam Hornáček 677b5840353SAdam Hornáček /** 678b5840353SAdam Hornáček * Gets the configuration's mandoc command. Default is {@code null}. 679b5840353SAdam Hornáček * @return the configured value 680b5840353SAdam Hornáček */ getMandoc()681b5840353SAdam Hornáček public String getMandoc() { 682b5840353SAdam Hornáček return mandoc; 683b5840353SAdam Hornáček } 684b5840353SAdam Hornáček 685b5840353SAdam Hornáček /** 686b5840353SAdam Hornáček * Sets the configuration's mandoc command. 687b5840353SAdam Hornáček * @param value A program name (full-path if necessary) or {@code null} 688b5840353SAdam Hornáček */ setMandoc(String value)689b5840353SAdam Hornáček public void setMandoc(String value) { 690b5840353SAdam Hornáček this.mandoc = value; 691b5840353SAdam Hornáček } 692b5840353SAdam Hornáček 693b5840353SAdam Hornáček /** 694b5840353SAdam Hornáček * Gets the total number of context lines per file to show in cases where it 695b5840353SAdam Hornáček * is limited. Default is 10. 696b5840353SAdam Hornáček * @return a value greater than zero 697b5840353SAdam Hornáček */ getContextLimit()698b5840353SAdam Hornáček public short getContextLimit() { 699b5840353SAdam Hornáček return contextLimit; 700b5840353SAdam Hornáček } 701b5840353SAdam Hornáček 702b5840353SAdam Hornáček /** 703b5840353SAdam Hornáček * Sets the total number of context lines per file to show in cases where it 704b5840353SAdam Hornáček * is limited. 705b5840353SAdam Hornáček * @param value a value greater than zero 706b5840353SAdam Hornáček * @throws IllegalArgumentException if {@code value} is not positive 707b5840353SAdam Hornáček */ setContextLimit(short value)708b5840353SAdam Hornáček public void setContextLimit(short value) throws IllegalArgumentException { 709b5840353SAdam Hornáček if (value < 1) { 710b5840353SAdam Hornáček throw new IllegalArgumentException( 711b5840353SAdam Hornáček String.format(NONPOSITIVE_NUMBER_ERROR, "contextLimit", value)); 712b5840353SAdam Hornáček } 713b5840353SAdam Hornáček this.contextLimit = value; 714b5840353SAdam Hornáček } 715b5840353SAdam Hornáček 716b5840353SAdam Hornáček /** 717b5840353SAdam Hornáček * Gets the number of context lines to show before or after any match. 718b5840353SAdam Hornáček * Default is zero. 719b5840353SAdam Hornáček * @return a value greater than or equal to zero 720b5840353SAdam Hornáček */ getContextSurround()721b5840353SAdam Hornáček public short getContextSurround() { 722b5840353SAdam Hornáček return contextSurround; 723b5840353SAdam Hornáček } 724b5840353SAdam Hornáček 725b5840353SAdam Hornáček /** 726b5840353SAdam Hornáček * Sets the number of context lines to show before or after any match. 727b5840353SAdam Hornáček * @param value a value greater than or equal to zero 728b5840353SAdam Hornáček * @throws IllegalArgumentException if {@code value} is negative 729b5840353SAdam Hornáček */ setContextSurround(short value)730b5840353SAdam Hornáček public void setContextSurround(short value) 731b5840353SAdam Hornáček throws IllegalArgumentException { 732b5840353SAdam Hornáček if (value < 0) { 733b5840353SAdam Hornáček throw new IllegalArgumentException( 734b5840353SAdam Hornáček String.format(NEGATIVE_NUMBER_ERROR, "contextSurround", value)); 735b5840353SAdam Hornáček } 736b5840353SAdam Hornáček this.contextSurround = value; 737b5840353SAdam Hornáček } 738b5840353SAdam Hornáček getCachePages()739b5840353SAdam Hornáček public int getCachePages() { 740b5840353SAdam Hornáček return cachePages; 741b5840353SAdam Hornáček } 742b5840353SAdam Hornáček 743b5840353SAdam Hornáček /** 744ff44f24aSAdam Hornáček * Set the cache pages to a new value. 745b5840353SAdam Hornáček * 746b5840353SAdam Hornáček * @param cachePages the new value 747b5840353SAdam Hornáček * @throws IllegalArgumentException when the cachePages is negative 748b5840353SAdam Hornáček */ setCachePages(int cachePages)749b5840353SAdam Hornáček public void setCachePages(int cachePages) throws IllegalArgumentException { 750b5840353SAdam Hornáček if (cachePages < 0) { 751b5840353SAdam Hornáček throw new IllegalArgumentException( 752b5840353SAdam Hornáček String.format(NEGATIVE_NUMBER_ERROR, "cachePages", cachePages)); 753b5840353SAdam Hornáček } 754b5840353SAdam Hornáček this.cachePages = cachePages; 755b5840353SAdam Hornáček } 756b5840353SAdam Hornáček getHitsPerPage()757b5840353SAdam Hornáček public int getHitsPerPage() { 758b5840353SAdam Hornáček return hitsPerPage; 759b5840353SAdam Hornáček } 760b5840353SAdam Hornáček 761b5840353SAdam Hornáček /** 762ff44f24aSAdam Hornáček * Set the hits per page to a new value. 763b5840353SAdam Hornáček * 764b5840353SAdam Hornáček * @param hitsPerPage the new value 765b5840353SAdam Hornáček * @throws IllegalArgumentException when the hitsPerPage is negative 766b5840353SAdam Hornáček */ setHitsPerPage(int hitsPerPage)767b5840353SAdam Hornáček public void setHitsPerPage(int hitsPerPage) throws IllegalArgumentException { 768b5840353SAdam Hornáček if (hitsPerPage < 0) { 769b5840353SAdam Hornáček throw new IllegalArgumentException( 770b5840353SAdam Hornáček String.format(NEGATIVE_NUMBER_ERROR, "hitsPerPage", hitsPerPage)); 771b5840353SAdam Hornáček } 772b5840353SAdam Hornáček this.hitsPerPage = hitsPerPage; 773b5840353SAdam Hornáček } 774b5840353SAdam Hornáček 775b5840353SAdam Hornáček /** 776b5840353SAdam Hornáček * Should the history be enabled ? 777b5840353SAdam Hornáček * 778b5840353SAdam Hornáček * @return {@code true} if history is enabled, {@code false} otherwise 779b5840353SAdam Hornáček */ isHistoryEnabled()780b5840353SAdam Hornáček public boolean isHistoryEnabled() { 781b5840353SAdam Hornáček return historyEnabled; 782b5840353SAdam Hornáček } 783b5840353SAdam Hornáček 784b5840353SAdam Hornáček /** 785b5840353SAdam Hornáček * Set whether history should be enabled. 786b5840353SAdam Hornáček * 787b5840353SAdam Hornáček * @param flag if {@code true} enable history 788b5840353SAdam Hornáček */ setHistoryEnabled(boolean flag)789b5840353SAdam Hornáček public void setHistoryEnabled(boolean flag) { 790b5840353SAdam Hornáček this.historyEnabled = flag; 791b5840353SAdam Hornáček } 792b5840353SAdam Hornáček 793b5840353SAdam Hornáček /** 794b5840353SAdam Hornáček * Should the history log be cached? 795b5840353SAdam Hornáček * 796b5840353SAdam Hornáček * @return {@code true} if a {@code HistoryCache} implementation should be 797b5840353SAdam Hornáček * used, {@code false} otherwise 798b5840353SAdam Hornáček */ isHistoryCache()799b5840353SAdam Hornáček public boolean isHistoryCache() { 800b5840353SAdam Hornáček return historyCache; 801b5840353SAdam Hornáček } 802b5840353SAdam Hornáček 803b5840353SAdam Hornáček /** 804b5840353SAdam Hornáček * Set whether history should be cached. 805b5840353SAdam Hornáček * 806b5840353SAdam Hornáček * @param historyCache if {@code true} enable history cache 807b5840353SAdam Hornáček */ setHistoryCache(boolean historyCache)808b5840353SAdam Hornáček public void setHistoryCache(boolean historyCache) { 809b5840353SAdam Hornáček this.historyCache = historyCache; 810b5840353SAdam Hornáček } 811b5840353SAdam Hornáček isFetchHistoryWhenNotInCache()812b5840353SAdam Hornáček public boolean isFetchHistoryWhenNotInCache() { 813b5840353SAdam Hornáček return fetchHistoryWhenNotInCache; 814b5840353SAdam Hornáček } 815b5840353SAdam Hornáček setFetchHistoryWhenNotInCache(boolean nofetch)816b5840353SAdam Hornáček public void setFetchHistoryWhenNotInCache(boolean nofetch) { 817b5840353SAdam Hornáček this.fetchHistoryWhenNotInCache = nofetch; 818b5840353SAdam Hornáček } 819b5840353SAdam Hornáček isHandleHistoryOfRenamedFiles()820b5840353SAdam Hornáček public boolean isHandleHistoryOfRenamedFiles() { 821b5840353SAdam Hornáček return handleHistoryOfRenamedFiles; 822b5840353SAdam Hornáček } 823b5840353SAdam Hornáček setHandleHistoryOfRenamedFiles(boolean enable)824b5840353SAdam Hornáček public void setHandleHistoryOfRenamedFiles(boolean enable) { 825b5840353SAdam Hornáček this.handleHistoryOfRenamedFiles = enable; 826b5840353SAdam Hornáček } 827b5840353SAdam Hornáček setMergeCommitsEnabled(boolean flag)8288e5e1036SVladimir Kotal public void setMergeCommitsEnabled(boolean flag) { 8298e5e1036SVladimir Kotal this.mergeCommitsEnabled = flag; 8308e5e1036SVladimir Kotal } 8318e5e1036SVladimir Kotal isMergeCommitsEnabled()8328e5e1036SVladimir Kotal public boolean isMergeCommitsEnabled() { 8338e5e1036SVladimir Kotal return mergeCommitsEnabled; 8348e5e1036SVladimir Kotal } 8358e5e1036SVladimir Kotal isNavigateWindowEnabled()836326dace0SVladimir Kotal public boolean isNavigateWindowEnabled() { 837326dace0SVladimir Kotal return navigateWindowEnabled; 838326dace0SVladimir Kotal } 839326dace0SVladimir Kotal setNavigateWindowEnabled(boolean navigateWindowEnabled)840326dace0SVladimir Kotal public void setNavigateWindowEnabled(boolean navigateWindowEnabled) { 841326dace0SVladimir Kotal this.navigateWindowEnabled = navigateWindowEnabled; 842326dace0SVladimir Kotal } 843326dace0SVladimir Kotal getProjects()844b5840353SAdam Hornáček public Map<String, Project> getProjects() { 845b5840353SAdam Hornáček return projects; 846b5840353SAdam Hornáček } 847b5840353SAdam Hornáček setProjects(Map<String, Project> projects)848b5840353SAdam Hornáček public void setProjects(Map<String, Project> projects) { 849b5840353SAdam Hornáček this.projects = projects; 850b5840353SAdam Hornáček } 851b5840353SAdam Hornáček 852b5840353SAdam Hornáček /** 853b5840353SAdam Hornáček * Adds a group to the set. This is performed upon configuration parsing 854b5840353SAdam Hornáček * 855b5840353SAdam Hornáček * @param group group 856b5840353SAdam Hornáček * @throws IOException when group is not unique across the set 857b5840353SAdam Hornáček */ addGroup(Group group)858b5840353SAdam Hornáček public void addGroup(Group group) throws IOException { 859b5840353SAdam Hornáček if (!groups.add(group)) { 860b5840353SAdam Hornáček throw new IOException( 861b5840353SAdam Hornáček String.format("Duplicate group name '%s' in configuration.", 862b5840353SAdam Hornáček group.getName())); 863b5840353SAdam Hornáček } 864b5840353SAdam Hornáček } 865b5840353SAdam Hornáček getGroups()866b5840353SAdam Hornáček public Set<Group> getGroups() { 867b5840353SAdam Hornáček return groups; 868b5840353SAdam Hornáček } 869b5840353SAdam Hornáček setGroups(Set<Group> groups)870b5840353SAdam Hornáček public void setGroups(Set<Group> groups) { 871b5840353SAdam Hornáček this.groups = groups; 872b5840353SAdam Hornáček } 873b5840353SAdam Hornáček getSourceRoot()874b5840353SAdam Hornáček public String getSourceRoot() { 875b5840353SAdam Hornáček return sourceRoot; 876b5840353SAdam Hornáček } 877b5840353SAdam Hornáček setSourceRoot(String sourceRoot)878b5840353SAdam Hornáček public void setSourceRoot(String sourceRoot) { 879b5840353SAdam Hornáček this.sourceRoot = sourceRoot; 880b5840353SAdam Hornáček } 881b5840353SAdam Hornáček getDataRoot()882b5840353SAdam Hornáček public String getDataRoot() { 883b5840353SAdam Hornáček return dataRoot; 884b5840353SAdam Hornáček } 885b5840353SAdam Hornáček 886b5840353SAdam Hornáček /** 887b5840353SAdam Hornáček * Sets data root. 888b5840353SAdam Hornáček * 88961b71b09SAdam Hornacek * This method also sets the pluginDirectory if it is not already set. 890b5840353SAdam Hornáček * 891b5840353SAdam Hornáček * @see #setPluginDirectory(java.lang.String) 892b5840353SAdam Hornáček * 893b5840353SAdam Hornáček * @param dataRoot data root path 894b5840353SAdam Hornáček */ setDataRoot(String dataRoot)895b5840353SAdam Hornáček public void setDataRoot(String dataRoot) { 896b5840353SAdam Hornáček if (dataRoot != null && getPluginDirectory() == null) { 897b5840353SAdam Hornáček setPluginDirectory(dataRoot + "/../" + PLUGIN_DIRECTORY_DEFAULT); 898b5840353SAdam Hornáček } 899b5840353SAdam Hornáček this.dataRoot = dataRoot; 900b5840353SAdam Hornáček } 901b5840353SAdam Hornáček 902a03922c4SAdam Hornáček /** 9037d060254SAdam Hornáček * If {@link #includeRoot} is not set, {@link #dataRoot} will be returned. 904a03922c4SAdam Hornáček * @return web include root directory 905a03922c4SAdam Hornáček */ getIncludeRoot()906a03922c4SAdam Hornáček public String getIncludeRoot() { 907a03922c4SAdam Hornáček return includeRoot != null ? includeRoot : dataRoot; 908a03922c4SAdam Hornáček } 909a03922c4SAdam Hornáček setIncludeRoot(String newRoot)910a03922c4SAdam Hornáček public void setIncludeRoot(String newRoot) { 911a03922c4SAdam Hornáček this.includeRoot = newRoot; 912a03922c4SAdam Hornáček } 913a03922c4SAdam Hornáček getRepositories()914b5840353SAdam Hornáček public List<RepositoryInfo> getRepositories() { 915b5840353SAdam Hornáček return repositories; 916b5840353SAdam Hornáček } 917b5840353SAdam Hornáček setRepositories(List<RepositoryInfo> repositories)918b5840353SAdam Hornáček public void setRepositories(List<RepositoryInfo> repositories) { 919b5840353SAdam Hornáček this.repositories = repositories; 920b5840353SAdam Hornáček } 921b5840353SAdam Hornáček addRepositories(List<RepositoryInfo> repositories)922b5840353SAdam Hornáček public void addRepositories(List<RepositoryInfo> repositories) { 923b5840353SAdam Hornáček this.repositories.addAll(repositories); 924b5840353SAdam Hornáček } 925b5840353SAdam Hornáček setGenerateHtml(boolean generateHtml)926b5840353SAdam Hornáček public void setGenerateHtml(boolean generateHtml) { 927b5840353SAdam Hornáček this.generateHtml = generateHtml; 928b5840353SAdam Hornáček } 929b5840353SAdam Hornáček isGenerateHtml()930b5840353SAdam Hornáček public boolean isGenerateHtml() { 931b5840353SAdam Hornáček return generateHtml; 932b5840353SAdam Hornáček } 933b5840353SAdam Hornáček setDefaultProjects(Set<Project> defaultProjects)934b5840353SAdam Hornáček public void setDefaultProjects(Set<Project> defaultProjects) { 935b5840353SAdam Hornáček this.defaultProjects = defaultProjects; 936b5840353SAdam Hornáček } 937b5840353SAdam Hornáček getDefaultProjects()938b5840353SAdam Hornáček public Set<Project> getDefaultProjects() { 939b5840353SAdam Hornáček return defaultProjects; 940b5840353SAdam Hornáček } 941b5840353SAdam Hornáček getRamBufferSize()942b5840353SAdam Hornáček public double getRamBufferSize() { 943b5840353SAdam Hornáček return ramBufferSize; 944b5840353SAdam Hornáček } 945b5840353SAdam Hornáček 946b5840353SAdam Hornáček /** 947ff44f24aSAdam Hornáček * Set size of memory to be used for flushing docs (default 16 MB) (this can 948b5840353SAdam Hornáček * improve index speed a LOT) note that this is per thread (lucene uses 8 949ff44f24aSAdam Hornáček * threads by default in 4.x). 950b5840353SAdam Hornáček * 951b5840353SAdam Hornáček * @param ramBufferSize new size in MB 952b5840353SAdam Hornáček */ setRamBufferSize(double ramBufferSize)953b5840353SAdam Hornáček public void setRamBufferSize(double ramBufferSize) { 954b5840353SAdam Hornáček this.ramBufferSize = ramBufferSize; 955b5840353SAdam Hornáček } 956b5840353SAdam Hornáček isPrintProgress()957b5840353SAdam Hornáček public boolean isPrintProgress() { 958b5840353SAdam Hornáček return printProgress; 959b5840353SAdam Hornáček } 960b5840353SAdam Hornáček setPrintProgress(boolean printProgress)961b5840353SAdam Hornáček public void setPrintProgress(boolean printProgress) { 962b5840353SAdam Hornáček this.printProgress = printProgress; 963b5840353SAdam Hornáček } 964b5840353SAdam Hornáček setAllowLeadingWildcard(boolean allowLeadingWildcard)965b5840353SAdam Hornáček public void setAllowLeadingWildcard(boolean allowLeadingWildcard) { 966b5840353SAdam Hornáček this.allowLeadingWildcard = allowLeadingWildcard; 967b5840353SAdam Hornáček } 968b5840353SAdam Hornáček isAllowLeadingWildcard()969b5840353SAdam Hornáček public boolean isAllowLeadingWildcard() { 970b5840353SAdam Hornáček return allowLeadingWildcard; 971b5840353SAdam Hornáček } 972b5840353SAdam Hornáček isQuickContextScan()973b5840353SAdam Hornáček public boolean isQuickContextScan() { 974b5840353SAdam Hornáček return quickContextScan; 975b5840353SAdam Hornáček } 976b5840353SAdam Hornáček setQuickContextScan(boolean quickContextScan)977b5840353SAdam Hornáček public void setQuickContextScan(boolean quickContextScan) { 978b5840353SAdam Hornáček this.quickContextScan = quickContextScan; 979b5840353SAdam Hornáček } 980b5840353SAdam Hornáček setIgnoredNames(IgnoredNames ignoredNames)981b5840353SAdam Hornáček public void setIgnoredNames(IgnoredNames ignoredNames) { 982b5840353SAdam Hornáček this.ignoredNames = ignoredNames; 983b5840353SAdam Hornáček } 984b5840353SAdam Hornáček getIgnoredNames()985b5840353SAdam Hornáček public IgnoredNames getIgnoredNames() { 986b5840353SAdam Hornáček return ignoredNames; 987b5840353SAdam Hornáček } 988b5840353SAdam Hornáček setIncludedNames(Filter includedNames)989b5840353SAdam Hornáček public void setIncludedNames(Filter includedNames) { 990b5840353SAdam Hornáček this.includedNames = includedNames; 991b5840353SAdam Hornáček } 992b5840353SAdam Hornáček getIncludedNames()993b5840353SAdam Hornáček public Filter getIncludedNames() { 994b5840353SAdam Hornáček return includedNames; 995b5840353SAdam Hornáček } 996b5840353SAdam Hornáček setUserPage(String userPage)997b5840353SAdam Hornáček public void setUserPage(String userPage) { 998b5840353SAdam Hornáček this.userPage = userPage; 999b5840353SAdam Hornáček } 1000b5840353SAdam Hornáček getUserPage()1001b5840353SAdam Hornáček public String getUserPage() { 1002b5840353SAdam Hornáček return userPage; 1003b5840353SAdam Hornáček } 1004b5840353SAdam Hornáček setUserPageSuffix(String userPageSuffix)1005b5840353SAdam Hornáček public void setUserPageSuffix(String userPageSuffix) { 1006b5840353SAdam Hornáček this.userPageSuffix = userPageSuffix; 1007b5840353SAdam Hornáček } 1008b5840353SAdam Hornáček getUserPageSuffix()1009b5840353SAdam Hornáček public String getUserPageSuffix() { 1010b5840353SAdam Hornáček return userPageSuffix; 1011b5840353SAdam Hornáček } 1012b5840353SAdam Hornáček setBugPage(String bugPage)1013b5840353SAdam Hornáček public void setBugPage(String bugPage) { 1014b5840353SAdam Hornáček this.bugPage = bugPage; 1015b5840353SAdam Hornáček } 1016b5840353SAdam Hornáček getBugPage()1017b5840353SAdam Hornáček public String getBugPage() { 1018b5840353SAdam Hornáček return bugPage; 1019b5840353SAdam Hornáček } 1020b5840353SAdam Hornáček 1021b5840353SAdam Hornáček /** 1022ff44f24aSAdam Hornáček * Set the bug pattern to a new value. 1023b5840353SAdam Hornáček * 1024b5840353SAdam Hornáček * @param bugPattern the new pattern 1025b5840353SAdam Hornáček * @throws PatternSyntaxException when the pattern is not a valid regexp or 1026b5840353SAdam Hornáček * does not contain at least one capture group and the group does not 1027b5840353SAdam Hornáček * contain a single character 1028b5840353SAdam Hornáček */ setBugPattern(String bugPattern)1029b5840353SAdam Hornáček public void setBugPattern(String bugPattern) throws PatternSyntaxException { 103064819763SVladimir Kotal this.bugPattern = compilePattern(bugPattern); 1031b5840353SAdam Hornáček } 1032b5840353SAdam Hornáček getBugPattern()1033b5840353SAdam Hornáček public String getBugPattern() { 1034b5840353SAdam Hornáček return bugPattern; 1035b5840353SAdam Hornáček } 1036b5840353SAdam Hornáček getReviewPage()1037b5840353SAdam Hornáček public String getReviewPage() { 1038b5840353SAdam Hornáček return reviewPage; 1039b5840353SAdam Hornáček } 1040b5840353SAdam Hornáček setReviewPage(String reviewPage)1041b5840353SAdam Hornáček public void setReviewPage(String reviewPage) { 1042b5840353SAdam Hornáček this.reviewPage = reviewPage; 1043b5840353SAdam Hornáček } 1044b5840353SAdam Hornáček getReviewPattern()1045b5840353SAdam Hornáček public String getReviewPattern() { 1046b5840353SAdam Hornáček return reviewPattern; 1047b5840353SAdam Hornáček } 1048b5840353SAdam Hornáček 1049b5840353SAdam Hornáček /** 1050ff44f24aSAdam Hornáček * Set the review pattern to a new value. 1051b5840353SAdam Hornáček * 1052b5840353SAdam Hornáček * @param reviewPattern the new pattern 1053b5840353SAdam Hornáček * @throws PatternSyntaxException when the pattern is not a valid regexp or 1054b5840353SAdam Hornáček * does not contain at least one capture group and the group does not 1055b5840353SAdam Hornáček * contain a single character 1056b5840353SAdam Hornáček */ setReviewPattern(String reviewPattern)1057b5840353SAdam Hornáček public void setReviewPattern(String reviewPattern) throws PatternSyntaxException { 105864819763SVladimir Kotal this.reviewPattern = compilePattern(reviewPattern); 1059b5840353SAdam Hornáček } 1060b5840353SAdam Hornáček getWebappLAF()1061b5840353SAdam Hornáček public String getWebappLAF() { 1062b5840353SAdam Hornáček return webappLAF; 1063b5840353SAdam Hornáček } 1064b5840353SAdam Hornáček setWebappLAF(String webappLAF)1065b5840353SAdam Hornáček public void setWebappLAF(String webappLAF) { 1066b5840353SAdam Hornáček this.webappLAF = webappLAF; 1067b5840353SAdam Hornáček } 1068b5840353SAdam Hornáček 1069e829566cSChris Fraire /** 1070e829566cSChris Fraire * Gets a value indicating if the web app should run ctags as necessary. 1071e829566cSChris Fraire */ isWebappCtags()1072e829566cSChris Fraire public boolean isWebappCtags() { 1073e829566cSChris Fraire return webappCtags; 1074e829566cSChris Fraire } 1075e829566cSChris Fraire 1076e829566cSChris Fraire /** 1077e829566cSChris Fraire * Sets a value indicating if the web app should run ctags as necessary. 1078e829566cSChris Fraire */ setWebappCtags(boolean value)1079e829566cSChris Fraire public void setWebappCtags(boolean value) { 1080e829566cSChris Fraire this.webappCtags = value; 1081e829566cSChris Fraire } 1082e829566cSChris Fraire getRemoteScmSupported()1083b5840353SAdam Hornáček public RemoteSCM getRemoteScmSupported() { 1084b5840353SAdam Hornáček return remoteScmSupported; 1085b5840353SAdam Hornáček } 1086b5840353SAdam Hornáček setRemoteScmSupported(RemoteSCM remoteScmSupported)1087b5840353SAdam Hornáček public void setRemoteScmSupported(RemoteSCM remoteScmSupported) { 1088b5840353SAdam Hornáček this.remoteScmSupported = remoteScmSupported; 1089b5840353SAdam Hornáček } 1090b5840353SAdam Hornáček isOptimizeDatabase()1091b5840353SAdam Hornáček public boolean isOptimizeDatabase() { 1092b5840353SAdam Hornáček return optimizeDatabase; 1093b5840353SAdam Hornáček } 1094b5840353SAdam Hornáček setOptimizeDatabase(boolean optimizeDatabase)1095b5840353SAdam Hornáček public void setOptimizeDatabase(boolean optimizeDatabase) { 1096b5840353SAdam Hornáček this.optimizeDatabase = optimizeDatabase; 1097b5840353SAdam Hornáček } 1098b5840353SAdam Hornáček getLuceneLocking()1099b5840353SAdam Hornáček public LuceneLockName getLuceneLocking() { 1100b5840353SAdam Hornáček return luceneLocking; 1101b5840353SAdam Hornáček } 1102b5840353SAdam Hornáček 1103b5840353SAdam Hornáček /** 1104b5840353SAdam Hornáček * @param value off|on|simple|native where "on" is an alias for "simple". 1105b5840353SAdam Hornáček * Any other value is a fallback alias for "off" (with a logged warning). 1106b5840353SAdam Hornáček */ setLuceneLocking(LuceneLockName value)1107b5840353SAdam Hornáček public void setLuceneLocking(LuceneLockName value) { 1108b5840353SAdam Hornáček this.luceneLocking = value; 1109b5840353SAdam Hornáček } 1110b5840353SAdam Hornáček setCompressXref(boolean compressXref)1111b5840353SAdam Hornáček public void setCompressXref(boolean compressXref) { 1112b5840353SAdam Hornáček this.compressXref = compressXref; 1113b5840353SAdam Hornáček } 1114b5840353SAdam Hornáček isCompressXref()1115b5840353SAdam Hornáček public boolean isCompressXref() { 1116b5840353SAdam Hornáček return compressXref; 1117b5840353SAdam Hornáček } 1118b5840353SAdam Hornáček isIndexVersionedFilesOnly()1119b5840353SAdam Hornáček public boolean isIndexVersionedFilesOnly() { 1120b5840353SAdam Hornáček return indexVersionedFilesOnly; 1121b5840353SAdam Hornáček } 1122b5840353SAdam Hornáček setIndexVersionedFilesOnly(boolean indexVersionedFilesOnly)1123b5840353SAdam Hornáček public void setIndexVersionedFilesOnly(boolean indexVersionedFilesOnly) { 1124b5840353SAdam Hornáček this.indexVersionedFilesOnly = indexVersionedFilesOnly; 1125b5840353SAdam Hornáček } 1126b5840353SAdam Hornáček getIndexingParallelism()1127b5840353SAdam Hornáček public int getIndexingParallelism() { 1128b5840353SAdam Hornáček return indexingParallelism; 1129b5840353SAdam Hornáček } 1130b5840353SAdam Hornáček setIndexingParallelism(int value)1131b5840353SAdam Hornáček public void setIndexingParallelism(int value) { 1132c6f0939bSAdam Hornacek this.indexingParallelism = Math.max(value, 0); 1133b5840353SAdam Hornáček } 1134b5840353SAdam Hornáček getRepositoryInvalidationParallelism()11352123e367SVladimir Kotal public int getRepositoryInvalidationParallelism() { 11362123e367SVladimir Kotal return repositoryInvalidationParallelism; 11372123e367SVladimir Kotal } 11382123e367SVladimir Kotal setRepositoryInvalidationParallelism(int value)11392123e367SVladimir Kotal public void setRepositoryInvalidationParallelism(int value) { 11402123e367SVladimir Kotal this.repositoryInvalidationParallelism = Math.max(value, 0); 11412123e367SVladimir Kotal } 11422123e367SVladimir Kotal getHistoryParallelism()1143b5840353SAdam Hornáček public int getHistoryParallelism() { 1144b5840353SAdam Hornáček return historyParallelism; 1145b5840353SAdam Hornáček } 1146b5840353SAdam Hornáček setHistoryParallelism(int value)1147b5840353SAdam Hornáček public void setHistoryParallelism(int value) { 1148c6f0939bSAdam Hornacek this.historyParallelism = Math.max(value, 0); 1149b5840353SAdam Hornáček } 1150b5840353SAdam Hornáček getHistoryFileParallelism()1151dc607a84SVladimir Kotal public int getHistoryFileParallelism() { 1152dc607a84SVladimir Kotal return historyFileParallelism; 1153b5840353SAdam Hornáček } 1154b5840353SAdam Hornáček setHistoryFileParallelism(int value)1155dc607a84SVladimir Kotal public void setHistoryFileParallelism(int value) { 1156dc607a84SVladimir Kotal this.historyFileParallelism = Math.max(value, 0); 1157b5840353SAdam Hornáček } 1158b5840353SAdam Hornáček isTagsEnabled()1159b5840353SAdam Hornáček public boolean isTagsEnabled() { 1160b5840353SAdam Hornáček return this.tagsEnabled; 1161b5840353SAdam Hornáček } 1162b5840353SAdam Hornáček setTagsEnabled(boolean tagsEnabled)1163b5840353SAdam Hornáček public void setTagsEnabled(boolean tagsEnabled) { 1164b5840353SAdam Hornáček this.tagsEnabled = tagsEnabled; 1165b5840353SAdam Hornáček } 1166b5840353SAdam Hornáček setRevisionMessageCollapseThreshold(int threshold)1167b5840353SAdam Hornáček public void setRevisionMessageCollapseThreshold(int threshold) { 1168b5840353SAdam Hornáček this.revisionMessageCollapseThreshold = threshold; 1169b5840353SAdam Hornáček } 1170b5840353SAdam Hornáček getRevisionMessageCollapseThreshold()1171b5840353SAdam Hornáček public int getRevisionMessageCollapseThreshold() { 1172b5840353SAdam Hornáček return this.revisionMessageCollapseThreshold; 1173b5840353SAdam Hornáček } 1174b5840353SAdam Hornáček getCurrentIndexedCollapseThreshold()1175b5840353SAdam Hornáček public int getCurrentIndexedCollapseThreshold() { 1176b5840353SAdam Hornáček return currentIndexedCollapseThreshold; 1177b5840353SAdam Hornáček } 1178b5840353SAdam Hornáček setCurrentIndexedCollapseThreshold(int currentIndexedCollapseThreshold)1179b5840353SAdam Hornáček public void setCurrentIndexedCollapseThreshold(int currentIndexedCollapseThreshold) { 1180b5840353SAdam Hornáček this.currentIndexedCollapseThreshold = currentIndexedCollapseThreshold; 1181b5840353SAdam Hornáček } 1182b5840353SAdam Hornáček isDisplayRepositories()1183ad8a45cdSVladimir Kotal public boolean isDisplayRepositories() { 1184b5840353SAdam Hornáček return this.displayRepositories; 1185b5840353SAdam Hornáček } 1186b5840353SAdam Hornáček setDisplayRepositories(boolean flag)1187b5840353SAdam Hornáček public void setDisplayRepositories(boolean flag) { 1188b5840353SAdam Hornáček this.displayRepositories = flag; 1189b5840353SAdam Hornáček } 1190b5840353SAdam Hornáček getListDirsFirst()1191b5840353SAdam Hornáček public boolean getListDirsFirst() { 1192b5840353SAdam Hornáček return listDirsFirst; 1193b5840353SAdam Hornáček } 1194b5840353SAdam Hornáček setListDirsFirst(boolean flag)1195b5840353SAdam Hornáček public void setListDirsFirst(boolean flag) { 1196b5840353SAdam Hornáček listDirsFirst = flag; 1197b5840353SAdam Hornáček } 1198b5840353SAdam Hornáček 1199b5840353SAdam Hornáček /** 1200b5840353SAdam Hornáček * The name of the file relative to the <var>DATA_ROOT</var>, which should 1201b5840353SAdam Hornáček * be included into the footer of generated web pages. 1202b5840353SAdam Hornáček */ 1203b5840353SAdam Hornáček public static final String FOOTER_INCLUDE_FILE = "footer_include"; 1204b5840353SAdam Hornáček 1205b5840353SAdam Hornáček /** 1206b5840353SAdam Hornáček * The name of the file relative to the <var>DATA_ROOT</var>, which should 1207b5840353SAdam Hornáček * be included into the header of generated web pages. 1208b5840353SAdam Hornáček */ 1209b5840353SAdam Hornáček public static final String HEADER_INCLUDE_FILE = "header_include"; 1210b5840353SAdam Hornáček 1211b5840353SAdam Hornáček /** 1212b5840353SAdam Hornáček * The name of the file relative to the <var>DATA_ROOT</var>, which should 1213b5840353SAdam Hornáček * be included into the body of web app's "Home" page. 1214b5840353SAdam Hornáček */ 1215b5840353SAdam Hornáček public static final String BODY_INCLUDE_FILE = "body_include"; 1216b5840353SAdam Hornáček 1217b5840353SAdam Hornáček /** 1218b5840353SAdam Hornáček * The name of the file relative to the <var>DATA_ROOT</var>, which should 1219b5840353SAdam Hornáček * be included into the error page handling access forbidden errors - HTTP 1220b5840353SAdam Hornáček * code 403 Forbidden. 1221b5840353SAdam Hornáček */ 1222b5840353SAdam Hornáček public static final String E_FORBIDDEN_INCLUDE_FILE = "error_forbidden_include"; 1223b5840353SAdam Hornáček 122468c19b4cSAlexandrSergei4 122568c19b4cSAlexandrSergei4 /** 122668c19b4cSAlexandrSergei4 * The name of the file relative to the <var>DATA_ROOT</var>, which should 122768c19b4cSAlexandrSergei4 * be included into the HTTP header of generated web pages. 122868c19b4cSAlexandrSergei4 */ 122968c19b4cSAlexandrSergei4 public static final String HTTP_HEADER_INCLUDE_FILE = "http_header_include"; 123068c19b4cSAlexandrSergei4 1231b5840353SAdam Hornáček /** 1232f197cd77SVladimir Kotal * @return path to the file holding compiled path descriptions for the web application 1233f197cd77SVladimir Kotal */ getDtagsEftarPath()1234f197cd77SVladimir Kotal public Path getDtagsEftarPath() { 12350b77b425SVladimir Kotal return Paths.get(getDataRoot(), EFTAR_DTAGS_NAME); 1236f197cd77SVladimir Kotal } 1237f197cd77SVladimir Kotal getCTagsExtraOptionsFile()1238b5840353SAdam Hornáček public String getCTagsExtraOptionsFile() { 1239b5840353SAdam Hornáček return CTagsExtraOptionsFile; 1240b5840353SAdam Hornáček } 1241b5840353SAdam Hornáček setCTagsExtraOptionsFile(String filename)1242b5840353SAdam Hornáček public void setCTagsExtraOptionsFile(String filename) { 1243b5840353SAdam Hornáček this.CTagsExtraOptionsFile = filename; 1244b5840353SAdam Hornáček } 1245b5840353SAdam Hornáček getAllowedSymlinks()1246b5840353SAdam Hornáček public Set<String> getAllowedSymlinks() { 1247b5840353SAdam Hornáček return allowedSymlinks; 1248b5840353SAdam Hornáček } 1249b5840353SAdam Hornáček setAllowedSymlinks(Set<String> allowedSymlinks)1250b5840353SAdam Hornáček public void setAllowedSymlinks(Set<String> allowedSymlinks) { 1251b5840353SAdam Hornáček this.allowedSymlinks = allowedSymlinks; 1252b5840353SAdam Hornáček } 1253b5840353SAdam Hornáček getCanonicalRoots()12540e0ac58dSChris Fraire public Set<String> getCanonicalRoots() { 12550e0ac58dSChris Fraire return canonicalRoots; 12560e0ac58dSChris Fraire } 12570e0ac58dSChris Fraire setCanonicalRoots(Set<String> canonicalRoots)12580e0ac58dSChris Fraire public void setCanonicalRoots(Set<String> canonicalRoots) { 12590e0ac58dSChris Fraire this.canonicalRoots = canonicalRoots; 12600e0ac58dSChris Fraire } 12610e0ac58dSChris Fraire isObfuscatingEMailAddresses()1262b5840353SAdam Hornáček public boolean isObfuscatingEMailAddresses() { 1263b5840353SAdam Hornáček return obfuscatingEMailAddresses; 1264b5840353SAdam Hornáček } 1265b5840353SAdam Hornáček setObfuscatingEMailAddresses(boolean obfuscate)1266b5840353SAdam Hornáček public void setObfuscatingEMailAddresses(boolean obfuscate) { 1267b5840353SAdam Hornáček this.obfuscatingEMailAddresses = obfuscate; 1268b5840353SAdam Hornáček } 1269b5840353SAdam Hornáček isChattyStatusPage()1270b5840353SAdam Hornáček public boolean isChattyStatusPage() { 1271b5840353SAdam Hornáček return chattyStatusPage; 1272b5840353SAdam Hornáček } 1273b5840353SAdam Hornáček setChattyStatusPage(boolean chattyStatusPage)1274b5840353SAdam Hornáček public void setChattyStatusPage(boolean chattyStatusPage) { 1275b5840353SAdam Hornáček this.chattyStatusPage = chattyStatusPage; 1276b5840353SAdam Hornáček } 1277b5840353SAdam Hornáček isScopesEnabled()1278b5840353SAdam Hornáček public boolean isScopesEnabled() { 1279b5840353SAdam Hornáček return scopesEnabled; 1280b5840353SAdam Hornáček } 1281b5840353SAdam Hornáček setScopesEnabled(boolean scopesEnabled)1282b5840353SAdam Hornáček public void setScopesEnabled(boolean scopesEnabled) { 1283b5840353SAdam Hornáček this.scopesEnabled = scopesEnabled; 1284b5840353SAdam Hornáček } 1285b5840353SAdam Hornáček isFoldingEnabled()1286b5840353SAdam Hornáček public boolean isFoldingEnabled() { 1287b5840353SAdam Hornáček return foldingEnabled; 1288b5840353SAdam Hornáček } 1289b5840353SAdam Hornáček setFoldingEnabled(boolean foldingEnabled)1290b5840353SAdam Hornáček public void setFoldingEnabled(boolean foldingEnabled) { 1291b5840353SAdam Hornáček this.foldingEnabled = foldingEnabled; 1292b5840353SAdam Hornáček } 1293b5840353SAdam Hornáček getMaxSearchThreadCount()1294b5840353SAdam Hornáček public int getMaxSearchThreadCount() { 1295b5840353SAdam Hornáček return MaxSearchThreadCount; 1296b5840353SAdam Hornáček } 1297b5840353SAdam Hornáček setMaxSearchThreadCount(int count)1298b5840353SAdam Hornáček public void setMaxSearchThreadCount(int count) { 1299b5840353SAdam Hornáček this.MaxSearchThreadCount = count; 1300b5840353SAdam Hornáček } 1301b5840353SAdam Hornáček getMaxRevisionThreadCount()1302fb531549SVladimir Kotal public int getMaxRevisionThreadCount() { 1303fb531549SVladimir Kotal return MaxRevisionThreadCount; 1304fb531549SVladimir Kotal } 1305fb531549SVladimir Kotal setMaxRevisionThreadCount(int count)1306fb531549SVladimir Kotal public void setMaxRevisionThreadCount(int count) { 1307fb531549SVladimir Kotal this.MaxRevisionThreadCount = count; 1308fb531549SVladimir Kotal } 1309fb531549SVladimir Kotal isProjectsEnabled()1310b5840353SAdam Hornáček public boolean isProjectsEnabled() { 1311b5840353SAdam Hornáček return projectsEnabled; 1312b5840353SAdam Hornáček } 1313b5840353SAdam Hornáček setProjectsEnabled(boolean flag)1314b5840353SAdam Hornáček public void setProjectsEnabled(boolean flag) { 1315b5840353SAdam Hornáček this.projectsEnabled = flag; 1316b5840353SAdam Hornáček } 1317b5840353SAdam Hornáček getSuggesterConfig()1318911e8af0SAdam Hornáček public SuggesterConfig getSuggesterConfig() { 1319911e8af0SAdam Hornáček return suggesterConfig; 1320911e8af0SAdam Hornáček } 1321911e8af0SAdam Hornáček setSuggesterConfig(final SuggesterConfig config)1322911e8af0SAdam Hornáček public void setSuggesterConfig(final SuggesterConfig config) { 1323911e8af0SAdam Hornáček if (config == null) { 1324911e8af0SAdam Hornáček throw new IllegalArgumentException("Cannot set Suggester configuration to null"); 1325911e8af0SAdam Hornáček } 1326911e8af0SAdam Hornáček this.suggesterConfig = config; 1327911e8af0SAdam Hornáček } 1328911e8af0SAdam Hornáček getStatsdConfig()13290d7ace53SVladimir Kotal public StatsdConfig getStatsdConfig() { 13300d7ace53SVladimir Kotal return statsdConfig; 13310d7ace53SVladimir Kotal } 13320d7ace53SVladimir Kotal setStatsdConfig(final StatsdConfig config)13330d7ace53SVladimir Kotal public void setStatsdConfig(final StatsdConfig config) { 13340d7ace53SVladimir Kotal if (config == null) { 13350d7ace53SVladimir Kotal throw new IllegalArgumentException("Cannot set Statsd configuration to null"); 13360d7ace53SVladimir Kotal } 13370d7ace53SVladimir Kotal this.statsdConfig = config; 13380d7ace53SVladimir Kotal } 13390d7ace53SVladimir Kotal getDisabledRepositories()134029816c3bSChris Fraire public Set<String> getDisabledRepositories() { 134129816c3bSChris Fraire return disabledRepositories; 134229816c3bSChris Fraire } 134329816c3bSChris Fraire setDisabledRepositories(Set<String> disabledRepositories)134429816c3bSChris Fraire public void setDisabledRepositories(Set<String> disabledRepositories) { 134529816c3bSChris Fraire this.disabledRepositories = disabledRepositories; 134629816c3bSChris Fraire } 134729816c3bSChris Fraire getAuthenticationTokens()1348b0a23e73SVladimir Kotal public Set<String> getAuthenticationTokens() { 1349b0a23e73SVladimir Kotal return authenticationTokens; 1350b0a23e73SVladimir Kotal } 1351b0a23e73SVladimir Kotal setAuthenticationTokens(Set<String> tokens)1352b0a23e73SVladimir Kotal public void setAuthenticationTokens(Set<String> tokens) { 1353b0a23e73SVladimir Kotal this.authenticationTokens = tokens; 1354b0a23e73SVladimir Kotal } 1355b0a23e73SVladimir Kotal getIndexerAuthenticationToken()13568d34347cSVladimir Kotal public String getIndexerAuthenticationToken() { 13578d34347cSVladimir Kotal return indexerAuthenticationToken; 13588d34347cSVladimir Kotal } 13598d34347cSVladimir Kotal setIndexerAuthenticationToken(String token)13608d34347cSVladimir Kotal public void setIndexerAuthenticationToken(String token) { 13618d34347cSVladimir Kotal this.indexerAuthenticationToken = token; 13628d34347cSVladimir Kotal } 13638d34347cSVladimir Kotal isAllowInsecureTokens()136460e45c9fSVladimir Kotal public boolean isAllowInsecureTokens() { 136560e45c9fSVladimir Kotal return this.allowInsecureTokens; 136660e45c9fSVladimir Kotal } 136760e45c9fSVladimir Kotal setAllowInsecureTokens(boolean value)136860e45c9fSVladimir Kotal public void setAllowInsecureTokens(boolean value) { 136960e45c9fSVladimir Kotal this.allowInsecureTokens = value; 137060e45c9fSVladimir Kotal } 137160e45c9fSVladimir Kotal getHistoryChunkCount()1372a2f09795SVladimir Kotal public int getHistoryChunkCount() { 1373a2f09795SVladimir Kotal return historyChunkCount; 1374a2f09795SVladimir Kotal } 1375a2f09795SVladimir Kotal setHistoryChunkCount(int historyChunkCount)1376a2f09795SVladimir Kotal public void setHistoryChunkCount(int historyChunkCount) { 1377a2f09795SVladimir Kotal this.historyChunkCount = historyChunkCount; 1378a2f09795SVladimir Kotal } 1379a2f09795SVladimir Kotal isHistoryCachePerPartesEnabled()13805a635a8eSVladimir Kotal public boolean isHistoryCachePerPartesEnabled() { 13815a635a8eSVladimir Kotal return historyCachePerPartesEnabled; 13825a635a8eSVladimir Kotal } 13835a635a8eSVladimir Kotal setHistoryCachePerPartesEnabled(boolean historyCachePerPartesEnabled)13845a635a8eSVladimir Kotal public void setHistoryCachePerPartesEnabled(boolean historyCachePerPartesEnabled) { 13855a635a8eSVladimir Kotal this.historyCachePerPartesEnabled = historyCachePerPartesEnabled; 13865a635a8eSVladimir Kotal } 13875a635a8eSVladimir Kotal getServerName()13880516dd21SVladimir Kotal public String getServerName() { 13890516dd21SVladimir Kotal return serverName; 13900516dd21SVladimir Kotal } 13910516dd21SVladimir Kotal setServerName(String serverName)13920516dd21SVladimir Kotal public void setServerName(String serverName) { 13930516dd21SVladimir Kotal this.serverName = serverName; 13940516dd21SVladimir Kotal } 13950516dd21SVladimir Kotal getConnectTimeout()13961c258122SVladimir Kotal public int getConnectTimeout() { 13971c258122SVladimir Kotal return connectTimeout; 13981c258122SVladimir Kotal } 13991c258122SVladimir Kotal setConnectTimeout(int connectTimeout)14001c258122SVladimir Kotal public void setConnectTimeout(int connectTimeout) { 14011c258122SVladimir Kotal if (connectTimeout < 0) { 14021c258122SVladimir Kotal throw new IllegalArgumentException(String.format(NEGATIVE_NUMBER_ERROR, "connectTimeout", connectTimeout)); 14031c258122SVladimir Kotal } 14041c258122SVladimir Kotal this.connectTimeout = connectTimeout; 14051c258122SVladimir Kotal } 14061c258122SVladimir Kotal getApiTimeout()14071c258122SVladimir Kotal public int getApiTimeout() { 14081c258122SVladimir Kotal return apiTimeout; 14091c258122SVladimir Kotal } 14101c258122SVladimir Kotal setApiTimeout(int apiTimeout)14111c258122SVladimir Kotal public void setApiTimeout(int apiTimeout) { 14121c258122SVladimir Kotal if (apiTimeout < 0) { 14131c258122SVladimir Kotal throw new IllegalArgumentException(String.format(NEGATIVE_NUMBER_ERROR, "apiTimeout", apiTimeout)); 14141c258122SVladimir Kotal } 14151c258122SVladimir Kotal this.apiTimeout = apiTimeout; 14161c258122SVladimir Kotal } 14171c258122SVladimir Kotal isHistoryBasedReindex()1418f4571972SVladimir Kotal public boolean isHistoryBasedReindex() { 1419f4571972SVladimir Kotal return historyBasedReindex; 142012365fb4SVladimir Kotal } 142112365fb4SVladimir Kotal setHistoryBasedReindex(boolean flag)1422f4571972SVladimir Kotal public void setHistoryBasedReindex(boolean flag) { 1423f4571972SVladimir Kotal historyBasedReindex = flag; 142412365fb4SVladimir Kotal } 142512365fb4SVladimir Kotal 1426b5840353SAdam Hornáček /** 1427ff44f24aSAdam Hornáček * Write the current configuration to a file. 1428b5840353SAdam Hornáček * 1429b5840353SAdam Hornáček * @param file the file to write the configuration into 1430b5840353SAdam Hornáček * @throws IOException if an error occurs 1431b5840353SAdam Hornáček */ write(File file)1432b5840353SAdam Hornáček public void write(File file) throws IOException { 1433b5840353SAdam Hornáček try (FileOutputStream out = new FileOutputStream(file)) { 1434b5840353SAdam Hornáček this.encodeObject(out); 1435b5840353SAdam Hornáček } 1436b5840353SAdam Hornáček } 1437b5840353SAdam Hornáček getXMLRepresentationAsString()1438b5840353SAdam Hornáček public String getXMLRepresentationAsString() { 1439b5840353SAdam Hornáček ByteArrayOutputStream bos = new ByteArrayOutputStream(); 1440b5840353SAdam Hornáček this.encodeObject(bos); 1441b5840353SAdam Hornáček return bos.toString(); 1442b5840353SAdam Hornáček } 1443b5840353SAdam Hornáček encodeObject(OutputStream out)1444b5840353SAdam Hornáček public void encodeObject(OutputStream out) { 1445b5840353SAdam Hornáček try (XMLEncoder e = new XMLEncoder(new BufferedOutputStream(out))) { 1446b5840353SAdam Hornáček e.writeObject(this); 1447b5840353SAdam Hornáček } 1448b5840353SAdam Hornáček } 1449b5840353SAdam Hornáček read(File file)1450b5840353SAdam Hornáček public static Configuration read(File file) throws IOException { 1451b5840353SAdam Hornáček LOGGER.log(Level.INFO, "Reading configuration from {0}", file.getCanonicalPath()); 1452b5840353SAdam Hornáček try (FileInputStream in = new FileInputStream(file)) { 1453b5840353SAdam Hornáček return decodeObject(in); 1454b5840353SAdam Hornáček } 1455b5840353SAdam Hornáček } 1456b5840353SAdam Hornáček makeXMLStringAsConfiguration(String xmlconfig)1457b5840353SAdam Hornáček public static Configuration makeXMLStringAsConfiguration(String xmlconfig) throws IOException { 1458b5840353SAdam Hornáček final Configuration ret; 1459b5840353SAdam Hornáček final ByteArrayInputStream in = new ByteArrayInputStream(xmlconfig.getBytes()); 1460b5840353SAdam Hornáček ret = decodeObject(in); 1461b5840353SAdam Hornáček return ret; 1462b5840353SAdam Hornáček } 1463b5840353SAdam Hornáček 146434836723SVladimir Kotal @SuppressWarnings("lgtm[java/unsafe-deserialization]") decodeObject(InputStream in)1465b5840353SAdam Hornáček private static Configuration decodeObject(InputStream in) throws IOException { 1466b5840353SAdam Hornáček final Object ret; 1467b5840353SAdam Hornáček final LinkedList<Exception> exceptions = new LinkedList<>(); 1468c6f0939bSAdam Hornacek ExceptionListener listener = exceptions::addLast; 1469b5840353SAdam Hornáček 147081511796SAdam Hornacek try (XMLDecoder d = new XMLDecoder(new BufferedInputStream(in), null, listener, 147181511796SAdam Hornacek new ConfigurationClassLoader())) { 1472b5840353SAdam Hornáček ret = d.readObject(); 1473b5840353SAdam Hornáček } 1474b5840353SAdam Hornáček 1475b5840353SAdam Hornáček if (!(ret instanceof Configuration)) { 1476b5840353SAdam Hornáček throw new IOException("Not a valid config file"); 1477b5840353SAdam Hornáček } 1478b5840353SAdam Hornáček 1479b5840353SAdam Hornáček if (!exceptions.isEmpty()) { 1480b5840353SAdam Hornáček // There was an exception during parsing. 148134836723SVladimir Kotal // see addGroup() 1482b5840353SAdam Hornáček if (exceptions.getFirst() instanceof IOException) { 1483b5840353SAdam Hornáček throw (IOException) exceptions.getFirst(); 1484b5840353SAdam Hornáček } 1485b5840353SAdam Hornáček throw new IOException(exceptions.getFirst()); 1486b5840353SAdam Hornáček } 1487b5840353SAdam Hornáček 1488b5840353SAdam Hornáček Configuration conf = ((Configuration) ret); 1489b5840353SAdam Hornáček 149034836723SVladimir Kotal // Removes all non-root groups. 1491b5840353SAdam Hornáček // This ensures that when the configuration is reloaded then the set 1492b5840353SAdam Hornáček // contains only root groups. Subgroups are discovered again 1493b5840353SAdam Hornáček // as follows below 1494c6f0939bSAdam Hornacek conf.groups.removeIf(g -> g.getParent() != null); 1495b5840353SAdam Hornáček 1496b5840353SAdam Hornáček // Traversing subgroups and checking for duplicates, 1497b5840353SAdam Hornáček // effectively transforms the group tree to a structure (Set) 1498b5840353SAdam Hornáček // supporting an iterator. 1499b5840353SAdam Hornáček TreeSet<Group> copy = new TreeSet<>(); 1500b5840353SAdam Hornáček LinkedList<Group> stack = new LinkedList<>(conf.groups); 1501b5840353SAdam Hornáček while (!stack.isEmpty()) { 1502b5840353SAdam Hornáček Group group = stack.pollFirst(); 1503b5840353SAdam Hornáček stack.addAll(group.getSubgroups()); 1504b5840353SAdam Hornáček 1505b5840353SAdam Hornáček if (!copy.add(group)) { 1506b5840353SAdam Hornáček throw new IOException( 1507b5840353SAdam Hornáček String.format("Duplicate group name '%s' in configuration.", 1508b5840353SAdam Hornáček group.getName())); 1509b5840353SAdam Hornáček } 1510b5840353SAdam Hornáček 1511b5840353SAdam Hornáček // populate groups where the current group in in their subtree 1512b5840353SAdam Hornáček Group tmp = group.getParent(); 1513b5840353SAdam Hornáček while (tmp != null) { 1514b5840353SAdam Hornáček tmp.addDescendant(group); 1515b5840353SAdam Hornáček tmp = tmp.getParent(); 1516b5840353SAdam Hornáček } 1517b5840353SAdam Hornáček } 1518b5840353SAdam Hornáček conf.setGroups(copy); 1519b5840353SAdam Hornáček 1520fcbdc96bSChris Fraire /* 1521fcbdc96bSChris Fraire * Validate any defined canonicalRoot entries, and only include where 1522fcbdc96bSChris Fraire * validation succeeds. 1523fcbdc96bSChris Fraire */ 1524fcbdc96bSChris Fraire if (conf.canonicalRoots != null) { 1525fcbdc96bSChris Fraire conf.canonicalRoots = conf.canonicalRoots.stream().filter(s -> { 1526fcbdc96bSChris Fraire String problem = CanonicalRootValidator.validate(s, "canonicalRoot element"); 1527fcbdc96bSChris Fraire if (problem == null) { 1528fcbdc96bSChris Fraire return true; 1529fcbdc96bSChris Fraire } else { 1530fcbdc96bSChris Fraire LOGGER.warning(problem); 1531fcbdc96bSChris Fraire return false; 1532fcbdc96bSChris Fraire } 1533fcbdc96bSChris Fraire }).collect(Collectors.toCollection(HashSet::new)); 1534fcbdc96bSChris Fraire } 1535fcbdc96bSChris Fraire 1536b5840353SAdam Hornáček return conf; 1537b5840353SAdam Hornáček } 1538*61dce4cbSVladimir Kotal 1539*61dce4cbSVladimir Kotal public static class ConfigurationException extends Exception { 1540*61dce4cbSVladimir Kotal static final long serialVersionUID = -1; 1541*61dce4cbSVladimir Kotal ConfigurationException(String message)1542*61dce4cbSVladimir Kotal public ConfigurationException(String message) { 1543*61dce4cbSVladimir Kotal super(message); 1544*61dce4cbSVladimir Kotal } 1545*61dce4cbSVladimir Kotal } 1546*61dce4cbSVladimir Kotal 1547*61dce4cbSVladimir Kotal /** 1548*61dce4cbSVladimir Kotal * Check if configuration is populated and self-consistent. 1549*61dce4cbSVladimir Kotal * @throws ConfigurationException on error 1550*61dce4cbSVladimir Kotal */ checkConfiguration()1551*61dce4cbSVladimir Kotal public void checkConfiguration() throws ConfigurationException { 1552*61dce4cbSVladimir Kotal 1553*61dce4cbSVladimir Kotal if (getSourceRoot() == null) { 1554*61dce4cbSVladimir Kotal throw new ConfigurationException("Source root is not specified."); 1555*61dce4cbSVladimir Kotal } 1556*61dce4cbSVladimir Kotal 1557*61dce4cbSVladimir Kotal if (getDataRoot() == null) { 1558*61dce4cbSVladimir Kotal throw new ConfigurationException("Data root is not specified."); 1559*61dce4cbSVladimir Kotal } 1560*61dce4cbSVladimir Kotal 1561*61dce4cbSVladimir Kotal if (!new File(getSourceRoot()).canRead()) { 1562*61dce4cbSVladimir Kotal throw new ConfigurationException("Source root directory '" + getSourceRoot() + "' must be readable."); 1563*61dce4cbSVladimir Kotal } 1564*61dce4cbSVladimir Kotal 1565*61dce4cbSVladimir Kotal if (!new File(getDataRoot()).canWrite()) { 1566*61dce4cbSVladimir Kotal throw new ConfigurationException("Data root directory '" + getDataRoot() + "' must be writable."); 1567*61dce4cbSVladimir Kotal } 1568*61dce4cbSVladimir Kotal 1569*61dce4cbSVladimir Kotal if (!isHistoryEnabled() && isHistoryBasedReindex()) { 1570*61dce4cbSVladimir Kotal LOGGER.log(Level.INFO, "History based reindex is on, however history is off. " + 1571*61dce4cbSVladimir Kotal "History has to be enabled for history based reindex."); 1572*61dce4cbSVladimir Kotal } 1573*61dce4cbSVladimir Kotal 1574*61dce4cbSVladimir Kotal if (!isHistoryCache() && isHistoryBasedReindex()) { 1575*61dce4cbSVladimir Kotal LOGGER.log(Level.INFO, "History based reindex is on, however history cache is off. " + 1576*61dce4cbSVladimir Kotal "History cache has to be enabled for history based reindex."); 1577*61dce4cbSVladimir Kotal } 1578*61dce4cbSVladimir Kotal } 1579b5840353SAdam Hornáček } 1580