Skip to content

Commit

Permalink
SONAR-7899 Refactor server file system
Browse files Browse the repository at this point in the history
- new interface org.sonar.server.platform.ServerFileSystem
- deprecate org.sonar.api.platform.Server#getDeployDir()
  • Loading branch information
Simon Brandhof committed Jul 29, 2016
1 parent 13c05cb commit 7ce0fb3
Show file tree
Hide file tree
Showing 53 changed files with 414 additions and 244 deletions.
Expand Up @@ -21,7 +21,7 @@

import java.io.File;
import org.apache.commons.io.FileUtils;
import org.sonar.api.platform.ServerFileSystem;
import org.sonar.server.platform.ServerFileSystem;
import org.sonar.api.utils.ZipUtils;
import org.sonar.core.platform.ExplodedPlugin;
import org.sonar.core.platform.PluginInfo;
Expand Down
Expand Up @@ -33,7 +33,7 @@
import org.sonar.core.platform.PluginInfo;
import org.sonar.core.platform.PluginLoader;
import org.sonar.core.platform.PluginRepository;
import org.sonar.server.platform.DefaultServerFileSystem;
import org.sonar.server.platform.ServerFileSystem;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
Expand All @@ -48,15 +48,15 @@ public class CePluginRepository implements PluginRepository, Startable {
private static final String[] JAR_FILE_EXTENSIONS = new String[] {"jar"};
private static final String NOT_STARTED_YET = "not started yet";

private final DefaultServerFileSystem fs;
private final ServerFileSystem fs;
private final PluginLoader loader;
private final AtomicBoolean started = new AtomicBoolean(false);

// following fields are available after startup
private final Map<String, PluginInfo> pluginInfosByKeys = new HashMap<>();
private final Map<String, Plugin> pluginInstancesByKeys = new HashMap<>();

public CePluginRepository(DefaultServerFileSystem fs, PluginLoader loader) {
public CePluginRepository(ServerFileSystem fs, PluginLoader loader) {
this.fs = fs;
this.loader = loader;
}
Expand Down
Expand Up @@ -70,9 +70,9 @@
import org.sonar.server.component.ComponentFinder;
import org.sonar.server.component.ComponentService;
import org.sonar.server.computation.CeModule;
import org.sonar.server.computation.task.projectanalysis.ProjectAnalysisTaskModule;
import org.sonar.server.computation.CeQueueModule;
import org.sonar.server.computation.queue.PurgeCeActivities;
import org.sonar.server.computation.task.projectanalysis.ProjectAnalysisTaskModule;
import org.sonar.server.computation.taskprocessor.CeTaskProcessorModule;
import org.sonar.server.debt.DebtModelPluginRepository;
import org.sonar.server.debt.DebtRulesXMLImporter;
Expand All @@ -99,9 +99,9 @@
import org.sonar.server.notification.email.AlertsEmailTemplate;
import org.sonar.server.notification.email.EmailNotificationChannel;
import org.sonar.server.platform.DatabaseServerCompatibility;
import org.sonar.server.platform.DefaultServerFileSystem;
import org.sonar.server.platform.DefaultServerUpgradeStatus;
import org.sonar.server.platform.PersistentSettings;
import org.sonar.server.platform.ServerFileSystemImpl;
import org.sonar.server.platform.ServerImpl;
import org.sonar.server.platform.ServerLifecycleNotifier;
import org.sonar.server.platform.ServerLogging;
Expand Down Expand Up @@ -216,7 +216,7 @@ private static Object[] level1Components() {
DatabaseServerCompatibility.class,
DatabaseVersion.class,
PurgeProfiler.class,
DefaultServerFileSystem.class,
ServerFileSystemImpl.class,
// no TempFolderCleaner.class, responsibility of Web Server
new TempFolderProvider(),
System2.INSTANCE,
Expand Down
Expand Up @@ -24,7 +24,7 @@
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.platform.ServerFileSystem;
import org.sonar.server.platform.ServerFileSystem;
import org.sonar.core.platform.ExplodedPlugin;
import org.sonar.core.platform.PluginInfo;

Expand Down Expand Up @@ -97,6 +97,16 @@ public DumbFileSystem(TemporaryFolder temp) {
this.temp = temp;
}

@Override
public File getDataDir() {
throw new UnsupportedOperationException();
}

@Override
public File getDeployDir() {
throw new UnsupportedOperationException();
}

@Override
public File getHomeDir() {
throw new UnsupportedOperationException();
Expand All @@ -114,5 +124,30 @@ public File getTempDir() {
return tempDir;
}

@Override
public File getDeployedPluginsDir() {
throw new UnsupportedOperationException();
}

@Override
public File getDownloadedPluginsDir() {
throw new UnsupportedOperationException();
}

@Override
public File getInstalledPluginsDir() {
throw new UnsupportedOperationException();
}

@Override
public File getBundledPluginsDir() {
throw new UnsupportedOperationException();
}

@Override
public File getPluginIndex() {
throw new UnsupportedOperationException();
}

}
}
Expand Up @@ -32,7 +32,7 @@
import org.sonar.api.Plugin;
import org.sonar.core.platform.PluginInfo;
import org.sonar.core.platform.PluginLoader;
import org.sonar.server.platform.DefaultServerFileSystem;
import org.sonar.server.platform.ServerFileSystem;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
Expand All @@ -46,9 +46,9 @@ public class CePluginRepositoryTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();

DefaultServerFileSystem fs = mock(DefaultServerFileSystem.class, Mockito.RETURNS_DEEP_STUBS);
PluginLoader pluginLoader = new DumbPluginLoader();
CePluginRepository underTest = new CePluginRepository(fs, pluginLoader);
private ServerFileSystem fs = mock(ServerFileSystem.class, Mockito.RETURNS_DEEP_STUBS);
private PluginLoader pluginLoader = new DumbPluginLoader();
private CePluginRepository underTest = new CePluginRepository(fs, pluginLoader);

@After
public void tearDown() {
Expand Down
Expand Up @@ -30,27 +30,27 @@
import org.apache.commons.lang.CharUtils;
import org.apache.commons.lang.StringUtils;
import org.picocontainer.Startable;
import org.sonar.api.platform.Server;
import org.sonar.api.server.ServerSide;
import org.sonar.server.platform.ServerFileSystem;

/**
* JAR files to be downloaded by sonar-runner.
*/
@ServerSide
public class BatchIndex implements Startable {

private final Server server;
private final ServerFileSystem fs;
private String index;
private File batchDir;

public BatchIndex(Server server) {
this.server = server;
public BatchIndex(ServerFileSystem fs) {
this.fs = fs;
}

@Override
public void start() {
StringBuilder sb = new StringBuilder();
batchDir = new File(server.getRootDir(), "lib/batch");
batchDir = new File(fs.getHomeDir(), "lib/batch");
if (batchDir.exists()) {
Collection<File> files = FileUtils.listFiles(batchDir, HiddenFileFilter.VISIBLE, FileFilterUtils.directoryFileFilter());
for (File file : files) {
Expand Down
Expand Up @@ -26,9 +26,9 @@
import org.picocontainer.ComponentLifecycle;
import org.picocontainer.PicoContainer;
import org.picocontainer.injectors.ProviderAdapter;
import org.sonar.api.platform.ServerFileSystem;
import org.sonar.api.utils.TempFolder;
import org.sonar.api.utils.internal.DefaultTempFolder;
import org.sonar.server.platform.ServerFileSystem;

/**
* Provides a TempFolder instance pointing to a directory dedicated to the processing of a specific item.
Expand Down
@@ -0,0 +1,87 @@
/*
* SonarQube
* Copyright (C) 2009-2016 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.server.platform;

import java.io.File;

/**
* Replaces the incomplete {@link org.sonar.api.platform.ServerFileSystem} as many directories can't be
* published in API.
*
* @since 6.0
*/
public interface ServerFileSystem {

/**
* Directory that contains the persisted data to be kept on restarts and upgrades.
* @return an existing directory
*/
File getDataDir();

/**
* Directory accessible by scanners through web server
* @return a non-null directory that MAY exist
*/
File getDeployDir();

/**
* Root directory of the server installation
* @return an existing directory
*/
File getHomeDir();

/**
* Temporary directory, clean up on restarts
* @return an existing directory
*/
File getTempDir();

/**
* Files of plugins published by web server for scanners
* @return a non-null directory that MAY exist
*/
File getDeployedPluginsDir();

/**
* Directory of plugins downloaded through update center. Files
* will be moved to {@link #getInstalledPluginsDir()} on startup.
* @return an existing directory
*/
File getDownloadedPluginsDir();

/**
* Directory of currently installed plugins. Used at startup.
* @return an existing directory
*/
File getInstalledPluginsDir();

/**
* Directory of the plugins packaged by default with application. These
* plugins are installed during the first fresh startup.
* @return an existing directory
*/
File getBundledPluginsDir();

/**
* The file listing all the installed plugins. Used by scanner only.
* @return an existing file
*/
File getPluginIndex();
}
Expand Up @@ -20,61 +20,34 @@
package org.sonar.server.platform;

import java.io.File;
import java.io.IOException;
import javax.annotation.CheckForNull;
import org.apache.commons.io.FileUtils;
import org.picocontainer.Startable;
import org.sonar.api.config.Settings;
import org.sonar.api.platform.Server;
import org.sonar.api.platform.ServerFileSystem;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.process.ProcessProperties;
import org.sonar.server.app.TomcatContexts;

/**
* Introspect the filesystem and the classloader to get extension files at startup.
*
* @since 2.2
*/
public class DefaultServerFileSystem implements ServerFileSystem, Startable {
import static java.util.Objects.requireNonNull;

public class ServerFileSystemImpl implements ServerFileSystem, org.sonar.api.platform.ServerFileSystem, Startable {

private static final Logger LOGGER = Loggers.get(DefaultServerFileSystem.class);
private static final Logger LOGGER = Loggers.get(ServerFileSystemImpl.class);

private final Server server;
private final File homeDir;
private final File tempDir;

public DefaultServerFileSystem(Settings settings, Server server) {
this.server = server;
this.homeDir = new File(settings.getString(ProcessProperties.PATH_HOME));
this.tempDir = new File(settings.getString(ProcessProperties.PATH_TEMP));
}

/**
* for unit tests
*/
public DefaultServerFileSystem(File homeDir, File tempDir, Server server) {
this.homeDir = homeDir;
this.tempDir = tempDir;
this.server = server;
private final File dataDir;
private final File deployDir;

public ServerFileSystemImpl(Settings settings) {
this.homeDir = new File(requireNonNull(settings.getString(ProcessProperties.PATH_HOME)));
this.tempDir = new File(requireNonNull(settings.getString(ProcessProperties.PATH_TEMP)));
this.dataDir = new File(requireNonNull(settings.getString(ProcessProperties.PATH_DATA)));
this.deployDir = new File(this.dataDir, TomcatContexts.WEB_DEPLOY_PATH_RELATIVE_TO_DATA_DIR);
}

@Override
public void start() {
LOGGER.info("SonarQube home: " + homeDir.getAbsolutePath());

File deployDir = getDeployDir();
if (deployDir == null) {
throw new IllegalArgumentException("Web app directory does not exist");
}

File deprecated = getDeprecatedPluginsDir();
try {
FileUtils.forceMkdir(deprecated);
org.sonar.core.util.FileUtils.cleanDirectory(deprecated);
} catch (IOException e) {
throw new IllegalStateException("The following directory can not be created: " + deprecated.getAbsolutePath(), e);
}
}

@Override
Expand All @@ -92,31 +65,37 @@ public File getTempDir() {
return tempDir;
}

@CheckForNull
@Override
public File getDataDir() {
return dataDir;
}

@Override
public File getDeployDir() {
return server.getDeployDir();
return deployDir;
}

@Override
public File getDeployedPluginsDir() {
return new File(getDeployDir(), "plugins");
}

@Override
public File getDownloadedPluginsDir() {
return new File(getHomeDir(), "extensions/downloads");
}

@Override
public File getInstalledPluginsDir() {
return new File(getHomeDir(), "extensions/plugins");
}

@Override
public File getBundledPluginsDir() {
return new File(getHomeDir(), "lib/bundled-plugins");
}

public File getDeprecatedPluginsDir() {
return new File(getHomeDir(), "extensions/deprecated");
}

@Override
public File getPluginIndex() {
return new File(getDeployDir(), "plugins/index.txt");
}
Expand Down

0 comments on commit 7ce0fb3

Please sign in to comment.