RuntimeEnvironment.java revision 99
207N/A/*
207N/A * CDDL HEADER START
207N/A *
207N/A * The contents of this file are subject to the terms of the
207N/A * Common Development and Distribution License (the "License").
207N/A * You may not use this file except in compliance with the License.
207N/A *
207N/A * See LICENSE.txt included in this distribution for the specific
207N/A * language governing permissions and limitations under the License.
207N/A *
207N/A * When distributing Covered Code, include this CDDL HEADER in each
207N/A * file and include the License file at LICENSE.txt.
207N/A * If applicable, add the following below this CDDL HEADER, with the
207N/A * fields enclosed by brackets "[]" replaced with your own identifying
207N/A * information: Portions Copyright [yyyy] [name of copyright owner]
207N/A *
207N/A * CDDL HEADER END
207N/A */
207N/A
207N/A/*
207N/A * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
207N/A * Use is subject to license terms.
207N/A */
207N/Apackage org.opensolaris.opengrok.configuration;
207N/A
207N/Aimport java.beans.XMLDecoder;
207N/Aimport java.beans.XMLEncoder;
207N/Aimport java.io.BufferedInputStream;
207N/Aimport java.io.BufferedOutputStream;
207N/Aimport java.io.BufferedReader;
207N/Aimport java.io.File;
207N/Aimport java.io.FileInputStream;
207N/Aimport java.io.FileOutputStream;
282N/Aimport java.io.IOException;
207N/Aimport java.io.InputStreamReader;
261N/Aimport java.net.InetAddress;
320N/Aimport java.net.ServerSocket;
312N/Aimport java.net.Socket;
207N/Aimport java.net.SocketAddress;
207N/Aimport java.net.UnknownHostException;
207N/Aimport java.util.Collections;
207N/Aimport java.util.Date;
207N/Aimport java.util.HashMap;
207N/Aimport java.util.List;
207N/Aimport java.util.Map;
207N/Aimport org.opensolaris.opengrok.history.ExternalRepository;
207N/A
207N/A/**
656N/A * The RuntimeEnvironment class is used as a placeholder for the current
207N/A * configuration this execution context (classloader) is using.
207N/A */
207N/Apublic class RuntimeEnvironment {
207N/A private Configuration configuration;
678N/A private Map<Thread, Configuration> threadmap;
480N/A
207N/A private static RuntimeEnvironment instance = new RuntimeEnvironment();
207N/A
207N/A /**
207N/A * Get the one and only instance of the RuntimeEnvironment
207N/A * @return the one and only instance of the RuntimeEnvironment
207N/A */
207N/A public static RuntimeEnvironment getInstance() {
207N/A return instance;
207N/A }
207N/A
207N/A /**
207N/A * Creates a new instance of RuntimeEnvironment. Private to ensure a
207N/A * singleton pattern.
207N/A */
207N/A private RuntimeEnvironment() {
207N/A configuration = new Configuration();
207N/A threadmap = Collections.synchronizedMap(new HashMap<Thread, Configuration>());
207N/A }
207N/A
207N/A private Configuration getConfiguration() {
253N/A Configuration ret = configuration;
359N/A Configuration config = threadmap.get(Thread.currentThread());
207N/A
359N/A if (config != null) {
274N/A ret = config;
320N/A }
656N/A
656N/A return ret;
207N/A }
207N/A
207N/A /**
207N/A * Get the path to the where the index database is stored
207N/A * @return the path to the index database
207N/A */
207N/A public String getDataRootPath() {
207N/A return getConfiguration().getDataRoot();
207N/A }
207N/A
207N/A /**
207N/A * Get a file representing the index database
207N/A * @return the index database
207N/A */
207N/A public File getDataRootFile() {
207N/A File ret = null;
207N/A String file = getDataRootPath();
207N/A if (file != null) {
207N/A ret = new File(file);
207N/A }
207N/A
207N/A return ret;
207N/A }
261N/A
459N/A /**
207N/A * Set the path to where the index database is stored
459N/A * @param data the index database
261N/A * @throws IOException if the path cannot be resolved
207N/A */
207N/A public void setDataRoot(File data) throws IOException {
207N/A getConfiguration().setDataRoot(data.getCanonicalPath());
207N/A }
261N/A
207N/A /**
459N/A * Set the path to where the index database is stored
207N/A * @param dataRoot the index database
312N/A */
207N/A public void setDataRoot(String dataRoot) {
564N/A getConfiguration().setDataRoot(dataRoot);
564N/A }
207N/A
207N/A /**
564N/A * Get the path to where the sources are located
207N/A * @return path to where the sources are located
207N/A */
564N/A public String getSourceRootPath() {
564N/A return getConfiguration().getSourceRoot();
564N/A }
564N/A
564N/A /**
207N/A * Get a file representing the directory where the sources are located
207N/A * @return A file representing the directory where the sources are located
207N/A */
261N/A public File getSourceRootFile() {
261N/A File ret = null;
261N/A String file = getSourceRootPath();
261N/A if (file != null) {
261N/A ret = new File(file);
261N/A }
261N/A
320N/A return ret;
261N/A }
261N/A
261N/A /**
207N/A * Specify the source root
207N/A * @param source the location of the sources
207N/A * @throws IOException if the name cannot be resolved
668N/A */
668N/A public void setSourceRoot(File source) throws IOException {
668N/A getConfiguration().setSourceRoot(source.getCanonicalPath());
668N/A }
668N/A
668N/A /**
668N/A * Specify the source root
668N/A * @param sourceRoot the location of the sources
668N/A */
668N/A public void setSourceRoot(String sourceRoot) {
668N/A getConfiguration().setSourceRoot(sourceRoot);
668N/A }
668N/A
668N/A /**
668N/A * Do we have projects?
668N/A * @return true if we have projects
668N/A */
668N/A public boolean hasProjects() {
668N/A List<Project> proj = getProjects();
668N/A return (proj != null && proj.size() > 0);
668N/A }
668N/A
668N/A /**
668N/A * Get all of the projects
668N/A * @return a list containing all of the projects (may be null)
668N/A */
668N/A public List<Project> getProjects() {
668N/A return getConfiguration().getProjects();
668N/A }
668N/A
668N/A /**
668N/A * Set the list of the projects
668N/A * @param projects the list of projects to use
668N/A */
668N/A public void setProjects(List<Project> projects) {
668N/A getConfiguration().setProjects(projects);
668N/A }
668N/A
668N/A /**
668N/A * Register this thread in the thread/configuration map (so that all
668N/A * subsequent calls to the RuntimeEnvironment from this thread will use
668N/A * the same configuration
668N/A */
668N/A public void register() {
668N/A threadmap.put(Thread.currentThread(), configuration);
668N/A }
668N/A
668N/A /**
668N/A * Get the context name of the web application
668N/A * @return the web applications context name
668N/A */
668N/A public String getUrlPrefix() {
668N/A return getConfiguration().getUrlPrefix();
668N/A }
668N/A
668N/A /**
668N/A * Set the web context name
668N/A * @param urlPrefix the web applications context name
668N/A */
460N/A public void setUrlPrefix(String urlPrefix) {
580N/A getConfiguration().setUrlPrefix(urlPrefix);
580N/A }
580N/A
580N/A /**
580N/A * Get the name of the ctags program in use
580N/A * @return the name of the ctags program in use
580N/A */
580N/A public String getCtags() {
580N/A return getConfiguration().getCtags();
580N/A }
580N/A
580N/A /**
580N/A * Specify the CTags program to use
580N/A * @param ctags the ctags program to use
580N/A */
580N/A public void setCtags(String ctags) {
207N/A getConfiguration().setCtags(ctags);
580N/A }
580N/A
580N/A /**
580N/A * Validate that I have a Exuberant ctags program I may use
580N/A * @return true if success, false otherwise
580N/A */
580N/A public boolean validateExuberantCtags() {
580N/A String ctags = getCtags();
207N/A
580N/A //Check if exub ctags is available
580N/A Process ctagsProcess = null;
580N/A try {
580N/A ctagsProcess = Runtime.getRuntime().exec(new String[] {ctags, "--version" });
580N/A } catch (Exception e) {
580N/A }
580N/A try {
580N/A BufferedReader cin = new BufferedReader(new InputStreamReader(ctagsProcess.getInputStream()));
580N/A String ctagOut;
580N/A if (!((ctagOut = cin.readLine()) != null && ctagOut.startsWith("Exuberant Ctags"))) {
580N/A System.err.println("Error: No Exuberant Ctags found in PATH!\n" +
359N/A "(tried running " + ctags + ")\n" +
207N/A "Please use option -c to specify path to a good Exuberant Ctags program");
207N/A return false;
207N/A }
274N/A } catch (Exception e) {
274N/A System.err.println("Error: executing " + ctags + "! " +e.getLocalizedMessage() +
274N/A "\nPlease use option -c to specify path to a good Exuberant Ctags program");
274N/A return false;
274N/A }
297N/A
274N/A // reap the child process..
464N/A try {
274N/A int ret;
439N/A if ((ret = ctagsProcess.exitValue()) != 0) {
439N/A System.err.println("Error: ctags returned " + ret);
439N/A return false;
464N/A }
439N/A } catch (IllegalThreadStateException exp) {
297N/A // the process is still running??? just kill it..
439N/A ctagsProcess.destroy();
460N/A return true;
439N/A }
274N/A return true;
460N/A }
460N/A
274N/A /**
274N/A * Get the max time a SMC operation may use to avoid beeing cached
274N/A * @return the max time
274N/A */
207N/A public int getHistoryReaderTimeLimit() {
459N/A return getConfiguration().getHistoryCacheTime();
678N/A }
207N/A
678N/A /**
359N/A * Specify the maximum time a SCM operation should take before it will
359N/A * be cached (in ms)
459N/A * @param historyReaderTimeLimit the max time in ms before it is cached
359N/A */
359N/A public void setHistoryReaderTimeLimit(int historyReaderTimeLimit) {
359N/A getConfiguration().setHistoryCacheTime(historyReaderTimeLimit);
359N/A }
656N/A
694N/A /**
694N/A * Is history cache currently enabled?
656N/A * @return true if history cache is enabled
694N/A */
656N/A public boolean useHistoryCache() {
656N/A return getConfiguration().isHistoryCache();
656N/A }
656N/A
656N/A /**
207N/A * Specify if we should use history cache or not
816N/A * @param useHistoryCache set false if you do not want to use history cache
816N/A */
255N/A public void setUseHistoryCache(boolean useHistoryCache) {
207N/A getConfiguration().setHistoryCache(useHistoryCache);
456N/A }
460N/A
460N/A /**
460N/A * Should we generate HTML or not during the indexing phase
274N/A * @return true if HTML should be generated during the indexing phase
274N/A */
207N/A public boolean isGenerateHtml() {
651N/A return getConfiguration().isGenerateHtml();
274N/A }
274N/A
456N/A /**
274N/A * Specify if we should generate HTML or not during the indexing phase
274N/A * @param generateHtml set this to true to pregenerate HTML
274N/A */
274N/A public void setGenerateHtml(boolean generateHtml) {
274N/A getConfiguration().setGenerateHtml(generateHtml);
651N/A }
651N/A
274N/A /**
457N/A * Get the map of external SCM repositories available
457N/A * @return A map containing all available SCMs
457N/A */
207N/A public Map<String, ExternalRepository> getRepositories() {
457N/A return getConfiguration().getRepositories();
207N/A }
457N/A
457N/A /**
457N/A * Set the map of external SCM repositories
457N/A * @param repositories the repositories to use
457N/A */
457N/A public void setRepositories(Map<String, ExternalRepository> repositories) {
274N/A getConfiguration().setRepositories(repositories);
207N/A }
207N/A
207N/A /**
816N/A * Set the project that is specified to be the default project to use. The
207N/A * default project is the project you will search (from the web application)
207N/A * if the page request didn't contain the cookie..
508N/A * @param defaultProject The default project to use
207N/A */
207N/A public void setDefaultProject(Project defaultProject) {
656N/A getConfiguration().setDefaultProject(defaultProject);
656N/A }
656N/A
656N/A /**
656N/A * Get the project that is specified to be the default project to use. The
656N/A * default project is the project you will search (from the web application)
656N/A * if the page request didn't contain the cookie..
656N/A * @return the default project (may be null if not specified)
656N/A */
359N/A public Project getDefaultProject() {
359N/A return getConfiguration().getDefaultProject();
359N/A }
207N/A
207N/A /**
359N/A * Chandan wrote the following answer on the opengrok-discuss list:
253N/A * "Traditionally search engines (specially spiders) think that large files
253N/A * are junk. Large files tend to be multimedia files etc., which text
253N/A * search spiders do not want to chew. So they ignore the contents of
207N/A * the file after a cutoff length. Lucene does this by number of words,
667N/A * which is by default is 10,000."
667N/A * By default OpenGrok will increase this limit to 60000, but it may be
667N/A * overridden in the configuration file
672N/A * @return The maximum words to index
672N/A */
672N/A public int getIndexWordLimit() {
667N/A return getConfiguration().getIndexWordLimit();
672N/A }
672N/A
672N/A public void setIndexWordLimit(int indexWordLimit) {
667N/A getConfiguration().setIndexWordLimit(indexWordLimit);
207N/A }
207N/A
207N/A public boolean isVerbose() {
207N/A return getConfiguration().isVerbose();
270N/A }
270N/A
459N/A public void setVerbose(boolean verbose) {
270N/A getConfiguration().setVerbose(verbose);
312N/A }
564N/A
270N/A
270N/A /**
270N/A * Read an configuration file and set it as the current configuration.
564N/A * @param file the file to read
270N/A * @throws IOException if an error occurs
270N/A */
564N/A public void readConfiguration(File file) throws IOException {
564N/A XMLDecoder d = new XMLDecoder(
564N/A new BufferedInputStream(new FileInputStream(file)));
564N/A Object obj = d.readObject();
564N/A d.close();
359N/A
270N/A if (obj instanceof Configuration) {
270N/A configuration = (Configuration)obj;
270N/A System.out.println("Config file " + file.getName() + " successfully read");
270N/A } else {
270N/A throw new IOException("Not a valid config file");
678N/A }
320N/A }
270N/A
270N/A /**
270N/A * Write the current configuration to a file
270N/A * @param file the file to write the configuration into
270N/A * @throws IOException if an error occurs
270N/A */
270N/A public void writeConfiguration(File file) throws IOException {
270N/A XMLEncoder e = new XMLEncoder(
207N/A new BufferedOutputStream(new FileOutputStream(file)));
207N/A e.writeObject(getConfiguration());
207N/A e.close();
359N/A }
359N/A
359N/A /**
359N/A * Write the current configuration to a socket
359N/A * @param host the host address to receive the configuration
359N/A * @param port the port to use on the host
359N/A * @throws IOException if an error occurs
207N/A */
207N/A public void writeConfiguration(InetAddress host, int port) throws IOException {
207N/A Socket sock = new Socket(host, port);
320N/A XMLEncoder e = new XMLEncoder(sock.getOutputStream());
207N/A e.writeObject(getConfiguration());
816N/A e.close();
207N/A try {
207N/A sock.close();
320N/A } catch (Exception ex) {
207N/A ;
359N/A }
460N/A }
460N/A
460N/A private Thread configurationListenerThread;
359N/A private ServerSocket configServerSocket;
359N/A
359N/A /**
207N/A * Try to stop the configuration listener thread
320N/A */
207N/A public void stopConfigurationListenerThread() {
207N/A try {
207N/A configServerSocket.close();
207N/A } catch (Exception e) {}
207N/A }
508N/A
207N/A /**
207N/A * Start a thread to listen on a socket to receive new configurations
359N/A * to use.
359N/A * @param endpoint The socket address to listen on
359N/A * @return true if the endpoint was available (and the thread was started)
207N/A */
207N/A public boolean startConfigurationListenerThread(SocketAddress endpoint) {
207N/A boolean ret = false;
207N/A
207N/A try {
207N/A configServerSocket = new ServerSocket();
207N/A configServerSocket.bind(endpoint);
207N/A ret = true;
207N/A final ServerSocket sock = configServerSocket;
207N/A Thread t = new Thread(new Runnable() {
207N/A public void run() {
207N/A Socket s = null;
320N/A while (!sock.isClosed()) {
207N/A try {
207N/A System.out.flush();
207N/A s = sock.accept();
830N/A System.out.println((new Date()).toString() + " OpenGrok: Got request from " + s.getInetAddress().getHostAddress());
207N/A String line;
207N/A BufferedInputStream in = new BufferedInputStream(s.getInputStream());
320N/A
207N/A XMLDecoder d = new XMLDecoder(new BufferedInputStream(in));
207N/A Object obj = d.readObject();
320N/A d.close();
207N/A
207N/A if (obj instanceof Configuration) {
207N/A configuration = (Configuration)obj;
207N/A System.out.println("Configuration updated: " + configuration.getSourceRoot());
207N/A System.out.flush();
508N/A }
207N/A } catch (IOException e) {
207N/A e.printStackTrace();
207N/A } finally {
207N/A try { s.close(); } catch (Exception ex) { }
207N/A }
207N/A }
207N/A }
207N/A });
359N/A t.start();
359N/A } catch (UnknownHostException ex) {
359N/A ex.printStackTrace();
359N/A } catch (IOException ex) {
359N/A ex.printStackTrace();
359N/A }
359N/A
359N/A if (!ret && configServerSocket != null) {
359N/A try {
460N/A configServerSocket.close();
460N/A } catch (IOException ex) {
460N/A ;
359N/A }
359N/A }
359N/A
359N/A return ret;
359N/A }
253N/A}
253N/A