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     */
020    package org.sonar.server.platform;
021    
022    import org.apache.commons.io.FileUtils;
023    import org.apache.commons.io.filefilter.FileFilterUtils;
024    import org.apache.commons.lang.StringUtils;
025    import org.slf4j.Logger;
026    import org.slf4j.LoggerFactory;
027    import org.sonar.api.CoreProperties;
028    import org.sonar.api.config.Settings;
029    import org.sonar.api.platform.ServerFileSystem;
030    import org.sonar.jpa.session.DatabaseConnector;
031    
032    import java.io.File;
033    import java.io.FileFilter;
034    import java.io.IOException;
035    import java.util.ArrayList;
036    import java.util.Collections;
037    import java.util.List;
038    
039    /**
040     * Introspect the filesystem and the classloader to get extension files at startup.
041     *
042     * @since 2.2
043     */
044    public class DefaultServerFileSystem implements ServerFileSystem {
045    
046      private static final Logger LOGGER = LoggerFactory.getLogger(DefaultServerFileSystem.class);
047    
048      private DatabaseConnector databaseConnector;
049      private File deployDir;
050      private File homeDir;
051    
052      public DefaultServerFileSystem(DatabaseConnector databaseConnector, Settings settings) {
053        this.databaseConnector = databaseConnector;
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(DatabaseConnector databaseConnector, File homeDir, File deployDir) {
066        this.databaseConnector = databaseConnector;
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 getDeployDir() {
107        return deployDir;
108      }
109    
110      public File getDeployedJdbcDriver() {
111        return new File(deployDir, "jdbc-driver.jar");
112      }
113    
114      public File getDeployedPluginsDir() {
115        return new File(deployDir, "plugins");
116      }
117    
118      public File getDownloadedPluginsDir() {
119        return new File(getHomeDir(), "extensions/downloads");
120      }
121    
122      public File getRemovedPluginsDir() {
123        return new File(getHomeDir(), "extensions/trash");
124      }
125    
126      public File getJdbcDriver() {
127        String dialect = databaseConnector.getDialect().getId();
128        File dir = new File(getHomeDir(), "/extensions/jdbc-driver/" + dialect + "/");
129        List<File> jars = getFiles(dir, "jar");
130        if (jars.isEmpty()) {
131          throw new ServerStartException("No JDBC driver found in " + dir.getAbsolutePath());
132        }
133        if (jars.size() > 1) {
134          throw new ServerStartException("The directory " + dir.getAbsolutePath() + " accepts only a single JAR file");
135        }
136        return jars.get(0);
137      }
138    
139      public List<File> getCorePlugins() {
140        File corePluginsDir = new File(getHomeDir(), "lib/core-plugins");
141        return getFiles(corePluginsDir, "jar");
142      }
143    
144      public List<File> getUserPlugins() {
145        File pluginsDir = getUserPluginsDir();
146        return getFiles(pluginsDir, "jar");
147      }
148    
149      public File getUserPluginsDir() {
150        return new File(getHomeDir(), "extensions/plugins");
151      }
152    
153      public File getDeprecatedPluginsDir() {
154        return new File(getHomeDir(), "extensions/deprecated");
155      }
156    
157    
158      public File getPluginIndex() {
159        return new File(getDeployDir(), "plugins/index.txt");
160      }
161    
162      public List<File> getExtensions(String dirName, String... suffixes) {
163        File dir = new File(getHomeDir(), "extensions/rules/" + dirName);
164        if (dir.exists() && dir.isDirectory()) {
165          return getFiles(dir, suffixes);
166        }
167        return Collections.emptyList();
168      }
169    
170      public List<File> getPluginExtensionXml(String pluginKey) {
171        File dir = new File(getHomeDir(), "extensions/rules/" + pluginKey);
172        if (dir.exists() && dir.isDirectory()) {
173          return getFiles(dir, "xml");
174        }
175        return Collections.emptyList();
176      }
177    
178      private List<File> getFiles(File dir, String... fileSuffixes) {
179        List<File> files = new ArrayList<File>();
180        if (dir != null && dir.exists()) {
181          if (fileSuffixes != null && fileSuffixes.length > 0) {
182            files.addAll(FileUtils.listFiles(dir, fileSuffixes, false));
183          } else {
184            files.addAll(FileUtils.listFiles(dir, null, false));
185          }
186        }
187        return files;
188      }
189    }