From: Sébastien Lesaint Date: Fri, 22 Jun 2018 14:31:50 +0000 (+0200) Subject: move some classes from sonar-server to sonar-server-common X-Git-Tag: 7.5~924 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=1653051ae4b32591b04691cb4c22bcb75d4a404c;p=sonarqube.git move some classes from sonar-server to sonar-server-common --- diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/platform/ServerFileSystem.java b/server/sonar-server-common/src/main/java/org/sonar/server/platform/ServerFileSystem.java new file mode 100644 index 00000000000..983d2639308 --- /dev/null +++ b/server/sonar-server-common/src/main/java/org/sonar/server/platform/ServerFileSystem.java @@ -0,0 +1,75 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info 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. + */ +public interface ServerFileSystem { + + /** + * 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 directory which may or not exist + */ + File getDeployedPluginsDir(); + + /** + * Directory of plugins downloaded through update center. Files + * will be moved to {@link #getInstalledPluginsDir()} on startup. + * @return a directory which may or not exist + */ + File getDownloadedPluginsDir(); + + /** + * Directory of currently installed plugins. Used at startup. + * @return a directory which may or not exist + */ + File getInstalledPluginsDir(); + + /** + * The file listing all the installed plugins. Used by scanner only. + * @return an existing file + * @deprecated see {@link org.sonar.server.startup.GeneratePluginIndex} + */ + @Deprecated + File getPluginIndex(); + + /** + * Directory where plugins to be uninstalled are moved to. + * @return a directory which may or not exist + */ + File getUninstalledPluginsDir(); + +} diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/platform/ServerFileSystemImpl.java b/server/sonar-server-common/src/main/java/org/sonar/server/platform/ServerFileSystemImpl.java new file mode 100644 index 00000000000..9818d98584f --- /dev/null +++ b/server/sonar-server-common/src/main/java/org/sonar/server/platform/ServerFileSystemImpl.java @@ -0,0 +1,94 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info 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; +import org.picocontainer.Startable; +import org.sonar.api.config.Configuration; +import org.sonar.api.utils.log.Logger; +import org.sonar.api.utils.log.Loggers; + +import static org.sonar.process.ProcessProperties.Property.PATH_DATA; +import static org.sonar.process.ProcessProperties.Property.PATH_HOME; +import static org.sonar.process.ProcessProperties.Property.PATH_TEMP; + +public class ServerFileSystemImpl implements ServerFileSystem, org.sonar.api.platform.ServerFileSystem, Startable { + + private static final Logger LOGGER = Loggers.get(ServerFileSystemImpl.class); + + private final File homeDir; + private final File tempDir; + private final File deployDir; + private final File uninstallDir; + + public ServerFileSystemImpl(Configuration config) { + this.homeDir = new File(config.get(PATH_HOME.getKey()).get()); + this.tempDir = new File(config.get(PATH_TEMP.getKey()).get()); + File dataDir = new File(config.get(PATH_DATA.getKey()).get()); + this.deployDir = new File(dataDir, "web/deploy"); + this.uninstallDir = new File(getTempDir(), "uninstalled-plugins"); + } + + @Override + public void start() { + LOGGER.info("SonarQube home: " + homeDir.getAbsolutePath()); + } + + @Override + public void stop() { + // do nothing + } + + @Override + public File getHomeDir() { + return homeDir; + } + + @Override + public File getTempDir() { + return tempDir; + } + + @Override + public File getDeployedPluginsDir() { + return new File(deployDir, "plugins"); + } + + @Override + public File getDownloadedPluginsDir() { + return new File(getHomeDir(), "extensions/downloads"); + } + + @Override + public File getInstalledPluginsDir() { + return new File(getHomeDir(), "extensions/plugins"); + } + + @Override + public File getPluginIndex() { + return new File(deployDir, "plugins/index.txt"); + } + + @Override + public File getUninstalledPluginsDir() { + return uninstallDir; + } + +} diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/platform/package-info.java b/server/sonar-server-common/src/main/java/org/sonar/server/platform/package-info.java new file mode 100644 index 00000000000..1b2de9bebab --- /dev/null +++ b/server/sonar-server-common/src/main/java/org/sonar/server/platform/package-info.java @@ -0,0 +1,23 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info 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. + */ +@ParametersAreNonnullByDefault +package org.sonar.server.platform; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/user/UserSession.java b/server/sonar-server-common/src/main/java/org/sonar/server/user/UserSession.java new file mode 100644 index 00000000000..4eca7b6b46c --- /dev/null +++ b/server/sonar-server-common/src/main/java/org/sonar/server/user/UserSession.java @@ -0,0 +1,176 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info 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.user; + +import java.util.Collection; +import java.util.List; +import javax.annotation.CheckForNull; +import org.sonar.db.component.ComponentDto; +import org.sonar.db.organization.OrganizationDto; +import org.sonar.db.permission.OrganizationPermission; +import org.sonar.db.user.GroupDto; + +public interface UserSession { + + /** + * Login of the authenticated user. Returns {@code null} + * if {@link #isLoggedIn()} is {@code false}. + */ + @CheckForNull + String getLogin(); + + /** + * Uuid of the authenticated user. Returns {@code null} + * if {@link #isLoggedIn()} is {@code false}. + */ + @CheckForNull + String getUuid(); + + /** + * Name of the authenticated user. Returns {@code null} + * if {@link #isLoggedIn()} is {@code false}. + */ + @CheckForNull + String getName(); + + /** + * Database ID of the authenticated user. Returns {@code null} + * if {@link #isLoggedIn()} is {@code false}. + */ + @CheckForNull + Integer getUserId(); + + /** + * The groups that the logged-in user is member of. An empty + * collection is returned if {@link #isLoggedIn()} is {@code false}. + */ + Collection getGroups(); + + /** + * Whether the user is logged-in or anonymous. + */ + boolean isLoggedIn(); + + /** + * Whether the user has root privileges. If {@code true}, then user automatically + * benefits from all the permissions on all organizations and projects. + */ + boolean isRoot(); + + /** + * Ensures that {@link #isRoot()} returns {@code true} otherwise throws a + * {@link org.sonar.server.exceptions.ForbiddenException}. + */ + UserSession checkIsRoot(); + + /** + * Ensures that user is logged in otherwise throws {@link org.sonar.server.exceptions.UnauthorizedException}. + */ + UserSession checkLoggedIn(); + + /** + * Returns {@code true} if the permission is granted on the organization, otherwise {@code false}. + * + * If the organization does not exist, then returns {@code false}. + * + * Always returns {@code true} if {@link #isRoot()} is {@code true}, even if + * organization does not exist. + */ + boolean hasPermission(OrganizationPermission permission, OrganizationDto organization); + + boolean hasPermission(OrganizationPermission permission, String organizationUuid); + + /** + * Ensures that {@link #hasPermission(OrganizationPermission, OrganizationDto)} is {@code true}, + * otherwise throws a {@link org.sonar.server.exceptions.ForbiddenException}. + */ + UserSession checkPermission(OrganizationPermission permission, OrganizationDto organization); + + UserSession checkPermission(OrganizationPermission permission, String organizationUuid); + + /** + * Returns {@code true} if the permission is granted to user on the component, + * otherwise {@code false}. + * + * If the component does not exist, then returns {@code false}. + * + * Always returns {@code true} if {@link #isRoot()} is {@code true}, even if + * component does not exist. + * + * If the permission is not granted, then the organization permission is _not_ checked. + * + * @param component non-null component. + * @param permission project permission as defined by {@link org.sonar.core.permission.ProjectPermissions} + */ + boolean hasComponentPermission(String permission, ComponentDto component); + + /** + * Using {@link #hasComponentPermission(String, ComponentDto)} is recommended + * because it does not have to load project if the referenced component + * is not a project. + * + * @deprecated use {@link #hasComponentPermission(String, ComponentDto)} instead + */ + @Deprecated + boolean hasComponentUuidPermission(String permission, String componentUuid); + + /** + * Return the subset of specified components which the user has granted permission. + * An empty list is returned if input is empty or if no components are allowed to be + * accessed. + * If the input is ordered, then the returned components are in the same order. + * The duplicated components are returned duplicated too. + */ + List keepAuthorizedComponents(String permission, Collection components); + + /** + * Ensures that {@link #hasComponentPermission(String, ComponentDto)} is {@code true}, + * otherwise throws a {@link org.sonar.server.exceptions.ForbiddenException}. + */ + UserSession checkComponentPermission(String projectPermission, ComponentDto component); + + /** + * Ensures that {@link #hasComponentUuidPermission(String, String)} is {@code true}, + * otherwise throws a {@link org.sonar.server.exceptions.ForbiddenException}. + * + * @deprecated use {@link #checkComponentPermission(String, ComponentDto)} instead + */ + @Deprecated + UserSession checkComponentUuidPermission(String permission, String componentUuid); + + /** + * Whether user can administrate system, for example for using cross-organizations services + * like update center, system info or management of users. + * + * Returns {@code true} if: + *
    + *
  • {@link #isRoot()} is {@code true}
  • + *
  • organization feature is disabled and user is administrator of the (single) default organization
  • + *
+ */ + boolean isSystemAdministrator(); + + /** + * Ensures that {@link #isSystemAdministrator()} is {@code true}, + * otherwise throws {@link org.sonar.server.exceptions.ForbiddenException}. + */ + UserSession checkIsSystemAdministrator(); + +} diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/user/package-info.java b/server/sonar-server-common/src/main/java/org/sonar/server/user/package-info.java new file mode 100644 index 00000000000..63c7ca1e1fb --- /dev/null +++ b/server/sonar-server-common/src/main/java/org/sonar/server/user/package-info.java @@ -0,0 +1,23 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info 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. + */ +@ParametersAreNonnullByDefault +package org.sonar.server.user; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/util/AbstractStoppableExecutorService.java b/server/sonar-server-common/src/main/java/org/sonar/server/util/AbstractStoppableExecutorService.java new file mode 100644 index 00000000000..fb83b4f194b --- /dev/null +++ b/server/sonar-server-common/src/main/java/org/sonar/server/util/AbstractStoppableExecutorService.java @@ -0,0 +1,135 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info 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.util; + +import org.sonar.api.utils.log.Loggers; + +import java.util.Collection; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import static java.lang.String.format; + +/** + * Abstract implementation of StoppableExecutorService that implements the + * stop() method and delegates all methods to the provided ExecutorService instance. + */ +public abstract class AbstractStoppableExecutorService implements StoppableExecutorService { + protected final D delegate; + + public AbstractStoppableExecutorService(D delegate) { + this.delegate = delegate; + } + + @Override + public void stop() { + // Disable new tasks from being submitted + delegate.shutdown(); + try { + // Wait a while for existing tasks to terminate + if (!delegate.awaitTermination(5, TimeUnit.SECONDS)) { + // Cancel currently executing tasks + delegate.shutdownNow(); + // Wait a while for tasks to respond to being canceled + if (!delegate.awaitTermination(5, TimeUnit.SECONDS)) { + Loggers.get(getClass()).warn(format("Pool %s did not terminate", getClass().getSimpleName())); + } + } + } catch (InterruptedException ie) { + Loggers.get(getClass()).warn(format("Termination of pool %s failed", getClass().getSimpleName()), ie); + // (Re-)Cancel if current thread also interrupted + delegate.shutdownNow(); + } + } + + @Override + public void shutdown() { + delegate.shutdown(); + } + + @Override + public List shutdownNow() { + return delegate.shutdownNow(); + } + + @Override + public boolean isShutdown() { + return delegate.isShutdown(); + } + + @Override + public boolean isTerminated() { + return delegate.isTerminated(); + } + + @Override + public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { + return delegate.awaitTermination(timeout, unit); + } + + @Override + public Future submit(Callable task) { + return delegate.submit(task); + } + + @Override + public Future submit(Runnable task, T result) { + return delegate.submit(task, result); + } + + @Override + public Future submit(Runnable task) { + return delegate.submit(task); + } + + @Override + public List> invokeAll(Collection> tasks) throws InterruptedException { + return delegate.invokeAll(tasks); + } + + @Override + public List> invokeAll(Collection> tasks, + long timeout, + TimeUnit unit) throws InterruptedException { + return delegate.invokeAll(tasks, timeout, unit); + } + + @Override + public T invokeAny(Collection> tasks) throws InterruptedException, ExecutionException { + return delegate.invokeAny(tasks); + } + + @Override + public T invokeAny(Collection> tasks, + long timeout, + TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { + return delegate.invokeAny(tasks, timeout, unit); + } + + @Override + public void execute(Runnable command) { + delegate.execute(command); + } +} diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/util/AbstractStoppableScheduledExecutorServiceImpl.java b/server/sonar-server-common/src/main/java/org/sonar/server/util/AbstractStoppableScheduledExecutorServiceImpl.java new file mode 100644 index 00000000000..4bb4dd996c3 --- /dev/null +++ b/server/sonar-server-common/src/main/java/org/sonar/server/util/AbstractStoppableScheduledExecutorServiceImpl.java @@ -0,0 +1,52 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info 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.util; + +import java.util.concurrent.Callable; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +public class AbstractStoppableScheduledExecutorServiceImpl extends AbstractStoppableExecutorService + implements StoppableScheduledExecutorService { + public AbstractStoppableScheduledExecutorServiceImpl(T delegate) { + super(delegate); + } + + @Override + public ScheduledFuture schedule(Runnable command, long delay, TimeUnit unit) { + return delegate.schedule(command, delay, unit); + } + + @Override + public ScheduledFuture schedule(Callable callable, long delay, TimeUnit unit) { + return delegate.schedule(callable, delay, unit); + } + + @Override + public ScheduledFuture scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) { + return delegate.scheduleAtFixedRate(command, initialDelay, period, unit); + } + + @Override + public ScheduledFuture scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) { + return delegate.scheduleWithFixedDelay(command, initialDelay, delay, unit); + } +} diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/util/StoppableExecutorService.java b/server/sonar-server-common/src/main/java/org/sonar/server/util/StoppableExecutorService.java new file mode 100644 index 00000000000..d432d1195c1 --- /dev/null +++ b/server/sonar-server-common/src/main/java/org/sonar/server/util/StoppableExecutorService.java @@ -0,0 +1,34 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info 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.util; + +import java.util.concurrent.ExecutorService; + +/** + * ExecutorService that exposes a {@code stop} method which can be invoked by Pico container to shutdown properly + * the service. + */ +public interface StoppableExecutorService extends ExecutorService { + + /** + * Stops the ExecutorService nicely (ie. first let a little time for jobs to end and then abort them) + */ + void stop(); +} diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/util/StoppableScheduledExecutorService.java b/server/sonar-server-common/src/main/java/org/sonar/server/util/StoppableScheduledExecutorService.java new file mode 100644 index 00000000000..2bf77f69857 --- /dev/null +++ b/server/sonar-server-common/src/main/java/org/sonar/server/util/StoppableScheduledExecutorService.java @@ -0,0 +1,30 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info 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.util; + +import java.util.concurrent.ScheduledExecutorService; + +/** + * ScheduledExecutorService that exposes a {@code stop} method which can be invoked by Pico container to shutdown + * properly the service. + */ +public interface StoppableScheduledExecutorService extends ScheduledExecutorService, StoppableExecutorService { + +} diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/util/package-info.java b/server/sonar-server-common/src/main/java/org/sonar/server/util/package-info.java new file mode 100644 index 00000000000..43e6865562f --- /dev/null +++ b/server/sonar-server-common/src/main/java/org/sonar/server/util/package-info.java @@ -0,0 +1,23 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info 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. + */ +@ParametersAreNonnullByDefault +package org.sonar.server.util; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/util/AbstractStoppableExecutorServiceTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/util/AbstractStoppableExecutorServiceTest.java new file mode 100644 index 00000000000..6fa78b273eb --- /dev/null +++ b/server/sonar-server-common/src/test/java/org/sonar/server/util/AbstractStoppableExecutorServiceTest.java @@ -0,0 +1,200 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info 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.util; + +import com.google.common.collect.ImmutableList; +import org.junit.Test; +import org.mockito.InOrder; +import org.mockito.Mockito; + +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class AbstractStoppableExecutorServiceTest { + private static final Callable SOME_CALLABLE = new Callable() { + @Override + public String call() { + return null; + } + }; + private static final Runnable SOME_RUNNABLE = new Runnable() { + @Override + public void run() { + + } + }; + private static final String SOME_STRING = "some string"; + private static final long SOME_LONG = 100l; + private static final int TIMEOUT = 5; + private static final TimeUnit TIMEOUT_UNIT = TimeUnit.SECONDS; + + private ExecutorService executorService = mock(ExecutorService.class); + private InOrder inOrder = Mockito.inOrder(executorService); + private AbstractStoppableExecutorService underTest = new AbstractStoppableExecutorService(executorService) { + }; + public static final ImmutableList> CALLABLES = ImmutableList.of(SOME_CALLABLE); + + @Test + public void stop_calls_shutdown_and_verify_termination() throws InterruptedException { + when(executorService.awaitTermination(TIMEOUT, TIMEOUT_UNIT)).thenReturn(true); + + underTest.stop(); + + inOrder.verify(executorService).shutdown(); + inOrder.verify(executorService).awaitTermination(TIMEOUT, TIMEOUT_UNIT); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void stop_calls_shutdown_then_shutdownNow_if_not_terminated_and_check_termination_again() throws InterruptedException { + when(executorService.awaitTermination(TIMEOUT, TIMEOUT_UNIT)).thenReturn(false).thenReturn(true); + + underTest.stop(); + + inOrder.verify(executorService).shutdown(); + inOrder.verify(executorService).awaitTermination(TIMEOUT, TIMEOUT_UNIT); + inOrder.verify(executorService).shutdownNow(); + inOrder.verify(executorService).awaitTermination(TIMEOUT, TIMEOUT_UNIT); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void stop_calls_shutdownnow_if_interrupted_exception_is_raised() throws InterruptedException { + when(executorService.awaitTermination(TIMEOUT, TIMEOUT_UNIT)).thenThrow(new InterruptedException()); + + underTest.stop(); + + inOrder.verify(executorService).shutdown(); + inOrder.verify(executorService).awaitTermination(TIMEOUT, TIMEOUT_UNIT); + inOrder.verify(executorService).shutdownNow(); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void shutdown_delegates_to_executorService() { + underTest.shutdown(); + + inOrder.verify(executorService).shutdown(); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void shutdownNow_delegates_to_executorService() { + underTest.shutdownNow(); + + inOrder.verify(executorService).shutdownNow(); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void isShutdown_delegates_to_executorService() { + underTest.isShutdown(); + + inOrder.verify(executorService).isShutdown(); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void isTerminated_delegates_to_executorService() { + underTest.isTerminated(); + + inOrder.verify(executorService).isTerminated(); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void awaitTermination_delegates_to_executorService() throws InterruptedException { + underTest.awaitTermination(SOME_LONG, SECONDS); + + inOrder.verify(executorService).awaitTermination(SOME_LONG, SECONDS); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void submit_callable_delegates_to_executorService() { + underTest.submit(SOME_CALLABLE); + + inOrder.verify(executorService).submit(SOME_CALLABLE); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void submit_runnable_delegates_to_executorService() { + underTest.submit(SOME_RUNNABLE); + + inOrder.verify(executorService).submit(SOME_RUNNABLE); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void submit_runnable_with_result_delegates_to_executorService() { + underTest.submit(SOME_RUNNABLE, SOME_STRING); + + inOrder.verify(executorService).submit(SOME_RUNNABLE, SOME_STRING); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void invokeAll_delegates_to_executorService() throws InterruptedException { + underTest.invokeAll(CALLABLES); + + inOrder.verify(executorService).invokeAll(CALLABLES); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void invokeAll1_delegates_to_executorService() throws InterruptedException { + underTest.invokeAll(CALLABLES, SOME_LONG, SECONDS); + + inOrder.verify(executorService).invokeAll(CALLABLES, SOME_LONG, SECONDS); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void invokeAny_delegates_to_executorService() throws ExecutionException, InterruptedException { + underTest.invokeAny(CALLABLES); + + inOrder.verify(executorService).invokeAny(CALLABLES); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void invokeAny1_delegates_to_executorService() throws InterruptedException, ExecutionException, TimeoutException { + underTest.invokeAny(CALLABLES, SOME_LONG, SECONDS); + + inOrder.verify(executorService).invokeAny(CALLABLES, SOME_LONG, SECONDS); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void execute_delegates_to_executorService() { + underTest.execute(SOME_RUNNABLE); + + inOrder.verify(executorService).execute(SOME_RUNNABLE); + inOrder.verifyNoMoreInteractions(); + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerFileSystem.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerFileSystem.java deleted file mode 100644 index 983d2639308..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerFileSystem.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info 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. - */ -public interface ServerFileSystem { - - /** - * 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 directory which may or not exist - */ - File getDeployedPluginsDir(); - - /** - * Directory of plugins downloaded through update center. Files - * will be moved to {@link #getInstalledPluginsDir()} on startup. - * @return a directory which may or not exist - */ - File getDownloadedPluginsDir(); - - /** - * Directory of currently installed plugins. Used at startup. - * @return a directory which may or not exist - */ - File getInstalledPluginsDir(); - - /** - * The file listing all the installed plugins. Used by scanner only. - * @return an existing file - * @deprecated see {@link org.sonar.server.startup.GeneratePluginIndex} - */ - @Deprecated - File getPluginIndex(); - - /** - * Directory where plugins to be uninstalled are moved to. - * @return a directory which may or not exist - */ - File getUninstalledPluginsDir(); - -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerFileSystemImpl.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerFileSystemImpl.java deleted file mode 100644 index 34fe69c7e87..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerFileSystemImpl.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info 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; -import org.picocontainer.Startable; -import org.sonar.api.config.Configuration; -import org.sonar.api.utils.log.Logger; -import org.sonar.api.utils.log.Loggers; -import org.sonar.server.app.TomcatContexts; - -import static org.sonar.process.ProcessProperties.Property.PATH_DATA; -import static org.sonar.process.ProcessProperties.Property.PATH_HOME; -import static org.sonar.process.ProcessProperties.Property.PATH_TEMP; - -public class ServerFileSystemImpl implements ServerFileSystem, org.sonar.api.platform.ServerFileSystem, Startable { - - private static final Logger LOGGER = Loggers.get(ServerFileSystemImpl.class); - - private final File homeDir; - private final File tempDir; - private final File deployDir; - private final File uninstallDir; - - public ServerFileSystemImpl(Configuration config) { - this.homeDir = new File(config.get(PATH_HOME.getKey()).get()); - this.tempDir = new File(config.get(PATH_TEMP.getKey()).get()); - File dataDir = new File(config.get(PATH_DATA.getKey()).get()); - this.deployDir = new File(dataDir, TomcatContexts.WEB_DEPLOY_PATH_RELATIVE_TO_DATA_DIR); - this.uninstallDir = new File(getTempDir(), "uninstalled-plugins"); - } - - @Override - public void start() { - LOGGER.info("SonarQube home: " + homeDir.getAbsolutePath()); - } - - @Override - public void stop() { - // do nothing - } - - @Override - public File getHomeDir() { - return homeDir; - } - - @Override - public File getTempDir() { - return tempDir; - } - - @Override - public File getDeployedPluginsDir() { - return new File(deployDir, "plugins"); - } - - @Override - public File getDownloadedPluginsDir() { - return new File(getHomeDir(), "extensions/downloads"); - } - - @Override - public File getInstalledPluginsDir() { - return new File(getHomeDir(), "extensions/plugins"); - } - - @Override - public File getPluginIndex() { - return new File(deployDir, "plugins/index.txt"); - } - - @Override - public File getUninstalledPluginsDir() { - return uninstallDir; - } - -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/UserSession.java b/server/sonar-server/src/main/java/org/sonar/server/user/UserSession.java deleted file mode 100644 index 4eca7b6b46c..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/user/UserSession.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info 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.user; - -import java.util.Collection; -import java.util.List; -import javax.annotation.CheckForNull; -import org.sonar.db.component.ComponentDto; -import org.sonar.db.organization.OrganizationDto; -import org.sonar.db.permission.OrganizationPermission; -import org.sonar.db.user.GroupDto; - -public interface UserSession { - - /** - * Login of the authenticated user. Returns {@code null} - * if {@link #isLoggedIn()} is {@code false}. - */ - @CheckForNull - String getLogin(); - - /** - * Uuid of the authenticated user. Returns {@code null} - * if {@link #isLoggedIn()} is {@code false}. - */ - @CheckForNull - String getUuid(); - - /** - * Name of the authenticated user. Returns {@code null} - * if {@link #isLoggedIn()} is {@code false}. - */ - @CheckForNull - String getName(); - - /** - * Database ID of the authenticated user. Returns {@code null} - * if {@link #isLoggedIn()} is {@code false}. - */ - @CheckForNull - Integer getUserId(); - - /** - * The groups that the logged-in user is member of. An empty - * collection is returned if {@link #isLoggedIn()} is {@code false}. - */ - Collection getGroups(); - - /** - * Whether the user is logged-in or anonymous. - */ - boolean isLoggedIn(); - - /** - * Whether the user has root privileges. If {@code true}, then user automatically - * benefits from all the permissions on all organizations and projects. - */ - boolean isRoot(); - - /** - * Ensures that {@link #isRoot()} returns {@code true} otherwise throws a - * {@link org.sonar.server.exceptions.ForbiddenException}. - */ - UserSession checkIsRoot(); - - /** - * Ensures that user is logged in otherwise throws {@link org.sonar.server.exceptions.UnauthorizedException}. - */ - UserSession checkLoggedIn(); - - /** - * Returns {@code true} if the permission is granted on the organization, otherwise {@code false}. - * - * If the organization does not exist, then returns {@code false}. - * - * Always returns {@code true} if {@link #isRoot()} is {@code true}, even if - * organization does not exist. - */ - boolean hasPermission(OrganizationPermission permission, OrganizationDto organization); - - boolean hasPermission(OrganizationPermission permission, String organizationUuid); - - /** - * Ensures that {@link #hasPermission(OrganizationPermission, OrganizationDto)} is {@code true}, - * otherwise throws a {@link org.sonar.server.exceptions.ForbiddenException}. - */ - UserSession checkPermission(OrganizationPermission permission, OrganizationDto organization); - - UserSession checkPermission(OrganizationPermission permission, String organizationUuid); - - /** - * Returns {@code true} if the permission is granted to user on the component, - * otherwise {@code false}. - * - * If the component does not exist, then returns {@code false}. - * - * Always returns {@code true} if {@link #isRoot()} is {@code true}, even if - * component does not exist. - * - * If the permission is not granted, then the organization permission is _not_ checked. - * - * @param component non-null component. - * @param permission project permission as defined by {@link org.sonar.core.permission.ProjectPermissions} - */ - boolean hasComponentPermission(String permission, ComponentDto component); - - /** - * Using {@link #hasComponentPermission(String, ComponentDto)} is recommended - * because it does not have to load project if the referenced component - * is not a project. - * - * @deprecated use {@link #hasComponentPermission(String, ComponentDto)} instead - */ - @Deprecated - boolean hasComponentUuidPermission(String permission, String componentUuid); - - /** - * Return the subset of specified components which the user has granted permission. - * An empty list is returned if input is empty or if no components are allowed to be - * accessed. - * If the input is ordered, then the returned components are in the same order. - * The duplicated components are returned duplicated too. - */ - List keepAuthorizedComponents(String permission, Collection components); - - /** - * Ensures that {@link #hasComponentPermission(String, ComponentDto)} is {@code true}, - * otherwise throws a {@link org.sonar.server.exceptions.ForbiddenException}. - */ - UserSession checkComponentPermission(String projectPermission, ComponentDto component); - - /** - * Ensures that {@link #hasComponentUuidPermission(String, String)} is {@code true}, - * otherwise throws a {@link org.sonar.server.exceptions.ForbiddenException}. - * - * @deprecated use {@link #checkComponentPermission(String, ComponentDto)} instead - */ - @Deprecated - UserSession checkComponentUuidPermission(String permission, String componentUuid); - - /** - * Whether user can administrate system, for example for using cross-organizations services - * like update center, system info or management of users. - * - * Returns {@code true} if: - *
    - *
  • {@link #isRoot()} is {@code true}
  • - *
  • organization feature is disabled and user is administrator of the (single) default organization
  • - *
- */ - boolean isSystemAdministrator(); - - /** - * Ensures that {@link #isSystemAdministrator()} is {@code true}, - * otherwise throws {@link org.sonar.server.exceptions.ForbiddenException}. - */ - UserSession checkIsSystemAdministrator(); - -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/util/AbstractStoppableExecutorService.java b/server/sonar-server/src/main/java/org/sonar/server/util/AbstractStoppableExecutorService.java deleted file mode 100644 index fb83b4f194b..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/util/AbstractStoppableExecutorService.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info 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.util; - -import org.sonar.api.utils.log.Loggers; - -import java.util.Collection; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import static java.lang.String.format; - -/** - * Abstract implementation of StoppableExecutorService that implements the - * stop() method and delegates all methods to the provided ExecutorService instance. - */ -public abstract class AbstractStoppableExecutorService implements StoppableExecutorService { - protected final D delegate; - - public AbstractStoppableExecutorService(D delegate) { - this.delegate = delegate; - } - - @Override - public void stop() { - // Disable new tasks from being submitted - delegate.shutdown(); - try { - // Wait a while for existing tasks to terminate - if (!delegate.awaitTermination(5, TimeUnit.SECONDS)) { - // Cancel currently executing tasks - delegate.shutdownNow(); - // Wait a while for tasks to respond to being canceled - if (!delegate.awaitTermination(5, TimeUnit.SECONDS)) { - Loggers.get(getClass()).warn(format("Pool %s did not terminate", getClass().getSimpleName())); - } - } - } catch (InterruptedException ie) { - Loggers.get(getClass()).warn(format("Termination of pool %s failed", getClass().getSimpleName()), ie); - // (Re-)Cancel if current thread also interrupted - delegate.shutdownNow(); - } - } - - @Override - public void shutdown() { - delegate.shutdown(); - } - - @Override - public List shutdownNow() { - return delegate.shutdownNow(); - } - - @Override - public boolean isShutdown() { - return delegate.isShutdown(); - } - - @Override - public boolean isTerminated() { - return delegate.isTerminated(); - } - - @Override - public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { - return delegate.awaitTermination(timeout, unit); - } - - @Override - public Future submit(Callable task) { - return delegate.submit(task); - } - - @Override - public Future submit(Runnable task, T result) { - return delegate.submit(task, result); - } - - @Override - public Future submit(Runnable task) { - return delegate.submit(task); - } - - @Override - public List> invokeAll(Collection> tasks) throws InterruptedException { - return delegate.invokeAll(tasks); - } - - @Override - public List> invokeAll(Collection> tasks, - long timeout, - TimeUnit unit) throws InterruptedException { - return delegate.invokeAll(tasks, timeout, unit); - } - - @Override - public T invokeAny(Collection> tasks) throws InterruptedException, ExecutionException { - return delegate.invokeAny(tasks); - } - - @Override - public T invokeAny(Collection> tasks, - long timeout, - TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { - return delegate.invokeAny(tasks, timeout, unit); - } - - @Override - public void execute(Runnable command) { - delegate.execute(command); - } -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/util/AbstractStoppableScheduledExecutorServiceImpl.java b/server/sonar-server/src/main/java/org/sonar/server/util/AbstractStoppableScheduledExecutorServiceImpl.java deleted file mode 100644 index 4bb4dd996c3..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/util/AbstractStoppableScheduledExecutorServiceImpl.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info 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.util; - -import java.util.concurrent.Callable; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; - -public class AbstractStoppableScheduledExecutorServiceImpl extends AbstractStoppableExecutorService - implements StoppableScheduledExecutorService { - public AbstractStoppableScheduledExecutorServiceImpl(T delegate) { - super(delegate); - } - - @Override - public ScheduledFuture schedule(Runnable command, long delay, TimeUnit unit) { - return delegate.schedule(command, delay, unit); - } - - @Override - public ScheduledFuture schedule(Callable callable, long delay, TimeUnit unit) { - return delegate.schedule(callable, delay, unit); - } - - @Override - public ScheduledFuture scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) { - return delegate.scheduleAtFixedRate(command, initialDelay, period, unit); - } - - @Override - public ScheduledFuture scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) { - return delegate.scheduleWithFixedDelay(command, initialDelay, delay, unit); - } -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/util/StoppableExecutorService.java b/server/sonar-server/src/main/java/org/sonar/server/util/StoppableExecutorService.java deleted file mode 100644 index d432d1195c1..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/util/StoppableExecutorService.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info 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.util; - -import java.util.concurrent.ExecutorService; - -/** - * ExecutorService that exposes a {@code stop} method which can be invoked by Pico container to shutdown properly - * the service. - */ -public interface StoppableExecutorService extends ExecutorService { - - /** - * Stops the ExecutorService nicely (ie. first let a little time for jobs to end and then abort them) - */ - void stop(); -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/util/StoppableScheduledExecutorService.java b/server/sonar-server/src/main/java/org/sonar/server/util/StoppableScheduledExecutorService.java deleted file mode 100644 index 2bf77f69857..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/util/StoppableScheduledExecutorService.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info 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.util; - -import java.util.concurrent.ScheduledExecutorService; - -/** - * ScheduledExecutorService that exposes a {@code stop} method which can be invoked by Pico container to shutdown - * properly the service. - */ -public interface StoppableScheduledExecutorService extends ScheduledExecutorService, StoppableExecutorService { - -} diff --git a/server/sonar-server/src/test/java/org/sonar/server/util/AbstractStoppableExecutorServiceTest.java b/server/sonar-server/src/test/java/org/sonar/server/util/AbstractStoppableExecutorServiceTest.java deleted file mode 100644 index 6fa78b273eb..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/server/util/AbstractStoppableExecutorServiceTest.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info 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.util; - -import com.google.common.collect.ImmutableList; -import org.junit.Test; -import org.mockito.InOrder; -import org.mockito.Mockito; - -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class AbstractStoppableExecutorServiceTest { - private static final Callable SOME_CALLABLE = new Callable() { - @Override - public String call() { - return null; - } - }; - private static final Runnable SOME_RUNNABLE = new Runnable() { - @Override - public void run() { - - } - }; - private static final String SOME_STRING = "some string"; - private static final long SOME_LONG = 100l; - private static final int TIMEOUT = 5; - private static final TimeUnit TIMEOUT_UNIT = TimeUnit.SECONDS; - - private ExecutorService executorService = mock(ExecutorService.class); - private InOrder inOrder = Mockito.inOrder(executorService); - private AbstractStoppableExecutorService underTest = new AbstractStoppableExecutorService(executorService) { - }; - public static final ImmutableList> CALLABLES = ImmutableList.of(SOME_CALLABLE); - - @Test - public void stop_calls_shutdown_and_verify_termination() throws InterruptedException { - when(executorService.awaitTermination(TIMEOUT, TIMEOUT_UNIT)).thenReturn(true); - - underTest.stop(); - - inOrder.verify(executorService).shutdown(); - inOrder.verify(executorService).awaitTermination(TIMEOUT, TIMEOUT_UNIT); - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void stop_calls_shutdown_then_shutdownNow_if_not_terminated_and_check_termination_again() throws InterruptedException { - when(executorService.awaitTermination(TIMEOUT, TIMEOUT_UNIT)).thenReturn(false).thenReturn(true); - - underTest.stop(); - - inOrder.verify(executorService).shutdown(); - inOrder.verify(executorService).awaitTermination(TIMEOUT, TIMEOUT_UNIT); - inOrder.verify(executorService).shutdownNow(); - inOrder.verify(executorService).awaitTermination(TIMEOUT, TIMEOUT_UNIT); - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void stop_calls_shutdownnow_if_interrupted_exception_is_raised() throws InterruptedException { - when(executorService.awaitTermination(TIMEOUT, TIMEOUT_UNIT)).thenThrow(new InterruptedException()); - - underTest.stop(); - - inOrder.verify(executorService).shutdown(); - inOrder.verify(executorService).awaitTermination(TIMEOUT, TIMEOUT_UNIT); - inOrder.verify(executorService).shutdownNow(); - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void shutdown_delegates_to_executorService() { - underTest.shutdown(); - - inOrder.verify(executorService).shutdown(); - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void shutdownNow_delegates_to_executorService() { - underTest.shutdownNow(); - - inOrder.verify(executorService).shutdownNow(); - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void isShutdown_delegates_to_executorService() { - underTest.isShutdown(); - - inOrder.verify(executorService).isShutdown(); - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void isTerminated_delegates_to_executorService() { - underTest.isTerminated(); - - inOrder.verify(executorService).isTerminated(); - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void awaitTermination_delegates_to_executorService() throws InterruptedException { - underTest.awaitTermination(SOME_LONG, SECONDS); - - inOrder.verify(executorService).awaitTermination(SOME_LONG, SECONDS); - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void submit_callable_delegates_to_executorService() { - underTest.submit(SOME_CALLABLE); - - inOrder.verify(executorService).submit(SOME_CALLABLE); - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void submit_runnable_delegates_to_executorService() { - underTest.submit(SOME_RUNNABLE); - - inOrder.verify(executorService).submit(SOME_RUNNABLE); - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void submit_runnable_with_result_delegates_to_executorService() { - underTest.submit(SOME_RUNNABLE, SOME_STRING); - - inOrder.verify(executorService).submit(SOME_RUNNABLE, SOME_STRING); - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void invokeAll_delegates_to_executorService() throws InterruptedException { - underTest.invokeAll(CALLABLES); - - inOrder.verify(executorService).invokeAll(CALLABLES); - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void invokeAll1_delegates_to_executorService() throws InterruptedException { - underTest.invokeAll(CALLABLES, SOME_LONG, SECONDS); - - inOrder.verify(executorService).invokeAll(CALLABLES, SOME_LONG, SECONDS); - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void invokeAny_delegates_to_executorService() throws ExecutionException, InterruptedException { - underTest.invokeAny(CALLABLES); - - inOrder.verify(executorService).invokeAny(CALLABLES); - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void invokeAny1_delegates_to_executorService() throws InterruptedException, ExecutionException, TimeoutException { - underTest.invokeAny(CALLABLES, SOME_LONG, SECONDS); - - inOrder.verify(executorService).invokeAny(CALLABLES, SOME_LONG, SECONDS); - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void execute_delegates_to_executorService() { - underTest.execute(SOME_RUNNABLE); - - inOrder.verify(executorService).execute(SOME_RUNNABLE); - inOrder.verifyNoMoreInteractions(); - } -}