/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* See LICENSE.txt included in this distribution for the specific
* language governing permissions and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at LICENSE.txt.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Portions Copyright 2011, 2012 Jens Elkner.
*/
/**
* Placeholder class for all configuration variables. Due to the multithreaded
* nature of the web application, each thread will use the same instance of the
* configuration object for each page request. Class and methods should have
* package scope, but that didn't work with the XMLDecoder/XMLEncoder.
*/
public final class Configuration {
/** The common property key prefix used to access opengrok system properties */
/** The property name used to obtain the ctags command to use. */
PROPERTY_KEY_PREFIX + "analysis.Ctags";
/** The command to use if no ctags command was given explicitly */
/** Relative path wrt. servlet context to the default CSS to use */
/** The string property name used to get the date format pattern to use for
* directory listings in the web app. It needs to be a pattern acceptable
* by {@link java.text.SimpleDateFormat}.
* @see #DIRLIST_DATE_DEFAULT */
PROPERTY_KEY_PREFIX + "web.dirlist.date";
/** The boolean property name used to determine, whether the web app should
* show {@code Today} instead of the last modified date, if the file has
* been changed in the last 24 hours. */
PROPERTY_KEY_PREFIX + "web.dirlist.today";
public static final boolean DIRLIST_TODAY_DEFAULT = false;
/**
* Should the history log be cached?
*/
private boolean historyCache;
/**
* The maximum time in milliseconds {@code HistoryCache.get()} can take
* before its result is cached.
*/
private int historyCacheTime;
/**
* Should the history cache be stored in a database?
*/
private boolean historyCacheInDB;
private boolean generateHtml;
/**
* Default project will be used, when no project is selected and no project
* is in cookie, so basically only the first time you open the first page,
* or when you clear your web cookies
*/
private int indexWordLimit;
private boolean verbose;
//if below is set, then we count how many files per project we need to process and print percentage of completion per project
private boolean printProgress;
private boolean allowLeadingWildcard;
private boolean remoteScmSupported;
private boolean optimizeDatabase;
private boolean useLuceneLocking;
private boolean compressXref;
private boolean indexVersionedFilesOnly;
private int hitsPerPage;
private int cachePages;
private int scanningDepth;
private boolean obfuscatingEMailAddresses;
private boolean chattyStatusPage;
private int tabSize;
private boolean dirlistUseToday;
/**
* Get the default tab size (number of space characters per tab character)
*
* @return current tab size set.
* @see Project#getTabSize()
* @see org.opensolaris.opengrok.analysis.ExpandTabsReader
*/
public int getTabSize() {
return tabSize;
}
/**
* Set the default tab size (number of space characters per tab character)
*
* @param tabSize tabsize to set.
* @see Project#setTabSize(int)
* @see org.opensolaris.opengrok.analysis.ExpandTabsReader
*/
}
/**
* Get the depth of scanning for repositories in the directory tree relative
* to source root.
* @return the scan depth.
*/
public int getScanningDepth() {
return scanningDepth;
}
/**
* Set the depth of scanning for repositories in the directory tree relative
* to source root.
* @param scanningDepth the scan depth to set.
*/
this.scanningDepth = scanningDepth;
}
/**
* Creates a new instance of Configuration
*/
public Configuration() {
//defaults for an opengrok instance configuration
setHistoryCache(true);
setHistoryCacheTime(30);
setHistoryCacheInDB(false);
// TODO generate relative search paths, get rid of -w <webapp> option to indexer !
// setUrlPrefix(".." + Prefix.SEARCH_R + '?');
//below can cause an outofmemory error, since it is defaulting to NO LIMIT
setVerbose(false);
setPrintProgress(false);
setGenerateHtml(true);
setQuickContextScan(true);
setIgnoredNames(new IgnoredNames());
setIncludedNames(new Filter());
setBugPattern("\\b([12456789][0-9]{6})\\b");
setRemoteScmSupported(false);
setOptimizeDatabase(true);
setUsingLuceneLocking(false);
setCompressXref(true);
setIndexVersionedFilesOnly(false);
setHitsPerPage(25);
setCachePages(5);
//setTabSize(4);
}
/**
* Get the {@link SimpleDateFormat} pattern to use to show the last modified
* time in web app directory listings.
* @return an always usuable pattern for date formatting.
*/
return dirlistDatePattern;
}
/**
* Set the {@link SimpleDateFormat} pattern to use to show the last modified
* time in web app directory listings.
* @param pattern the pattern to use. Ignored if {@code null} or invalid.
*/
return;
}
try {
@SuppressWarnings("unused")
} catch (Exception e) {
}
}
/**
* Check, whether the web app should show {@code Today} instead of the last
* modified time if the target was changed within the last 24 hours.
* @return {@code true} if {@code Today} should be shown.
*/
public boolean isDirlistUseToday() {
return dirlistUseToday;
}
/**
* Set, whether the web app should show {@code Today} instead of the last
* modified time if the target was changed within the last 24 hours.
* @param enable use {@code true} if {@code Today} should be shown.
* @see #DIRLIST_TODAY_PROPERTY_KEY
*/
this.dirlistUseToday = enable;
}
/**
* Get the client command to use to access the repository for the given
* fully quallified classname.
* @param clazzName name of the targeting class
* @return {@code null} if not yet set, the client command otherwise.
*/
}
/**
* Set the client command to use to access the repository for the given
* fully quallified classname.
* @param clazzName name of the targeting class. If {@code null} this method
* does nothing.
* @param cmd the client command to use. If {@code null} the corresponding
* entry for the given clazzName get removed.
* @return the client command previously set, which might be {@code null}.
*/
return null;
}
}
}
/**
* Get a map of repository class names with the corresponding CLI command to
* access the repository it is able to handle.
* @return a unmodifyable map.
*/
}
/**
* Set the map of repository class names with the corresponding CLI command
* to access the repository it is able to handle.
* @param cmds the map to copy.
*/
}
/**
* Get the name of the ctags program in use
* @return the name of the ctags program in use
*/
return ctags;
}
/**
* Specify the CTags program to use
* @param ctags the ctags program to use
*/
}
/**
* Get the number of search result pages, which should be cached in
* a search result.
* @return the number of result pages to cache.
* @see #getHitsPerPage()
*/
public int getCachePages() {
return cachePages;
}
/**
* Set the number of search result pages, which should be cached in
* a search result.
* @param cachePages the number of result pages to cache.
* @see #getHitsPerPage()
*/
this.cachePages = cachePages;
}
/**
* Get the number of hits to display on one search result page.
* @return number of hits per page.
*/
public int getHitsPerPage() {
return hitsPerPage;
}
/**
* Set the number of hits to display on one search result page.
* @param hitsPerPage number of hits per page to set.
*/
this.hitsPerPage = hitsPerPage;
}
/**
* Should the history log be cached?
*
* @return {@code true} if a {@code HistoryCache} implementation should be
* used, {@code false} otherwise
*/
public boolean isHistoryCache() {
return historyCache;
}
/**
* Set whether history should be cached.
*
* @param historyCache if {@code true} enable history cache
*/
this.historyCache = historyCache;
}
/**
* How long can a history request take before it's cached? If the time is
* exceeded, the result is cached. This setting only affects
* {@code FileHistoryCache}.
*
* @return the maximum time in milliseconds a history request can take
* before it's cached
*/
public int getHistoryCacheTime() {
return historyCacheTime;
}
/**
* Set the maximum time a history request can take before it's cached. This
* setting is only respected if {@code FileHistoryCache} is used.
*
* @param historyCacheTime maximum time in milliseconds
*/
this.historyCacheTime = historyCacheTime;
}
/**
* Should the history cache be stored in a database? If yes,
* {@code JDBCHistoryCache} will be used to cache the history; otherwise,
* {@code FileHistoryCache} is used.
*
* @return whether the history cache should be stored in a database
*/
public boolean isHistoryCacheInDB() {
return historyCacheInDB;
}
/**
* Set whether the history cache should be stored in a database, and
* {@code JDBCHistoryCache} should be used instead of {@code
* FileHistoryCache}.
*
* @param historyCacheInDB whether the history cached should be stored in a
* database
*/
this.historyCacheInDB = historyCacheInDB;
}
/**
* Get all of the projects
* @return a list containing all of the projects (may be null)
*/
return projects;
}
/**
* Set the list of the projects
* @param projects the list of projects to use
*/
}
/**
* Do we have projects?
* @return true if we have projects
*/
public boolean hasProjects() {
}
try {
return s;
}
return file.getCanonicalPath();
} catch (IOException ex) {
+ ex.getMessage());
return s;
}
}
/**
* Specify the source root
* @param sourceRoot the location of the sources
*/
if (p != null) {
this.sourceRoot = p;
}
}
/**
* Get the path to where the sources are located
* @return path to where the sources are located
*/
return sourceRoot;
}
/**
* Get a file representing the directory where the sources are located
* @return A file representing the directory where the sources are located
*/
}
/**
* Returns a path relative to source root. This would just be a simple
* substring operation, except we need to support symlinks outside the
* source root.
* @param file A file to resolve
* @param stripCount Number of characters past source root to strip
* @throws IOException If an IO error occurs
* @throws FileNotFoundException If the file is not relative to source root
* @return Path relative to source root
*/
throws IOException
{
}
}
}
}
/**
* Set the path to where the index database is stored
* @param dataRoot the index database
*/
if (p != null) {
this.dataRoot = p;
}
}
/**
* Get the path to the where the index database is stored
* @return the path to the index database
*/
return dataRoot;
}
/**
* Get a file representing the index database
* @return the index database
*/
}
/**
* Get the map of known repositories.
* @return a possible empty list including {@code null}.
*/
return repositories;
}
/**
* Set the map of known repositories.
* @param repositories the repositories to set.
*/
this.repositories = repositories;
}
/**
* Get the the URL prefix to be used by the {@link
* org.opensolaris.opengrok.analysis.executables.JavaClassAnalyzer} as well
* as lexers (see {@link org.opensolaris.opengrok.analysis.JFlexXref}) when
* they create output with html links.
*
* @return the URI encoded prefix to use.
*/
return urlPrefix;
}
/**
* Set the URL prefix to be used by the {@link
* org.opensolaris.opengrok.analysis.executables.JavaClassAnalyzer} as well
* as lexers (see {@link org.opensolaris.opengrok.analysis.JFlexXref}) when
* they create output with html links.
*
* @param urlPrefix URI encoded prefix to set.
*/
}
/**
* Set whether to generate hyper text cross reference (xref) files
* offline (i.e. when indexing). If set to {@code false}, xref files are
* created on the fly on demand and gets disposed when served to the client
* - so saves disk space, but could be sightly slow and more resource
* demanding for the servlet container.
* @param generateHtml {@code true} to generate and cache xref files immediately.
*/
this.generateHtml = generateHtml;
}
/**
* Check, whether to generate and cache xref files immediately.
* @return {@code true} if immediate generation/caching is preferred.
*/
public boolean isGenerateHtml() {
return generateHtml;
}
/**
* Set the project that is specified to be the default project to use. The
* default project is the project you will search (from the web application)
* if the page request didn't contain the cookie.
* @param defaultProject The default project to use
*/
this.defaultProject = defaultProject;
}
/**
* Get the project that is specified to be the default project to use. The
* default project is the project you will search (from the web application)
* if the page request didn't contain the cookie.
* @return the default project (may be null if not specified)
*/
return defaultProject;
}
/**
* Chandan wrote the following answer on the opengrok-discuss list:
* "Traditionally search engines (specially spiders) think that large files
* are junk. Large files tend to be multimedia files etc., which text
* search spiders do not want to chew. So they ignore the contents of
* the file after a cutoff length. Lucene does this by number of words,
* which is by default is 10,000."
* By default OpenGrok will increase this limit to 60000, but it may be
* overridden in the configuration file
* @return The maximum words to index
*/
public int getIndexWordLimit() {
return indexWordLimit;
}
/**
* Set the number of words in a file Lucene will index.
* See getIndexWordLimit for a better description.
* @param indexWordLimit the number of words to index in a single file
*/
this.indexWordLimit = indexWordLimit;
}
/**
* Is the verbosity flag turned on?
* @return true if we can print extra information
*/
public boolean isVerbose() {
return verbose;
}
/**
* Set the verbosity flag (to add extra debug information in output)
* @param verbose new value
*/
}
/**
* Is the progress print flag turned on?
* @return {@code true} if we can print per project progress %
*/
public boolean isPrintProgress() {
return printProgress;
}
/**
* Set the printing of progress % flag (user convenience).
* @param enable {@code true} to enable progress printing.
*/
this.printProgress = enable;
}
/**
* Specify if a search may start with a wildcard. Note that queries
* that start with a wildcard will give a significant impact on the
* search performace (disabled by default).
* @param allowLeadingWildcard set to {@code true} to activate
*/
}
/**
* Is leading wildcards allowed?
* @return {@code true} if a search may start with a wildcard
*/
public boolean isAllowLeadingWildcard() {
return allowLeadingWildcard;
}
private boolean quickContextScan;
/**
* Check whether a quick context scan should be done.
* @return {@code true} if quick scan should be made.
* @see #setQuickContextScan(boolean)
*/
public boolean isQuickContextScan() {
return quickContextScan;
}
/**
* If set to {@code true}, at most 1 MiB of a file gets read into a buffer
* at once and than tokenized. Otherwise the whole file gets processed as
* usual, i.e. the file content gets read on demand when tokenizing and the
* whole file gets processed (no matter of its size).
* @param quickContextScan if {@code true} enable quick scanning
*/
this.quickContextScan = quickContextScan;
}
/**
* Takes precedence over {@link #getIncludedNames()}.
* @param ignoredNames stuff to ignore. If {@code null} defaults will be
* used instead.
*/
}
/**
* Takes precedence over {@link #getIncludedNames()}.
* @return stuff to ignore.
*/
return ignoredNames;
}
/**
* be indexed.
* @param includedNames stuff to index. {@code null} means everything.
* @see #setIgnoredNames(IgnoredNames)
*/
this.includedNames = includedNames;
}
/**
* be indexed.
* @return stuff to index. {@code null} means everything.
* @see #getIgnoredNames()
*/
return includedNames;
}
/**
* Set the user page for the history listing
* @param userPage the URI encoded URL fragment preceeding the username from
* history
*/
}
/**
* Get the user page for the history listing
* @return the URI encoded URL string fragment preceeding the username
*/
return userPage;
}
/**
* Set the user page suffix for the history listing
* @param userPageSuffix the URI encoded URL fragment following the username
* from history
*/
this.userPageSuffix = userPageSuffix;
}
/**
* Get the user page suffix for the history listing
* @return the URI encoded URL string fragment following the username
*/
return userPageSuffix;
}
/**
* Set the bug page for the history listing
* @param bugPage the URI encoded URL fragment preceeding the bug ID
*/
}
/**
* Get the bug page for the history listing
* @return the URI encoded URL string fragment preceeding the bug ID
*/
return bugPage;
}
/**
* Set the bug regex for the history listing
* @param bugPattern the regex to search history comments
*/
this.bugPattern = bugPattern;
}
/**
* Get the bug regex for the history listing
* @return the regex that is looked for in history comments
*/
return bugPattern;
}
/**
* Get the review (ARC) page for the history listing
* @return the URI encoded URL string fragment preceeding the review page ID
*/
return reviewPage;
}
/**
* Set the review (ARC) page for the history listing
* @param reviewPage the URI encoded URL fragment preceeding the review page ID
*/
this.reviewPage = reviewPage;
}
/**
* Get the review (ARC) regex for the history listing
* @return the regex that is looked for in history comments
*/
return reviewPattern;
}
/**
* Set the review (ARC) regex for the history listing
* @param reviewPattern the regex to search history comments
*/
this.reviewPattern = reviewPattern;
}
/**
* Get the name of the web app Look And Feel (LAF) theme to use. It gets
* used to construct the stylesheet and image include links in web pages
* and names a directory, which contains all this stuff.
* @return the name of the web app LAF
* @see #DEFAULT_STYLE
*/
return webappLAF;
}
/**
* Set the name of the web app Look And Feel (LAF) theme to use. It gets
* used to construct the stylesheet and image include links in web pages
* and names a directory, which contains all this stuff.
* @param webappLAF the name of the web app LAF. If {@code null} the default
* will be used.
* @see #DEFAULT_STYLE
*/
}
/**
* Check whether file histories should be retrieved from the related remote
* repositories when needed.
* @return {@code true} if fetch on demand is enabled.
*/
public boolean isRemoteScmSupported() {
return remoteScmSupported;
}
/**
* Set whether file histories should be retrieved from the related remote
* repositories when needed.
* @param remoteScmSupported {@code true} if fetch on demand is enabled.
*/
this.remoteScmSupported = remoteScmSupported;
}
/**
* Check, whether the lucene index database should be optimized (compact
* segments etc.) after indexing has been run.
* @return {@code true} if optimization is enabled.
*/
public boolean isOptimizeDatabase() {
return optimizeDatabase;
}
/**
* Set, whether the lucene index database should be optimized (compact
* segments etc.) after indexing has been run.
* @param optimizeDatabase {@code true} if optimization should be done.
*/
this.optimizeDatabase = optimizeDatabase;
}
/**
* Check, wheter lucene should lock index files when indexing to avoid
* concurrent access, reading invalid data.
* @return {@code true} if locking should be used.
*/
public boolean isUsingLuceneLocking() {
return useLuceneLocking;
}
/**
* Set wheter lucene should lock index files when indexing to avoid
* concurrent access, reading invalid data.
* @param useLuceneLocking {@code true} if locking should be used.
*/
this.useLuceneLocking = useLuceneLocking;
}
/**
* Set if we should compress the xref files or not. Applies to newly
* application automatically detects, whether an xref file is compressed
* and processes it properly.
* @param compressXref set to {@code true} if generated xref html files
* should be compressed
*/
this.compressXref = compressXref;
}
/**
* Set if we should compress generated xref html files?
* @return {@code true} if the xref html files should be compressed.
*/
public boolean isCompressXref() {
return compressXref;
}
/**
* Check, whether unversioned files should not be indexed.
* If {@code true}, it takes precedence over {@link #getIncludedNames()},
* i.e. files are not indexed when unversioned, even if they match an
* include name.
* @return {@code true} if indexing of unversioned files is disabled.
*/
public boolean isIndexVersionedFilesOnly() {
return indexVersionedFilesOnly;
}
/**
* Set, whether unversioned files should not be indexed.
* If set to {@code true}, it takes precedence over {@link #getIncludedNames()},
* i.e. files are not indexed when unversioned, even if they match an
* include name.
* @param indexVersionedFilesOnly {@code true} to disable indexing of
* unversioned files
*/
}
private transient long lastModified;
/**
* Get the time, when this instance has been modified. If not explicitly set
* or set to {@code 0}, it gets initialized with the time of the first call
* to this method after instantiation/de-serialization.
*
* @return time in milliseconds since 1 Jan 1970 00:00:00 GMT
*/
public long getLastModified() {
if (lastModified == 0) {
// since we use it for If-Last-Modified-Since evals, which has no
// millis, we need to clear the milliseconds part
}
return lastModified;
}
/**
* Set the time, when this configuration has been modified for the last time.
* @param lastModified the time in milliseconds since 1 Jan 1970 00:00:00 GMT
*/
}
/**
* Get the date of the last index update.
*
* @return the time of the last index update.
*/
if (indexLastModified == null) {
}
return indexLastModified;
}
/**
* Get the contents of a file or empty string if the file cannot be read.
*/
@SuppressWarnings("resource")
return "";
}
try {
}
/*
* should usually not happen
*/
+ "': " + e.getMessage());
} finally {
}
}
return "";
}
/**
* The name of the file relative to the <var>DATA_ROOT</var>, which should
* be included into the footer of generated web pages.
*/
/**
* Get the contents of the footer include file.
*
* @return an empty string if it could not be read successfully, the
* contents of the file otherwise.
* @see #FOOTER_INCLUDE_FILE
*/
}
return footer;
}
/**
* The name of the file relative to the <var>DATA_ROOT</var>, which should
* be included into the footer of generated web pages.
*/
/**
* Get the contents of the footer include file.
*
* @return an empty string if it could not be read successfully, the
* contents of the file otherwise.
* @see #HEADER_INCLUDE_FILE
*/
}
return header;
}
/**
* The name of the file relative to the <var>DATA_ROOT</var>, which should
* be included into the body of web app's "Home" page.
*/
/**
* Get the contents of the body include file.
* @return an empty string if it could not be read successfully, the
* contents of the file otherwise.
* @see Configuration#BODY_INCLUDE_FILE
*/
}
return body;
}
/**
* The name of the eftar file relative to the <var>DATA_ROOT</var>, which
* contains definition tags.
*/
/**
* Get the eftar file, which contains definition tags.
*
* @return {@code null} if there is no such file, the file otherwise.
*/
if (dtagsEftar == null) {
try {
} catch (SecurityException e) {
dtagsEftar = "";
}
} else {
dtagsEftar = "";
}
}
}
/**
* Get the fully quallified class name of the history database driver to use.
* @return the database driver class name.
*/
return databaseDriver;
}
/**
* Set the fully quallified class name of the history database driver to use.
* @param databaseDriver the database driver class name to set.
*/
this.databaseDriver = databaseDriver;
}
/**
* Get the JDBC connection URL to use to connect to the history database.
* @return the JDBC connection URL to use.
*/
return databaseUrl;
}
/**
* Set the JDBC connection URL to use to connect to the history database.
* @param databaseUrl the JDBC connection URL to set.
*/
this.databaseUrl = databaseUrl;
}
/**
* Get the optional file to be used to handover additional options to the
* ctags command.
* @return {@code null} if not set, the options filename otherwise.
*/
return ctagsOptionsFile;
}
/**
* Set the file to be used to handover additional options to the ctags
* command.
* @param filename the options filename to use. Might be {@code null}.
*/
this.ctagsOptionsFile = filename;
}
/**
* Get the pathnames of symlinks, which are allowed to be processed (e.g.
* indexed, tokenized, etc.).
* @return a possible empty set.
*/
return allowedSymlinks;
}
/**
* Set the pathnames of symlinks, which are allowed to be processed (e.g.
* indexed, tokenized, etc.).
* @param allowedSymlinks symlinks to allow. {@code null} means none.
*/
if (allowedSymlinks == null) {
this.allowedSymlinks.clear();
} else {
}
}
/**
* Check whether e-mail addresses should be obfuscated in the xref.
* @return {@code true} if obfuscation is needed.
*/
public boolean isObfuscatingEMailAddresses() {
return obfuscatingEMailAddresses;
}
/**
* Set whether e-mail addresses should be obfuscated in the xref.
* @param obfuscate {@code true} if obfuscation is needed.
*/
this.obfuscatingEMailAddresses = obfuscate;
}
/**
* Should status.jsp print internal settings, like paths and database
* URLs?
*
* @return {@code true} if status.jsp should show the configuration.
*/
public boolean isChattyStatusPage() {
return chattyStatusPage;
}
/**
* Set whether status.jsp should print internal settings.
*
* @param chattyStatusPage {@code true} if internal settings should be printed.
*/
this.chattyStatusPage = chattyStatusPage;
}
/**
* Write the current configuration to a file
*
* @param file the file to write the configuration into
* @throws IOException if an error occurs
*/
@SuppressWarnings("resource")
try {
this.encodeObject(out);
} finally {
}
}
/**
* Serialize this instance into an XML formatted string.
* @return this instance as xml string
*/
this.encodeObject(bos);
}
e.writeObject(this);
e.close();
}
/**
* Read the file containing a serialized {@link Configuration} instance and
* return the marshalled instance.
* @param file the file to read
* @return the un-serialized Configuration instance represented by the file.
*/
@SuppressWarnings("resource")
try {
return decodeObject(in);
} finally {
}
}
/**
* Read the given string representing a in XML serialized {@link Configuration}
* and return the marshalled instance.
* @param xmlconfig serialized config to read.
* @return the un-serialized Configuration instance represented by the string.
* @throws IOException if the string cannot be decoded.
*/
throws IOException
{
final Configuration ret;
return ret;
}
d.close();
if (!(ret instanceof Configuration)) {
throw new IOException("Not a valid config file");
}
return (Configuration)ret;
}
}