From: Sébastien Lesaint Date: Fri, 22 Jun 2018 11:33:23 +0000 (+0200) Subject: create module sonar-ce-task X-Git-Tag: 7.5~928 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=ce684ddae14d1927a3111f43b537a22cb3168ebf;p=sonarqube.git create module sonar-ce-task --- diff --git a/server/sonar-ce-task-projectanalysis/build.gradle b/server/sonar-ce-task-projectanalysis/build.gradle index 5644d921ad0..90ca771974e 100644 --- a/server/sonar-ce-task-projectanalysis/build.gradle +++ b/server/sonar-ce-task-projectanalysis/build.gradle @@ -37,6 +37,7 @@ dependencies { compileOnly 'com.google.code.findbugs:jsr305' compileOnly project(':sonar-core') + compileOnly project(':server:sonar-ce-task') compileOnly project(':server:sonar-db-dao') compileOnly project(':server:sonar-process') compileOnly project(':server:sonar-server-common') @@ -54,6 +55,7 @@ dependencies { testCompile 'org.mockito:mockito-core' testCompile 'org.reflections:reflections' testCompile project(':server:sonar-db-testing') + testCompile project(path: ":server:sonar-ce-task", configuration: "tests") testCompile project(path: ":server:sonar-server", configuration: "tests") } diff --git a/server/sonar-ce-task/build.gradle b/server/sonar-ce-task/build.gradle new file mode 100644 index 00000000000..66ad1d81185 --- /dev/null +++ b/server/sonar-ce-task/build.gradle @@ -0,0 +1,66 @@ +description = 'Definition of a Compute Engine task and utility "framework" and classes to code one' + +sonarqube { + properties { + property 'sonar.projectName', "${projectTitle} :: Compute Engine :: Task" + } +} + +sourceSets { + test { + resources { + srcDirs += ['src/test/projects'] + } + } +} + + +import org.apache.tools.ant.filters.ReplaceTokens +processResources { + filesMatching('build.properties') { + filter ReplaceTokens, tokens: [ + 'buildNumber': release ? 'git rev-parse HEAD'.execute().text.trim() : 'N/A' + ] + } +} + +dependencies { + // please keep the list grouped by configuration and ordered by name + + compile 'org.picocontainer:picocontainer' + compile 'org.slf4j:jul-to-slf4j' + compile 'org.slf4j:slf4j-api' + + compile project(':server:sonar-process') + compile project(':sonar-core') + compileOnly project(path: ':sonar-plugin-api') + + compileOnly 'com.google.code.findbugs:jsr305' + + testCompile 'ch.qos.logback:logback-access' + testCompile 'ch.qos.logback:logback-classic' + testCompile 'ch.qos.logback:logback-core' + testCompile 'com.google.code.findbugs:jsr305' + testCompile 'com.h2database:h2' + testCompile 'com.tngtech.java:junit-dataprovider' + testCompile 'junit:junit' + testCompile 'org.apache.logging.log4j:log4j-api' + testCompile 'org.apache.logging.log4j:log4j-core' + testCompile 'org.assertj:assertj-core' + testCompile 'org.assertj:assertj-guava' + testCompile 'org.mockito:mockito-core' + testCompile 'org.reflections:reflections' +} + +task testJar(type: Jar) { + classifier = 'tests' + from sourceSets.test.output +} + +configurations { + tests +} + +artifacts { + tests testJar +} diff --git a/server/sonar-ce-task/src/main/java/org/sonar/server/computation/CeTask.java b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/CeTask.java new file mode 100644 index 00000000000..f0d4f06ddcf --- /dev/null +++ b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/CeTask.java @@ -0,0 +1,166 @@ +/* + * 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.computation; + +import com.google.common.base.MoreObjects; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +import static com.google.common.base.Strings.emptyToNull; +import static java.util.Objects.requireNonNull; + +@Immutable +public class CeTask { + + private final String organizationUuid; + private final String type; + private final String uuid; + private final String componentUuid; + private final String componentKey; + private final String componentName; + private final String submitterUuid; + + private CeTask(Builder builder) { + this.organizationUuid = requireNonNull(emptyToNull(builder.organizationUuid), "organizationUuid can't be null nor empty"); + this.uuid = requireNonNull(emptyToNull(builder.uuid), "uuid can't be null nor empty"); + this.type = requireNonNull(emptyToNull(builder.type), "type can't be null nor empty"); + this.componentUuid = emptyToNull(builder.componentUuid); + this.componentKey = emptyToNull(builder.componentKey); + this.componentName = emptyToNull(builder.componentName); + this.submitterUuid = emptyToNull(builder.submitterUuid); + } + + public String getOrganizationUuid() { + return organizationUuid; + } + + public String getUuid() { + return uuid; + } + + public String getType() { + return type; + } + + @CheckForNull + public String getComponentUuid() { + return componentUuid; + } + + @CheckForNull + public String getComponentKey() { + return componentKey; + } + + @CheckForNull + public String getComponentName() { + return componentName; + } + + @CheckForNull + public String getSubmitterUuid() { + return submitterUuid; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("organizationUuid", organizationUuid) + .add("type", type) + .add("uuid", uuid) + .add("componentUuid", componentUuid) + .add("componentKey", componentKey) + .add("componentName", componentName) + .add("submitterUuid", submitterUuid) + .toString(); + } + + @Override + public boolean equals(@Nullable Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + CeTask ceTask = (CeTask) o; + return uuid.equals(ceTask.uuid); + } + + @Override + public int hashCode() { + return uuid.hashCode(); + } + + public static final class Builder { + private String organizationUuid; + private String uuid; + private String type; + private String componentUuid; + private String componentKey; + private String componentName; + private String submitterUuid; + + public Builder setOrganizationUuid(String organizationUuid) { + this.organizationUuid = organizationUuid; + return this; + } + + // FIXME remove this method when organization support is added to the Compute Engine queue + public boolean hasOrganizationUuid() { + return organizationUuid != null; + } + + public Builder setUuid(String uuid) { + this.uuid = uuid; + return this; + } + + public Builder setType(String type) { + this.type = type; + return this; + } + + public Builder setComponentUuid(String componentUuid) { + this.componentUuid = componentUuid; + return this; + } + + public Builder setComponentKey(@Nullable String s) { + this.componentKey = s; + return this; + } + + public Builder setComponentName(@Nullable String s) { + this.componentName = s; + return this; + } + + public Builder setSubmitterUuid(@Nullable String s) { + this.submitterUuid = s; + return this; + } + + public CeTask build() { + return new CeTask(this); + } + } +} diff --git a/server/sonar-ce-task/src/main/java/org/sonar/server/computation/CeTaskResult.java b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/CeTaskResult.java new file mode 100644 index 00000000000..73dcb927513 --- /dev/null +++ b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/CeTaskResult.java @@ -0,0 +1,33 @@ +/* + * 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.computation; + +import java.util.Optional; + +/** + * Represents the result of the processing of a {@link CeTask}. + */ +@FunctionalInterface +public interface CeTaskResult { + /** + * The UUID of the analysis created, if any, for the Component in {@link CeTask} + */ + Optional getAnalysisUuid(); +} diff --git a/server/sonar-ce-task/src/main/java/org/sonar/server/computation/log/CeTaskLogging.java b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/log/CeTaskLogging.java new file mode 100644 index 00000000000..8f1dbba3ced --- /dev/null +++ b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/log/CeTaskLogging.java @@ -0,0 +1,37 @@ +/* + * 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.computation.log; + +import org.slf4j.MDC; +import org.sonar.server.computation.CeTask; + +public class CeTaskLogging { + + public static final String MDC_CE_TASK_UUID = "ceTaskUuid"; + + public void initForTask(CeTask task) { + MDC.put(MDC_CE_TASK_UUID, task.getUuid()); + } + + public void clearForTask() { + MDC.remove(MDC_CE_TASK_UUID); + } + +} diff --git a/server/sonar-ce-task/src/main/java/org/sonar/server/computation/log/package-info.java b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/log/package-info.java new file mode 100644 index 00000000000..1088bac9be7 --- /dev/null +++ b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/log/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.computation.log; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-ce-task/src/main/java/org/sonar/server/computation/package-info.java b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/package-info.java new file mode 100644 index 00000000000..2b97ccbf4fc --- /dev/null +++ b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/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.computation; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-ce-task/src/main/java/org/sonar/server/computation/task/container/EagerStart.java b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/task/container/EagerStart.java new file mode 100644 index 00000000000..10ab10abf01 --- /dev/null +++ b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/task/container/EagerStart.java @@ -0,0 +1,33 @@ +/* + * 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.computation.task.container; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Components with this annotation will be eagerly started when loaded into the {@link TaskContainerImpl}. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface EagerStart { +} diff --git a/server/sonar-ce-task/src/main/java/org/sonar/server/computation/task/container/TaskContainer.java b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/task/container/TaskContainer.java new file mode 100644 index 00000000000..ba9a14b28c0 --- /dev/null +++ b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/task/container/TaskContainer.java @@ -0,0 +1,50 @@ +/* + * 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.computation.task.container; + +import org.picocontainer.PicoContainer; +import org.sonar.server.computation.CeTask; +import org.sonar.core.platform.ComponentContainer; +import org.sonar.core.platform.ContainerPopulator; + +/** + * The Compute Engine task container. Created for a specific parent {@link ComponentContainer} and a specific {@link CeTask}. + */ +public interface TaskContainer extends ContainerPopulator.Container, AutoCloseable { + + ComponentContainer getParent(); + + /** + * Starts task container, starting any startable component in it. + */ + void bootup(); + + /** + * Cleans up resources after process has been called and has returned. + */ + @Override + void close(); + + /** + * Access to the underlying pico container. + */ + PicoContainer getPicoContainer(); + +} diff --git a/server/sonar-ce-task/src/main/java/org/sonar/server/computation/task/container/TaskContainerImpl.java b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/task/container/TaskContainerImpl.java new file mode 100644 index 00000000000..3902a1b9709 --- /dev/null +++ b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/task/container/TaskContainerImpl.java @@ -0,0 +1,93 @@ +/* + * 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.computation.task.container; + +import java.util.List; +import org.picocontainer.ComponentAdapter; +import org.picocontainer.ComponentMonitor; +import org.picocontainer.DefaultPicoContainer; +import org.picocontainer.MutablePicoContainer; +import org.picocontainer.behaviors.OptInCaching; +import org.picocontainer.lifecycle.ReflectionLifecycleStrategy; +import org.picocontainer.monitors.NullComponentMonitor; +import org.sonar.api.config.PropertyDefinitions; +import org.sonar.api.utils.log.Loggers; +import org.sonar.core.platform.ComponentContainer; +import org.sonar.core.platform.ContainerPopulator; +import org.sonar.core.platform.Module; +import org.sonar.core.platform.StopSafeReflectionLifecycleStrategy; + +import static java.util.Objects.requireNonNull; + +public class TaskContainerImpl extends ComponentContainer implements TaskContainer { + + public TaskContainerImpl(ComponentContainer parent, ContainerPopulator populator) { + super(createContainer(requireNonNull(parent)), parent.getComponentByType(PropertyDefinitions.class)); + + populateContainer(requireNonNull(populator)); + } + + private void populateContainer(ContainerPopulator populator) { + populator.populateContainer(this); + populateFromModules(); + } + + private void populateFromModules() { + List modules = getComponentsByType(Module.class); + for (Module module : modules) { + module.configure(this); + } + } + + /** + * Creates a PicContainer which extends the specified ComponentContainer but is not referenced in return + * and lazily starts its components. + */ + private static MutablePicoContainer createContainer(ComponentContainer parent) { + ComponentMonitor componentMonitor = new NullComponentMonitor(); + ReflectionLifecycleStrategy lifecycleStrategy = new StopSafeReflectionLifecycleStrategy(componentMonitor) { + @Override + public boolean isLazy(ComponentAdapter adapter) { + return adapter.getComponentImplementation().getAnnotation(EagerStart.class) == null; + } + }; + + return new DefaultPicoContainer(new OptInCaching(), lifecycleStrategy, parent.getPicoContainer(), componentMonitor); + } + + @Override + public void bootup() { + startComponents(); + } + + @Override + public String toString() { + return "TaskContainerImpl"; + } + + @Override + public void close() { + try { + stopComponents(); + } catch (Throwable t) { + Loggers.get(TaskContainerImpl.class).error("Cleanup of container failed", t); + } + } +} diff --git a/server/sonar-ce-task/src/main/java/org/sonar/server/computation/task/container/package-info.java b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/task/container/package-info.java new file mode 100644 index 00000000000..f01956fbb38 --- /dev/null +++ b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/task/container/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.computation.task.container; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-ce-task/src/main/java/org/sonar/server/computation/task/step/ComputationStep.java b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/task/step/ComputationStep.java new file mode 100644 index 00000000000..f8fd66fe961 --- /dev/null +++ b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/task/step/ComputationStep.java @@ -0,0 +1,31 @@ +/* + * 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.computation.task.step; + +/** + * A way of splitting the processing of a task into smaller items which can be executed sequencially + * by {@link ComputationStepExecutor}. + */ +public interface ComputationStep { + + void execute(); + + String getDescription(); +} diff --git a/server/sonar-ce-task/src/main/java/org/sonar/server/computation/task/step/ComputationStepExecutor.java b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/task/step/ComputationStepExecutor.java new file mode 100644 index 00000000000..536121f29ca --- /dev/null +++ b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/task/step/ComputationStepExecutor.java @@ -0,0 +1,83 @@ +/* + * 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.computation.task.step; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.sonar.api.utils.log.Logger; +import org.sonar.api.utils.log.Loggers; +import org.sonar.core.util.logs.Profiler; + +public final class ComputationStepExecutor { + private static final Logger LOGGER = Loggers.get(ComputationStepExecutor.class); + + private final ComputationSteps steps; + @CheckForNull + private final Listener listener; + + /** + * Used when no {@link ComputationStepExecutor.Listener} is available in pico + * container. + */ + public ComputationStepExecutor(ComputationSteps steps) { + this(steps, null); + } + + public ComputationStepExecutor(ComputationSteps steps, @Nullable Listener listener) { + this.steps = steps; + this.listener = listener; + } + + public void execute() { + Profiler stepProfiler = Profiler.create(LOGGER); + boolean allStepsExecuted = false; + try { + executeSteps(stepProfiler); + allStepsExecuted = true; + } finally { + if (listener != null) { + executeListener(allStepsExecuted); + } + } + } + + private void executeSteps(Profiler stepProfiler) { + for (ComputationStep step : steps.instances()) { + stepProfiler.start(); + step.execute(); + stepProfiler.stopDebug(step.getDescription()); + } + } + + private void executeListener(boolean allStepsExecuted) { + try { + listener.finished(allStepsExecuted); + } catch (Throwable e) { + // any Throwable throws by the listener going up the stack might hide an Exception/Error thrown by the step and + // cause it be swallowed. We don't wan't that => we catch Throwable + LOGGER.error("Execution of listener failed", e); + } + } + + @FunctionalInterface + public interface Listener { + void finished(boolean allStepsExecuted); + } +} diff --git a/server/sonar-ce-task/src/main/java/org/sonar/server/computation/task/step/ComputationSteps.java b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/task/step/ComputationSteps.java new file mode 100644 index 00000000000..c35ca8f6a38 --- /dev/null +++ b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/task/step/ComputationSteps.java @@ -0,0 +1,39 @@ +/* + * 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.computation.task.step; + +import java.util.List; + +/** + * Ordered list of steps classes and instances to be executed in a Compute Engine process. + */ +public interface ComputationSteps { + /** + * List of all {@link ComputationStep}, + * ordered by execution sequence. + */ + List> orderedStepClasses(); + + /** + * List of all {@link ComputationStep}, + * ordered by execution sequence. + */ + Iterable instances(); +} diff --git a/server/sonar-ce-task/src/main/java/org/sonar/server/computation/task/step/ExecuteStatelessInitExtensionsStep.java b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/task/step/ExecuteStatelessInitExtensionsStep.java new file mode 100644 index 00000000000..b587083d88b --- /dev/null +++ b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/task/step/ExecuteStatelessInitExtensionsStep.java @@ -0,0 +1,56 @@ +/* + * 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.computation.task.step; + +import org.sonar.api.ce.ComputeEngineSide; + +/** + * Execute {@link StatelessInitExtension} instances in no specific order. + * If an extension fails (throws an exception), consecutive extensions + * won't be called. + */ +@ComputeEngineSide +public class ExecuteStatelessInitExtensionsStep implements ComputationStep { + + private final StatelessInitExtension[] extensions; + + public ExecuteStatelessInitExtensionsStep(StatelessInitExtension[] extensions) { + this.extensions = extensions; + } + + /** + * Used when zero {@link StatelessInitExtension} are registered into container. + */ + public ExecuteStatelessInitExtensionsStep() { + this(new StatelessInitExtension[0]); + } + + @Override + public void execute() { + for (StatelessInitExtension extension : extensions) { + extension.onInit(); + } + } + + @Override + public String getDescription() { + return "Initialize"; + } +} diff --git a/server/sonar-ce-task/src/main/java/org/sonar/server/computation/task/step/StatelessInitExtension.java b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/task/step/StatelessInitExtension.java new file mode 100644 index 00000000000..aedc81e8347 --- /dev/null +++ b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/task/step/StatelessInitExtension.java @@ -0,0 +1,41 @@ +/* + * 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.computation.task.step; + +import org.sonar.api.ExtensionPoint; +import org.sonar.api.ce.ComputeEngineSide; + +/** + * Extension point that is called during processing of a task + * by {@link ExecuteStatelessInitExtensionsStep}. + * It is stateless, the same instance is reused for all tasks. + * As a consequence Compute Engine task components can't be injected + * as dependencies. + */ +@ComputeEngineSide +@ExtensionPoint +public interface StatelessInitExtension { + + /** + * This method can make the task fail by throwing a {@link RuntimeException} + */ + void onInit(); + +} diff --git a/server/sonar-ce-task/src/main/java/org/sonar/server/computation/task/step/TypedException.java b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/task/step/TypedException.java new file mode 100644 index 00000000000..b600f90f7e3 --- /dev/null +++ b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/task/step/TypedException.java @@ -0,0 +1,33 @@ +/* + * 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.computation.task.step; + +/** + * This interface is implemented by the exceptions + * that provide a type of error when failing + * a Compute Engine task. + * The error type is persisted and available in + * the tasks returned by the web services api/ce. + */ +public interface TypedException { + + String getType(); + +} diff --git a/server/sonar-ce-task/src/main/java/org/sonar/server/computation/task/step/package-info.java b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/task/step/package-info.java new file mode 100644 index 00000000000..5868b7cccc4 --- /dev/null +++ b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/task/step/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.computation.task.step; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-ce-task/src/main/java/org/sonar/server/computation/taskprocessor/MutableTaskResultHolder.java b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/taskprocessor/MutableTaskResultHolder.java new file mode 100644 index 00000000000..5e4409b1b73 --- /dev/null +++ b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/taskprocessor/MutableTaskResultHolder.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.computation.taskprocessor; + +import org.sonar.server.computation.CeTaskResult; + +public interface MutableTaskResultHolder extends TaskResultHolder { + /** + * @throws NullPointerException if {@code taskResult} is {@code null} + * @throws IllegalStateException if a {@link CeTaskResult} has already been set in the holder + */ + void setResult(CeTaskResult taskResult); +} diff --git a/server/sonar-ce-task/src/main/java/org/sonar/server/computation/taskprocessor/MutableTaskResultHolderImpl.java b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/taskprocessor/MutableTaskResultHolderImpl.java new file mode 100644 index 00000000000..6fe1e53913e --- /dev/null +++ b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/taskprocessor/MutableTaskResultHolderImpl.java @@ -0,0 +1,44 @@ +/* + * 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.computation.taskprocessor; + +import javax.annotation.CheckForNull; +import org.sonar.server.computation.CeTaskResult; + +import static com.google.common.base.Preconditions.checkState; +import static java.util.Objects.requireNonNull; + +public class MutableTaskResultHolderImpl implements MutableTaskResultHolder { + @CheckForNull + private CeTaskResult result; + + @Override + public CeTaskResult getResult() { + checkState(this.result != null, "No CeTaskResult has been set in the holder"); + return this.result; + } + + @Override + public void setResult(CeTaskResult taskResult) { + requireNonNull(taskResult, "taskResult can not be null"); + checkState(this.result == null, "CeTaskResult has already been set in the holder"); + this.result = taskResult; + } +} diff --git a/server/sonar-ce-task/src/main/java/org/sonar/server/computation/taskprocessor/TaskResultHolder.java b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/taskprocessor/TaskResultHolder.java new file mode 100644 index 00000000000..b4c3e978150 --- /dev/null +++ b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/taskprocessor/TaskResultHolder.java @@ -0,0 +1,29 @@ +/* + * 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.computation.taskprocessor; + +import org.sonar.server.computation.CeTaskResult; + +public interface TaskResultHolder { + /** + * @throws IllegalStateException if holder holds no CeTaskResult + */ + CeTaskResult getResult(); +} diff --git a/server/sonar-ce-task/src/main/java/org/sonar/server/computation/util/InitializedProperty.java b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/util/InitializedProperty.java new file mode 100644 index 00000000000..01170eb9fde --- /dev/null +++ b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/util/InitializedProperty.java @@ -0,0 +1,43 @@ +/* + * 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.computation.util; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; + +public class InitializedProperty { + private E property; + private boolean initialized = false; + + public InitializedProperty setProperty(@Nullable E property) { + this.property = property; + this.initialized = true; + return this; + } + + @CheckForNull + public E getProperty() { + return property; + } + + public boolean isInitialized() { + return initialized; + } +} diff --git a/server/sonar-ce-task/src/main/java/org/sonar/server/computation/util/package-info.java b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/util/package-info.java new file mode 100644 index 00000000000..415bc7b76f9 --- /dev/null +++ b/server/sonar-ce-task/src/main/java/org/sonar/server/computation/util/package-info.java @@ -0,0 +1,24 @@ +/* + * 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.computation.util; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/server/sonar-ce-task/src/test/java/org/sonar/server/computation/CeTaskTest.java b/server/sonar-ce-task/src/test/java/org/sonar/server/computation/CeTaskTest.java new file mode 100644 index 00000000000..b42261f5eb7 --- /dev/null +++ b/server/sonar-ce-task/src/test/java/org/sonar/server/computation/CeTaskTest.java @@ -0,0 +1,148 @@ +/* + * 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.computation; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import static org.assertj.core.api.Assertions.assertThat; + +public class CeTaskTest { + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private CeTask.Builder underTest = new CeTask.Builder(); + + @Test + public void build_fails_with_NPE_if_organizationUuid_is_null() { + expectedException.expect(NullPointerException.class); + expectedException.expectMessage("organizationUuid can't be null nor empty"); + + underTest.build(); + } + + @Test + public void build_fails_with_NPE_if_organizationUuid_is_empty() { + underTest.setOrganizationUuid(""); + + expectedException.expect(NullPointerException.class); + expectedException.expectMessage("organizationUuid can't be null nor empty"); + + underTest.build(); + } + + @Test + public void build_fails_with_NPE_if_uid_is_null() { + underTest.setOrganizationUuid("org1"); + + expectedException.expect(NullPointerException.class); + expectedException.expectMessage("uuid can't be null nor empty"); + + underTest.build(); + } + + @Test + public void build_fails_with_NPE_if_uuid_is_empty() { + underTest.setOrganizationUuid("org1").setUuid(""); + + expectedException.expect(NullPointerException.class); + expectedException.expectMessage("uuid can't be null nor empty"); + + underTest.build(); + } + + @Test + public void build_fails_with_NPE_if_type_is_null() { + underTest.setOrganizationUuid("org1").setUuid("uuid"); + + expectedException.expect(NullPointerException.class); + expectedException.expectMessage("type can't be null nor empty"); + + underTest.build(); + } + + @Test + public void build_fails_with_NPE_if_type_is_empty() { + underTest.setOrganizationUuid("org1").setUuid("uuid").setType(""); + + expectedException.expect(NullPointerException.class); + expectedException.expectMessage("type can't be null nor empty"); + + underTest.build(); + } + + @Test + public void verify_getters() { + underTest.setOrganizationUuid("org1"); + underTest.setType("TYPE_1"); + underTest.setUuid("UUID_1"); + underTest.setSubmitterUuid("LOGIN_1"); + underTest.setComponentKey("COMPONENT_KEY_1"); + underTest.setComponentUuid("COMPONENT_UUID_1"); + underTest.setComponentName("The component"); + + CeTask task = underTest.build(); + + assertThat(task.getOrganizationUuid()).isEqualTo("org1"); + assertThat(task.getUuid()).isEqualTo("UUID_1"); + assertThat(task.getType()).isEqualTo("TYPE_1"); + assertThat(task.getSubmitterUuid()).isEqualTo("LOGIN_1"); + assertThat(task.getComponentKey()).isEqualTo("COMPONENT_KEY_1"); + assertThat(task.getComponentUuid()).isEqualTo("COMPONENT_UUID_1"); + assertThat(task.getComponentName()).isEqualTo("The component"); + } + + @Test + public void empty_in_component_properties_is_considered_as_null() { + CeTask ceTask = underTest.setOrganizationUuid("org1").setUuid("uuid").setType("type") + .setComponentKey("") + .setComponentName("") + .setComponentUuid("") + .build(); + + assertThat(ceTask.getComponentKey()).isNull(); + assertThat(ceTask.getComponentName()).isNull(); + assertThat(ceTask.getComponentUuid()).isNull(); + } + + @Test + public void empty_in_submitterLogin_is_considered_as_null() { + CeTask ceTask = underTest.setOrganizationUuid("org1").setUuid("uuid").setType("type") + .setSubmitterUuid("") + .build(); + + assertThat(ceTask.getSubmitterUuid()).isNull(); + } + + @Test + public void equals_and_hashCode_on_uuid() { + underTest.setOrganizationUuid("org1").setType("TYPE_1").setUuid("UUID_1"); + CeTask task1 = underTest.build(); + CeTask task1bis = underTest.build(); + CeTask task2 = new CeTask.Builder().setOrganizationUuid("org1").setType("TYPE_1").setUuid("UUID_2").build(); + + assertThat(task1.equals(task1)).isTrue(); + assertThat(task1.equals(task1bis)).isTrue(); + assertThat(task1.equals(task2)).isFalse(); + assertThat(task1.hashCode()).isEqualTo(task1.hashCode()); + assertThat(task1.hashCode()).isEqualTo(task1bis.hashCode()); + } +} diff --git a/server/sonar-ce-task/src/test/java/org/sonar/server/computation/log/CeTaskLoggingTest.java b/server/sonar-ce-task/src/test/java/org/sonar/server/computation/log/CeTaskLoggingTest.java new file mode 100644 index 00000000000..5193eb1efd8 --- /dev/null +++ b/server/sonar-ce-task/src/test/java/org/sonar/server/computation/log/CeTaskLoggingTest.java @@ -0,0 +1,78 @@ +/* + * 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.computation.log; + +import ch.qos.logback.core.joran.spi.JoranException; +import org.junit.After; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.mockito.Mockito; +import org.slf4j.MDC; +import org.sonar.process.logging.LogbackHelper; +import org.sonar.server.computation.CeTask; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; +import static org.sonar.server.computation.log.CeTaskLogging.MDC_CE_TASK_UUID; + +public class CeTaskLoggingTest { + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private LogbackHelper helper = new LogbackHelper(); + private CeTaskLogging underTest = new CeTaskLogging(); + + @After + public void resetLogback() throws JoranException { + helper.resetFromXml("/logback-test.xml"); + } + + @After + public void cleanMDC() { + MDC.clear(); + } + + @Test + public void initForTask_stores_task_uuid_in_MDC() { + String uuid = "ce_task_uuid"; + + underTest.initForTask(createCeTask(uuid)); + + assertThat(MDC.get(MDC_CE_TASK_UUID)).isEqualTo(uuid); + } + + private CeTask createCeTask(String uuid) { + CeTask ceTask = Mockito.mock(CeTask.class); + when(ceTask.getUuid()).thenReturn(uuid); + return ceTask; + } + + @Test + public void clearForTask_removes_task_uuid_from_MDC() { + MDC.put(MDC_CE_TASK_UUID, "some_value"); + + underTest.clearForTask(); + + assertThat(MDC.get(MDC_CE_TASK_UUID)).isNull(); + } + +} diff --git a/server/sonar-ce-task/src/test/java/org/sonar/server/computation/task/ChangeLogLevel.java b/server/sonar-ce-task/src/test/java/org/sonar/server/computation/task/ChangeLogLevel.java new file mode 100644 index 00000000000..3260b7263cd --- /dev/null +++ b/server/sonar-ce-task/src/test/java/org/sonar/server/computation/task/ChangeLogLevel.java @@ -0,0 +1,40 @@ +/* + * 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.computation.task; + +import org.sonar.api.utils.log.Logger; +import org.sonar.api.utils.log.LoggerLevel; +import org.sonar.api.utils.log.Loggers; + +public final class ChangeLogLevel implements AutoCloseable { + private final Logger logger; + private final LoggerLevel previous; + + public ChangeLogLevel(Class clazz, LoggerLevel newLevel) { + this.logger = Loggers.get(clazz); + this.previous = logger.getLevel(); + logger.setLevel(newLevel); + } + + @Override + public void close() { + logger.setLevel(previous); + } +} diff --git a/server/sonar-ce-task/src/test/java/org/sonar/server/computation/task/container/TaskContainerImplTest.java b/server/sonar-ce-task/src/test/java/org/sonar/server/computation/task/container/TaskContainerImplTest.java new file mode 100644 index 00000000000..debaac8a916 --- /dev/null +++ b/server/sonar-ce-task/src/test/java/org/sonar/server/computation/task/container/TaskContainerImplTest.java @@ -0,0 +1,114 @@ +/* + * 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.computation.task.container; + +import org.junit.Test; +import org.picocontainer.Startable; +import org.sonar.core.platform.ComponentContainer; +import org.sonar.core.platform.ContainerPopulator; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +public class TaskContainerImplTest { + private ComponentContainer parent = new ComponentContainer(); + private ContainerPopulator populator = mock(ContainerPopulator.class); + + @Test(expected = NullPointerException.class) + public void constructor_fails_fast_on_null_container() { + new TaskContainerImpl(null, mock(ContainerPopulator.class)); + } + + @Test(expected = NullPointerException.class) + public void constructor_fails_fast_on_null_item() { + new TaskContainerImpl(new ComponentContainer(), null); + } + + @Test + public void calls_method_populateContainer_of_passed_in_populator() { + TaskContainerImpl ceContainer = new TaskContainerImpl(parent, populator); + + verify(populator).populateContainer(ceContainer); + } + + @Test + public void ce_container_is_not_child_of_specified_container() { + TaskContainerImpl ceContainer = new TaskContainerImpl(parent, populator); + + assertThat(parent.getChildren()).isEmpty(); + verify(populator).populateContainer(ceContainer); + } + + @Test + public void bootup_starts_components_lazily_unless_they_are_annotated_with_EagerStart() { + final DefaultStartable defaultStartable = new DefaultStartable(); + final EagerStartable eagerStartable = new EagerStartable(); + TaskContainerImpl ceContainer = new TaskContainerImpl(parent, container -> { + container.add(defaultStartable); + container.add(eagerStartable); + }); + ceContainer.bootup(); + + assertThat(defaultStartable.startCalls).isEqualTo(0); + assertThat(defaultStartable.stopCalls).isEqualTo(0); + assertThat(eagerStartable.startCalls).isEqualTo(1); + assertThat(eagerStartable.stopCalls).isEqualTo(0); + } + + @Test + public void close_stops_started_components() { + final DefaultStartable defaultStartable = new DefaultStartable(); + final EagerStartable eagerStartable = new EagerStartable(); + TaskContainerImpl ceContainer = new TaskContainerImpl(parent, container -> { + container.add(defaultStartable); + container.add(eagerStartable); + }); + ceContainer.bootup(); + + ceContainer.close(); + + assertThat(defaultStartable.startCalls).isEqualTo(0); + assertThat(defaultStartable.stopCalls).isEqualTo(0); + assertThat(eagerStartable.startCalls).isEqualTo(1); + assertThat(eagerStartable.stopCalls).isEqualTo(1); + } + + public static class DefaultStartable implements Startable { + protected int startCalls = 0; + protected int stopCalls = 0; + + @Override + public void start() { + startCalls++; + } + + @Override + public void stop() { + stopCalls++; + } + } + + @EagerStart + public static class EagerStartable extends DefaultStartable { + } + + +} diff --git a/server/sonar-ce-task/src/test/java/org/sonar/server/computation/task/step/ComputationStepExecutorTest.java b/server/sonar-ce-task/src/test/java/org/sonar/server/computation/task/step/ComputationStepExecutorTest.java new file mode 100644 index 00000000000..19050a279bf --- /dev/null +++ b/server/sonar-ce-task/src/test/java/org/sonar/server/computation/task/step/ComputationStepExecutorTest.java @@ -0,0 +1,166 @@ +/* + * 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.computation.task.step; + +import java.util.Arrays; +import java.util.List; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.mockito.InOrder; +import org.sonar.api.utils.log.LogTester; +import org.sonar.api.utils.log.LoggerLevel; +import org.sonar.server.computation.task.ChangeLogLevel; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.fail; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +public class ComputationStepExecutorTest { + @Rule + public LogTester logTester = new LogTester(); + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private final ComputationStepExecutor.Listener listener = mock(ComputationStepExecutor.Listener.class); + private final ComputationStep computationStep1 = mockComputationStep("step1"); + private final ComputationStep computationStep2 = mockComputationStep("step2"); + private final ComputationStep computationStep3 = mockComputationStep("step3"); + + @Test + public void execute_call_execute_on_each_ComputationStep_in_order_returned_by_instances_method() { + new ComputationStepExecutor(mockComputationSteps(computationStep1, computationStep2, computationStep3)) + .execute(); + + InOrder inOrder = inOrder(computationStep1, computationStep2, computationStep3); + inOrder.verify(computationStep1).execute(); + inOrder.verify(computationStep1).getDescription(); + inOrder.verify(computationStep2).execute(); + inOrder.verify(computationStep2).getDescription(); + inOrder.verify(computationStep3).execute(); + inOrder.verify(computationStep3).getDescription(); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void execute_let_exception_thrown_by_ComputationStep_go_up_as_is() { + String message = "Exception should go up"; + + ComputationStep computationStep = mockComputationStep("step1"); + doThrow(new RuntimeException(message)) + .when(computationStep) + .execute(); + + ComputationStepExecutor computationStepExecutor = new ComputationStepExecutor(mockComputationSteps(computationStep)); + + expectedException.expect(RuntimeException.class); + expectedException.expectMessage(message); + + computationStepExecutor.execute(); + } + + @Test + public void execute_does_not_log_end_timing_for_each_ComputationStep_called_when_level_is_INFO() { + List infoLogs = execute_logs_end_timing_for_each_ComputationStep_called_when_(LoggerLevel.INFO); + assertThat(infoLogs).isEmpty(); + } + + @Test + public void execute_logs_end_timing_for_each_ComputationStep_called_when_level_is_DEBUG() { + List infoLogs = execute_logs_end_timing_for_each_ComputationStep_called_when_(LoggerLevel.DEBUG); + assertThat(infoLogs).hasSize(2); + assertThat(infoLogs.get(0)).contains("step1 | time="); + assertThat(infoLogs.get(1)).contains("step2 | time="); + } + + @Test + public void execute_logs_end_timing_for_each_ComputationStep_called_when_level_is_TRACE() { + List infoLogs = execute_logs_end_timing_for_each_ComputationStep_called_when_(LoggerLevel.TRACE); + assertThat(infoLogs).hasSize(2); + assertThat(infoLogs.get(0)).contains("step1 | time="); + assertThat(infoLogs.get(1)).contains("step2 | time="); + } + + private List execute_logs_end_timing_for_each_ComputationStep_called_when_(LoggerLevel level) { + try (ChangeLogLevel executor = new ChangeLogLevel(ComputationStepExecutor.class, level); + ChangeLogLevel step1 = new ChangeLogLevel(computationStep1.getClass(), level); + ChangeLogLevel step2 = new ChangeLogLevel(computationStep2.getClass(), level)) { + new ComputationStepExecutor(mockComputationSteps(computationStep1, computationStep2)) + .execute(); + + return logTester.logs(LoggerLevel.DEBUG); + } + } + + @Test + public void execute_calls_listener_finished_method_with_all_step_runs() { + new ComputationStepExecutor(mockComputationSteps(computationStep1, computationStep2), listener) + .execute(); + + verify(listener).finished(true); + verifyNoMoreInteractions(listener); + } + + @Test + public void execute_calls_listener_finished_method_even_if_a_step_throws_an_exception() { + RuntimeException toBeThrown = new RuntimeException("simulating failing execute Step method"); + doThrow(toBeThrown) + .when(computationStep1) + .execute(); + + try { + new ComputationStepExecutor(mockComputationSteps(computationStep1, computationStep2), listener) + .execute(); + fail("exception toBeThrown should have been raised"); + } catch (RuntimeException e) { + assertThat(e).isSameAs(toBeThrown); + verify(listener).finished(false); + verifyNoMoreInteractions(listener); + } + } + + @Test + public void execute_does_not_fail_if_listener_throws_Throwable() { + ComputationStepExecutor.Listener listener = mock(ComputationStepExecutor.Listener.class); + doThrow(new Error("Facking error thrown by Listener")) + .when(listener) + .finished(anyBoolean()); + + new ComputationStepExecutor(mockComputationSteps(computationStep1), listener).execute(); + } + + private static ComputationSteps mockComputationSteps(ComputationStep... computationSteps) { + ComputationSteps steps = mock(ComputationSteps.class); + when(steps.instances()).thenReturn(Arrays.asList(computationSteps)); + return steps; + } + + private static ComputationStep mockComputationStep(String desc) { + ComputationStep mock = mock(ComputationStep.class); + when(mock.getDescription()).thenReturn(desc); + return mock; + } +} diff --git a/server/sonar-ce-task/src/test/java/org/sonar/server/computation/task/step/ExecuteStatelessInitExtensionsStepTest.java b/server/sonar-ce-task/src/test/java/org/sonar/server/computation/task/step/ExecuteStatelessInitExtensionsStepTest.java new file mode 100644 index 00000000000..fdf4049bf35 --- /dev/null +++ b/server/sonar-ce-task/src/test/java/org/sonar/server/computation/task/step/ExecuteStatelessInitExtensionsStepTest.java @@ -0,0 +1,89 @@ +/* + * 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.computation.task.step; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.mockito.InOrder; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +public class ExecuteStatelessInitExtensionsStepTest { + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Test + public void test_getDescription() { + ExecuteStatelessInitExtensionsStep underTest = new ExecuteStatelessInitExtensionsStep(); + + assertThat(underTest.getDescription()).isEqualTo("Initialize"); + } + + @Test + public void do_nothing_if_no_extensions() { + ExecuteStatelessInitExtensionsStep underTest = new ExecuteStatelessInitExtensionsStep(); + + // no failure + underTest.execute(); + } + + @Test + public void execute_extensions() { + StatelessInitExtension ext1 = mock(StatelessInitExtension.class); + StatelessInitExtension ext2 = mock(StatelessInitExtension.class); + + ExecuteStatelessInitExtensionsStep underTest = new ExecuteStatelessInitExtensionsStep( + new StatelessInitExtension[] {ext1, ext2}); + underTest.execute(); + + InOrder inOrder = inOrder(ext1, ext2); + inOrder.verify(ext1).onInit(); + inOrder.verify(ext2).onInit(); + } + + @Test + public void fail_if_an_extension_throws_an_exception() { + StatelessInitExtension ext1 = mock(StatelessInitExtension.class); + StatelessInitExtension ext2 = mock(StatelessInitExtension.class); + doThrow(new IllegalStateException("BOOM")).when(ext2).onInit(); + StatelessInitExtension ext3 = mock(StatelessInitExtension.class); + + ExecuteStatelessInitExtensionsStep underTest = new ExecuteStatelessInitExtensionsStep( + new StatelessInitExtension[] {ext1, ext2, ext3}); + + try { + underTest.execute(); + fail(); + } catch (IllegalStateException e) { + assertThat(e).hasMessage("BOOM"); + verify(ext1).onInit(); + verify(ext3, never()).onInit(); + } + } + +} diff --git a/server/sonar-ce-task/src/test/java/org/sonar/server/computation/task/step/StepsExplorer.java b/server/sonar-ce-task/src/test/java/org/sonar/server/computation/task/step/StepsExplorer.java new file mode 100644 index 00000000000..1f836dee41c --- /dev/null +++ b/server/sonar-ce-task/src/test/java/org/sonar/server/computation/task/step/StepsExplorer.java @@ -0,0 +1,68 @@ +/* + * 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.computation.task.step; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import java.lang.reflect.Modifier; +import java.util.Set; +import javax.annotation.Nonnull; +import org.reflections.Reflections; + +import static com.google.common.base.Predicates.notNull; +import static com.google.common.collect.FluentIterable.from; + +public class StepsExplorer { + /** + * Compute set of canonical names of classes implementing ComputationStep in the specified package using reflection. + */ + public static Set retrieveStepPackageStepsCanonicalNames(String packageName) { + Reflections reflections = new Reflections(packageName); + + return from(reflections.getSubTypesOf(ComputationStep.class)) + .filter(NotAbstractClass.INSTANCE) + .transform(ClassToCanonicalName.INSTANCE) + // anonymous classes do not have canonical names + .filter(notNull()) + .toSet(); + } + + private enum NotAbstractClass implements Predicate> { + INSTANCE; + + @Override + public boolean apply(Class input) { + return !Modifier.isAbstract(input.getModifiers()); + } + } + + public static Function, String> toCanonicalName() { + return ClassToCanonicalName.INSTANCE; + } + + private enum ClassToCanonicalName implements Function, String> { + INSTANCE; + + @Override + public String apply(@Nonnull Class input) { + return input.getCanonicalName(); + } + } +} diff --git a/server/sonar-ce-task/src/test/java/org/sonar/server/computation/taskprocessor/MutableTaskResultHolderImplTest.java b/server/sonar-ce-task/src/test/java/org/sonar/server/computation/taskprocessor/MutableTaskResultHolderImplTest.java new file mode 100644 index 00000000000..f81de440ad6 --- /dev/null +++ b/server/sonar-ce-task/src/test/java/org/sonar/server/computation/taskprocessor/MutableTaskResultHolderImplTest.java @@ -0,0 +1,70 @@ +/* + * 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.computation.taskprocessor; + +import org.assertj.core.api.Assertions; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.server.computation.CeTaskResult; + +import static org.mockito.Mockito.mock; + +public class MutableTaskResultHolderImplTest { + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private MutableTaskResultHolder underTest = new MutableTaskResultHolderImpl(); + + @Test + public void getResult_throws_ISE_if_no_CeTaskResult_is_set() { + expectedException.expect(IllegalStateException.class); + expectedException.expectMessage("No CeTaskResult has been set in the holder"); + + underTest.getResult(); + } + + @Test + public void getResult_returns_object_set_with_setResult() { + CeTaskResult taskResult = mock(CeTaskResult.class); + + underTest.setResult(taskResult); + + Assertions.assertThat(underTest.getResult()).isSameAs(taskResult); + } + + @Test + public void setResult_throws_NPE_if_CeTaskResult_argument_is_null() { + expectedException.expect(NullPointerException.class); + expectedException.expectMessage("taskResult can not be null"); + + underTest.setResult(null); + } + + @Test + public void setResult_throws_ISE_if_called_twice() { + underTest.setResult(mock(CeTaskResult.class)); + + expectedException.expect(IllegalStateException.class); + expectedException.expectMessage("CeTaskResult has already been set in the holder"); + + underTest.setResult(mock(CeTaskResult.class)); + } +} diff --git a/server/sonar-ce-task/src/test/resources/logback-test.xml b/server/sonar-ce-task/src/test/resources/logback-test.xml new file mode 100644 index 00000000000..3e34b0f9fc8 --- /dev/null +++ b/server/sonar-ce-task/src/test/resources/logback-test.xml @@ -0,0 +1,26 @@ + + + + + + + + %d{yyyy.MM.dd HH:mm:ss} %-5level %msg%n + + + + + + + + + + + + + + + + + + diff --git a/server/sonar-ce/build.gradle b/server/sonar-ce/build.gradle index 9befb0e3a06..a98c2448250 100644 --- a/server/sonar-ce/build.gradle +++ b/server/sonar-ce/build.gradle @@ -11,6 +11,7 @@ dependencies { compile 'com.google.protobuf:protobuf-java' compile 'org.nanohttpd:nanohttpd' + compile project(':server:sonar-ce-task') compile project(':server:sonar-ce-task-projectanalysis') compile project(':server:sonar-server') diff --git a/server/sonar-server/build.gradle b/server/sonar-server/build.gradle index c62666ca78b..ee6ae5f52b2 100644 --- a/server/sonar-server/build.gradle +++ b/server/sonar-server/build.gradle @@ -47,6 +47,7 @@ dependencies { compile 'org.sonarsource.update-center:sonar-update-center-common' compile 'org.mindrot:jbcrypt' + compile project(':server:sonar-ce-task') compile project(':server:sonar-db-dao') compile project(':server:sonar-db-migration') compile project(':server:sonar-plugin-bridge') @@ -80,7 +81,6 @@ dependencies { testCompile 'org.eclipse.jetty:jetty-servlet' testCompile 'org.hamcrest:hamcrest-all' testCompile 'org.mockito:mockito-core' - testCompile 'org.reflections:reflections' testCompile 'org.subethamail:subethasmtp' testCompile project(':server:sonar-db-testing') } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/CeTask.java b/server/sonar-server/src/main/java/org/sonar/server/computation/CeTask.java deleted file mode 100644 index f0d4f06ddcf..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/CeTask.java +++ /dev/null @@ -1,166 +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.computation; - -import com.google.common.base.MoreObjects; -import javax.annotation.CheckForNull; -import javax.annotation.Nullable; -import javax.annotation.concurrent.Immutable; - -import static com.google.common.base.Strings.emptyToNull; -import static java.util.Objects.requireNonNull; - -@Immutable -public class CeTask { - - private final String organizationUuid; - private final String type; - private final String uuid; - private final String componentUuid; - private final String componentKey; - private final String componentName; - private final String submitterUuid; - - private CeTask(Builder builder) { - this.organizationUuid = requireNonNull(emptyToNull(builder.organizationUuid), "organizationUuid can't be null nor empty"); - this.uuid = requireNonNull(emptyToNull(builder.uuid), "uuid can't be null nor empty"); - this.type = requireNonNull(emptyToNull(builder.type), "type can't be null nor empty"); - this.componentUuid = emptyToNull(builder.componentUuid); - this.componentKey = emptyToNull(builder.componentKey); - this.componentName = emptyToNull(builder.componentName); - this.submitterUuid = emptyToNull(builder.submitterUuid); - } - - public String getOrganizationUuid() { - return organizationUuid; - } - - public String getUuid() { - return uuid; - } - - public String getType() { - return type; - } - - @CheckForNull - public String getComponentUuid() { - return componentUuid; - } - - @CheckForNull - public String getComponentKey() { - return componentKey; - } - - @CheckForNull - public String getComponentName() { - return componentName; - } - - @CheckForNull - public String getSubmitterUuid() { - return submitterUuid; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(this) - .add("organizationUuid", organizationUuid) - .add("type", type) - .add("uuid", uuid) - .add("componentUuid", componentUuid) - .add("componentKey", componentKey) - .add("componentName", componentName) - .add("submitterUuid", submitterUuid) - .toString(); - } - - @Override - public boolean equals(@Nullable Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - CeTask ceTask = (CeTask) o; - return uuid.equals(ceTask.uuid); - } - - @Override - public int hashCode() { - return uuid.hashCode(); - } - - public static final class Builder { - private String organizationUuid; - private String uuid; - private String type; - private String componentUuid; - private String componentKey; - private String componentName; - private String submitterUuid; - - public Builder setOrganizationUuid(String organizationUuid) { - this.organizationUuid = organizationUuid; - return this; - } - - // FIXME remove this method when organization support is added to the Compute Engine queue - public boolean hasOrganizationUuid() { - return organizationUuid != null; - } - - public Builder setUuid(String uuid) { - this.uuid = uuid; - return this; - } - - public Builder setType(String type) { - this.type = type; - return this; - } - - public Builder setComponentUuid(String componentUuid) { - this.componentUuid = componentUuid; - return this; - } - - public Builder setComponentKey(@Nullable String s) { - this.componentKey = s; - return this; - } - - public Builder setComponentName(@Nullable String s) { - this.componentName = s; - return this; - } - - public Builder setSubmitterUuid(@Nullable String s) { - this.submitterUuid = s; - return this; - } - - public CeTask build() { - return new CeTask(this); - } - } -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/CeTaskResult.java b/server/sonar-server/src/main/java/org/sonar/server/computation/CeTaskResult.java deleted file mode 100644 index 73dcb927513..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/CeTaskResult.java +++ /dev/null @@ -1,33 +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.computation; - -import java.util.Optional; - -/** - * Represents the result of the processing of a {@link CeTask}. - */ -@FunctionalInterface -public interface CeTaskResult { - /** - * The UUID of the analysis created, if any, for the Component in {@link CeTask} - */ - Optional getAnalysisUuid(); -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/log/CeTaskLogging.java b/server/sonar-server/src/main/java/org/sonar/server/computation/log/CeTaskLogging.java deleted file mode 100644 index 8f1dbba3ced..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/log/CeTaskLogging.java +++ /dev/null @@ -1,37 +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.computation.log; - -import org.slf4j.MDC; -import org.sonar.server.computation.CeTask; - -public class CeTaskLogging { - - public static final String MDC_CE_TASK_UUID = "ceTaskUuid"; - - public void initForTask(CeTask task) { - MDC.put(MDC_CE_TASK_UUID, task.getUuid()); - } - - public void clearForTask() { - MDC.remove(MDC_CE_TASK_UUID); - } - -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/log/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/computation/log/package-info.java deleted file mode 100644 index 1088bac9be7..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/log/package-info.java +++ /dev/null @@ -1,23 +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. - */ -@ParametersAreNonnullByDefault -package org.sonar.server.computation.log; - -import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/computation/package-info.java deleted file mode 100644 index 2b97ccbf4fc..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/package-info.java +++ /dev/null @@ -1,23 +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. - */ -@ParametersAreNonnullByDefault -package org.sonar.server.computation; - -import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/container/EagerStart.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/container/EagerStart.java deleted file mode 100644 index 10ab10abf01..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/container/EagerStart.java +++ /dev/null @@ -1,33 +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.computation.task.container; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Components with this annotation will be eagerly started when loaded into the {@link TaskContainerImpl}. - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -public @interface EagerStart { -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/container/TaskContainer.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/container/TaskContainer.java deleted file mode 100644 index ba9a14b28c0..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/container/TaskContainer.java +++ /dev/null @@ -1,50 +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.computation.task.container; - -import org.picocontainer.PicoContainer; -import org.sonar.server.computation.CeTask; -import org.sonar.core.platform.ComponentContainer; -import org.sonar.core.platform.ContainerPopulator; - -/** - * The Compute Engine task container. Created for a specific parent {@link ComponentContainer} and a specific {@link CeTask}. - */ -public interface TaskContainer extends ContainerPopulator.Container, AutoCloseable { - - ComponentContainer getParent(); - - /** - * Starts task container, starting any startable component in it. - */ - void bootup(); - - /** - * Cleans up resources after process has been called and has returned. - */ - @Override - void close(); - - /** - * Access to the underlying pico container. - */ - PicoContainer getPicoContainer(); - -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/container/TaskContainerImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/container/TaskContainerImpl.java deleted file mode 100644 index 3902a1b9709..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/container/TaskContainerImpl.java +++ /dev/null @@ -1,93 +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.computation.task.container; - -import java.util.List; -import org.picocontainer.ComponentAdapter; -import org.picocontainer.ComponentMonitor; -import org.picocontainer.DefaultPicoContainer; -import org.picocontainer.MutablePicoContainer; -import org.picocontainer.behaviors.OptInCaching; -import org.picocontainer.lifecycle.ReflectionLifecycleStrategy; -import org.picocontainer.monitors.NullComponentMonitor; -import org.sonar.api.config.PropertyDefinitions; -import org.sonar.api.utils.log.Loggers; -import org.sonar.core.platform.ComponentContainer; -import org.sonar.core.platform.ContainerPopulator; -import org.sonar.core.platform.Module; -import org.sonar.core.platform.StopSafeReflectionLifecycleStrategy; - -import static java.util.Objects.requireNonNull; - -public class TaskContainerImpl extends ComponentContainer implements TaskContainer { - - public TaskContainerImpl(ComponentContainer parent, ContainerPopulator populator) { - super(createContainer(requireNonNull(parent)), parent.getComponentByType(PropertyDefinitions.class)); - - populateContainer(requireNonNull(populator)); - } - - private void populateContainer(ContainerPopulator populator) { - populator.populateContainer(this); - populateFromModules(); - } - - private void populateFromModules() { - List modules = getComponentsByType(Module.class); - for (Module module : modules) { - module.configure(this); - } - } - - /** - * Creates a PicContainer which extends the specified ComponentContainer but is not referenced in return - * and lazily starts its components. - */ - private static MutablePicoContainer createContainer(ComponentContainer parent) { - ComponentMonitor componentMonitor = new NullComponentMonitor(); - ReflectionLifecycleStrategy lifecycleStrategy = new StopSafeReflectionLifecycleStrategy(componentMonitor) { - @Override - public boolean isLazy(ComponentAdapter adapter) { - return adapter.getComponentImplementation().getAnnotation(EagerStart.class) == null; - } - }; - - return new DefaultPicoContainer(new OptInCaching(), lifecycleStrategy, parent.getPicoContainer(), componentMonitor); - } - - @Override - public void bootup() { - startComponents(); - } - - @Override - public String toString() { - return "TaskContainerImpl"; - } - - @Override - public void close() { - try { - stopComponents(); - } catch (Throwable t) { - Loggers.get(TaskContainerImpl.class).error("Cleanup of container failed", t); - } - } -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/container/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/container/package-info.java deleted file mode 100644 index f01956fbb38..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/container/package-info.java +++ /dev/null @@ -1,23 +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. - */ -@ParametersAreNonnullByDefault -package org.sonar.server.computation.task.container; - -import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/step/ComputationStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/step/ComputationStep.java deleted file mode 100644 index f8fd66fe961..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/step/ComputationStep.java +++ /dev/null @@ -1,31 +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.computation.task.step; - -/** - * A way of splitting the processing of a task into smaller items which can be executed sequencially - * by {@link ComputationStepExecutor}. - */ -public interface ComputationStep { - - void execute(); - - String getDescription(); -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/step/ComputationStepExecutor.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/step/ComputationStepExecutor.java deleted file mode 100644 index 536121f29ca..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/step/ComputationStepExecutor.java +++ /dev/null @@ -1,83 +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.computation.task.step; - -import javax.annotation.CheckForNull; -import javax.annotation.Nullable; -import org.sonar.api.utils.log.Logger; -import org.sonar.api.utils.log.Loggers; -import org.sonar.core.util.logs.Profiler; - -public final class ComputationStepExecutor { - private static final Logger LOGGER = Loggers.get(ComputationStepExecutor.class); - - private final ComputationSteps steps; - @CheckForNull - private final Listener listener; - - /** - * Used when no {@link ComputationStepExecutor.Listener} is available in pico - * container. - */ - public ComputationStepExecutor(ComputationSteps steps) { - this(steps, null); - } - - public ComputationStepExecutor(ComputationSteps steps, @Nullable Listener listener) { - this.steps = steps; - this.listener = listener; - } - - public void execute() { - Profiler stepProfiler = Profiler.create(LOGGER); - boolean allStepsExecuted = false; - try { - executeSteps(stepProfiler); - allStepsExecuted = true; - } finally { - if (listener != null) { - executeListener(allStepsExecuted); - } - } - } - - private void executeSteps(Profiler stepProfiler) { - for (ComputationStep step : steps.instances()) { - stepProfiler.start(); - step.execute(); - stepProfiler.stopDebug(step.getDescription()); - } - } - - private void executeListener(boolean allStepsExecuted) { - try { - listener.finished(allStepsExecuted); - } catch (Throwable e) { - // any Throwable throws by the listener going up the stack might hide an Exception/Error thrown by the step and - // cause it be swallowed. We don't wan't that => we catch Throwable - LOGGER.error("Execution of listener failed", e); - } - } - - @FunctionalInterface - public interface Listener { - void finished(boolean allStepsExecuted); - } -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/step/ComputationSteps.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/step/ComputationSteps.java deleted file mode 100644 index c35ca8f6a38..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/step/ComputationSteps.java +++ /dev/null @@ -1,39 +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.computation.task.step; - -import java.util.List; - -/** - * Ordered list of steps classes and instances to be executed in a Compute Engine process. - */ -public interface ComputationSteps { - /** - * List of all {@link ComputationStep}, - * ordered by execution sequence. - */ - List> orderedStepClasses(); - - /** - * List of all {@link ComputationStep}, - * ordered by execution sequence. - */ - Iterable instances(); -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/step/ExecuteStatelessInitExtensionsStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/step/ExecuteStatelessInitExtensionsStep.java deleted file mode 100644 index b587083d88b..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/step/ExecuteStatelessInitExtensionsStep.java +++ /dev/null @@ -1,56 +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.computation.task.step; - -import org.sonar.api.ce.ComputeEngineSide; - -/** - * Execute {@link StatelessInitExtension} instances in no specific order. - * If an extension fails (throws an exception), consecutive extensions - * won't be called. - */ -@ComputeEngineSide -public class ExecuteStatelessInitExtensionsStep implements ComputationStep { - - private final StatelessInitExtension[] extensions; - - public ExecuteStatelessInitExtensionsStep(StatelessInitExtension[] extensions) { - this.extensions = extensions; - } - - /** - * Used when zero {@link StatelessInitExtension} are registered into container. - */ - public ExecuteStatelessInitExtensionsStep() { - this(new StatelessInitExtension[0]); - } - - @Override - public void execute() { - for (StatelessInitExtension extension : extensions) { - extension.onInit(); - } - } - - @Override - public String getDescription() { - return "Initialize"; - } -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/step/StatelessInitExtension.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/step/StatelessInitExtension.java deleted file mode 100644 index aedc81e8347..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/step/StatelessInitExtension.java +++ /dev/null @@ -1,41 +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.computation.task.step; - -import org.sonar.api.ExtensionPoint; -import org.sonar.api.ce.ComputeEngineSide; - -/** - * Extension point that is called during processing of a task - * by {@link ExecuteStatelessInitExtensionsStep}. - * It is stateless, the same instance is reused for all tasks. - * As a consequence Compute Engine task components can't be injected - * as dependencies. - */ -@ComputeEngineSide -@ExtensionPoint -public interface StatelessInitExtension { - - /** - * This method can make the task fail by throwing a {@link RuntimeException} - */ - void onInit(); - -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/step/TypedException.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/step/TypedException.java deleted file mode 100644 index b600f90f7e3..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/step/TypedException.java +++ /dev/null @@ -1,33 +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.computation.task.step; - -/** - * This interface is implemented by the exceptions - * that provide a type of error when failing - * a Compute Engine task. - * The error type is persisted and available in - * the tasks returned by the web services api/ce. - */ -public interface TypedException { - - String getType(); - -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/step/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/step/package-info.java deleted file mode 100644 index 5868b7cccc4..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/step/package-info.java +++ /dev/null @@ -1,23 +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. - */ -@ParametersAreNonnullByDefault -package org.sonar.server.computation.task.step; - -import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/MutableTaskResultHolder.java b/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/MutableTaskResultHolder.java deleted file mode 100644 index 5e4409b1b73..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/MutableTaskResultHolder.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.computation.taskprocessor; - -import org.sonar.server.computation.CeTaskResult; - -public interface MutableTaskResultHolder extends TaskResultHolder { - /** - * @throws NullPointerException if {@code taskResult} is {@code null} - * @throws IllegalStateException if a {@link CeTaskResult} has already been set in the holder - */ - void setResult(CeTaskResult taskResult); -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/MutableTaskResultHolderImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/MutableTaskResultHolderImpl.java deleted file mode 100644 index 6fe1e53913e..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/MutableTaskResultHolderImpl.java +++ /dev/null @@ -1,44 +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.computation.taskprocessor; - -import javax.annotation.CheckForNull; -import org.sonar.server.computation.CeTaskResult; - -import static com.google.common.base.Preconditions.checkState; -import static java.util.Objects.requireNonNull; - -public class MutableTaskResultHolderImpl implements MutableTaskResultHolder { - @CheckForNull - private CeTaskResult result; - - @Override - public CeTaskResult getResult() { - checkState(this.result != null, "No CeTaskResult has been set in the holder"); - return this.result; - } - - @Override - public void setResult(CeTaskResult taskResult) { - requireNonNull(taskResult, "taskResult can not be null"); - checkState(this.result == null, "CeTaskResult has already been set in the holder"); - this.result = taskResult; - } -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/TaskResultHolder.java b/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/TaskResultHolder.java deleted file mode 100644 index b4c3e978150..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/TaskResultHolder.java +++ /dev/null @@ -1,29 +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.computation.taskprocessor; - -import org.sonar.server.computation.CeTaskResult; - -public interface TaskResultHolder { - /** - * @throws IllegalStateException if holder holds no CeTaskResult - */ - CeTaskResult getResult(); -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/util/InitializedProperty.java b/server/sonar-server/src/main/java/org/sonar/server/computation/util/InitializedProperty.java deleted file mode 100644 index 01170eb9fde..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/util/InitializedProperty.java +++ /dev/null @@ -1,43 +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.computation.util; - -import javax.annotation.CheckForNull; -import javax.annotation.Nullable; - -public class InitializedProperty { - private E property; - private boolean initialized = false; - - public InitializedProperty setProperty(@Nullable E property) { - this.property = property; - this.initialized = true; - return this; - } - - @CheckForNull - public E getProperty() { - return property; - } - - public boolean isInitialized() { - return initialized; - } -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/util/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/computation/util/package-info.java deleted file mode 100644 index 415bc7b76f9..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/util/package-info.java +++ /dev/null @@ -1,24 +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. - */ -@ParametersAreNonnullByDefault -package org.sonar.server.computation.util; - -import javax.annotation.ParametersAreNonnullByDefault; - diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/CeTaskTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/CeTaskTest.java deleted file mode 100644 index b42261f5eb7..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/CeTaskTest.java +++ /dev/null @@ -1,148 +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.computation; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import static org.assertj.core.api.Assertions.assertThat; - -public class CeTaskTest { - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - private CeTask.Builder underTest = new CeTask.Builder(); - - @Test - public void build_fails_with_NPE_if_organizationUuid_is_null() { - expectedException.expect(NullPointerException.class); - expectedException.expectMessage("organizationUuid can't be null nor empty"); - - underTest.build(); - } - - @Test - public void build_fails_with_NPE_if_organizationUuid_is_empty() { - underTest.setOrganizationUuid(""); - - expectedException.expect(NullPointerException.class); - expectedException.expectMessage("organizationUuid can't be null nor empty"); - - underTest.build(); - } - - @Test - public void build_fails_with_NPE_if_uid_is_null() { - underTest.setOrganizationUuid("org1"); - - expectedException.expect(NullPointerException.class); - expectedException.expectMessage("uuid can't be null nor empty"); - - underTest.build(); - } - - @Test - public void build_fails_with_NPE_if_uuid_is_empty() { - underTest.setOrganizationUuid("org1").setUuid(""); - - expectedException.expect(NullPointerException.class); - expectedException.expectMessage("uuid can't be null nor empty"); - - underTest.build(); - } - - @Test - public void build_fails_with_NPE_if_type_is_null() { - underTest.setOrganizationUuid("org1").setUuid("uuid"); - - expectedException.expect(NullPointerException.class); - expectedException.expectMessage("type can't be null nor empty"); - - underTest.build(); - } - - @Test - public void build_fails_with_NPE_if_type_is_empty() { - underTest.setOrganizationUuid("org1").setUuid("uuid").setType(""); - - expectedException.expect(NullPointerException.class); - expectedException.expectMessage("type can't be null nor empty"); - - underTest.build(); - } - - @Test - public void verify_getters() { - underTest.setOrganizationUuid("org1"); - underTest.setType("TYPE_1"); - underTest.setUuid("UUID_1"); - underTest.setSubmitterUuid("LOGIN_1"); - underTest.setComponentKey("COMPONENT_KEY_1"); - underTest.setComponentUuid("COMPONENT_UUID_1"); - underTest.setComponentName("The component"); - - CeTask task = underTest.build(); - - assertThat(task.getOrganizationUuid()).isEqualTo("org1"); - assertThat(task.getUuid()).isEqualTo("UUID_1"); - assertThat(task.getType()).isEqualTo("TYPE_1"); - assertThat(task.getSubmitterUuid()).isEqualTo("LOGIN_1"); - assertThat(task.getComponentKey()).isEqualTo("COMPONENT_KEY_1"); - assertThat(task.getComponentUuid()).isEqualTo("COMPONENT_UUID_1"); - assertThat(task.getComponentName()).isEqualTo("The component"); - } - - @Test - public void empty_in_component_properties_is_considered_as_null() { - CeTask ceTask = underTest.setOrganizationUuid("org1").setUuid("uuid").setType("type") - .setComponentKey("") - .setComponentName("") - .setComponentUuid("") - .build(); - - assertThat(ceTask.getComponentKey()).isNull(); - assertThat(ceTask.getComponentName()).isNull(); - assertThat(ceTask.getComponentUuid()).isNull(); - } - - @Test - public void empty_in_submitterLogin_is_considered_as_null() { - CeTask ceTask = underTest.setOrganizationUuid("org1").setUuid("uuid").setType("type") - .setSubmitterUuid("") - .build(); - - assertThat(ceTask.getSubmitterUuid()).isNull(); - } - - @Test - public void equals_and_hashCode_on_uuid() { - underTest.setOrganizationUuid("org1").setType("TYPE_1").setUuid("UUID_1"); - CeTask task1 = underTest.build(); - CeTask task1bis = underTest.build(); - CeTask task2 = new CeTask.Builder().setOrganizationUuid("org1").setType("TYPE_1").setUuid("UUID_2").build(); - - assertThat(task1.equals(task1)).isTrue(); - assertThat(task1.equals(task1bis)).isTrue(); - assertThat(task1.equals(task2)).isFalse(); - assertThat(task1.hashCode()).isEqualTo(task1.hashCode()); - assertThat(task1.hashCode()).isEqualTo(task1bis.hashCode()); - } -} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/log/CeTaskLoggingTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/log/CeTaskLoggingTest.java deleted file mode 100644 index 5193eb1efd8..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/log/CeTaskLoggingTest.java +++ /dev/null @@ -1,78 +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.computation.log; - -import ch.qos.logback.core.joran.spi.JoranException; -import org.junit.After; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.mockito.Mockito; -import org.slf4j.MDC; -import org.sonar.process.logging.LogbackHelper; -import org.sonar.server.computation.CeTask; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.when; -import static org.sonar.server.computation.log.CeTaskLogging.MDC_CE_TASK_UUID; - -public class CeTaskLoggingTest { - - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - private LogbackHelper helper = new LogbackHelper(); - private CeTaskLogging underTest = new CeTaskLogging(); - - @After - public void resetLogback() throws JoranException { - helper.resetFromXml("/logback-test.xml"); - } - - @After - public void cleanMDC() { - MDC.clear(); - } - - @Test - public void initForTask_stores_task_uuid_in_MDC() { - String uuid = "ce_task_uuid"; - - underTest.initForTask(createCeTask(uuid)); - - assertThat(MDC.get(MDC_CE_TASK_UUID)).isEqualTo(uuid); - } - - private CeTask createCeTask(String uuid) { - CeTask ceTask = Mockito.mock(CeTask.class); - when(ceTask.getUuid()).thenReturn(uuid); - return ceTask; - } - - @Test - public void clearForTask_removes_task_uuid_from_MDC() { - MDC.put(MDC_CE_TASK_UUID, "some_value"); - - underTest.clearForTask(); - - assertThat(MDC.get(MDC_CE_TASK_UUID)).isNull(); - } - -} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/ChangeLogLevel.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/ChangeLogLevel.java deleted file mode 100644 index 3260b7263cd..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/ChangeLogLevel.java +++ /dev/null @@ -1,40 +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.computation.task; - -import org.sonar.api.utils.log.Logger; -import org.sonar.api.utils.log.LoggerLevel; -import org.sonar.api.utils.log.Loggers; - -public final class ChangeLogLevel implements AutoCloseable { - private final Logger logger; - private final LoggerLevel previous; - - public ChangeLogLevel(Class clazz, LoggerLevel newLevel) { - this.logger = Loggers.get(clazz); - this.previous = logger.getLevel(); - logger.setLevel(newLevel); - } - - @Override - public void close() { - logger.setLevel(previous); - } -} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/container/TaskContainerImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/container/TaskContainerImplTest.java deleted file mode 100644 index debaac8a916..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/container/TaskContainerImplTest.java +++ /dev/null @@ -1,114 +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.computation.task.container; - -import org.junit.Test; -import org.picocontainer.Startable; -import org.sonar.core.platform.ComponentContainer; -import org.sonar.core.platform.ContainerPopulator; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - -public class TaskContainerImplTest { - private ComponentContainer parent = new ComponentContainer(); - private ContainerPopulator populator = mock(ContainerPopulator.class); - - @Test(expected = NullPointerException.class) - public void constructor_fails_fast_on_null_container() { - new TaskContainerImpl(null, mock(ContainerPopulator.class)); - } - - @Test(expected = NullPointerException.class) - public void constructor_fails_fast_on_null_item() { - new TaskContainerImpl(new ComponentContainer(), null); - } - - @Test - public void calls_method_populateContainer_of_passed_in_populator() { - TaskContainerImpl ceContainer = new TaskContainerImpl(parent, populator); - - verify(populator).populateContainer(ceContainer); - } - - @Test - public void ce_container_is_not_child_of_specified_container() { - TaskContainerImpl ceContainer = new TaskContainerImpl(parent, populator); - - assertThat(parent.getChildren()).isEmpty(); - verify(populator).populateContainer(ceContainer); - } - - @Test - public void bootup_starts_components_lazily_unless_they_are_annotated_with_EagerStart() { - final DefaultStartable defaultStartable = new DefaultStartable(); - final EagerStartable eagerStartable = new EagerStartable(); - TaskContainerImpl ceContainer = new TaskContainerImpl(parent, container -> { - container.add(defaultStartable); - container.add(eagerStartable); - }); - ceContainer.bootup(); - - assertThat(defaultStartable.startCalls).isEqualTo(0); - assertThat(defaultStartable.stopCalls).isEqualTo(0); - assertThat(eagerStartable.startCalls).isEqualTo(1); - assertThat(eagerStartable.stopCalls).isEqualTo(0); - } - - @Test - public void close_stops_started_components() { - final DefaultStartable defaultStartable = new DefaultStartable(); - final EagerStartable eagerStartable = new EagerStartable(); - TaskContainerImpl ceContainer = new TaskContainerImpl(parent, container -> { - container.add(defaultStartable); - container.add(eagerStartable); - }); - ceContainer.bootup(); - - ceContainer.close(); - - assertThat(defaultStartable.startCalls).isEqualTo(0); - assertThat(defaultStartable.stopCalls).isEqualTo(0); - assertThat(eagerStartable.startCalls).isEqualTo(1); - assertThat(eagerStartable.stopCalls).isEqualTo(1); - } - - public static class DefaultStartable implements Startable { - protected int startCalls = 0; - protected int stopCalls = 0; - - @Override - public void start() { - startCalls++; - } - - @Override - public void stop() { - stopCalls++; - } - } - - @EagerStart - public static class EagerStartable extends DefaultStartable { - } - - -} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/step/ComputationStepExecutorTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/step/ComputationStepExecutorTest.java deleted file mode 100644 index 19050a279bf..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/step/ComputationStepExecutorTest.java +++ /dev/null @@ -1,166 +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.computation.task.step; - -import java.util.Arrays; -import java.util.List; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.mockito.InOrder; -import org.sonar.api.utils.log.LogTester; -import org.sonar.api.utils.log.LoggerLevel; -import org.sonar.server.computation.task.ChangeLogLevel; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.fail; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -public class ComputationStepExecutorTest { - @Rule - public LogTester logTester = new LogTester(); - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - private final ComputationStepExecutor.Listener listener = mock(ComputationStepExecutor.Listener.class); - private final ComputationStep computationStep1 = mockComputationStep("step1"); - private final ComputationStep computationStep2 = mockComputationStep("step2"); - private final ComputationStep computationStep3 = mockComputationStep("step3"); - - @Test - public void execute_call_execute_on_each_ComputationStep_in_order_returned_by_instances_method() { - new ComputationStepExecutor(mockComputationSteps(computationStep1, computationStep2, computationStep3)) - .execute(); - - InOrder inOrder = inOrder(computationStep1, computationStep2, computationStep3); - inOrder.verify(computationStep1).execute(); - inOrder.verify(computationStep1).getDescription(); - inOrder.verify(computationStep2).execute(); - inOrder.verify(computationStep2).getDescription(); - inOrder.verify(computationStep3).execute(); - inOrder.verify(computationStep3).getDescription(); - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void execute_let_exception_thrown_by_ComputationStep_go_up_as_is() { - String message = "Exception should go up"; - - ComputationStep computationStep = mockComputationStep("step1"); - doThrow(new RuntimeException(message)) - .when(computationStep) - .execute(); - - ComputationStepExecutor computationStepExecutor = new ComputationStepExecutor(mockComputationSteps(computationStep)); - - expectedException.expect(RuntimeException.class); - expectedException.expectMessage(message); - - computationStepExecutor.execute(); - } - - @Test - public void execute_does_not_log_end_timing_for_each_ComputationStep_called_when_level_is_INFO() { - List infoLogs = execute_logs_end_timing_for_each_ComputationStep_called_when_(LoggerLevel.INFO); - assertThat(infoLogs).isEmpty(); - } - - @Test - public void execute_logs_end_timing_for_each_ComputationStep_called_when_level_is_DEBUG() { - List infoLogs = execute_logs_end_timing_for_each_ComputationStep_called_when_(LoggerLevel.DEBUG); - assertThat(infoLogs).hasSize(2); - assertThat(infoLogs.get(0)).contains("step1 | time="); - assertThat(infoLogs.get(1)).contains("step2 | time="); - } - - @Test - public void execute_logs_end_timing_for_each_ComputationStep_called_when_level_is_TRACE() { - List infoLogs = execute_logs_end_timing_for_each_ComputationStep_called_when_(LoggerLevel.TRACE); - assertThat(infoLogs).hasSize(2); - assertThat(infoLogs.get(0)).contains("step1 | time="); - assertThat(infoLogs.get(1)).contains("step2 | time="); - } - - private List execute_logs_end_timing_for_each_ComputationStep_called_when_(LoggerLevel level) { - try (ChangeLogLevel executor = new ChangeLogLevel(ComputationStepExecutor.class, level); - ChangeLogLevel step1 = new ChangeLogLevel(computationStep1.getClass(), level); - ChangeLogLevel step2 = new ChangeLogLevel(computationStep2.getClass(), level)) { - new ComputationStepExecutor(mockComputationSteps(computationStep1, computationStep2)) - .execute(); - - return logTester.logs(LoggerLevel.DEBUG); - } - } - - @Test - public void execute_calls_listener_finished_method_with_all_step_runs() { - new ComputationStepExecutor(mockComputationSteps(computationStep1, computationStep2), listener) - .execute(); - - verify(listener).finished(true); - verifyNoMoreInteractions(listener); - } - - @Test - public void execute_calls_listener_finished_method_even_if_a_step_throws_an_exception() { - RuntimeException toBeThrown = new RuntimeException("simulating failing execute Step method"); - doThrow(toBeThrown) - .when(computationStep1) - .execute(); - - try { - new ComputationStepExecutor(mockComputationSteps(computationStep1, computationStep2), listener) - .execute(); - fail("exception toBeThrown should have been raised"); - } catch (RuntimeException e) { - assertThat(e).isSameAs(toBeThrown); - verify(listener).finished(false); - verifyNoMoreInteractions(listener); - } - } - - @Test - public void execute_does_not_fail_if_listener_throws_Throwable() { - ComputationStepExecutor.Listener listener = mock(ComputationStepExecutor.Listener.class); - doThrow(new Error("Facking error thrown by Listener")) - .when(listener) - .finished(anyBoolean()); - - new ComputationStepExecutor(mockComputationSteps(computationStep1), listener).execute(); - } - - private static ComputationSteps mockComputationSteps(ComputationStep... computationSteps) { - ComputationSteps steps = mock(ComputationSteps.class); - when(steps.instances()).thenReturn(Arrays.asList(computationSteps)); - return steps; - } - - private static ComputationStep mockComputationStep(String desc) { - ComputationStep mock = mock(ComputationStep.class); - when(mock.getDescription()).thenReturn(desc); - return mock; - } -} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/step/ExecuteStatelessInitExtensionsStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/step/ExecuteStatelessInitExtensionsStepTest.java deleted file mode 100644 index fdf4049bf35..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/step/ExecuteStatelessInitExtensionsStepTest.java +++ /dev/null @@ -1,89 +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.computation.task.step; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.mockito.InOrder; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; - -public class ExecuteStatelessInitExtensionsStepTest { - - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - @Test - public void test_getDescription() { - ExecuteStatelessInitExtensionsStep underTest = new ExecuteStatelessInitExtensionsStep(); - - assertThat(underTest.getDescription()).isEqualTo("Initialize"); - } - - @Test - public void do_nothing_if_no_extensions() { - ExecuteStatelessInitExtensionsStep underTest = new ExecuteStatelessInitExtensionsStep(); - - // no failure - underTest.execute(); - } - - @Test - public void execute_extensions() { - StatelessInitExtension ext1 = mock(StatelessInitExtension.class); - StatelessInitExtension ext2 = mock(StatelessInitExtension.class); - - ExecuteStatelessInitExtensionsStep underTest = new ExecuteStatelessInitExtensionsStep( - new StatelessInitExtension[] {ext1, ext2}); - underTest.execute(); - - InOrder inOrder = inOrder(ext1, ext2); - inOrder.verify(ext1).onInit(); - inOrder.verify(ext2).onInit(); - } - - @Test - public void fail_if_an_extension_throws_an_exception() { - StatelessInitExtension ext1 = mock(StatelessInitExtension.class); - StatelessInitExtension ext2 = mock(StatelessInitExtension.class); - doThrow(new IllegalStateException("BOOM")).when(ext2).onInit(); - StatelessInitExtension ext3 = mock(StatelessInitExtension.class); - - ExecuteStatelessInitExtensionsStep underTest = new ExecuteStatelessInitExtensionsStep( - new StatelessInitExtension[] {ext1, ext2, ext3}); - - try { - underTest.execute(); - fail(); - } catch (IllegalStateException e) { - assertThat(e).hasMessage("BOOM"); - verify(ext1).onInit(); - verify(ext3, never()).onInit(); - } - } - -} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/step/StepsExplorer.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/step/StepsExplorer.java deleted file mode 100644 index 1f836dee41c..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/step/StepsExplorer.java +++ /dev/null @@ -1,68 +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.computation.task.step; - -import com.google.common.base.Function; -import com.google.common.base.Predicate; -import java.lang.reflect.Modifier; -import java.util.Set; -import javax.annotation.Nonnull; -import org.reflections.Reflections; - -import static com.google.common.base.Predicates.notNull; -import static com.google.common.collect.FluentIterable.from; - -public class StepsExplorer { - /** - * Compute set of canonical names of classes implementing ComputationStep in the specified package using reflection. - */ - public static Set retrieveStepPackageStepsCanonicalNames(String packageName) { - Reflections reflections = new Reflections(packageName); - - return from(reflections.getSubTypesOf(ComputationStep.class)) - .filter(NotAbstractClass.INSTANCE) - .transform(ClassToCanonicalName.INSTANCE) - // anonymous classes do not have canonical names - .filter(notNull()) - .toSet(); - } - - private enum NotAbstractClass implements Predicate> { - INSTANCE; - - @Override - public boolean apply(Class input) { - return !Modifier.isAbstract(input.getModifiers()); - } - } - - public static Function, String> toCanonicalName() { - return ClassToCanonicalName.INSTANCE; - } - - private enum ClassToCanonicalName implements Function, String> { - INSTANCE; - - @Override - public String apply(@Nonnull Class input) { - return input.getCanonicalName(); - } - } -} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/taskprocessor/MutableTaskResultHolderImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/taskprocessor/MutableTaskResultHolderImplTest.java deleted file mode 100644 index f81de440ad6..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/taskprocessor/MutableTaskResultHolderImplTest.java +++ /dev/null @@ -1,70 +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.computation.taskprocessor; - -import org.assertj.core.api.Assertions; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.sonar.server.computation.CeTaskResult; - -import static org.mockito.Mockito.mock; - -public class MutableTaskResultHolderImplTest { - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - private MutableTaskResultHolder underTest = new MutableTaskResultHolderImpl(); - - @Test - public void getResult_throws_ISE_if_no_CeTaskResult_is_set() { - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage("No CeTaskResult has been set in the holder"); - - underTest.getResult(); - } - - @Test - public void getResult_returns_object_set_with_setResult() { - CeTaskResult taskResult = mock(CeTaskResult.class); - - underTest.setResult(taskResult); - - Assertions.assertThat(underTest.getResult()).isSameAs(taskResult); - } - - @Test - public void setResult_throws_NPE_if_CeTaskResult_argument_is_null() { - expectedException.expect(NullPointerException.class); - expectedException.expectMessage("taskResult can not be null"); - - underTest.setResult(null); - } - - @Test - public void setResult_throws_ISE_if_called_twice() { - underTest.setResult(mock(CeTaskResult.class)); - - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage("CeTaskResult has already been set in the holder"); - - underTest.setResult(mock(CeTaskResult.class)); - } -} diff --git a/settings.gradle b/settings.gradle index 0a5d241e0b2..7ca50832a31 100644 --- a/settings.gradle +++ b/settings.gradle @@ -4,6 +4,7 @@ include 'plugins:sonar-xoo-plugin' include 'server:sonar-bitbucketcloud' include 'server:sonar-ce' +include 'server:sonar-ce-task' include 'server:sonar-ce-task-projectanalysis' include 'server:sonar-db-testing' include 'server:sonar-db-core'