001/*
002 * Sonar, open source software quality management tool.
003 * Copyright (C) 2008-2012 SonarSource
004 * mailto:contact AT sonarsource DOT com
005 *
006 * Sonar is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 3 of the License, or (at your option) any later version.
010 *
011 * Sonar is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014 * Lesser General Public License for more details.
015 *
016 * You should have received a copy of the GNU Lesser General Public
017 * License along with Sonar; if not, write to the Free Software
018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
019 */
020package org.sonar.server.platform;
021
022import org.apache.commons.io.FileUtils;
023import org.apache.commons.io.filefilter.FileFilterUtils;
024import org.apache.commons.lang.StringUtils;
025import org.slf4j.Logger;
026import org.slf4j.LoggerFactory;
027import org.sonar.api.CoreProperties;
028import org.sonar.api.config.Settings;
029import org.sonar.api.platform.ServerFileSystem;
030import org.sonar.core.persistence.Database;
031
032import java.io.File;
033import java.io.FileFilter;
034import java.io.IOException;
035import java.util.ArrayList;
036import java.util.Collections;
037import java.util.List;
038
039/**
040 * Introspect the filesystem and the classloader to get extension files at startup.
041 *
042 * @since 2.2
043 */
044public class DefaultServerFileSystem implements ServerFileSystem {
045
046  private static final Logger LOGGER = LoggerFactory.getLogger(DefaultServerFileSystem.class);
047
048  private Database database;
049  private File deployDir;
050  private File homeDir;
051
052  public DefaultServerFileSystem(Database database, Settings settings) {
053    this.database = database;
054    this.homeDir = new File(settings.getString(CoreProperties.SONAR_HOME));
055
056    String deployPath = settings.getString(ServerSettings.DEPLOY_DIR);
057    if (StringUtils.isNotBlank(deployPath)) {
058      this.deployDir = new File(deployPath);
059    }
060  }
061
062  /**
063   * for unit tests
064   */
065  public DefaultServerFileSystem(Database database, File homeDir, File deployDir) {
066    this.database = database;
067    this.deployDir = deployDir;
068    this.homeDir = homeDir;
069  }
070
071  public void start() {
072    LOGGER.info("Sonar home: " + homeDir.getAbsolutePath());
073    if (!homeDir.isDirectory() || !homeDir.exists()) {
074      throw new ServerStartException("Sonar home directory does not exist");
075    }
076
077    if (deployDir == null) {
078      throw new ServerStartException("The target directory to deploy libraries is not set");
079    }
080
081    try {
082      LOGGER.info("Deploy dir: " + deployDir.getAbsolutePath());
083      FileUtils.forceMkdir(deployDir);
084      for (File subDirectory : deployDir.listFiles((FileFilter) FileFilterUtils.directoryFileFilter())) {
085        FileUtils.cleanDirectory(subDirectory);
086      }
087
088    } catch (IOException e) {
089      throw new ServerStartException("The following directory can not be created: " + deployDir.getAbsolutePath(), e);
090    }
091
092    File deprecated = getDeprecatedPluginsDir();
093    try {
094      FileUtils.forceMkdir(deprecated);
095      FileUtils.cleanDirectory(deprecated);
096
097    } catch (IOException e) {
098      throw new ServerStartException("The following directory can not be created: " + deprecated.getAbsolutePath(), e);
099    }
100  }
101
102  public File getHomeDir() {
103    return homeDir;
104  }
105
106  public File getTempDir() {
107    return new File(homeDir, "temp");
108  }
109
110  public File getDeployDir() {
111    return deployDir;
112  }
113
114  public File getDeployedJdbcDriver() {
115    return new File(deployDir, "jdbc-driver.jar");
116  }
117
118  public File getDeployedPluginsDir() {
119    return new File(deployDir, "plugins");
120  }
121
122  public File getDownloadedPluginsDir() {
123    return new File(getHomeDir(), "extensions/downloads");
124  }
125
126  public File getRemovedPluginsDir() {
127    return new File(getHomeDir(), "extensions/trash");
128  }
129
130  public File getJdbcDriver() {
131    String dialect = database.getDialect().getId();
132    File dir = new File(getHomeDir(), "/extensions/jdbc-driver/" + dialect + "/");
133    List<File> jars = getFiles(dir, "jar");
134    if (jars.isEmpty()) {
135      throw new ServerStartException("No JDBC driver found in " + dir.getAbsolutePath());
136    }
137    if (jars.size() > 1) {
138      throw new ServerStartException("The directory " + dir.getAbsolutePath() + " accepts only a single JAR file");
139    }
140    return jars.get(0);
141  }
142
143  public List<File> getCorePlugins() {
144    File corePluginsDir = new File(getHomeDir(), "lib/core-plugins");
145    return getFiles(corePluginsDir, "jar");
146  }
147
148  public List<File> getUserPlugins() {
149    File pluginsDir = getUserPluginsDir();
150    return getFiles(pluginsDir, "jar");
151  }
152
153  public File getUserPluginsDir() {
154    return new File(getHomeDir(), "extensions/plugins");
155  }
156
157  public File getDeprecatedPluginsDir() {
158    return new File(getHomeDir(), "extensions/deprecated");
159  }
160
161
162  public File getPluginIndex() {
163    return new File(getDeployDir(), "plugins/index.txt");
164  }
165
166  public List<File> getExtensions(String dirName, String... suffixes) {
167    File dir = new File(getHomeDir(), "extensions/rules/" + dirName);
168    if (dir.exists() && dir.isDirectory()) {
169      return getFiles(dir, suffixes);
170    }
171    return Collections.emptyList();
172  }
173
174  public List<File> getPluginExtensionXml(String pluginKey) {
175    File dir = new File(getHomeDir(), "extensions/rules/" + pluginKey);
176    if (dir.exists() && dir.isDirectory()) {
177      return getFiles(dir, "xml");
178    }
179    return Collections.emptyList();
180  }
181
182  private List<File> getFiles(File dir, String... fileSuffixes) {
183    List<File> files = new ArrayList<File>();
184    if (dir != null && dir.exists()) {
185      if (fileSuffixes != null && fileSuffixes.length > 0) {
186        files.addAll(FileUtils.listFiles(dir, fileSuffixes, false));
187      } else {
188        files.addAll(FileUtils.listFiles(dir, null, false));
189      }
190    }
191    return files;
192  }
193}