diff options
author | Simon Brandhof <simon.brandhof@sonarsource.com> | 2015-07-04 00:34:24 +0200 |
---|---|---|
committer | Simon Brandhof <simon.brandhof@sonarsource.com> | 2015-07-04 17:00:08 +0200 |
commit | 1df148803610cd54f182b8636f01c0e6ece92b19 (patch) | |
tree | 8b6d2919ebe3575556b8796fd95a2b89996933ff /sonar-db | |
parent | 1018747567d50056a49aa7c8421d596f18f25344 (diff) | |
download | sonarqube-1df148803610cd54f182b8636f01c0e6ece92b19.tar.gz sonarqube-1df148803610cd54f182b8636f01c0e6ece92b19.zip |
Extract module sonar-db
Diffstat (limited to 'sonar-db')
764 files changed, 48762 insertions, 0 deletions
diff --git a/sonar-db/pom.xml b/sonar-db/pom.xml new file mode 100644 index 00000000000..422677b6342 --- /dev/null +++ b/sonar-db/pom.xml @@ -0,0 +1,135 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.codehaus.sonar</groupId> + <artifactId>sonar</artifactId> + <version>5.2-SNAPSHOT</version> + </parent> + + <artifactId>sonar-db</artifactId> + + <name>SonarQube :: Database</name> + <description>Create and request SonarQube schema</description> + + <dependencies> + <dependency> + <groupId>com.google.code.findbugs</groupId> + <artifactId>jsr305</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>commons-codec</groupId> + <artifactId>commons-codec</artifactId> + </dependency> + <dependency> + <groupId>org.codehaus.sonar</groupId> + <artifactId>sonar-batch-protocol</artifactId> + </dependency> + <dependency> + <groupId>org.codehaus.sonar</groupId> + <artifactId>sonar-core</artifactId> + </dependency> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>sonar-plugin-api</artifactId> + </dependency> + <dependency> + <groupId>org.mybatis</groupId> + <artifactId>mybatis</artifactId> + </dependency> + <dependency> + <groupId>commons-dbcp</groupId> + <artifactId>commons-dbcp</artifactId> + </dependency> + <dependency> + <groupId>commons-dbutils</groupId> + <artifactId>commons-dbutils</artifactId> + </dependency> + <dependency> + <groupId>net.jpountz.lz4</groupId> + <artifactId>lz4</artifactId> + </dependency> + + <!-- logging --> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + </dependency> + <dependency> + <groupId>ch.qos.logback</groupId> + <artifactId>logback-classic</artifactId> + </dependency> + <dependency> + <groupId>ch.qos.logback</groupId> + <artifactId>logback-core</artifactId> + </dependency> + + <!-- tests --> + <dependency> + <groupId>org.codehaus.sonar</groupId> + <artifactId>sonar-testing-harness</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.dbunit</groupId> + <artifactId>dbunit</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>com.google.code.bean-matchers</groupId> + <artifactId>bean-matchers</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.simpleframework</groupId> + <artifactId>simple</artifactId> + <version>4.1.21</version> + <scope>test</scope> + </dependency> + + + <!-- + JDBC drivers for MyBatis integration tests. + They can't be moved to the profile run-mybatis-its because + --> + <dependency> + <groupId>mysql</groupId> + <artifactId>mysql-connector-java</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.postgresql</groupId> + <artifactId>postgresql</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>net.sourceforge.jtds</groupId> + <artifactId>jtds</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>com.h2database</groupId> + <artifactId>h2</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>test-jar</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> diff --git a/sonar-db/src/main/java/org/sonar/batch/index/ResourceCopy.java b/sonar-db/src/main/java/org/sonar/batch/index/ResourceCopy.java new file mode 100644 index 00000000000..6a3ccd83029 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/batch/index/ResourceCopy.java @@ -0,0 +1,29 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.batch.index; + +/** + * Used by views !! + */ +public interface ResourceCopy { + + int getCopyResourceId(); + +} diff --git a/sonar-db/src/main/java/org/sonar/core/issue/ActionPlanStats.java b/sonar-db/src/main/java/org/sonar/core/issue/ActionPlanStats.java new file mode 100644 index 00000000000..593ec0d63ca --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/core/issue/ActionPlanStats.java @@ -0,0 +1,76 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.core.issue; + +import java.util.Date; +import org.sonar.api.issue.ActionPlan; +import org.sonar.api.utils.internal.Uuids; + +public class ActionPlanStats extends DefaultActionPlan { + + private int totalIssues; + private int unresolvedIssues; + + private ActionPlanStats() { + + } + + public static ActionPlanStats create(String name) { + ActionPlanStats actionPlan = new ActionPlanStats(); + actionPlan.setKey(Uuids.create()); + Date now = new Date(); + actionPlan.setName(name); + actionPlan.setStatus(ActionPlan.STATUS_OPEN); + actionPlan.setCreatedAt(now).setUpdatedAt(now); + return actionPlan; + } + + public int totalIssues() { + return totalIssues; + } + + public ActionPlanStats setTotalIssues(int totalIssues) { + this.totalIssues = totalIssues; + return this; + } + + public int unresolvedIssues() { + return unresolvedIssues; + } + + public ActionPlanStats setUnresolvedIssues(int unresolvedIssues) { + this.unresolvedIssues = unresolvedIssues; + return this; + } + + public int resolvedIssues() { + return totalIssues - unresolvedIssues; + } + + public boolean isOpen() { + return ActionPlan.STATUS_OPEN.equals(status()); + } + + public boolean overDue() { + Date deadline = deadLine(); + return isOpen() && deadline != null && new Date().after(deadline); + } +} diff --git a/sonar-db/src/main/java/org/sonar/core/issue/db/package-info.java b/sonar-db/src/main/java/org/sonar/core/issue/db/package-info.java new file mode 100644 index 00000000000..55dc4912649 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/core/issue/db/package-info.java @@ -0,0 +1,24 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.core.issue.db; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/sonar-db/src/main/java/org/sonar/core/issue/package-info.java b/sonar-db/src/main/java/org/sonar/core/issue/package-info.java new file mode 100644 index 00000000000..0b6aa438498 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/core/issue/package-info.java @@ -0,0 +1,24 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.core.issue; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/sonar-db/src/main/java/org/sonar/core/permission/ComponentPermissions.java b/sonar-db/src/main/java/org/sonar/core/permission/ComponentPermissions.java new file mode 100644 index 00000000000..4d2522cae47 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/core/permission/ComponentPermissions.java @@ -0,0 +1,38 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.core.permission; + +import com.google.common.collect.ImmutableList; +import java.util.List; +import org.sonar.api.web.UserRole; + +/** + * Holds the constants representing the various component permissions that can be assigned to users & groups + * + */ +public final class ComponentPermissions { + + /** + * All the component permissions values, ordered from {@link UserRole#USER} to {@link UserRole#CODEVIEWER}. + */ + public static final List<String> ALL = ImmutableList.of(UserRole.USER, UserRole.ADMIN, UserRole.ISSUE_ADMIN, UserRole.CODEVIEWER); + +} diff --git a/sonar-db/src/main/java/org/sonar/core/permission/GlobalPermissions.java b/sonar-db/src/main/java/org/sonar/core/permission/GlobalPermissions.java new file mode 100644 index 00000000000..9f671e16794 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/core/permission/GlobalPermissions.java @@ -0,0 +1,48 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.core.permission; + +import com.google.common.collect.ImmutableList; +import java.util.List; + +/** + * Holds the constants representing the various global permissions that can be assigned to users & groups + * + */ +public final class GlobalPermissions { + + public static final String SYSTEM_ADMIN = "admin"; + public static final String QUALITY_PROFILE_ADMIN = "profileadmin"; + public static final String DASHBOARD_SHARING = "shareDashboard"; + public static final String SCAN_EXECUTION = "scan"; + public static final String PREVIEW_EXECUTION = "dryRunScan"; + public static final String PROVISIONING = "provisioning"; + + /** + * All the global permissions values, ordered from {@link #SYSTEM_ADMIN} to {@link #PROVISIONING}. + */ + public static final List<String> ALL = ImmutableList.of(SYSTEM_ADMIN, QUALITY_PROFILE_ADMIN, DASHBOARD_SHARING, SCAN_EXECUTION, PREVIEW_EXECUTION, PROVISIONING); + + private GlobalPermissions() { + // only static methods + } + +} diff --git a/sonar-db/src/main/java/org/sonar/core/permission/GroupWithPermission.java b/sonar-db/src/main/java/org/sonar/core/permission/GroupWithPermission.java new file mode 100644 index 00000000000..0dcc1d7ce1d --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/core/permission/GroupWithPermission.java @@ -0,0 +1,83 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.core.permission; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; + +public class GroupWithPermission { + + private String name; + private String description; + private boolean hasPermission; + + public String name() { + return name; + } + + public GroupWithPermission setName(String name) { + this.name = name; + return this; + } + + @CheckForNull + public String description() { + return description; + } + + public GroupWithPermission setDescription(@Nullable String description) { + this.description = description; + return this; + } + + public boolean hasPermission() { + return hasPermission; + } + + public GroupWithPermission hasPermission(boolean hasPermission) { + this.hasPermission = hasPermission; + return this; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + GroupWithPermission that = (GroupWithPermission) o; + return name.equals(that.name); + } + + @Override + public int hashCode() { + return name.hashCode(); + } +} diff --git a/sonar-db/src/main/java/org/sonar/core/permission/UserWithPermission.java b/sonar-db/src/main/java/org/sonar/core/permission/UserWithPermission.java new file mode 100644 index 00000000000..69a2f77a28a --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/core/permission/UserWithPermission.java @@ -0,0 +1,79 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.core.permission; + +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; + +public class UserWithPermission { + + private String login; + private String name; + private boolean hasPermission; + + public String login() { + return login; + } + + public UserWithPermission setLogin(String login) { + this.login = login; + return this; + } + + public String name() { + return name; + } + + public UserWithPermission setName(String name) { + this.name = name; + return this; + } + + public boolean hasPermission() { + return hasPermission; + } + + public UserWithPermission hasPermission(boolean hasPermission) { + this.hasPermission = hasPermission; + return this; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + UserWithPermission that = (UserWithPermission) o; + return login.equals(that.login); + } + + @Override + public int hashCode() { + return login.hashCode(); + } +} diff --git a/sonar-db/src/main/java/org/sonar/core/permission/package-info.java b/sonar-db/src/main/java/org/sonar/core/permission/package-info.java new file mode 100644 index 00000000000..7e8c924d2ca --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/core/permission/package-info.java @@ -0,0 +1,25 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.core.permission; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/sonar-db/src/main/java/org/sonar/core/timemachine/Periods.java b/sonar-db/src/main/java/org/sonar/core/timemachine/Periods.java new file mode 100644 index 00000000000..2d16c7137d0 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/core/timemachine/Periods.java @@ -0,0 +1,195 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.core.timemachine; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.apache.commons.lang.StringUtils; +import org.sonar.api.CoreProperties; +import org.sonar.api.config.Settings; +import org.sonar.api.database.model.Snapshot; +import org.sonar.api.i18n.I18n; +import org.sonar.api.server.ServerSide; + +import static org.sonar.api.utils.DateUtils.longToDate; + +@ServerSide +public class Periods { + + private final Settings settings; + private final I18n i18n; + + public Periods(Settings settings, I18n i18n) { + this.settings = settings; + this.i18n = i18n; + } + + @CheckForNull + public String label(Snapshot snapshot, int periodIndex) { + return label(snapshot.getPeriodMode(periodIndex), snapshot.getPeriodModeParameter(periodIndex), longToDate(snapshot.getPeriodDateMs(periodIndex))); + } + + @CheckForNull + public String abbreviation(Snapshot snapshot, int periodIndex) { + return abbreviation(snapshot.getPeriodMode(periodIndex), snapshot.getPeriodModeParameter(periodIndex), longToDate(snapshot.getPeriodDateMs(periodIndex))); + } + + @CheckForNull + public String label(int periodIndex) { + String periodProperty = settings.getString(CoreProperties.TIMEMACHINE_PERIOD_PREFIX + periodIndex); + PeriodParameters periodParameters = new PeriodParameters(periodProperty); + return label(periodParameters.getMode(), periodParameters.getParam(), periodParameters.getDate()); + } + + @CheckForNull + public String abbreviation(int periodIndex) { + String periodProperty = settings.getString(CoreProperties.TIMEMACHINE_PERIOD_PREFIX + periodIndex); + PeriodParameters periodParameters = new PeriodParameters(periodProperty); + return abbreviation(periodParameters.getMode(), periodParameters.getParam(), periodParameters.getDate()); + } + + @CheckForNull + public String label(String mode, String param, Date date) { + return label(mode, param, convertDate(date), false); + } + + @CheckForNull + public String label(String mode, String param, String date) { + return label(mode, param, date, false); + } + + @CheckForNull + public String abbreviation(String mode, String param, Date date) { + return label(mode, param, convertDate(date), true); + } + + @CheckForNull + private String label(String mode, @Nullable String param, @Nullable String date, boolean shortLabel) { + String label; + if (CoreProperties.TIMEMACHINE_MODE_DAYS.equals(mode)) { + label = label("over_x_days", shortLabel, param); + if (date != null) { + label = label("over_x_days_detailed", shortLabel, param, date); + } + } else if (CoreProperties.TIMEMACHINE_MODE_VERSION.equals(mode)) { + label = label("since_version", shortLabel, param); + if (date != null) { + label = label("since_version_detailed", shortLabel, param, date); + } + } else if (CoreProperties.TIMEMACHINE_MODE_PREVIOUS_ANALYSIS.equals(mode)) { + label = label("since_previous_analysis", shortLabel); + if (date != null) { + label = label("since_previous_analysis_detailed", shortLabel, date); + } + } else if (CoreProperties.TIMEMACHINE_MODE_PREVIOUS_VERSION.equals(mode)) { + label = label("since_previous_version", shortLabel); + if (param != null) { + label = label("since_previous_version_detailed", shortLabel, param); + if (date != null) { + label = label("since_previous_version_detailed", shortLabel, param, date); + } + } + } else if (CoreProperties.TIMEMACHINE_MODE_DATE.equals(mode)) { + label = label("since_x", shortLabel, date); + } else { + throw new IllegalArgumentException("This mode is not supported : " + mode); + } + return label; + } + + private String label(String key, boolean shortLabel, Object... parameters) { + String msgKey = key; + if (shortLabel) { + msgKey += ".short"; + } + return i18n.message(getLocale(), msgKey, null, parameters); + } + + @CheckForNull + private static String convertDate(Date date) { + if (date != null) { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy MMM dd"); + return dateFormat.format(date); + } + return null; + } + + private static Locale getLocale() { + return Locale.ENGLISH; + } + + private static class PeriodParameters { + + private String mode = null; + private String param = null; + private Date date = null; + + public PeriodParameters(String periodProperty) { + if (CoreProperties.TIMEMACHINE_MODE_PREVIOUS_ANALYSIS.equals(periodProperty) || CoreProperties.TIMEMACHINE_MODE_PREVIOUS_VERSION.equals(periodProperty)) { + mode = periodProperty; + } else if (findByDays(periodProperty) != null) { + mode = CoreProperties.TIMEMACHINE_MODE_DAYS; + param = Integer.toString(findByDays(periodProperty)); + } else if (findByDate(periodProperty) != null) { + mode = CoreProperties.TIMEMACHINE_MODE_DATE; + date = findByDate(periodProperty); + } else if (StringUtils.isNotBlank(periodProperty)) { + mode = CoreProperties.TIMEMACHINE_MODE_VERSION; + param = periodProperty; + } else { + throw new IllegalArgumentException("Unknown period property : " + periodProperty); + } + } + + private static Integer findByDays(String property) { + try { + return Integer.parseInt(property); + } catch (NumberFormatException e) { + return null; + } + } + + private static Date findByDate(String property) { + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); + try { + return format.parse(property); + } catch (ParseException e) { + return null; + } + } + + public String getMode() { + return mode; + } + + public String getParam() { + return param; + } + + public Date getDate() { + return date; + } + } + +} diff --git a/sonar-db/src/main/java/org/sonar/core/timemachine/package-info.java b/sonar-db/src/main/java/org/sonar/core/timemachine/package-info.java new file mode 100644 index 00000000000..039fb6393df --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/core/timemachine/package-info.java @@ -0,0 +1,24 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.core.timemachine; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/sonar-db/src/main/java/org/sonar/core/user/DefaultUserFinder.java b/sonar-db/src/main/java/org/sonar/core/user/DefaultUserFinder.java new file mode 100644 index 00000000000..16d2867c6c0 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/core/user/DefaultUserFinder.java @@ -0,0 +1,69 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.core.user; + +import com.google.common.collect.Lists; +import java.util.Collection; +import java.util.List; +import javax.annotation.CheckForNull; +import org.sonar.api.user.User; +import org.sonar.api.user.UserFinder; +import org.sonar.api.user.UserQuery; +import org.sonar.db.user.UserDao; +import org.sonar.db.user.UserDto; + +/** + * @since 3.6 + */ +public class DefaultUserFinder implements UserFinder { + + private final UserDao userDao; + + public DefaultUserFinder(UserDao userDao) { + this.userDao = userDao; + } + + @Override + @CheckForNull + public User findByLogin(String login) { + UserDto dto = userDao.selectActiveUserByLogin(login); + return dto != null ? dto.toUser() : null; + } + + @Override + public List<User> findByLogins(List<String> logins) { + List<UserDto> dtos = userDao.selectUsersByLogins(logins); + return toUsers(dtos); + } + + @Override + public List<User> find(UserQuery query) { + List<UserDto> dtos = userDao.selectUsers(query); + return toUsers(dtos); + } + + private List<User> toUsers(Collection<UserDto> dtos) { + List<User> users = Lists.newArrayList(); + for (UserDto dto : dtos) { + users.add(dto.toUser()); + } + return users; + } +} diff --git a/sonar-db/src/main/java/org/sonar/core/user/DeprecatedUserFinder.java b/sonar-db/src/main/java/org/sonar/core/user/DeprecatedUserFinder.java new file mode 100644 index 00000000000..2413ce4babc --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/core/user/DeprecatedUserFinder.java @@ -0,0 +1,58 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.core.user; + +import javax.annotation.Nullable; +import org.sonar.api.database.model.User; +import org.sonar.api.security.UserFinder; +import org.sonar.db.user.UserDao; +import org.sonar.db.user.UserDto; + +/** + * @since 2.10 + */ +public class DeprecatedUserFinder implements UserFinder { + + private final UserDao userDao; + + public DeprecatedUserFinder(UserDao userDao) { + this.userDao = userDao; + } + + @Override + public User findById(int id) { + return copy(userDao.getUser(id)); + } + + @Override + public User findByLogin(String login) { + return copy(userDao.selectActiveUserByLogin(login)); + } + + private User copy(@Nullable UserDto dto) { + if (dto != null) { + User user = new User().setEmail(dto.getEmail()).setLogin(dto.getLogin()).setName(dto.getName()); + user.setId(dto.getId().intValue()); + return user; + } + return null; + } + +} diff --git a/sonar-db/src/main/java/org/sonar/core/user/GroupMembership.java b/sonar-db/src/main/java/org/sonar/core/user/GroupMembership.java new file mode 100644 index 00000000000..1e8715dead4 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/core/user/GroupMembership.java @@ -0,0 +1,92 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.core.user; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; + +public class GroupMembership { + + private Long id; + private String name; + private String description; + private boolean isMember; + + public Long id() { + return id; + } + + public GroupMembership setId(Long id) { + this.id = id; + return this; + } + + public String name() { + return name; + } + + public GroupMembership setName(String name) { + this.name = name; + return this; + } + + @CheckForNull + public String description() { + return description; + } + + public GroupMembership setDescription(@Nullable String description) { + this.description = description; + return this; + } + + public boolean isMember() { + return isMember; + } + + public GroupMembership setMember(boolean isMember) { + this.isMember = isMember; + return this; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + GroupMembership that = (GroupMembership) o; + return name.equals(that.name); + } + + @Override + public int hashCode() { + return name.hashCode(); + } +} diff --git a/sonar-db/src/main/java/org/sonar/core/user/package-info.java b/sonar-db/src/main/java/org/sonar/core/user/package-info.java new file mode 100644 index 00000000000..73bfef46c33 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/core/user/package-info.java @@ -0,0 +1,25 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.core.user; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/sonar-db/src/main/java/org/sonar/db/BatchSession.java b/sonar-db/src/main/java/org/sonar/db/BatchSession.java new file mode 100644 index 00000000000..3e6d0b89867 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/BatchSession.java @@ -0,0 +1,221 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db; + +import java.util.List; +import java.util.Map; +import org.apache.ibatis.executor.BatchResult; +import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator; +import org.apache.ibatis.executor.keygen.KeyGenerator; +import org.apache.ibatis.mapping.MappedStatement; +import org.apache.ibatis.session.Configuration; +import org.apache.ibatis.session.ResultHandler; +import org.apache.ibatis.session.RowBounds; +import org.apache.ibatis.session.SqlSession; +import org.sonar.db.deprecated.ClusterAction; +import org.sonar.db.deprecated.WorkQueue; + +public class BatchSession extends DbSession { + + public static final int MAX_BATCH_SIZE = 250; + + private final int batchSize; + private int count = 0; + + BatchSession(WorkQueue<?> queue, SqlSession session) { + this(queue, session, MAX_BATCH_SIZE); + } + + BatchSession(WorkQueue<?> queue, SqlSession session, int batchSize) { + super(queue, session); + this.batchSize = batchSize; + } + + @Override + public void enqueue(ClusterAction action) { + increment(); + super.enqueue(action); + } + + @Override + public void select(String statement, Object parameter, ResultHandler handler) { + reset(); + super.select(statement, parameter, handler); + } + + @Override + public void select(String statement, ResultHandler handler) { + reset(); + super.select(statement, handler); + } + + @Override + public <T> T selectOne(String statement) { + reset(); + return super.selectOne(statement); + } + + @Override + public <T> T selectOne(String statement, Object parameter) { + reset(); + return super.selectOne(statement, parameter); + } + + @Override + public <E> List<E> selectList(String statement) { + reset(); + return super.selectList(statement); + } + + @Override + public <E> List<E> selectList(String statement, Object parameter) { + reset(); + return super.selectList(statement, parameter); + } + + @Override + public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) { + reset(); + return super.selectList(statement, parameter, rowBounds); + } + + @Override + public <K, V> Map<K, V> selectMap(String statement, String mapKey) { + reset(); + return super.selectMap(statement, mapKey); + } + + @Override + public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey) { + reset(); + return super.selectMap(statement, parameter, mapKey); + } + + @Override + public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds) { + reset(); + return super.selectMap(statement, parameter, mapKey, rowBounds); + } + + @Override + public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) { + reset(); + super.select(statement, parameter, rowBounds, handler); + } + + @Override + public int insert(String statement) { + makeSureGeneratedKeysAreNotUsedInBatchInserts(statement); + increment(); + return super.insert(statement); + } + + @Override + public int insert(String statement, Object parameter) { + makeSureGeneratedKeysAreNotUsedInBatchInserts(statement); + increment(); + return super.insert(statement, parameter); + } + + private void makeSureGeneratedKeysAreNotUsedInBatchInserts(String statement) { + Configuration configuration = super.getConfiguration(); + if (null != configuration) { + MappedStatement mappedStatement = configuration.getMappedStatement(statement); + if (null != mappedStatement) { + KeyGenerator keyGenerator = mappedStatement.getKeyGenerator(); + if (keyGenerator instanceof Jdbc3KeyGenerator) { + throw new IllegalStateException("Batch inserts cannot use generated keys"); + } + } + } + } + + @Override + public int update(String statement) { + increment(); + return super.update(statement); + } + + @Override + public int update(String statement, Object parameter) { + increment(); + return super.update(statement, parameter); + } + + @Override + public int delete(String statement) { + increment(); + return super.delete(statement); + } + + @Override + public int delete(String statement, Object parameter) { + increment(); + return super.delete(statement, parameter); + } + + @Override + public void commit() { + super.commit(); + reset(); + } + + @Override + public void commit(boolean force) { + super.commit(force); + reset(); + } + + @Override + public void rollback() { + super.rollback(); + reset(); + } + + @Override + public void rollback(boolean force) { + super.rollback(force); + reset(); + } + + @Override + public List<BatchResult> flushStatements() { + List<BatchResult> batchResults = super.flushStatements(); + reset(); + return batchResults; + } + + @Override + public <T> T getMapper(Class<T> type) { + return getConfiguration().getMapper(type, this); + } + + private BatchSession increment() { + count += 1; + if (count >= batchSize) { + commit(); + } + return this; + } + + private void reset() { + count = 0; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/Dao.java b/sonar-db/src/main/java/org/sonar/db/Dao.java new file mode 100644 index 00000000000..99bd33d1eb5 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/Dao.java @@ -0,0 +1,23 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db; + +public interface Dao { +} diff --git a/sonar-db/src/main/java/org/sonar/db/DaoUtils.java b/sonar-db/src/main/java/org/sonar/db/DaoUtils.java new file mode 100644 index 00000000000..5c0d3269e3c --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/DaoUtils.java @@ -0,0 +1,149 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import org.sonar.db.component.ResourceDao; +import org.sonar.db.component.ResourceIndexerDao; +import org.sonar.db.component.ResourceKeyUpdaterDao; +import org.sonar.db.dashboard.ActiveDashboardDao; +import org.sonar.db.dashboard.DashboardDao; +import org.sonar.db.debt.CharacteristicDao; +import org.sonar.db.duplication.DuplicationDao; +import org.sonar.db.issue.ActionPlanDao; +import org.sonar.db.issue.ActionPlanStatsDao; +import org.sonar.db.issue.IssueChangeDao; +import org.sonar.db.issue.IssueDao; +import org.sonar.db.issue.IssueFilterDao; +import org.sonar.db.issue.IssueFilterFavouriteDao; +import org.sonar.db.loadedtemplate.LoadedTemplateDao; +import org.sonar.db.notification.NotificationQueueDao; +import org.sonar.db.permission.PermissionDao; +import org.sonar.db.permission.PermissionTemplateDao; +import org.sonar.db.property.PropertiesDao; +import org.sonar.db.purge.PurgeDao; +import org.sonar.db.qualitygate.QualityGateConditionDao; +import org.sonar.db.qualityprofile.ActiveRuleDao; +import org.sonar.db.qualityprofile.QualityProfileDao; +import org.sonar.db.rule.RuleDao; +import org.sonar.db.semaphore.SemaphoreDao; +import org.sonar.db.user.AuthorDao; +import org.sonar.db.user.AuthorizationDao; +import org.sonar.db.user.GroupMembershipDao; +import org.sonar.db.user.RoleDao; +import org.sonar.db.user.UserDao; + +import static com.google.common.collect.Lists.newArrayList; + +public final class DaoUtils { + + private static final int PARTITION_SIZE_FOR_ORACLE = 1000; + + private DaoUtils() { + // only static stuff + } + + public static List<Class> getDaoClasses() { + return ImmutableList.<Class>of( + ActionPlanDao.class, + ActionPlanStatsDao.class, + ActiveDashboardDao.class, + ActiveRuleDao.class, + AuthorDao.class, + AuthorizationDao.class, + DashboardDao.class, + DuplicationDao.class, + GroupMembershipDao.class, + IssueDao.class, + IssueChangeDao.class, + IssueFilterDao.class, + IssueFilterFavouriteDao.class, + LoadedTemplateDao.class, + NotificationQueueDao.class, + PermissionDao.class, + PermissionTemplateDao.class, + PropertiesDao.class, + QualityGateConditionDao.class, + QualityProfileDao.class, + PurgeDao.class, + CharacteristicDao.class, + ResourceIndexerDao.class, + ResourceDao.class, + ResourceKeyUpdaterDao.class, + RoleDao.class, + RuleDao.class, + SemaphoreDao.class, + UserDao.class + ); + } + + /** + * Partition by 1000 elements a list of input and execute a function on each part. + * + * The goal is to prevent issue with ORACLE when there's more than 1000 elements in a 'in ('X', 'Y', ...)' + * and with MsSQL when there's more than 2000 parameters in a query + */ + public static <OUTPUT, INPUT> List<OUTPUT> executeLargeInputs(Collection<INPUT> input, Function<List<INPUT>, List<OUTPUT>> function) { + if (input.isEmpty()) { + return Collections.emptyList(); + } + List<OUTPUT> results = newArrayList(); + List<List<INPUT>> partitionList = Lists.partition(newArrayList(input), PARTITION_SIZE_FOR_ORACLE); + for (List<INPUT> partition : partitionList) { + List<OUTPUT> subResults = function.apply(partition); + results.addAll(subResults); + } + return results; + } + + /** + * Partition by 1000 elements a list of input and execute a function on each part. + * The function has not output (ex: delete operation) + * + * The goal is to prevent issue with ORACLE when there's more than 1000 elements in a 'in ('X', 'Y', ...)' + * and with MsSQL when there's more than 2000 parameters in a query + */ + public static <INPUT> void executeLargeInputsWithoutOutput(Collection<INPUT> input, Function<List<INPUT>, Void> function) { + if (input.isEmpty()) { + return; + } + + List<List<INPUT>> partitions = Lists.partition(newArrayList(input), PARTITION_SIZE_FOR_ORACLE); + for (List<INPUT> partition : partitions) { + function.apply(partition); + } + } + + public static String repeatCondition(String sql, int count, String separator) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < count; i++) { + sb.append(sql); + if (i < count - 1) { + sb.append(" ").append(separator).append(" "); + } + } + return sb.toString(); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/Database.java b/sonar-db/src/main/java/org/sonar/db/Database.java new file mode 100644 index 00000000000..6b747edee76 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/Database.java @@ -0,0 +1,39 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db; + +import javax.sql.DataSource; +import org.picocontainer.Startable; +import org.sonar.db.dialect.Dialect; + +/** + * @since 2.12 + */ +public interface Database extends Startable { + /** + * Returns the configured datasource. Null as long as start() is not executed. + */ + DataSource getDataSource(); + + /** + * @return the dialect or null if start() has not been executed + */ + Dialect getDialect(); +} diff --git a/sonar-db/src/main/java/org/sonar/db/DatabaseUtils.java b/sonar-db/src/main/java/org/sonar/db/DatabaseUtils.java new file mode 100644 index 00000000000..28ac5923b72 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/DatabaseUtils.java @@ -0,0 +1,69 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import javax.annotation.Nullable; +import org.slf4j.LoggerFactory; + +/** + * @since 2.13 + */ +public final class DatabaseUtils { + private DatabaseUtils() { + // only static methods + } + + public static void closeQuietly(@Nullable Connection connection) { + if (connection != null) { + try { + connection.close(); + } catch (SQLException e) { + LoggerFactory.getLogger(DatabaseUtils.class).warn("Fail to close connection", e); + // ignore + } + } + } + + public static void closeQuietly(@Nullable Statement stmt) { + if (stmt != null) { + try { + stmt.close(); + } catch (SQLException e) { + LoggerFactory.getLogger(DatabaseUtils.class).warn("Fail to close statement", e); + // ignore + } + } + } + + public static void closeQuietly(@Nullable ResultSet rs) { + if (rs != null) { + try { + rs.close(); + } catch (SQLException e) { + LoggerFactory.getLogger(DatabaseUtils.class).warn("Fail to close result set", e); + // ignore + } + } + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/DbSession.java b/sonar-db/src/main/java/org/sonar/db/DbSession.java new file mode 100644 index 00000000000..d5760462d52 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/DbSession.java @@ -0,0 +1,201 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db; + +import java.sql.Connection; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import org.apache.ibatis.executor.BatchResult; +import org.apache.ibatis.session.Configuration; +import org.apache.ibatis.session.ResultHandler; +import org.apache.ibatis.session.RowBounds; +import org.apache.ibatis.session.SqlSession; +import org.sonar.db.deprecated.ClusterAction; +import org.sonar.db.deprecated.WorkQueue; + +public class DbSession implements SqlSession { + + private List<ClusterAction> actions; + + private WorkQueue queue; + private SqlSession session; + private int actionCount; + + DbSession(WorkQueue queue, SqlSession session) { + this.actionCount = 0; + this.session = session; + this.queue = queue; + this.actions = new ArrayList<>(); + } + + public void enqueue(ClusterAction action) { + actionCount++; + this.actions.add(action); + } + + public int getActionCount() { + return actionCount; + } + + @Override + public void commit() { + session.commit(); + queue.enqueue(actions); + actions.clear(); + } + + @Override + public void commit(boolean force) { + session.commit(force); + queue.enqueue(actions); + actions.clear(); + } + + /** + * We only care about the the commit section. + * The rest is simply passed to its parent. + */ + + @Override + public <T> T selectOne(String statement) { + return session.selectOne(statement); + } + + @Override + public <T> T selectOne(String statement, Object parameter) { + return session.selectOne(statement, parameter); + } + + @Override + public <E> List<E> selectList(String statement) { + return session.selectList(statement); + } + + @Override + public <E> List<E> selectList(String statement, Object parameter) { + return session.selectList(statement, parameter); + } + + @Override + public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) { + return session.selectList(statement, parameter, rowBounds); + } + + @Override + public <K, V> Map<K, V> selectMap(String statement, String mapKey) { + return session.selectMap(statement, mapKey); + } + + @Override + public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey) { + return session.selectMap(statement, parameter, mapKey); + } + + @Override + public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds) { + return session.selectMap(statement, parameter, mapKey, rowBounds); + } + + @Override + public void select(String statement, Object parameter, ResultHandler handler) { + session.select(statement, parameter, handler); + } + + @Override + public void select(String statement, ResultHandler handler) { + session.select(statement, handler); + } + + @Override + public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) { + session.select(statement, parameter, rowBounds, handler); + } + + @Override + public int insert(String statement) { + return session.insert(statement); + } + + @Override + public int insert(String statement, Object parameter) { + return session.insert(statement, parameter); + } + + @Override + public int update(String statement) { + return session.update(statement); + } + + @Override + public int update(String statement, Object parameter) { + return session.update(statement, parameter); + } + + @Override + public int delete(String statement) { + return session.delete(statement); + } + + @Override + public int delete(String statement, Object parameter) { + return session.delete(statement, parameter); + } + + @Override + public void rollback() { + session.rollback(); + } + + @Override + public void rollback(boolean force) { + session.rollback(force); + } + + @Override + public List<BatchResult> flushStatements() { + return session.flushStatements(); + } + + @Override + public void close() { + session.close(); + } + + @Override + public void clearCache() { + session.clearCache(); + } + + @Override + public Configuration getConfiguration() { + return session.getConfiguration(); + } + + @Override + public <T> T getMapper(Class<T> type) { + return session.getMapper(type); + } + + @Override + public Connection getConnection() { + return session.getConnection(); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/DdlUtils.java b/sonar-db/src/main/java/org/sonar/db/DdlUtils.java new file mode 100644 index 00000000000..52e64e59728 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/DdlUtils.java @@ -0,0 +1,68 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db; + +import java.io.PrintWriter; +import java.sql.Connection; +import org.apache.commons.io.output.NullWriter; +import org.apache.ibatis.io.Resources; +import org.apache.ibatis.jdbc.ScriptRunner; + +/** + * Util class to create Sonar database tables + * + * @since 2.12 + */ +public final class DdlUtils { + + private DdlUtils() { + } + + public static boolean supportsDialect(String dialect) { + return "h2".equals(dialect); + } + + /** + * The connection is commited in this method but not closed. + */ + public static void createSchema(Connection connection, String dialect) { + executeScript(connection, "org/sonar/db/version/schema-" + dialect + ".ddl"); + executeScript(connection, "org/sonar/db/version/rows-" + dialect + ".sql"); + } + + public static void executeScript(Connection connection, String path) { + ScriptRunner scriptRunner = newScriptRunner(connection); + try { + scriptRunner.runScript(Resources.getResourceAsReader(path)); + connection.commit(); + + } catch (Exception e) { + throw new IllegalStateException("Fail to restore: " + path, e); + } + } + + private static ScriptRunner newScriptRunner(Connection connection) { + ScriptRunner scriptRunner = new ScriptRunner(connection); + scriptRunner.setDelimiter(";"); + scriptRunner.setStopOnError(true); + scriptRunner.setLogWriter(new PrintWriter(new NullWriter())); + return scriptRunner; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/DefaultDatabase.java b/sonar-db/src/main/java/org/sonar/db/DefaultDatabase.java new file mode 100644 index 00000000000..c5e5e1c12b8 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/DefaultDatabase.java @@ -0,0 +1,188 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db; + +import com.google.common.annotations.VisibleForTesting; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import javax.sql.DataSource; +import org.apache.commons.dbcp.BasicDataSource; +import org.apache.commons.dbcp.BasicDataSourceFactory; +import org.apache.commons.dbutils.DbUtils; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.config.Settings; +import org.sonar.api.database.DatabaseProperties; +import org.sonar.db.dialect.Dialect; +import org.sonar.db.dialect.DialectUtils; +import org.sonar.db.profiling.ProfiledDataSource; + +/** + * @since 2.12 + */ +public class DefaultDatabase implements Database { + + private static final Logger LOG = LoggerFactory.getLogger(Database.class); + + private static final String DEFAULT_URL = "jdbc:h2:tcp://localhost/sonar"; + private static final String SONAR_JDBC = "sonar.jdbc."; + private static final String SONAR_JDBC_DIALECT = "sonar.jdbc.dialect"; + private static final String SONAR_JDBC_URL = "sonar.jdbc.url"; + + private Settings settings; + private BasicDataSource datasource; + private Dialect dialect; + private Properties properties; + + public DefaultDatabase(Settings settings) { + this.settings = settings; + } + + @Override + public void start() { + try { + initSettings(); + initDatasource(); + checkConnection(); + doAfterStart(); + + } catch (Exception e) { + throw new IllegalStateException("Fail to connect to database", e); + } + } + + /** + * Override to execute post-startup code. + */ + protected void doAfterStart() { + // nothing to do + } + + @VisibleForTesting + void initSettings() { + properties = new Properties(); + completeProperties(settings, properties, SONAR_JDBC); + completeDefaultProperties(properties); + doCompleteProperties(properties); + + dialect = DialectUtils.find(properties.getProperty(SONAR_JDBC_DIALECT), properties.getProperty(SONAR_JDBC_URL)); + properties.setProperty(DatabaseProperties.PROP_DRIVER, dialect.getDefaultDriverClassName()); + } + + private void initDatasource() throws Exception {// NOSONAR this exception is thrown by BasicDataSourceFactory + // but it's correctly caught by start() + LOG.info("Create JDBC datasource for " + properties.getProperty(DatabaseProperties.PROP_URL, DEFAULT_URL)); + datasource = (BasicDataSource) BasicDataSourceFactory.createDataSource(extractCommonsDbcpProperties(properties)); + datasource.setConnectionInitSqls(dialect.getConnectionInitStatements()); + datasource.setValidationQuery(dialect.getValidationQuery()); + if ("TRACE".equals(settings.getString("sonar.log.level"))) { + datasource = new ProfiledDataSource(datasource); + } + } + + private void checkConnection() { + Connection connection = null; + try { + LOG.debug("Testing JDBC connection"); + connection = datasource.getConnection(); + } catch (SQLException e) { + throw new IllegalStateException("Can not connect to database. Please check connectivity and settings (see the properties prefixed by 'sonar.jdbc.').", e); + } finally { + DbUtils.closeQuietly(connection); + } + } + + @Override + public void stop() { + if (datasource != null) { + try { + datasource.close(); + } catch (SQLException e) { + throw new IllegalStateException("Fail to stop JDBC connection pool", e); + } + } + } + + @Override + public final Dialect getDialect() { + return dialect; + } + + @Override + public final DataSource getDataSource() { + return datasource; + } + + public final Properties getProperties() { + return properties; + } + + /** + * Override this method to add JDBC properties at runtime + */ + protected void doCompleteProperties(Properties properties) { + // open-close principle + } + + private static void completeProperties(Settings settings, Properties properties, String prefix) { + List<String> jdbcKeys = settings.getKeysStartingWith(prefix); + for (String jdbcKey : jdbcKeys) { + String value = settings.getString(jdbcKey); + properties.setProperty(jdbcKey, value); + } + } + + @VisibleForTesting + static Properties extractCommonsDbcpProperties(Properties properties) { + Properties result = new Properties(); + for (Map.Entry<Object, Object> entry : properties.entrySet()) { + String key = (String) entry.getKey(); + if (StringUtils.startsWith(key, SONAR_JDBC)) { + result.setProperty(StringUtils.removeStart(key, SONAR_JDBC), (String) entry.getValue()); + } + } + + // This property is required by the Ruby Oracle enhanced adapter. + // It directly uses the Connection implementation provided by the Oracle driver + result.setProperty("accessToUnderlyingConnectionAllowed", "true"); + return result; + } + + private static void completeDefaultProperties(Properties props) { + completeDefaultProperty(props, DatabaseProperties.PROP_URL, DEFAULT_URL); + completeDefaultProperty(props, DatabaseProperties.PROP_USER, props.getProperty(DatabaseProperties.PROP_USER_DEPRECATED, DatabaseProperties.PROP_USER_DEFAULT_VALUE)); + completeDefaultProperty(props, DatabaseProperties.PROP_PASSWORD, DatabaseProperties.PROP_PASSWORD_DEFAULT_VALUE); + } + + private static void completeDefaultProperty(Properties props, String key, String defaultValue) { + if (props.getProperty(key) == null && defaultValue != null) { + props.setProperty(key, defaultValue); + } + } + + @Override + public String toString() { + return "Database[" + (properties != null ? properties.getProperty(SONAR_JDBC_URL) : "?") + "]"; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/Dto.java b/sonar-db/src/main/java/org/sonar/db/Dto.java new file mode 100644 index 00000000000..e5b9c494e97 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/Dto.java @@ -0,0 +1,49 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db; + +import java.io.Serializable; +import java.util.Date; + +public abstract class Dto<K extends Serializable> { + + private Date createdAt; + private Date updatedAt; + + public abstract K getKey(); + + public Dto setCreatedAt(Date datetime) { + this.createdAt = datetime; + return this; + } + + public Dto setUpdatedAt(Date datetime) { + this.updatedAt = datetime; + return this; + } + + public final Date getCreatedAt() { + return this.createdAt; + } + + public final Date getUpdatedAt() { + return this.updatedAt; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/IsAliveMapper.java b/sonar-db/src/main/java/org/sonar/db/IsAliveMapper.java new file mode 100644 index 00000000000..75c63cf70a1 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/IsAliveMapper.java @@ -0,0 +1,29 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db; + +public interface IsAliveMapper { + int IS_ALIVE_RETURNED_VALUE = 1; + + /** + * Always return {@link #IS_ALIVE_RETURNED_VALUE} unless a database or connection error occurs. + */ + int isAlive(); +} diff --git a/sonar-db/src/main/java/org/sonar/db/MyBatis.java b/sonar-db/src/main/java/org/sonar/db/MyBatis.java new file mode 100644 index 00000000000..a6aa01cbc4f --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/MyBatis.java @@ -0,0 +1,326 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db; + +import ch.qos.logback.classic.Level; +import com.google.common.io.Closeables; +import java.io.InputStream; +import javax.annotation.Nullable; +import org.apache.ibatis.builder.xml.XMLMapperBuilder; +import org.apache.ibatis.logging.LogFactory; +import org.apache.ibatis.mapping.Environment; +import org.apache.ibatis.session.Configuration; +import org.apache.ibatis.session.ExecutorType; +import org.apache.ibatis.session.SqlSession; +import org.apache.ibatis.session.SqlSessionFactory; +import org.apache.ibatis.session.SqlSessionFactoryBuilder; +import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory; +import org.apache.ibatis.type.JdbcType; +import org.slf4j.LoggerFactory; +import org.sonar.db.activity.ActivityDto; +import org.sonar.db.activity.ActivityMapper; +import org.sonar.db.component.ComponentDto; +import org.sonar.db.component.ComponentIndexMapper; +import org.sonar.db.component.ComponentLinkDto; +import org.sonar.db.component.ComponentLinkMapper; +import org.sonar.db.component.ComponentMapper; +import org.sonar.db.component.FilePathWithHashDto; +import org.sonar.db.component.ResourceDto; +import org.sonar.db.component.ResourceIndexDto; +import org.sonar.db.component.ResourceIndexerMapper; +import org.sonar.db.component.ResourceKeyUpdaterMapper; +import org.sonar.db.component.ResourceMapper; +import org.sonar.db.component.SnapshotDto; +import org.sonar.db.component.SnapshotMapper; +import org.sonar.db.component.UuidWithProjectUuidDto; +import org.sonar.db.compute.AnalysisReportDto; +import org.sonar.db.compute.AnalysisReportMapper; +import org.sonar.db.dashboard.ActiveDashboardDto; +import org.sonar.db.dashboard.ActiveDashboardMapper; +import org.sonar.db.dashboard.DashboardDto; +import org.sonar.db.dashboard.DashboardMapper; +import org.sonar.db.dashboard.WidgetDto; +import org.sonar.db.dashboard.WidgetMapper; +import org.sonar.db.dashboard.WidgetPropertyDto; +import org.sonar.db.dashboard.WidgetPropertyMapper; +import org.sonar.db.debt.CharacteristicDto; +import org.sonar.db.debt.CharacteristicMapper; +import org.sonar.db.debt.RequirementMigrationDto; +import org.sonar.db.deprecated.WorkQueue; +import org.sonar.db.dialect.Dialect; +import org.sonar.db.duplication.DuplicationMapper; +import org.sonar.db.duplication.DuplicationUnitDto; +import org.sonar.db.event.EventDto; +import org.sonar.db.event.EventMapper; +import org.sonar.db.issue.ActionPlanDto; +import org.sonar.db.issue.ActionPlanMapper; +import org.sonar.db.issue.ActionPlanStatsDto; +import org.sonar.db.issue.ActionPlanStatsMapper; +import org.sonar.db.issue.IssueChangeDto; +import org.sonar.db.issue.IssueChangeMapper; +import org.sonar.db.issue.IssueDto; +import org.sonar.db.issue.IssueFilterDto; +import org.sonar.db.issue.IssueFilterFavouriteDto; +import org.sonar.db.issue.IssueFilterFavouriteMapper; +import org.sonar.db.issue.IssueFilterMapper; +import org.sonar.db.issue.IssueMapper; +import org.sonar.db.loadedtemplate.LoadedTemplateDto; +import org.sonar.db.loadedtemplate.LoadedTemplateMapper; +import org.sonar.db.measure.CustomMeasureDto; +import org.sonar.db.measure.CustomMeasureMapper; +import org.sonar.db.measure.MeasureDto; +import org.sonar.db.measure.MeasureFilterDto; +import org.sonar.db.measure.MeasureFilterMapper; +import org.sonar.db.measure.MeasureMapper; +import org.sonar.db.metric.MetricMapper; +import org.sonar.db.notification.NotificationQueueDto; +import org.sonar.db.notification.NotificationQueueMapper; +import org.sonar.db.permission.GroupWithPermissionDto; +import org.sonar.db.permission.PermissionTemplateDto; +import org.sonar.db.permission.PermissionTemplateGroupDto; +import org.sonar.db.permission.PermissionTemplateMapper; +import org.sonar.db.permission.PermissionTemplateUserDto; +import org.sonar.db.permission.UserWithPermissionDto; +import org.sonar.db.property.PropertiesMapper; +import org.sonar.db.property.PropertyDto; +import org.sonar.db.purge.IdUuidPair; +import org.sonar.db.purge.PurgeMapper; +import org.sonar.db.purge.PurgeableSnapshotDto; +import org.sonar.db.qualitygate.ProjectQgateAssociationDto; +import org.sonar.db.qualitygate.ProjectQgateAssociationMapper; +import org.sonar.db.qualitygate.QualityGateConditionDto; +import org.sonar.db.qualitygate.QualityGateConditionMapper; +import org.sonar.db.qualitygate.QualityGateDto; +import org.sonar.db.qualitygate.QualityGateMapper; +import org.sonar.db.qualityprofile.ActiveRuleDto; +import org.sonar.db.qualityprofile.ActiveRuleMapper; +import org.sonar.db.qualityprofile.ActiveRuleParamDto; +import org.sonar.db.qualityprofile.QualityProfileDto; +import org.sonar.db.qualityprofile.QualityProfileMapper; +import org.sonar.db.rule.RuleDto; +import org.sonar.db.rule.RuleMapper; +import org.sonar.db.rule.RuleParamDto; +import org.sonar.db.semaphore.SemaphoreDto; +import org.sonar.db.semaphore.SemaphoreMapper; +import org.sonar.db.source.FileSourceMapper; +import org.sonar.db.user.AuthorDto; +import org.sonar.db.user.AuthorMapper; +import org.sonar.db.user.GroupDto; +import org.sonar.db.user.GroupMapper; +import org.sonar.db.user.GroupMembershipDto; +import org.sonar.db.user.GroupMembershipMapper; +import org.sonar.db.user.GroupRoleDto; +import org.sonar.db.user.RoleMapper; +import org.sonar.db.user.UserDto; +import org.sonar.db.user.UserGroupDto; +import org.sonar.db.user.UserGroupMapper; +import org.sonar.db.user.UserMapper; +import org.sonar.db.user.UserRoleDto; +import org.sonar.db.version.SchemaMigrationDto; +import org.sonar.db.version.SchemaMigrationMapper; +import org.sonar.db.version.v44.Migration44Mapper; +import org.sonar.db.version.v45.Migration45Mapper; +import org.sonar.db.version.v50.Migration50Mapper; + +public class MyBatis { + + private final Database database; + private SqlSessionFactory sessionFactory; + + // TODO this queue should directly be an IndexQueue. Pending move of persistence to sonar-server + private WorkQueue<?> queue; + + public MyBatis(Database database, WorkQueue<?> queue) { + this.database = database; + this.queue = queue; + } + + public static void closeQuietly(@Nullable SqlSession session) { + if (session != null) { + try { + session.close(); + } catch (Exception e) { + LoggerFactory.getLogger(MyBatis.class).warn("Fail to close session", e); + // do not re-throw the exception + } + } + } + + private static JdbcTransactionFactory createTransactionFactory() { + return new JdbcTransactionFactory(); + } + + public MyBatis start() { + LogFactory.useSlf4jLogging(); + + Configuration conf = new Configuration(); + conf.setEnvironment(new Environment("production", createTransactionFactory(), database.getDataSource())); + conf.setUseGeneratedKeys(true); + conf.setLazyLoadingEnabled(false); + conf.setJdbcTypeForNull(JdbcType.NULL); + Dialect dialect = database.getDialect(); + conf.setDatabaseId(dialect.getId()); + conf.getVariables().setProperty("_true", dialect.getTrueSqlValue()); + conf.getVariables().setProperty("_false", dialect.getFalseSqlValue()); + conf.getVariables().setProperty("_scrollFetchSize", String.valueOf(dialect.getScrollDefaultFetchSize())); + + loadAlias(conf, "ActiveDashboard", ActiveDashboardDto.class); + loadAlias(conf, "Author", AuthorDto.class); + loadAlias(conf, "Component", ComponentDto.class); + loadAlias(conf, "ComponentLink", ComponentLinkDto.class); + loadAlias(conf, "Dashboard", DashboardDto.class); + loadAlias(conf, "DuplicationUnit", DuplicationUnitDto.class); + loadAlias(conf, "Group", GroupDto.class); + loadAlias(conf, "GroupRole", GroupRoleDto.class); + loadAlias(conf, "GroupMembership", GroupMembershipDto.class); + loadAlias(conf, "LoadedTemplate", LoadedTemplateDto.class); + loadAlias(conf, "MeasureFilter", MeasureFilterDto.class); + loadAlias(conf, "NotificationQueue", NotificationQueueDto.class); + loadAlias(conf, "Property", PropertyDto.class); + loadAlias(conf, "PurgeableSnapshot", PurgeableSnapshotDto.class); + loadAlias(conf, "QualityGate", QualityGateDto.class); + loadAlias(conf, "QualityGateCondition", QualityGateConditionDto.class); + loadAlias(conf, "ProjectQgateAssociation", ProjectQgateAssociationDto.class); + loadAlias(conf, "Resource", ResourceDto.class); + loadAlias(conf, "ResourceIndex", ResourceIndexDto.class); + loadAlias(conf, "Rule", RuleDto.class); + loadAlias(conf, "RuleParam", RuleParamDto.class); + loadAlias(conf, "Snapshot", SnapshotDto.class); + loadAlias(conf, "Semaphore", SemaphoreDto.class); + loadAlias(conf, "SchemaMigration", SchemaMigrationDto.class); + loadAlias(conf, "User", UserDto.class); + loadAlias(conf, "UserRole", UserRoleDto.class); + loadAlias(conf, "UserGroup", UserGroupDto.class); + loadAlias(conf, "Widget", WidgetDto.class); + loadAlias(conf, "WidgetProperty", WidgetPropertyDto.class); + loadAlias(conf, "Measure", MeasureDto.class); + loadAlias(conf, "Issue", IssueDto.class); + loadAlias(conf, "IssueChange", IssueChangeDto.class); + loadAlias(conf, "IssueFilter", IssueFilterDto.class); + loadAlias(conf, "IssueFilterFavourite", IssueFilterFavouriteDto.class); + loadAlias(conf, "ActionPlanIssue", ActionPlanDto.class); + loadAlias(conf, "ActionPlanStats", ActionPlanStatsDto.class); + loadAlias(conf, "PermissionTemplate", PermissionTemplateDto.class); + loadAlias(conf, "PermissionTemplateUser", PermissionTemplateUserDto.class); + loadAlias(conf, "PermissionTemplateGroup", PermissionTemplateGroupDto.class); + loadAlias(conf, "Characteristic", CharacteristicDto.class); + loadAlias(conf, "UserWithPermission", UserWithPermissionDto.class); + loadAlias(conf, "GroupWithPermission", GroupWithPermissionDto.class); + loadAlias(conf, "QualityProfile", QualityProfileDto.class); + loadAlias(conf, "ActiveRule", ActiveRuleDto.class); + loadAlias(conf, "ActiveRuleParam", ActiveRuleParamDto.class); + loadAlias(conf, "RequirementMigration", RequirementMigrationDto.class); + loadAlias(conf, "Activity", ActivityDto.class); + loadAlias(conf, "AnalysisReport", AnalysisReportDto.class); + loadAlias(conf, "IdUuidPair", IdUuidPair.class); + loadAlias(conf, "FilePathWithHash", FilePathWithHashDto.class); + loadAlias(conf, "UuidWithProjectUuid", UuidWithProjectUuidDto.class); + loadAlias(conf, "Event", EventDto.class); + loadAlias(conf, "CustomMeasure", CustomMeasureDto.class); + + // AuthorizationMapper has to be loaded before IssueMapper because this last one used it + loadMapper(conf, "org.sonar.db.user.AuthorizationMapper"); + // ResourceMapper has to be loaded before IssueMapper because this last one used it + loadMapper(conf, ResourceMapper.class); + + loadMapper(conf, "org.sonar.db.permission.PermissionMapper"); + Class<?>[] mappers = {ActivityMapper.class, ActiveDashboardMapper.class, AuthorMapper.class, DashboardMapper.class, + DuplicationMapper.class, + IssueMapper.class, IssueChangeMapper.class, IssueFilterMapper.class, IssueFilterFavouriteMapper.class, + IsAliveMapper.class, + LoadedTemplateMapper.class, MeasureFilterMapper.class, Migration44Mapper.class, PermissionTemplateMapper.class, PropertiesMapper.class, PurgeMapper.class, + ResourceKeyUpdaterMapper.class, ResourceIndexerMapper.class, RoleMapper.class, RuleMapper.class, + SchemaMigrationMapper.class, SemaphoreMapper.class, UserMapper.class, GroupMapper.class, UserGroupMapper.class, WidgetMapper.class, WidgetPropertyMapper.class, + FileSourceMapper.class, ActionPlanMapper.class, + ActionPlanStatsMapper.class, + NotificationQueueMapper.class, CharacteristicMapper.class, + GroupMembershipMapper.class, QualityProfileMapper.class, ActiveRuleMapper.class, + MeasureMapper.class, MetricMapper.class, CustomMeasureMapper.class, QualityGateMapper.class, QualityGateConditionMapper.class, ComponentMapper.class, SnapshotMapper.class, + ProjectQgateAssociationMapper.class, EventMapper.class, + AnalysisReportMapper.class, ComponentIndexMapper.class, ComponentLinkMapper.class, + Migration45Mapper.class, Migration50Mapper.class + }; + loadMappers(conf, mappers); + + sessionFactory = new SqlSessionFactoryBuilder().build(conf); + return this; + } + + public SqlSessionFactory getSessionFactory() { + return sessionFactory; + } + + /** + * @deprecated since 4.4. Replaced by <code>openSession(false)</code>. + */ + @Deprecated + public SqlSession openSession() { + return openSession(false); + } + + /** + * @deprecated since 4.4. Replaced by <code>openSession(true)</code>. + */ + @Deprecated + public BatchSession openBatchSession() { + return (BatchSession) openSession(true); + } + + /** + * @since 4.4 + */ + public DbSession openSession(boolean batch) { + if (batch) { + SqlSession session = sessionFactory.openSession(ExecutorType.BATCH); + return new BatchSession(queue, session); + } + SqlSession session = sessionFactory.openSession(ExecutorType.REUSE); + return new DbSession(queue, session); + } + + private void loadMappers(Configuration mybatisConf, Class<?>... mapperClasses) { + for (Class mapperClass : mapperClasses) { + loadMapper(mybatisConf, mapperClass); + } + } + + private void loadMapper(Configuration configuration, Class mapperClass) { + loadMapper(configuration, mapperClass.getName()); + } + + private void loadMapper(Configuration configuration, String mapperName) { + InputStream input = null; + try { + input = getClass().getResourceAsStream("/" + mapperName.replace('.', '/') + ".xml"); + new XMLMapperBuilder(input, configuration, mapperName, configuration.getSqlFragments()).parse(); + configuration.addLoadedResource(mapperName); + ((ch.qos.logback.classic.Logger) LoggerFactory.getLogger(mapperName)).setLevel(Level.INFO); + } catch (Exception e) { + throw new IllegalArgumentException("Unable to load mapper " + mapperName, e); + } finally { + Closeables.closeQuietly(input); + } + } + + private void loadAlias(Configuration conf, String alias, Class dtoClass) { + conf.getTypeAliasRegistry().registerAlias(alias, dtoClass); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/activity/ActivityDto.java b/sonar-db/src/main/java/org/sonar/db/activity/ActivityDto.java new file mode 100644 index 00000000000..2f0b91aabb1 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/activity/ActivityDto.java @@ -0,0 +1,104 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.activity; + +import java.util.Date; +import javax.annotation.Nullable; +import org.apache.commons.lang.builder.ReflectionToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; + +public class ActivityDto { + + private String key; + private String message; + private String type; + private String action; + private String author; + private String data; + private Date createdAt; + + public ActivityDto setKey(String key) { + this.key = key; + return this; + } + + public String getKey() { + return key; + } + + public Date getCreatedAt() { + return createdAt; + } + + public ActivityDto setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + return this; + } + + public String getType() { + return type; + } + + public ActivityDto setType(String type) { + this.type = type; + return this; + } + + public String getAuthor() { + return author; + } + + public ActivityDto setAuthor(@Nullable String author) { + this.author = author; + return this; + } + + public String getData() { + return data; + } + + public ActivityDto setData(String data) { + this.data = data; + return this; + } + + public String getMessage() { + return message; + } + + public ActivityDto setMessage(@Nullable String message) { + this.message = message; + return this; + } + + public String getAction() { + return action; + } + + public ActivityDto setAction(String action) { + this.action = action; + return this; + } + + @Override + public String toString() { + return ReflectionToStringBuilder.toString(this, ToStringStyle.MULTI_LINE_STYLE); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/activity/ActivityMapper.java b/sonar-db/src/main/java/org/sonar/db/activity/ActivityMapper.java new file mode 100644 index 00000000000..467db557e8e --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/activity/ActivityMapper.java @@ -0,0 +1,26 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.activity; + +public interface ActivityMapper { + + void insert(ActivityDto dto); + +} diff --git a/sonar-db/src/main/java/org/sonar/db/activity/package-info.java b/sonar-db/src/main/java/org/sonar/db/activity/package-info.java new file mode 100644 index 00000000000..10134a6fce2 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/activity/package-info.java @@ -0,0 +1,25 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.activity; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/sonar-db/src/main/java/org/sonar/db/component/ComponentDto.java b/sonar-db/src/main/java/org/sonar/db/component/ComponentDto.java new file mode 100644 index 00000000000..4e034e4a19b --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/component/ComponentDto.java @@ -0,0 +1,304 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.component; + +import java.util.Date; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.sonar.api.component.Component; +import org.sonar.api.resources.Scopes; + +public class ComponentDto implements Component { + + public static final String MODULE_UUID_PATH_SEP = "."; + + private Long id; + private String uuid; + private String kee; + private String scope; + private String qualifier; + + private String projectUuid; + private String moduleUuid; + private String moduleUuidPath; + private Long parentProjectId; + private Long copyResourceId; + + private String path; + private String deprecatedKey; + private String name; + private String longName; + private String language; + private String description; + private boolean enabled = true; + + private Date createdAt; + private Long authorizationUpdatedAt; + + public Long getId() { + return id; + } + + public ComponentDto setId(Long id) { + this.id = id; + return this; + } + + public String uuid() { + return uuid; + } + + public ComponentDto setUuid(String uuid) { + this.uuid = uuid; + return this; + } + + @Override + public String key() { + return kee; + } + + public String scope() { + return scope; + } + + public ComponentDto setScope(String scope) { + this.scope = scope; + return this; + } + + @Override + public String qualifier() { + return qualifier; + } + + public ComponentDto setQualifier(String qualifier) { + this.qualifier = qualifier; + return this; + } + + @CheckForNull + public String deprecatedKey() { + return deprecatedKey; + } + + public ComponentDto setDeprecatedKey(@Nullable String deprecatedKey) { + this.deprecatedKey = deprecatedKey; + return this; + } + + /** + * Return the root project uuid. On a root project, return itself + */ + public String projectUuid() { + return projectUuid; + } + + public ComponentDto setProjectUuid(String projectUuid) { + this.projectUuid = projectUuid; + return this; + } + + /** + * Return the direct module of a component. Will be null on projects + */ + @CheckForNull + public String moduleUuid() { + return moduleUuid; + } + + public ComponentDto setModuleUuid(@Nullable String moduleUuid) { + this.moduleUuid = moduleUuid; + return this; + } + + /** + * Return the path from the project to the last modules + */ + public String moduleUuidPath() { + return moduleUuidPath; + } + + public ComponentDto setModuleUuidPath(String moduleUuidPath) { + this.moduleUuidPath = moduleUuidPath; + return this; + } + + @CheckForNull + @Override + public String path() { + return path; + } + + public ComponentDto setPath(@Nullable String path) { + this.path = path; + return this; + } + + @Override + public String name() { + return name; + } + + public ComponentDto setName(String name) { + this.name = name; + return this; + } + + @Override + public String longName() { + return longName; + } + + public ComponentDto setLongName(String longName) { + this.longName = longName; + return this; + } + + @CheckForNull + public String language() { + return language; + } + + public ComponentDto setLanguage(@Nullable String language) { + this.language = language; + return this; + } + + @CheckForNull + public String description() { + return description; + } + + public ComponentDto setDescription(@Nullable String description) { + this.description = description; + return this; + } + + @CheckForNull + public Long parentProjectId() { + return parentProjectId; + } + + public ComponentDto setParentProjectId(@Nullable Long parentProjectId) { + this.parentProjectId = parentProjectId; + return this; + } + + public boolean isEnabled() { + return enabled; + } + + public ComponentDto setEnabled(boolean enabled) { + this.enabled = enabled; + return this; + } + + public Long getCopyResourceId() { + return copyResourceId; + } + + public ComponentDto setCopyResourceId(Long copyResourceId) { + this.copyResourceId = copyResourceId; + return this; + } + + public Date getCreatedAt() { + return createdAt; + } + + public ComponentDto setCreatedAt(Date datetime) { + this.createdAt = datetime; + return this; + } + + /** + * Only available on projects + */ + @CheckForNull + public Long getAuthorizationUpdatedAt() { + return authorizationUpdatedAt; + } + + public ComponentDto setAuthorizationUpdatedAt(@Nullable Long authorizationUpdatedAt) { + this.authorizationUpdatedAt = authorizationUpdatedAt; + return this; + } + + public String getKey() { + return key(); + } + + public ComponentDto setKey(String key) { + this.kee = key; + return this; + } + + public boolean isRootProject() { + return moduleUuid == null && Scopes.PROJECT.equals(scope); + } + + // FIXME equals/hashCode mean nothing on DTOs, especially when on id + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ComponentDto that = (ComponentDto) o; + if (id != null ? !id.equals(that.id) : that.id != null) { + return false; + } + return true; + } + + // FIXME equals/hashCode mean nothing on DTOs, especially when on id + @Override + public int hashCode() { + return id != null ? id.hashCode() : 0; + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .append("id", id) + .append("uuid", uuid) + .append("kee", kee) + .append("scope", scope) + .append("qualifier", qualifier) + .append("projectUuid", projectUuid) + .append("moduleUuid", moduleUuid) + .append("moduleUuidPath", moduleUuidPath) + .append("parentProjectId", parentProjectId) + .append("copyResourceId", copyResourceId) + .append("path", path) + .append("deprecatedKey", deprecatedKey) + .append("name", name) + .append("longName", longName) + .append("language", language) + .append("enabled", enabled) + .append("authorizationUpdatedAt", authorizationUpdatedAt) + .toString(); + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/component/ComponentIndexMapper.java b/sonar-db/src/main/java/org/sonar/db/component/ComponentIndexMapper.java new file mode 100644 index 00000000000..44eafac3a24 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/component/ComponentIndexMapper.java @@ -0,0 +1,29 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.component; + +import java.util.List; +import org.apache.ibatis.annotations.Param; + +public interface ComponentIndexMapper { + + List<Long> selectProjectIdsFromQueryAndViewOrSubViewUuid(@Param("query") String query, @Param("viewUuidQuery") String viewUuidQuery); +} diff --git a/sonar-db/src/main/java/org/sonar/db/component/ComponentLinkDto.java b/sonar-db/src/main/java/org/sonar/db/component/ComponentLinkDto.java new file mode 100644 index 00000000000..62cc435966b --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/component/ComponentLinkDto.java @@ -0,0 +1,90 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.component; + +import com.google.common.collect.ImmutableList; +import java.util.List; + +/** + * Component links should be merge in a 'links' column (using protobuf for instance) of the projects table. + * But to do this we'll have to wait for the measure filters page (where links are displayed) to be rewritten in JS/WS (because it's in Rails for the moment). + */ +public class ComponentLinkDto { + + public static final String TYPE_HOME_PAGE = "homepage"; + public static final String TYPE_CI = "ci"; + public static final String TYPE_ISSUE_TRACKER = "issue"; + public static final String TYPE_SOURCES = "scm"; + public static final String TYPE_SOURCES_DEV = "scm_dev"; + + public static final List<String> PROVIDED_TYPES = ImmutableList.of(TYPE_HOME_PAGE, TYPE_CI, TYPE_ISSUE_TRACKER, TYPE_SOURCES, TYPE_SOURCES_DEV); + + private Long id; + private String componentUuid; + private String type; + private String name; + private String href; + + public String getName() { + return name; + } + + public ComponentLinkDto setName(String name) { + this.name = name; + return this; + } + + public String getComponentUuid() { + return componentUuid; + } + + public ComponentLinkDto setComponentUuid(String componentUuid) { + this.componentUuid = componentUuid; + return this; + } + + public String getHref() { + return href; + } + + public ComponentLinkDto setHref(String href) { + this.href = href; + return this; + } + + public Long getId() { + return id; + } + + public ComponentLinkDto setId(Long id) { + this.id = id; + return this; + } + + public String getType() { + return type; + } + + public ComponentLinkDto setType(String type) { + this.type = type; + return this; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/component/ComponentLinkMapper.java b/sonar-db/src/main/java/org/sonar/db/component/ComponentLinkMapper.java new file mode 100644 index 00000000000..2b7fe818914 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/component/ComponentLinkMapper.java @@ -0,0 +1,35 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.component; + +import java.util.List; + +public interface ComponentLinkMapper { + + List<ComponentLinkDto> selectByComponentUuid(String componentUuid); + + void insert(ComponentLinkDto dto); + + void update(ComponentLinkDto dto); + + void delete(long id); + +} diff --git a/sonar-db/src/main/java/org/sonar/db/component/ComponentMapper.java b/sonar-db/src/main/java/org/sonar/db/component/ComponentMapper.java new file mode 100644 index 00000000000..ac38353e9a6 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/component/ComponentMapper.java @@ -0,0 +1,110 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.component; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.session.RowBounds; + +/** + * @since 4.3 + */ +public interface ComponentMapper { + + @CheckForNull + ComponentDto selectByKey(String key); + + @CheckForNull + ComponentDto selectById(long id); + + @CheckForNull + ComponentDto selectByUuid(String uuid); + + /** + * Return sub project of component keys + */ + List<ComponentDto> selectSubProjectsByComponentUuids(@Param("uuids") Collection<String> uuids); + + List<ComponentDto> selectByKeys(@Param("keys") Collection<String> keys); + + List<ComponentDto> selectByIds(@Param("ids") Collection<Long> ids); + + List<ComponentDto> selectByUuids(@Param("uuids") Collection<String> uuids); + + List<String> selectExistingUuids(@Param("uuids") Collection<String> uuids); + + /** + * Return all project (PRJ/TRK) uuids + */ + List<String> selectProjectUuids(); + + /** + * Return all descendant modules (including itself) from a given component uuid and scope + */ + List<ComponentDto> selectDescendantModules(@Param("moduleUuid") String moduleUuid, @Param(value = "scope") String scope, + @Param(value = "excludeDisabled") boolean excludeDisabled); + + /** + * Return all files from a given project uuid and scope + */ + List<FilePathWithHashDto> selectEnabledFilesFromProject(@Param("projectUuid") String projectUuid); + + /** + * Return all descendant files from a given module uuid and scope + */ + List<FilePathWithHashDto> selectDescendantFiles(@Param("moduleUuid") String moduleUuid, @Param(value = "scope") String scope, + @Param(value = "excludeDisabled") boolean excludeDisabled); + + /** + * Return uuids and project uuids from list of qualifiers + * + * It's using a join on snapshots in order to use he indexed columns snapshots.qualifier + */ + List<UuidWithProjectUuidDto> selectUuidsForQualifiers(@Param("qualifiers") String... qualifiers); + + /** + * Return all components of a project + */ + List<ComponentDto> selectComponentsFromProjectKeyAndScope(@Param("projectKey") String projectKey, @Nullable @Param("scope") String scope); + + /** + * Return technical projects from a view or a sub-view + */ + List<String> selectProjectsFromView(@Param("viewUuidLikeQuery") String viewUuidLikeQuery, @Param("projectViewUuid") String projectViewUuid); + + long countById(long id); + + List<ComponentDto> selectProvisionedProjects(Map<String, String> parameters, RowBounds rowBounds); + + int countProvisionedProjects(Map<String, String> parameters); + + List<ComponentDto> selectGhostProjects(Map<String, String> parameters, RowBounds rowBounds); + + long countGhostProjects(Map<String, String> parameters); + + void insert(ComponentDto componentDto); + + void update(ComponentDto componentDto); +} diff --git a/sonar-db/src/main/java/org/sonar/db/component/FilePathWithHashDto.java b/sonar-db/src/main/java/org/sonar/db/component/FilePathWithHashDto.java new file mode 100644 index 00000000000..85e3c45ceb6 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/component/FilePathWithHashDto.java @@ -0,0 +1,61 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.component; + +public class FilePathWithHashDto { + + private String uuid; + private String moduleUuid; + private String path; + private String srcHash; + + public String getSrcHash() { + return srcHash; + } + + public void setSrcHash(String srcHash) { + this.srcHash = srcHash; + } + + public String getModuleUuid() { + return moduleUuid; + } + + public void setModuleUuid(String moduleUuid) { + this.moduleUuid = moduleUuid; + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/component/ResourceDao.java b/sonar-db/src/main/java/org/sonar/db/component/ResourceDao.java new file mode 100644 index 00000000000..2ebd03ec015 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/component/ResourceDao.java @@ -0,0 +1,373 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.component; + +import com.google.common.base.Function; +import com.google.common.collect.Iterables; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import javax.annotation.CheckForNull; +import javax.annotation.Nonnull; +import org.apache.ibatis.session.SqlSession; +import org.sonar.api.component.Component; +import org.sonar.api.resources.Scopes; +import org.sonar.api.utils.System2; +import org.sonar.api.utils.internal.Uuids; +import org.sonar.db.Dao; +import org.sonar.db.DbSession; +import org.sonar.db.MyBatis; + +import static com.google.common.collect.Lists.newArrayList; + +public class ResourceDao implements Dao { + private MyBatis mybatis; + private System2 system2; + + public ResourceDao(MyBatis mybatis, System2 system2) { + this.mybatis = mybatis; + this.system2 = system2; + } + + public List<ResourceDto> getResources(ResourceQuery query) { + SqlSession session = mybatis.openSession(false); + try { + return session.getMapper(ResourceMapper.class).selectResources(query); + } finally { + MyBatis.closeQuietly(session); + } + } + + public List<ResourceDto> getResources(ResourceQuery query, SqlSession session) { + return session.getMapper(ResourceMapper.class).selectResources(query); + } + + /** + * Return a single result or null. If the request returns multiple rows, then + * the first row is returned. + */ + @CheckForNull + public ResourceDto getResource(ResourceQuery query) { + DbSession session = mybatis.openSession(false); + try { + return getResource(query, session); + } finally { + MyBatis.closeQuietly(session); + } + } + + @CheckForNull + public ResourceDto getResource(ResourceQuery query, DbSession session) { + List<ResourceDto> resources = getResources(query, session); + if (!resources.isEmpty()) { + return resources.get(0); + } + return null; + } + + public List<Long> getResourceIds(ResourceQuery query) { + SqlSession session = mybatis.openSession(false); + try { + return session.getMapper(ResourceMapper.class).selectResourceIds(query); + } finally { + MyBatis.closeQuietly(session); + } + } + + public ResourceDto getResource(long projectId) { + SqlSession session = mybatis.openSession(false); + try { + return getResource(projectId, session); + } finally { + MyBatis.closeQuietly(session); + } + } + + @CheckForNull + public ResourceDto getResource(String componentUuid) { + SqlSession session = mybatis.openSession(false); + try { + return session.getMapper(ResourceMapper.class).selectResourceByUuid(componentUuid); + } finally { + MyBatis.closeQuietly(session); + } + } + + public ResourceDto getResource(long projectId, SqlSession session) { + return session.getMapper(ResourceMapper.class).selectResource(projectId); + } + + @CheckForNull + public SnapshotDto getLastSnapshot(String resourceKey, SqlSession session) { + return session.getMapper(ResourceMapper.class).selectLastSnapshotByResourceKey(resourceKey); + } + + @CheckForNull + public SnapshotDto getLastSnapshotByResourceUuid(String componentUuid, SqlSession session) { + return session.getMapper(ResourceMapper.class).selectLastSnapshotByResourceUuid(componentUuid); + } + + public List<ResourceDto> getDescendantProjects(long projectId) { + SqlSession session = mybatis.openSession(false); + try { + return getDescendantProjects(projectId, session); + } finally { + MyBatis.closeQuietly(session); + } + } + + public List<ResourceDto> getDescendantProjects(long projectId, SqlSession session) { + ResourceMapper mapper = session.getMapper(ResourceMapper.class); + List<ResourceDto> resources = newArrayList(); + appendChildProjects(projectId, mapper, resources); + return resources; + } + + private void appendChildProjects(long projectId, ResourceMapper mapper, List<ResourceDto> resources) { + List<ResourceDto> subProjects = mapper.selectDescendantProjects(projectId); + for (ResourceDto subProject : subProjects) { + resources.add(subProject); + appendChildProjects(subProject.getId(), mapper, resources); + } + } + + /** + * Used by the Views Plugin + */ + public ResourceDao insertOrUpdate(ResourceDto... resources) { + SqlSession session = mybatis.openSession(false); + ResourceMapper mapper = session.getMapper(ResourceMapper.class); + Date now = new Date(system2.now()); + try { + for (ResourceDto resource : resources) { + if (resource.getId() == null) { + // Fix for Views + if (resource.getUuid() == null && Scopes.PROJECT.equals(resource.getScope())) { + String uuid = Uuids.create(); + resource.setUuid(uuid); + resource.setProjectUuid(uuid); + resource.setModuleUuidPath(""); + } + resource.setCreatedAt(now); + resource.setAuthorizationUpdatedAt(now.getTime()); + mapper.insert(resource); + } else { + mapper.update(resource); + } + } + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + return this; + } + + /** + * Should not be called from batch side (used to reindex permission in E/S) + */ + public void updateAuthorizationDate(Long projectId, SqlSession session) { + session.getMapper(ResourceMapper.class).updateAuthorizationDate(projectId, system2.now()); + } + + @CheckForNull + public Component findByKey(String key) { + ResourceDto resourceDto = getResource(ResourceQuery.create().setKey(key)); + return resourceDto != null ? toComponent(resourceDto) : null; + } + + @CheckForNull + public Component findById(Long id, SqlSession session) { + ResourceDto resourceDto = getResource(id, session); + return resourceDto != null ? toComponent(resourceDto) : null; + } + + /** + * Return the root project of a component. + * Will return the component itself if it's already the root project + * Can return null if the component does not exists. + * + * The implementation should rather use a new column already containing the root project, see https://jira.sonarsource.com/browse/SONAR-5188. + */ + @CheckForNull + public ResourceDto getRootProjectByComponentKey(DbSession session, String componentKey) { + ResourceDto component = getResource(ResourceQuery.create().setKey(componentKey), session); + if (component != null) { + Long rootId = component.getRootId(); + if (rootId != null) { + return getParentModuleByComponentId(rootId, session); + } else { + return component; + } + } + return null; + } + + @CheckForNull + public ResourceDto getRootProjectByComponentKey(String componentKey) { + DbSession session = mybatis.openSession(false); + try { + return getRootProjectByComponentKey(session, componentKey); + } finally { + MyBatis.closeQuietly(session); + } + } + + @CheckForNull + ResourceDto getParentModuleByComponentId(Long componentId, DbSession session) { + ResourceDto component = getResource(componentId, session); + if (component != null) { + Long rootId = component.getRootId(); + if (rootId != null) { + return getParentModuleByComponentId(rootId, session); + } else { + return component; + } + } + return null; + } + + /** + * Return the root project of a component. + * Will return the component itself if it's already the root project + * Can return null if the component that does exists. + * + * The implementation should rather use a new column already containing the root project, see https://jira.sonarsource.com/browse/SONAR-5188. + */ + @CheckForNull + public ResourceDto getRootProjectByComponentId(long componentId) { + DbSession session = mybatis.openSession(false); + try { + ResourceDto component = getParentModuleByComponentId(componentId, session); + Long rootId = component != null ? component.getRootId() : null; + if (rootId != null) { + return getParentModuleByComponentId(rootId, session); + } else { + return component; + } + } finally { + MyBatis.closeQuietly(session); + } + } + + public List<Component> selectProjectsByQualifiers(Collection<String> qualifiers) { + if (qualifiers.isEmpty()) { + return Collections.emptyList(); + } + SqlSession session = mybatis.openSession(false); + try { + return toComponents(session.getMapper(ResourceMapper.class).selectProjectsByQualifiers(qualifiers)); + } finally { + MyBatis.closeQuietly(session); + } + } + + /** + * Return enabled projects including not completed ones, ie without snapshots or without snapshot having islast=true + */ + public List<Component> selectProjectsIncludingNotCompletedOnesByQualifiers(Collection<String> qualifiers) { + if (qualifiers.isEmpty()) { + return Collections.emptyList(); + } + SqlSession session = mybatis.openSession(false); + try { + return toComponents(session.getMapper(ResourceMapper.class).selectProjectsIncludingNotCompletedOnesByQualifiers(qualifiers)); + } finally { + MyBatis.closeQuietly(session); + } + } + + /** + * Return ghosts projects : + * - not enabled projects + * - enabled projects without snapshot having islast=true + * - enabled projects without snapshot + */ + public List<Component> selectGhostsProjects(Collection<String> qualifiers) { + if (qualifiers.isEmpty()) { + return Collections.emptyList(); + } + SqlSession session = mybatis.openSession(false); + try { + return toComponents(session.getMapper(ResourceMapper.class).selectGhostsProjects(qualifiers)); + } finally { + MyBatis.closeQuietly(session); + } + } + + /** + * Return provisioned projects = enabled projects without snapshot + */ + public List<ResourceDto> selectProvisionedProjects(Collection<String> qualifiers) { + if (qualifiers.isEmpty()) { + return Collections.emptyList(); + } + SqlSession session = mybatis.openSession(false); + try { + return session.getMapper(ResourceMapper.class).selectProvisionedProjects(qualifiers); + } finally { + MyBatis.closeQuietly(session); + } + } + + /** + * Return provisioned project with given key + */ + public ResourceDto selectProvisionedProject(DbSession session, String key) { + return session.getMapper(ResourceMapper.class).selectProvisionedProject(key); + } + + public ResourceDto selectProvisionedProject(String key) { + DbSession session = mybatis.openSession(false); + try { + return selectProvisionedProject(session, key); + } finally { + MyBatis.closeQuietly(session); + } + } + + public static ComponentDto toComponent(ResourceDto resourceDto) { + return new ComponentDto() + .setId(resourceDto.getId()) + .setKey(resourceDto.getKey()) + .setPath(resourceDto.getPath()) + .setLongName(resourceDto.getLongName()) + .setName(resourceDto.getName()) + .setQualifier(resourceDto.getQualifier()); + } + + public static List<Component> toComponents(List<ResourceDto> resourceDto) { + return newArrayList(Iterables.transform(resourceDto, ToComponent.INSTANCE)); + } + + public void insertUsingExistingSession(ResourceDto resourceDto, SqlSession session) { + ResourceMapper resourceMapper = session.getMapper(ResourceMapper.class); + resourceMapper.insert(resourceDto); + } + + private enum ToComponent implements Function<ResourceDto, Component> { + INSTANCE; + + @Override + public Component apply(@Nonnull ResourceDto resourceDto) { + return toComponent(resourceDto); + } + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/component/ResourceDto.java b/sonar-db/src/main/java/org/sonar/db/component/ResourceDto.java new file mode 100644 index 00000000000..769ee2376fc --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/component/ResourceDto.java @@ -0,0 +1,226 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.component; + +import java.util.Date; + +public class ResourceDto { + + private Long id; + private String uuid; + private String projectUuid; + private String moduleUuid; + private String moduleUuidPath; + private String key; + private String deprecatedKey; + private String name; + private String longName; + private Long rootId; + private String path; + private String scope; + private String qualifier; + private boolean enabled = true; + private String description; + private String language; + private Long copyResourceId; + private Long personId; + private Date createdAt; + private Long authorizationUpdatedAt; + + public Long getId() { + return id; + } + + public ResourceDto setId(Long id) { + this.id = id; + return this; + } + + public String getUuid() { + return uuid; + } + + public ResourceDto setUuid(String uuid) { + this.uuid = uuid; + return this; + } + + public String getProjectUuid() { + return projectUuid; + } + + public ResourceDto setProjectUuid(String projectUuid) { + this.projectUuid = projectUuid; + return this; + } + + public String getModuleUuid() { + return moduleUuid; + } + + public ResourceDto setModuleUuid(String moduleUuid) { + this.moduleUuid = moduleUuid; + return this; + } + + public String getModuleUuidPath() { + return moduleUuidPath; + } + + public ResourceDto setModuleUuidPath(String moduleUuidPath) { + this.moduleUuidPath = moduleUuidPath; + return this; + } + + public String getName() { + return name; + } + + public ResourceDto setName(String name) { + this.name = name; + return this; + } + + public String getKey() { + return key; + } + + public ResourceDto setKey(String s) { + this.key = s; + return this; + } + + public String getDeprecatedKey() { + return deprecatedKey; + } + + public ResourceDto setDeprecatedKey(String s) { + this.deprecatedKey = s; + return this; + } + + public Long getRootId() { + return rootId; + } + + public ResourceDto setRootId(Long rootId) { + this.rootId = rootId; + return this; + } + + public String getPath() { + return path; + } + + public ResourceDto setPath(String s) { + this.path = s; + return this; + } + + public String getLongName() { + return longName; + } + + public ResourceDto setLongName(String longName) { + this.longName = longName; + return this; + } + + public String getScope() { + return scope; + } + + public ResourceDto setScope(String scope) { + this.scope = scope; + return this; + } + + public String getQualifier() { + return qualifier; + } + + public ResourceDto setQualifier(String qualifier) { + this.qualifier = qualifier; + return this; + } + + public boolean isEnabled() { + return enabled; + } + + public ResourceDto setEnabled(boolean b) { + this.enabled = b; + return this; + } + + public String getDescription() { + return description; + } + + public ResourceDto setDescription(String description) { + this.description = description; + return this; + } + + public String getLanguage() { + return language; + } + + public ResourceDto setLanguage(String language) { + this.language = language; + return this; + } + + public Long getCopyResourceId() { + return copyResourceId; + } + + public ResourceDto setCopyResourceId(Long copyResourceId) { + this.copyResourceId = copyResourceId; + return this; + } + + public Long getPersonId() { + return personId; + } + + public ResourceDto setPersonId(Long personId) { + this.personId = personId; + return this; + } + + public Date getCreatedAt() { + return createdAt;// NOSONAR May expose internal representation by returning reference to mutable object + } + + public ResourceDto setCreatedAt(Date date) { + this.createdAt = date;// NOSONAR May expose internal representation by incorporating reference to mutable object + return this; + } + + public Long getAuthorizationUpdatedAt() { + return authorizationUpdatedAt; + } + + public ResourceDto setAuthorizationUpdatedAt(Long authorizationUpdatedAt) { + this.authorizationUpdatedAt = authorizationUpdatedAt; + return this; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/component/ResourceIndexDto.java b/sonar-db/src/main/java/org/sonar/db/component/ResourceIndexDto.java new file mode 100644 index 00000000000..90ac0944274 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/component/ResourceIndexDto.java @@ -0,0 +1,93 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.component; + +public final class ResourceIndexDto { + private Long id; + private String key; + private int position; + private int nameSize; + private long resourceId; + private long rootProjectId; + private String qualifier; + + public Long getId() { + return id; + } + + public ResourceIndexDto setId(Long id) { + this.id = id; + return this; + } + + public String getKey() { + return key; + } + + public ResourceIndexDto setKey(String key) { + this.key = key; + return this; + } + + public int getPosition() { + return position; + } + + public ResourceIndexDto setPosition(int i) { + this.position = i; + return this; + } + + public long getResourceId() { + return resourceId; + } + + public ResourceIndexDto setResourceId(long i) { + this.resourceId = i; + return this; + } + + public long getRootProjectId() { + return rootProjectId; + } + + public ResourceIndexDto setRootProjectId(long i) { + this.rootProjectId = i; + return this; + } + + public int getNameSize() { + return nameSize; + } + + public ResourceIndexDto setNameSize(int i) { + this.nameSize = i; + return this; + } + + public String getQualifier() { + return qualifier; + } + + public ResourceIndexDto setQualifier(String qualifier) { + this.qualifier = qualifier; + return this; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/component/ResourceIndexerDao.java b/sonar-db/src/main/java/org/sonar/db/component/ResourceIndexerDao.java new file mode 100644 index 00000000000..6a61ef714e6 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/component/ResourceIndexerDao.java @@ -0,0 +1,216 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.component; + +import org.apache.commons.lang.StringUtils; +import org.apache.ibatis.session.ResultContext; +import org.apache.ibatis.session.ResultHandler; +import org.apache.ibatis.session.SqlSession; +import org.sonar.api.resources.Qualifiers; +import org.sonar.api.resources.Scopes; +import org.sonar.db.DbSession; +import org.sonar.db.MyBatis; + +public class ResourceIndexerDao { + + private static final String SELECT_RESOURCES = "org.sonar.db.component.ResourceIndexerMapper.selectResources"; + public static final int MINIMUM_KEY_SIZE = 3; + public static final int SINGLE_INDEX_SIZE = 2; + + // The scopes and qualifiers that are not in the following constants are not indexed at all. + // Directories and packages are explicitly excluded. + private static final String[] RENAMABLE_QUALIFIERS = {Qualifiers.PROJECT, Qualifiers.MODULE, Qualifiers.VIEW, Qualifiers.SUBVIEW}; + private static final String[] RENAMABLE_SCOPES = {Scopes.PROJECT}; + private static final String[] NOT_RENAMABLE_QUALIFIERS = {Qualifiers.FILE, Qualifiers.UNIT_TEST_FILE, Qualifiers.CLASS}; + private static final String[] NOT_RENAMABLE_SCOPES = {Scopes.FILE}; + + private final MyBatis mybatis; + + public ResourceIndexerDao(MyBatis mybatis) { + this.mybatis = mybatis; + } + + /** + * This method is reentrant. It can be executed even if the project is already indexed. + */ + public ResourceIndexerDao indexProject(final long rootProjectId) { + DbSession session = mybatis.openSession(true); + try { + indexProject(rootProjectId, session); + session.commit(); + return this; + + } finally { + MyBatis.closeQuietly(session); + } + } + + public void indexProject(final long rootProjectId, DbSession session) { + ResourceIndexerMapper mapper = session.getMapper(ResourceIndexerMapper.class); + doIndexProject(rootProjectId, session, mapper); + } + + /** + * This method is reentrant. It can be executed even if some projects are already indexed. + */ + public ResourceIndexerDao indexProjects() { + final DbSession session = mybatis.openSession(true); + try { + final ResourceIndexerMapper mapper = session.getMapper(ResourceIndexerMapper.class); + session.select("org.sonar.db.component.ResourceIndexerMapper.selectRootProjectIds", /* workaround to get booleans */ResourceIndexerQuery.create(), new ResultHandler() { + @Override + public void handleResult(ResultContext context) { + Integer rootProjectId = (Integer) context.getResultObject(); + doIndexProject(rootProjectId, session, mapper); + session.commit(); + } + }); + return this; + + } finally { + MyBatis.closeQuietly(session); + } + } + + private void doIndexProject(long rootProjectId, SqlSession session, final ResourceIndexerMapper mapper) { + // non indexed resources + ResourceIndexerQuery query = ResourceIndexerQuery.create() + .setNonIndexedOnly(true) + .setQualifiers(NOT_RENAMABLE_QUALIFIERS) + .setScopes(NOT_RENAMABLE_SCOPES) + .setRootProjectId(rootProjectId); + + session.select(SELECT_RESOURCES, query, new ResultHandler() { + @Override + public void handleResult(ResultContext context) { + ResourceDto resource = (ResourceDto) context.getResultObject(); + doIndex(resource, mapper); + } + }); + + // some resources can be renamed, so index must be regenerated + // -> delete existing rows and create them again + query = ResourceIndexerQuery.create() + .setNonIndexedOnly(false) + .setQualifiers(RENAMABLE_QUALIFIERS) + .setScopes(RENAMABLE_SCOPES) + .setRootProjectId(rootProjectId); + + session.select(SELECT_RESOURCES, query, new ResultHandler() { + @Override + public void handleResult(ResultContext context) { + ResourceDto resource = (ResourceDto) context.getResultObject(); + + mapper.deleteByResourceId(resource.getId()); + doIndex(resource, mapper); + } + }); + } + + void doIndex(ResourceDto resource, ResourceIndexerMapper mapper) { + String key = nameToKey(resource.getName()); + if (key.length() >= MINIMUM_KEY_SIZE || key.length() == SINGLE_INDEX_SIZE) { + insertIndexEntries(key, resource.getId(), resource.getQualifier(), resource.getRootId(), resource.getName().length(), mapper); + } + } + + public boolean indexResource(long id) { + DbSession session = mybatis.openSession(false); + try { + return indexResource(session, id); + } finally { + MyBatis.closeQuietly(session); + } + } + + public boolean indexResource(DbSession session, long id) { + boolean indexed = false; + ResourceIndexerMapper mapper = session.getMapper(ResourceIndexerMapper.class); + ResourceDto resource = mapper.selectResourceToIndex(id); + if (resource != null) { + Long rootId = resource.getRootId(); + if (rootId == null) { + rootId = resource.getId(); + } + indexed = indexResource(resource.getId(), resource.getName(), resource.getQualifier(), rootId, session, mapper); + } + return indexed; + } + + public boolean indexResource(int id, String name, String qualifier, int rootId) { + boolean indexed = false; + SqlSession session = mybatis.openSession(false); + ResourceIndexerMapper mapper = session.getMapper(ResourceIndexerMapper.class); + try { + indexed = indexResource(id, name, qualifier, rootId, session, mapper); + } finally { + MyBatis.closeQuietly(session); + } + return indexed; + } + + private boolean indexResource(long id, String name, String qualifier, long rootId, SqlSession session, ResourceIndexerMapper mapper) { + boolean indexed = false; + String key = nameToKey(name); + if (key.length() >= MINIMUM_KEY_SIZE || key.length() == SINGLE_INDEX_SIZE) { + indexed = true; + boolean toBeIndexed = sanitizeIndex(id, key, mapper); + if (toBeIndexed) { + insertIndexEntries(key, id, qualifier, rootId, name.length(), mapper); + session.commit(); + } + } + return indexed; + } + + private void insertIndexEntries(String key, long resourceId, String qualifier, long rootId, int nameLength, ResourceIndexerMapper mapper) { + ResourceIndexDto dto = new ResourceIndexDto() + .setResourceId(resourceId) + .setQualifier(qualifier) + .setRootProjectId(rootId) + .setNameSize(nameLength); + + int maxPosition = key.length() == SINGLE_INDEX_SIZE ? 0 : key.length() - MINIMUM_KEY_SIZE; + for (int position = 0; position <= maxPosition; position++) { + dto.setPosition(position); + dto.setKey(StringUtils.substring(key, position)); + mapper.insert(dto); + } + } + + /** + * Return true if the resource must be indexed, false if the resource is already indexed. + * If the resource is indexed with a different key, then this index is dropped and the + * resource must be indexed again. + */ + private boolean sanitizeIndex(long resourceId, String key, ResourceIndexerMapper mapper) { + ResourceIndexDto masterIndex = mapper.selectMasterIndexByResourceId(resourceId); + if (masterIndex != null && !StringUtils.equals(key, masterIndex.getKey())) { + // resource has been renamed -> drop existing indexes + mapper.deleteByResourceId(resourceId); + masterIndex = null; + } + return masterIndex == null; + } + + static String nameToKey(String input) { + return StringUtils.lowerCase(StringUtils.trimToEmpty(input)); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/component/ResourceIndexerMapper.java b/sonar-db/src/main/java/org/sonar/db/component/ResourceIndexerMapper.java new file mode 100644 index 00000000000..ecbacc7da82 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/component/ResourceIndexerMapper.java @@ -0,0 +1,31 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.component; + +public interface ResourceIndexerMapper { + + ResourceIndexDto selectMasterIndexByResourceId(long resourceId); + + ResourceDto selectResourceToIndex(long resourceId); + + void deleteByResourceId(long resourceId); + + void insert(ResourceIndexDto dto); +} diff --git a/sonar-db/src/main/java/org/sonar/db/component/ResourceIndexerQuery.java b/sonar-db/src/main/java/org/sonar/db/component/ResourceIndexerQuery.java new file mode 100644 index 00000000000..f05204aa130 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/component/ResourceIndexerQuery.java @@ -0,0 +1,70 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.component; + +final class ResourceIndexerQuery { + private long rootProjectId; + private String[] scopes = null; + private String[] qualifiers = null; + private boolean nonIndexedOnly = false; + + private ResourceIndexerQuery() { + } + + public static ResourceIndexerQuery create() { + return new ResourceIndexerQuery(); + } + + public String[] getScopes() { + return scopes; + } + + public String[] getQualifiers() { + return qualifiers; + } + + public ResourceIndexerQuery setScopes(String[] scopes) { + this.scopes = scopes; + return this; + } + + public ResourceIndexerQuery setQualifiers(String[] qualifiers) { + this.qualifiers = qualifiers; + return this; + } + + public long getRootProjectId() { + return rootProjectId; + } + + public ResourceIndexerQuery setRootProjectId(long i) { + this.rootProjectId = i; + return this; + } + + public boolean isNonIndexedOnly() { + return nonIndexedOnly; + } + + public ResourceIndexerQuery setNonIndexedOnly(boolean b) { + this.nonIndexedOnly = b; + return this; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/component/ResourceKeyUpdaterDao.java b/sonar-db/src/main/java/org/sonar/db/component/ResourceKeyUpdaterDao.java new file mode 100644 index 00000000000..6441c88df37 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/component/ResourceKeyUpdaterDao.java @@ -0,0 +1,156 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.component; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.apache.commons.lang.StringUtils; +import org.apache.ibatis.session.SqlSession; +import org.sonar.db.DbSession; +import org.sonar.db.MyBatis; + +/** + * Class used to rename the key of a project and its resources. + * + * @since 3.2 + */ +public class ResourceKeyUpdaterDao { + private MyBatis mybatis; + + public ResourceKeyUpdaterDao(MyBatis mybatis) { + this.mybatis = mybatis; + } + + public void updateKey(long projectId, String newKey) { + DbSession session = mybatis.openSession(true); + ResourceKeyUpdaterMapper mapper = session.getMapper(ResourceKeyUpdaterMapper.class); + try { + if (mapper.countResourceByKey(newKey) > 0) { + throw new IllegalStateException("Impossible to update key: a resource with \"" + newKey + "\" key already exists."); + } + + // must SELECT first everything + ResourceDto project = mapper.selectProject(projectId); + String projectOldKey = project.getKey(); + List<ResourceDto> resources = mapper.selectProjectResources(projectId); + resources.add(project); + + // and then proceed with the batch UPDATE at once + runBatchUpdateForAllResources(resources, projectOldKey, newKey, mapper); + + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + public Map<String, String> checkModuleKeysBeforeRenaming(long projectId, String stringToReplace, String replacementString) { + SqlSession session = mybatis.openSession(false); + ResourceKeyUpdaterMapper mapper = session.getMapper(ResourceKeyUpdaterMapper.class); + Map<String, String> result = Maps.newHashMap(); + try { + Set<ResourceDto> modules = collectAllModules(projectId, stringToReplace, mapper); + for (ResourceDto module : modules) { + String newKey = computeNewKey(module, stringToReplace, replacementString); + if (mapper.countResourceByKey(newKey) > 0) { + result.put(module.getKey(), "#duplicate_key#"); + } else { + result.put(module.getKey(), newKey); + } + } + } finally { + MyBatis.closeQuietly(session); + } + return result; + } + + public void bulkUpdateKey(DbSession session, long projectId, String stringToReplace, String replacementString) { + ResourceKeyUpdaterMapper mapper = session.getMapper(ResourceKeyUpdaterMapper.class); + // must SELECT first everything + Set<ResourceDto> modules = collectAllModules(projectId, stringToReplace, mapper); + checkNewNameOfAllModules(modules, stringToReplace, replacementString, mapper); + Map<ResourceDto, List<ResourceDto>> allResourcesByModuleMap = Maps.newHashMap(); + for (ResourceDto module : modules) { + allResourcesByModuleMap.put(module, mapper.selectProjectResources(module.getId())); + } + + // and then proceed with the batch UPDATE at once + for (ResourceDto module : modules) { + String oldModuleKey = module.getKey(); + String newModuleKey = computeNewKey(module, stringToReplace, replacementString); + Collection<ResourceDto> resources = Lists.newArrayList(module); + resources.addAll(allResourcesByModuleMap.get(module)); + runBatchUpdateForAllResources(resources, oldModuleKey, newModuleKey, mapper); + } + } + + public void bulkUpdateKey(long projectId, String stringToReplace, String replacementString) { + DbSession session = mybatis.openSession(true); + try { + bulkUpdateKey(session, projectId, stringToReplace, replacementString); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + private static String computeNewKey(ResourceDto resource, String stringToReplace, String replacementString) { + return resource.getKey().replaceAll(stringToReplace, replacementString); + } + + private static void runBatchUpdateForAllResources(Collection<ResourceDto> resources, String oldKey, String newKey, ResourceKeyUpdaterMapper mapper) { + for (ResourceDto resource : resources) { + String resourceKey = resource.getKey(); + resource.setKey(newKey + resourceKey.substring(oldKey.length(), resourceKey.length())); + String resourceDeprecatedKey = resource.getDeprecatedKey(); + if (StringUtils.isNotBlank(resourceDeprecatedKey)) { + resource.setDeprecatedKey(newKey + resourceDeprecatedKey.substring(oldKey.length(), resourceDeprecatedKey.length())); + } + mapper.update(resource); + } + } + + private Set<ResourceDto> collectAllModules(long projectId, String stringToReplace, ResourceKeyUpdaterMapper mapper) { + ResourceDto project = mapper.selectProject(projectId); + Set<ResourceDto> modules = Sets.newHashSet(); + if (project.getKey().contains(stringToReplace)) { + modules.add(project); + } + for (ResourceDto submodule : mapper.selectDescendantProjects(projectId)) { + modules.addAll(collectAllModules(submodule.getId(), stringToReplace, mapper)); + } + return modules; + } + + private void checkNewNameOfAllModules(Set<ResourceDto> modules, String stringToReplace, String replacementString, ResourceKeyUpdaterMapper mapper) { + for (ResourceDto module : modules) { + String newName = computeNewKey(module, stringToReplace, replacementString); + if (mapper.countResourceByKey(newName) > 0) { + throw new IllegalStateException("Impossible to update key: a resource with \"" + newName + "\" key already exists."); + } + } + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/component/ResourceKeyUpdaterMapper.java b/sonar-db/src/main/java/org/sonar/db/component/ResourceKeyUpdaterMapper.java new file mode 100644 index 00000000000..de5b61e2af0 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/component/ResourceKeyUpdaterMapper.java @@ -0,0 +1,39 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.component; + +import java.util.List; + +/** + * @since 3.2 + */ +public interface ResourceKeyUpdaterMapper { + + int countResourceByKey(String key); + + ResourceDto selectProject(long projectId); + + List<ResourceDto> selectProjectResources(long projectId); + + List<ResourceDto> selectDescendantProjects(long projectId); + + void update(ResourceDto resource); + +} diff --git a/sonar-db/src/main/java/org/sonar/db/component/ResourceMapper.java b/sonar-db/src/main/java/org/sonar/db/component/ResourceMapper.java new file mode 100644 index 00000000000..885527065fb --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/component/ResourceMapper.java @@ -0,0 +1,81 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.component; + +import java.util.Collection; +import java.util.List; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.session.ResultHandler; + +public interface ResourceMapper { + SnapshotDto selectSnapshot(Long snapshotId); + + SnapshotDto selectLastSnapshotByResourceKey(String resourceKey); + + SnapshotDto selectLastSnapshotByResourceUuid(String componentUuid); + + ResourceDto selectResource(long id); + + ResourceDto selectResourceByUuid(String uuid); + + List<ResourceDto> selectDescendantProjects(long rootProjectId); + + /** + * @since 3.0 + */ + List<ResourceDto> selectResources(ResourceQuery query); + + /** + * @since 3.0 + */ + List<Long> selectResourceIds(ResourceQuery query); + + /** + * @since 3.2 + */ + void selectResources(ResourceQuery query, ResultHandler resultHandler); + + /** + * @since 3.6 + */ + ResourceDto selectRootProjectByComponentKey(@Param("componentKey") String componentKey); + + /** + * @since 3.6 + */ + ResourceDto selectRootProjectByComponentId(@Param("componentId") long componentId); + + List<ResourceDto> selectProjectsIncludingNotCompletedOnesByQualifiers(@Param("qualifiers") Collection<String> qualifier); + + List<ResourceDto> selectProjectsByQualifiers(@Param("qualifiers") Collection<String> qualifier); + + List<ResourceDto> selectGhostsProjects(@Param("qualifiers") Collection<String> qualifier); + + List<ResourceDto> selectProvisionedProjects(@Param("qualifiers") Collection<String> qualifier); + + ResourceDto selectProvisionedProject(@Param("key") String key); + + void insert(ResourceDto resource); + + void update(ResourceDto resource); + + void updateAuthorizationDate(@Param("projectId") Long projectId, @Param("authorizationDate") Long authorizationDate); + +} diff --git a/sonar-db/src/main/java/org/sonar/db/component/ResourceQuery.java b/sonar-db/src/main/java/org/sonar/db/component/ResourceQuery.java new file mode 100644 index 00000000000..898c5b0b528 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/component/ResourceQuery.java @@ -0,0 +1,63 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.component; + +/** + * @since 3.0 + */ +public class ResourceQuery { + private String[] qualifiers = null; + private String key = null; + private boolean excludeDisabled = false; + + private ResourceQuery() { + } + + public static ResourceQuery create() { + return new ResourceQuery(); + } + + public String[] getQualifiers() { + return qualifiers; + } + + public ResourceQuery setQualifiers(String[] qualifiers) { + this.qualifiers = qualifiers; + return this; + } + + public String getKey() { + return key; + } + + public ResourceQuery setKey(String key) { + this.key = key; + return this; + } + + public boolean isExcludeDisabled() { + return excludeDisabled; + } + + public ResourceQuery setExcludeDisabled(boolean b) { + this.excludeDisabled = b; + return this; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/component/SnapshotDto.java b/sonar-db/src/main/java/org/sonar/db/component/SnapshotDto.java new file mode 100644 index 00000000000..c421ce1b51f --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/component/SnapshotDto.java @@ -0,0 +1,345 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.component; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; + +public final class SnapshotDto { + + /** + * This status is set on the snapshot at the beginning of the batch + */ + public static final String STATUS_UNPROCESSED = "U"; + public static final String STATUS_PROCESSED = "P"; + + private static final String INDEX_SHOULD_BE_IN_RANGE_FROM_1_TO_5 = "Index should be in range from 1 to 5"; + + private Long id; + private Long parentId; + private Long rootId; + private Long rootProjectId; + + private Long createdAt; + private Long buildDate; + private Long componentId; + private String status = STATUS_UNPROCESSED; + private Integer purgeStatus; + private Boolean last; + private String scope; + private String qualifier; + private String version; + private String path; + private Integer depth; + + private String period1Mode; + private String period2Mode; + private String period3Mode; + private String period4Mode; + private String period5Mode; + + private String period1Param; + private String period2Param; + private String period3Param; + private String period4Param; + private String period5Param; + + private Long period1Date; + private Long period2Date; + private Long period3Date; + private Long period4Date; + private Long period5Date; + + public Long getId() { + return id; + } + + public SnapshotDto setId(Long id) { + this.id = id; + return this; + } + + @CheckForNull + public Long getParentId() { + return parentId; + } + + public SnapshotDto setParentId(@Nullable Long parentId) { + this.parentId = parentId; + return this; + } + + /** + * Root id is null on project's snapshot + */ + @CheckForNull + public Long getRootId() { + return rootId; + } + + public SnapshotDto setRootId(@Nullable Long rootId) { + this.rootId = rootId; + return this; + } + + public Long getBuildDate() { + return buildDate; + } + + public SnapshotDto setBuildDate(Long buildDate) { + this.buildDate = buildDate; + return this; + } + + public Long getComponentId() { + return componentId; + } + + public SnapshotDto setComponentId(Long componentId) { + this.componentId = componentId; + return this; + } + + public String getStatus() { + return status; + } + + public SnapshotDto setStatus(String status) { + this.status = status; + return this; + } + + @CheckForNull + public Integer getPurgeStatus() { + return purgeStatus; + } + + public SnapshotDto setPurgeStatus(@Nullable Integer purgeStatus) { + this.purgeStatus = purgeStatus; + return this; + } + + public Boolean getLast() { + return last; + } + + public SnapshotDto setLast(Boolean last) { + this.last = last; + return this; + } + + public String getScope() { + return scope; + } + + public SnapshotDto setScope(String scope) { + this.scope = scope; + return this; + } + + public String getQualifier() { + return qualifier; + } + + public SnapshotDto setQualifier(String qualifier) { + this.qualifier = qualifier; + return this; + } + + /** + * Version is only available on projects and modules + */ + @CheckForNull + public String getVersion() { + return version; + } + + public SnapshotDto setVersion(@Nullable String version) { + this.version = version; + return this; + } + + /** + * On project's snapshot, the path is empty (or null on Oracle) + */ + @CheckForNull + public String getPath() { + return path; + } + + public SnapshotDto setPath(@Nullable String path) { + this.path = path; + return this; + } + + public Integer getDepth() { + return depth; + } + + public SnapshotDto setDepth(Integer depth) { + this.depth = depth; + return this; + } + + public Long getRootProjectId() { + return rootProjectId; + } + + public SnapshotDto setRootProjectId(Long rootProjectId) { + this.rootProjectId = rootProjectId; + return this; + } + + public SnapshotDto setPeriodMode(int index, @Nullable String p) { + switch (index) { + case 1: + period1Mode = p; + break; + case 2: + period2Mode = p; + break; + case 3: + period3Mode = p; + break; + case 4: + period4Mode = p; + break; + case 5: + period5Mode = p; + break; + default: + throw new IndexOutOfBoundsException(INDEX_SHOULD_BE_IN_RANGE_FROM_1_TO_5); + } + return this; + } + + @CheckForNull + public String getPeriodMode(int index) { + switch (index) { + case 1: + return period1Mode; + case 2: + return period2Mode; + case 3: + return period3Mode; + case 4: + return period4Mode; + case 5: + return period5Mode; + default: + throw new IndexOutOfBoundsException(INDEX_SHOULD_BE_IN_RANGE_FROM_1_TO_5); + } + } + + public SnapshotDto setPeriodParam(int index, @Nullable String p) { + switch (index) { + case 1: + period1Param = p; + break; + case 2: + period2Param = p; + break; + case 3: + period3Param = p; + break; + case 4: + period4Param = p; + break; + case 5: + period5Param = p; + break; + default: + throw new IndexOutOfBoundsException(INDEX_SHOULD_BE_IN_RANGE_FROM_1_TO_5); + } + return this; + } + + @CheckForNull + public String getPeriodModeParameter(int periodIndex) { + switch (periodIndex) { + case 1: + return period1Param; + case 2: + return period2Param; + case 3: + return period3Param; + case 4: + return period4Param; + case 5: + return period5Param; + default: + throw new IndexOutOfBoundsException(INDEX_SHOULD_BE_IN_RANGE_FROM_1_TO_5); + } + } + + public SnapshotDto setPeriodDate(int index, @Nullable Long date) { + switch (index) { + case 1: + period1Date = date; + break; + case 2: + period2Date = date; + break; + case 3: + period3Date = date; + break; + case 4: + period4Date = date; + break; + case 5: + period5Date = date; + break; + default: + throw new IndexOutOfBoundsException(INDEX_SHOULD_BE_IN_RANGE_FROM_1_TO_5); + } + return this; + } + + @CheckForNull + public Long getPeriodDate(int periodIndex) { + switch (periodIndex) { + case 1: + return period1Date; + case 2: + return period2Date; + case 3: + return period3Date; + case 4: + return period4Date; + case 5: + return period5Date; + default: + throw new IndexOutOfBoundsException(INDEX_SHOULD_BE_IN_RANGE_FROM_1_TO_5); + } + } + + public SnapshotDto setCreatedAt(Long createdAt) { + this.createdAt = createdAt; + return this; + } + + public Long getCreatedAt() { + return createdAt; + } + + public Long getRootIdOrSelf() { + return getRootId() == null ? getId() : getRootId(); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/component/SnapshotMapper.java b/sonar-db/src/main/java/org/sonar/db/component/SnapshotMapper.java new file mode 100644 index 00000000000..d9f29d97d0c --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/component/SnapshotMapper.java @@ -0,0 +1,48 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.component; + +import java.util.List; +import javax.annotation.CheckForNull; +import org.apache.ibatis.annotations.Param; + +public interface SnapshotMapper { + + @CheckForNull + SnapshotDto selectByKey(long id); + + void insert(SnapshotDto snapshot); + + @CheckForNull + SnapshotDto selectLastSnapshot(Long resourceId); + + List<SnapshotDto> selectSnapshotsByQuery(@Param("query") SnapshotQuery query); + + List<SnapshotDto> selectPreviousVersionSnapshots(@Param(value = "componentId") Long componentId, @Param(value = "lastVersion") String lastVersion); + + List<SnapshotDto> selectSnapshotAndChildrenOfScope(@Param(value = "snapshot") Long resourceId, @Param(value = "scope") String scope); + + int updateSnapshotAndChildrenLastFlagAndStatus(@Param(value = "root") Long rootId, @Param(value = "pathRootId") Long pathRootId, + @Param(value = "path") String path, @Param(value = "isLast") boolean isLast, @Param(value = "status") String status); + + int updateSnapshotAndChildrenLastFlag(@Param(value = "root") Long rootId, @Param(value = "pathRootId") Long pathRootId, + @Param(value = "path") String path, @Param(value = "isLast") boolean isLast); +} diff --git a/sonar-db/src/main/java/org/sonar/db/component/SnapshotQuery.java b/sonar-db/src/main/java/org/sonar/db/component/SnapshotQuery.java new file mode 100644 index 00000000000..fd03cfeb9de --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/component/SnapshotQuery.java @@ -0,0 +1,136 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.component; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; + +public final class SnapshotQuery { + + public enum SORT_FIELD { + BY_DATE("created_at"); + final String fieldName; + + SORT_FIELD(String fieldName) { + this.fieldName = fieldName; + } + } + + public enum SORT_ORDER { + ASC("asc"), DESC("desc"); + final String order; + + SORT_ORDER(String order) { + this.order = order; + } + } + + private Long componentId; + private Long createdAfter; + private Long createdBefore; + private String status; + private String version; + private Boolean isLast; + private String sortField; + private String sortOrder; + + /** + * filter to return snapshots created at or after a given date + */ + @CheckForNull + public Long getCreatedAfter() { + return createdAfter; + } + + public SnapshotQuery setCreatedAfter(@Nullable Long createdAfter) { + this.createdAfter = createdAfter; + return this; + } + + /** + * filter to return snapshots created before a given date + */ + @CheckForNull + public Long getCreatedBefore() { + return createdBefore; + } + + public SnapshotQuery setCreatedBefore(@Nullable Long createdBefore) { + this.createdBefore = createdBefore; + return this; + } + + @CheckForNull + public Boolean getIsLast() { + return isLast; + } + + public SnapshotQuery setIsLast(@Nullable Boolean isLast) { + this.isLast = isLast; + return this; + } + + @CheckForNull + public Long getComponentId() { + return componentId; + } + + public SnapshotQuery setComponentId(@Nullable Long componentId) { + this.componentId = componentId; + return this; + } + + @CheckForNull + public String getStatus() { + return status; + } + + public SnapshotQuery setStatus(@Nullable String status) { + this.status = status; + return this; + } + + @CheckForNull + public String getVersion() { + return version; + } + + public SnapshotQuery setVersion(@Nullable String version) { + this.version = version; + return this; + } + + public SnapshotQuery setSort(SORT_FIELD sortField, SORT_ORDER sortOrder) { + this.sortField = sortField.fieldName; + this.sortOrder = sortOrder.order; + return this; + } + + @CheckForNull + public String getSortField() { + return sortField; + } + + @CheckForNull + public String getSortOrder() { + return sortOrder; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/component/UuidWithProjectUuidDto.java b/sonar-db/src/main/java/org/sonar/db/component/UuidWithProjectUuidDto.java new file mode 100644 index 00000000000..d8667623b01 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/component/UuidWithProjectUuidDto.java @@ -0,0 +1,45 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.component; + +public class UuidWithProjectUuidDto { + + private String uuid; + private String projectUuid; + + public String getProjectUuid() { + return projectUuid; + } + + public UuidWithProjectUuidDto setProjectUuid(String projectUuid) { + this.projectUuid = projectUuid; + return this; + } + + public String getUuid() { + return uuid; + } + + public UuidWithProjectUuidDto setUuid(String uuid) { + this.uuid = uuid; + return this; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/component/package-info.java b/sonar-db/src/main/java/org/sonar/db/component/package-info.java new file mode 100644 index 00000000000..ccaf374bc27 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/component/package-info.java @@ -0,0 +1,24 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.component; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/sonar-db/src/main/java/org/sonar/db/compute/AnalysisReportDto.java b/sonar-db/src/main/java/org/sonar/db/compute/AnalysisReportDto.java new file mode 100644 index 00000000000..010afe179e7 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/compute/AnalysisReportDto.java @@ -0,0 +1,143 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.compute; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Objects; +import javax.annotation.CheckForNull; + +public class AnalysisReportDto { + private Long id; + private String projectKey; + private String projectName; + private Status status; + private String uuid; + private Long createdAt; + private Long updatedAt; + private Long startedAt; + private Long finishedAt; + + @VisibleForTesting + public static AnalysisReportDto newForTests(Long id) { + AnalysisReportDto report = new AnalysisReportDto(); + report.id = id; + + return report; + } + + public String getProjectKey() { + return projectKey; + } + + public AnalysisReportDto setProjectKey(String projectKey) { + this.projectKey = projectKey; + return this; + } + + public String getProjectName() { + return projectName; + } + + public AnalysisReportDto setProjectName(String projectName) { + this.projectName = projectName; + return this; + } + + public Status getStatus() { + return status; + } + + public AnalysisReportDto setStatus(Status status) { + this.status = status; + return this; + } + + public String getUuid() { + return uuid; + } + + public AnalysisReportDto setUuid(String s) { + this.uuid = s; + return this; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + @Override + public String toString() { + return Objects.toStringHelper(this) + .add("id", getId()) + .add("projectKey", getProjectKey()) + .add("uuid", getUuid()) + .add("status", getStatus()) + .add("createdAt", getCreatedAt()) + .add("startedAt", getStartedAt()) + .add("finishedAt", getFinishedAt()) + .toString(); + } + + @CheckForNull + public Long getStartedAt() { + return startedAt; + } + + public AnalysisReportDto setStartedAt(Long startedAt) { + this.startedAt = startedAt; + return this; + } + + @CheckForNull + public Long getFinishedAt() { + return finishedAt; + } + + public AnalysisReportDto setFinishedAt(Long finishedAt) { + this.finishedAt = finishedAt; + return this; + } + + public Long getCreatedAt() { + return createdAt; + } + + public AnalysisReportDto setCreatedAt(Long createdAt) { + this.createdAt = createdAt; + return this; + } + + public Long getUpdatedAt() { + return updatedAt; + } + + public AnalysisReportDto setUpdatedAt(Long updatedAt) { + this.updatedAt = updatedAt; + return this; + } + + public enum Status { + PENDING, WORKING, SUCCESS, FAILED, CANCELLED + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/compute/AnalysisReportMapper.java b/sonar-db/src/main/java/org/sonar/db/compute/AnalysisReportMapper.java new file mode 100644 index 00000000000..daa9e465a89 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/compute/AnalysisReportMapper.java @@ -0,0 +1,49 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.compute; + +import java.util.List; +import org.apache.ibatis.annotations.Param; + +public interface AnalysisReportMapper { + List<AnalysisReportDto> selectByProjectKey(String projectKey); + + List<Long> selectAvailables( + @Param("availableStatus") AnalysisReportDto.Status availableStatus, + @Param("busyStatus") AnalysisReportDto.Status busyStatus); + + void resetAllToPendingStatus(@Param("updatedAt") long updatedAt); + + void truncate(); + + void insert(AnalysisReportDto reportDto); + + int update(AnalysisReportDto report); + + int updateWithBookingReport(@Param("id") Long id, @Param("startedAt") long startedAt, + @Param("availableStatus") AnalysisReportDto.Status availableStatus, + @Param("busyStatus") AnalysisReportDto.Status busyStatus); + + AnalysisReportDto selectById(long id); + + void delete(long id); + + List<AnalysisReportDto> selectAll(); +} diff --git a/sonar-db/src/main/java/org/sonar/db/compute/package-info.java b/sonar-db/src/main/java/org/sonar/db/compute/package-info.java new file mode 100644 index 00000000000..240f322233d --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/compute/package-info.java @@ -0,0 +1,25 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.compute; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/sonar-db/src/main/java/org/sonar/db/dashboard/ActiveDashboardDao.java b/sonar-db/src/main/java/org/sonar/db/dashboard/ActiveDashboardDao.java new file mode 100644 index 00000000000..8463da58cfa --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/dashboard/ActiveDashboardDao.java @@ -0,0 +1,84 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.dashboard; + +import java.util.List; +import javax.annotation.Nullable; +import org.apache.ibatis.session.SqlSession; +import org.sonar.api.server.ServerSide; +import org.sonar.db.Dao; +import org.sonar.db.MyBatis; + +@ServerSide +public class ActiveDashboardDao implements Dao { + + private MyBatis mybatis; + + public ActiveDashboardDao(MyBatis mybatis) { + this.mybatis = mybatis; + } + + public void insert(ActiveDashboardDto activeDashboardDto) { + SqlSession session = mybatis.openSession(false); + try { + getMapper(session).insert(activeDashboardDto); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + public int selectMaxOrderIndexForNullUser() { + SqlSession session = mybatis.openSession(false); + try { + Integer max = getMapper(session).selectMaxOrderIndexForNullUser(); + return max != null ? max.intValue() : 0; + } finally { + session.close(); + } + + } + + public List<DashboardDto> selectGlobalDashboardsForUserLogin(@Nullable String login) { + SqlSession session = mybatis.openSession(false); + try { + return getMapper(session).selectGlobalDashboardsForUserLogin(login); + } finally { + session.close(); + } + } + + public List<DashboardDto> selectProjectDashboardsForUserLogin(@Nullable String login) { + SqlSession session = mybatis.openSession(false); + try { + return selectProjectDashboardsForUserLogin(session, login); + } finally { + session.close(); + } + } + + public List<DashboardDto> selectProjectDashboardsForUserLogin(SqlSession session, @Nullable String login) { + return getMapper(session).selectProjectDashboardsForUserLogin(login); + } + + private ActiveDashboardMapper getMapper(SqlSession session) { + return session.getMapper(ActiveDashboardMapper.class); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/dashboard/ActiveDashboardDto.java b/sonar-db/src/main/java/org/sonar/db/dashboard/ActiveDashboardDto.java new file mode 100644 index 00000000000..7bdb6fcaa58 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/dashboard/ActiveDashboardDto.java @@ -0,0 +1,106 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.dashboard; + +import com.google.common.base.Objects; + +public final class ActiveDashboardDto { + private Long id; + private Long dashboardId; + private Long userId; + private Integer orderIndex; + + /** + * @return the id + */ + public Long getId() { + return id; + } + + /** + * @param id the id to set + */ + public ActiveDashboardDto setId(Long id) { + this.id = id; + return this; + } + + /** + * @return the dashboardId + */ + public Long getDashboardId() { + return dashboardId; + } + + /** + * @param dashboardId the dashboardId to set + */ + public ActiveDashboardDto setDashboardId(Long dashboardId) { + this.dashboardId = dashboardId; + return this; + } + + /** + * @return the userId + */ + public Long getUserId() { + return userId; + } + + /** + * @param userId the userId to set + */ + public ActiveDashboardDto setUserId(Long userId) { + this.userId = userId; + return this; + } + + /** + * @return the orderIndex + */ + public Integer getOrderIndex() { + return orderIndex; + } + + /** + * @param orderIndex the orderIndex to set + */ + public ActiveDashboardDto setOrderIndex(Integer orderIndex) { + this.orderIndex = orderIndex; + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ActiveDashboardDto that = (ActiveDashboardDto) o; + return !(id != null ? !id.equals(that.id) : that.id != null); + } + + @Override + public int hashCode() { + return Objects.hashCode(id); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/dashboard/ActiveDashboardMapper.java b/sonar-db/src/main/java/org/sonar/db/dashboard/ActiveDashboardMapper.java new file mode 100644 index 00000000000..83c1ef4e08b --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/dashboard/ActiveDashboardMapper.java @@ -0,0 +1,37 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.dashboard; + +import java.util.List; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.apache.ibatis.annotations.Param; + +public interface ActiveDashboardMapper { + + void insert(ActiveDashboardDto activeDashboardDto); + + @CheckForNull + Integer selectMaxOrderIndexForNullUser(); + + List<DashboardDto> selectGlobalDashboardsForUserLogin(@Nullable @Param("login") String login); + + List<DashboardDto> selectProjectDashboardsForUserLogin(@Nullable @Param("login") String login); +} diff --git a/sonar-db/src/main/java/org/sonar/db/dashboard/DashboardDao.java b/sonar-db/src/main/java/org/sonar/db/dashboard/DashboardDao.java new file mode 100644 index 00000000000..40b151e7ec9 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/dashboard/DashboardDao.java @@ -0,0 +1,65 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.dashboard; + +import org.apache.ibatis.session.SqlSession; +import org.sonar.db.Dao; +import org.sonar.db.MyBatis; + +public class DashboardDao implements Dao { + + private MyBatis mybatis; + + public DashboardDao(MyBatis mybatis) { + this.mybatis = mybatis; + } + + public DashboardDto selectGlobalDashboard(String name) { + SqlSession session = mybatis.openSession(false); + try { + DashboardMapper mapper = session.getMapper(DashboardMapper.class); + return mapper.selectGlobalDashboard(name); + } finally { + MyBatis.closeQuietly(session); + } + } + + public void insert(DashboardDto dashboardDto) { + SqlSession session = mybatis.openSession(false); + DashboardMapper dashboardMapper = session.getMapper(DashboardMapper.class); + WidgetMapper widgetMapper = session.getMapper(WidgetMapper.class); + WidgetPropertyMapper widgetPropertyMapper = session.getMapper(WidgetPropertyMapper.class); + try { + dashboardMapper.insert(dashboardDto); + for (WidgetDto widgetDto : dashboardDto.getWidgets()) { + widgetDto.setDashboardId(dashboardDto.getId()); + widgetMapper.insert(widgetDto); + for (WidgetPropertyDto widgetPropertyDto : widgetDto.getWidgetProperties()) { + widgetPropertyDto.setWidgetId(widgetDto.getId()); + widgetPropertyMapper.insert(widgetPropertyDto); + } + } + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/dashboard/DashboardDto.java b/sonar-db/src/main/java/org/sonar/db/dashboard/DashboardDto.java new file mode 100644 index 00000000000..4b56a8937b6 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/dashboard/DashboardDto.java @@ -0,0 +1,115 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.dashboard; + +import com.google.common.collect.Lists; +import java.util.Collection; +import java.util.List; +import org.sonar.db.Dto; + +public final class DashboardDto extends Dto<Long> { + + private Long id; + private Long userId; + private String name; + private String description; + private String columnLayout; + private boolean shared; + private boolean global; + private List<WidgetDto> widgetDtos = Lists.newArrayList(); + + public Long getId() { + return id; + } + + @Override + public Long getKey() { + return id; + } + + public DashboardDto setId(Long id) { + this.id = id; + return this; + } + + public Long getUserId() { + return userId; + } + + public DashboardDto setUserId(Long userId) { + this.userId = userId; + return this; + } + + public String getName() { + return name; + } + + public DashboardDto setName(String name) { + this.name = name; + return this; + } + + public String getDescription() { + return description; + } + + public DashboardDto setDescription(String description) { + this.description = description; + return this; + } + + public String getColumnLayout() { + return columnLayout; + } + + public DashboardDto setColumnLayout(String columnLayout) { + this.columnLayout = columnLayout; + return this; + } + + public boolean getShared() { + return shared; + } + + public DashboardDto setShared(boolean shared) { + this.shared = shared; + return this; + } + + public boolean getGlobal() { + return global; + } + + public DashboardDto setGlobal(boolean global) { + this.global = global; + return this; + } + + public Collection<WidgetDto> getWidgets() { + return widgetDtos; + } + + public DashboardDto addWidget(WidgetDto widgetDto) { + widgetDtos.add(widgetDto); + return this; + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/dashboard/DashboardMapper.java b/sonar-db/src/main/java/org/sonar/db/dashboard/DashboardMapper.java new file mode 100644 index 00000000000..a6222c6fcb8 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/dashboard/DashboardMapper.java @@ -0,0 +1,50 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.dashboard; + +import javax.annotation.CheckForNull; +import org.apache.ibatis.annotations.Insert; +import org.apache.ibatis.annotations.Options; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +public interface DashboardMapper { + + String COLUMNS = "id, user_id as \"userId\", name, description, column_layout as \"columnLayout\", " + + "shared, is_global as \"global\", created_at as \"createdAt\", updated_at as \"updatedAt\""; + + @CheckForNull + @Select("select " + COLUMNS + " from dashboards where id=#{id}") + DashboardDto selectById(long id); + + @CheckForNull + @Select("select " + COLUMNS + " from dashboards where id=#{id} and (shared=${_true} or user_id=${userId})") + DashboardDto selectAllowedById(@Param("id") long id, @Param("userId") long userId); + + @CheckForNull + @Select("select " + COLUMNS + " from dashboards WHERE name=#{id} and user_id is null") + DashboardDto selectGlobalDashboard(String name); + + @Insert("INSERT INTO dashboards (user_id, name, description, column_layout, shared, is_global, created_at, " + + "updated_at) VALUES (#{userId}, #{name}, #{description}, #{columnLayout}, #{shared}, " + + "#{global}, #{createdAt}, #{updatedAt})") + @Options(keyColumn = "id", useGeneratedKeys = true, keyProperty = "id") + void insert(DashboardDto dashboardDto); +} diff --git a/sonar-db/src/main/java/org/sonar/db/dashboard/WidgetDto.java b/sonar-db/src/main/java/org/sonar/db/dashboard/WidgetDto.java new file mode 100644 index 00000000000..02e0a428163 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/dashboard/WidgetDto.java @@ -0,0 +1,205 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.dashboard; + +import com.google.common.collect.Lists; +import java.util.Collection; +import java.util.Date; +import java.util.List; + +public class WidgetDto { + private Long id; + private Long dashboardId; + private String widgetKey; + private String name; + private String description; + private Integer columnIndex; + private Integer rowIndex; + private boolean configured; + private Integer resourceId; + private Date createdAt; + private Date updatedAt; + private List<WidgetPropertyDto> widgetPropertyDtos = Lists.newArrayList(); + + /** + * @return the id + */ + public Long getId() { + return id; + } + + /** + * @param id the id to set + */ + public WidgetDto setId(Long id) { + this.id = id; + return this; + } + + /** + * @return the dashboardId + */ + public Long getDashboardId() { + return dashboardId; + } + + /** + * @param dashboardId the dashboardId to set + */ + public WidgetDto setDashboardId(Long dashboardId) { + this.dashboardId = dashboardId; + return this; + } + + public String getWidgetKey() { + return widgetKey; + } + + public WidgetDto setWidgetKey(String s) { + this.widgetKey = s; + return this; + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name the name to set + */ + public WidgetDto setName(String name) { + this.name = name; + return this; + } + + /** + * @return the description + */ + public String getDescription() { + return description; + } + + /** + * @param description the description to set + */ + public WidgetDto setDescription(String description) { + this.description = description; + return this; + } + + /** + * @return the columnIndex + */ + public Integer getColumnIndex() { + return columnIndex; + } + + /** + * @param columnIndex the columnIndex to set + */ + public WidgetDto setColumnIndex(Integer columnIndex) { + this.columnIndex = columnIndex; + return this; + } + + /** + * @return the rowIndex + */ + public Integer getRowIndex() { + return rowIndex; + } + + /** + * @param rowIndex the rowIndex to set + */ + public WidgetDto setRowIndex(Integer rowIndex) { + this.rowIndex = rowIndex; + return this; + } + + /** + * @return the configured + */ + public boolean getConfigured() { + return configured; + } + + /** + * @param configured the configured to set + */ + public WidgetDto setConfigured(boolean configured) { + this.configured = configured; + return this; + } + + /** + * @return the widgetProperties + */ + public Collection<WidgetPropertyDto> getWidgetProperties() { + return widgetPropertyDtos; + } + + /** + * @param widgetPropertyDto the widgetProperty to set + */ + public WidgetDto addWidgetProperty(WidgetPropertyDto widgetPropertyDto) { + widgetPropertyDtos.add(widgetPropertyDto); + return this; + } + + /** + * @return the resourceId + * @since 3.1 + */ + public Integer getResourceId() { + return resourceId; + } + + /** + * @param resourceId the resourceId to set + * @since 3.1 + */ + public WidgetDto setResourceId(Integer resourceId) { + this.resourceId = resourceId; + return this; + } + + public WidgetDto setCreatedAt(Date datetime) { + this.createdAt = datetime; + return this; + } + + public WidgetDto setUpdatedAt(Date datetime) { + this.updatedAt = datetime; + return this; + } + + public final Date getCreatedAt() { + return this.createdAt; + } + + public final Date getUpdatedAt() { + return this.updatedAt; + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/dashboard/WidgetMapper.java b/sonar-db/src/main/java/org/sonar/db/dashboard/WidgetMapper.java new file mode 100644 index 00000000000..c82e1b4c924 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/dashboard/WidgetMapper.java @@ -0,0 +1,57 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.dashboard; + +import java.util.Collection; +import org.apache.ibatis.annotations.Insert; +import org.apache.ibatis.annotations.Options; +import org.apache.ibatis.annotations.Update; + +public interface WidgetMapper { + + @Insert("insert into widgets (dashboard_id, widget_key, name, description, column_index, " + + " row_index, configured, created_at, updated_at, resource_id)" + + " values (#{dashboardId,jdbcType=INTEGER}, #{widgetKey,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, " + + " #{description,jdbcType=VARCHAR}, #{columnIndex,jdbcType=INTEGER}, " + + " #{rowIndex,jdbcType=INTEGER}, #{configured,jdbcType=BOOLEAN}, #{createdAt,jdbcType=TIMESTAMP}, #{updatedAt,jdbcType=TIMESTAMP}, #{resourceId,jdbcType=INTEGER})") + @Options(keyColumn = "id", useGeneratedKeys = true, keyProperty = "id") + void insert(WidgetDto widgetDto); + + WidgetDto selectById(long widgetId); + + Collection<WidgetDto> selectByDashboard(long dashboardKey); + + Collection<WidgetDto> selectAll(); + + @Update("UPDATE widgets SET " + + "dashboard_id=#{dashboardId,jdbcType=INTEGER}, " + + "widget_key=#{widgetKey,jdbcType=VARCHAR}, " + + "name=#{name,jdbcType=VARCHAR}, " + + "description=#{description,jdbcType=VARCHAR}, " + + "column_index=#{columnIndex,jdbcType=INTEGER}, " + + "row_index=#{rowIndex,jdbcType=INTEGER}, " + + "configured=#{configured,jdbcType=BOOLEAN}, " + + "created_at=#{createdAt,jdbcType=TIMESTAMP}, " + + "updated_at=#{updatedAt,jdbcType=TIMESTAMP}, " + + "resource_id=#{resourceId,jdbcType=INTEGER} " + + "WHERE id=#{id}") + @Options(useGeneratedKeys = false) + void update(WidgetDto item); +} diff --git a/sonar-db/src/main/java/org/sonar/db/dashboard/WidgetPropertyDto.java b/sonar-db/src/main/java/org/sonar/db/dashboard/WidgetPropertyDto.java new file mode 100644 index 00000000000..0cbf5caa77c --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/dashboard/WidgetPropertyDto.java @@ -0,0 +1,75 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.dashboard; + +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.ListMultimap; +import java.util.Collection; + +public class WidgetPropertyDto { + private Long id; + private Long widgetId; + private String propertyKey; + private String textValue; + + public Long getId() { + return id; + } + + public WidgetPropertyDto setId(Long id) { + this.id = id; + return this; + } + + public Long getWidgetId() { + return widgetId; + } + + public WidgetPropertyDto setWidgetId(Long widgetId) { + this.widgetId = widgetId; + return this; + } + + public String getPropertyKey() { + return propertyKey; + } + + public WidgetPropertyDto setPropertyKey(String s) { + this.propertyKey = s; + return this; + } + + public String getTextValue() { + return textValue; + } + + public WidgetPropertyDto setTextValue(String s) { + this.textValue = s; + return this; + } + + public static ListMultimap<Long, WidgetPropertyDto> groupByWidgetId(Collection<WidgetPropertyDto> properties) { + ListMultimap<Long, WidgetPropertyDto> group = ArrayListMultimap.create(); + for (WidgetPropertyDto property : properties) { + group.put(property.getWidgetId(), property); + } + return group; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/dashboard/WidgetPropertyMapper.java b/sonar-db/src/main/java/org/sonar/db/dashboard/WidgetPropertyMapper.java new file mode 100644 index 00000000000..46432fba6b8 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/dashboard/WidgetPropertyMapper.java @@ -0,0 +1,46 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.dashboard; + +import java.util.Collection; +import java.util.List; +import javax.annotation.CheckForNull; +import org.apache.ibatis.annotations.Insert; +import org.apache.ibatis.annotations.Options; +import org.apache.ibatis.annotations.Select; + +public interface WidgetPropertyMapper { + + String COLUMNS = "wp.id, wp.widget_id as \"widgetId\", wp.kee as \"propertyKey\", wp.text_value as \"textValue\""; + + @Insert("insert into widget_properties (widget_id, kee, text_value) values (#{widgetId}, #{propertyKey}, #{textValue})") + @Options(keyColumn = "id", useGeneratedKeys = true, keyProperty = "id") + void insert(WidgetPropertyDto dto); + + @CheckForNull + @Select("select " + COLUMNS + " from widget_properties wp where wp.id=#{id}") + WidgetPropertyDto selectById(long propertyId); + + @Select("select " + COLUMNS + " from widget_properties wp " + + "inner join widgets w on w.id=wp.widget_id where w.dashboard_id=#{id}") + Collection<WidgetPropertyDto> selectByDashboard(long dashboardKey); + + void deleteByWidgetIds(List<Long> widgetIds); +} diff --git a/sonar-db/src/main/java/org/sonar/db/dashboard/package-info.java b/sonar-db/src/main/java/org/sonar/db/dashboard/package-info.java new file mode 100644 index 00000000000..389a1fac572 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/dashboard/package-info.java @@ -0,0 +1,24 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.dashboard; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/sonar-db/src/main/java/org/sonar/db/debt/CharacteristicDao.java b/sonar-db/src/main/java/org/sonar/db/debt/CharacteristicDao.java new file mode 100644 index 00000000000..789c94a1f12 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/debt/CharacteristicDao.java @@ -0,0 +1,221 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.debt; + +import com.google.common.collect.Lists; +import java.util.Collection; +import java.util.List; +import javax.annotation.CheckForNull; +import org.apache.ibatis.session.SqlSession; +import org.sonar.db.Dao; +import org.sonar.db.DbSession; +import org.sonar.db.MyBatis; + +import static com.google.common.collect.Lists.newArrayList; + +public class CharacteristicDao implements Dao { + + private final MyBatis mybatis; + + public CharacteristicDao(MyBatis mybatis) { + this.mybatis = mybatis; + } + + /** + * @return enabled root characteristics and characteristics + */ + public List<CharacteristicDto> selectEnabledCharacteristics() { + SqlSession session = mybatis.openSession(false); + try { + return selectEnabledCharacteristics(session); + } finally { + MyBatis.closeQuietly(session); + } + } + + public List<CharacteristicDto> selectEnabledCharacteristics(SqlSession session) { + return session.getMapper(CharacteristicMapper.class).selectEnabledCharacteristics(); + } + + /** + * @return all characteristics + */ + public List<CharacteristicDto> selectCharacteristics() { + SqlSession session = mybatis.openSession(false); + try { + return selectCharacteristics(session); + } finally { + MyBatis.closeQuietly(session); + } + } + + public List<CharacteristicDto> selectCharacteristics(SqlSession session) { + return session.getMapper(CharacteristicMapper.class).selectCharacteristics(); + } + + /** + * @return only enabled root characteristics, order by order + */ + public List<CharacteristicDto> selectEnabledRootCharacteristics() { + SqlSession session = mybatis.openSession(false); + try { + return selectEnabledRootCharacteristics(session); + } finally { + MyBatis.closeQuietly(session); + } + } + + /** + * @return only enabled root characteristics, order by order + */ + public List<CharacteristicDto> selectEnabledRootCharacteristics(SqlSession session) { + return session.getMapper(CharacteristicMapper.class).selectEnabledRootCharacteristics(); + } + + public List<CharacteristicDto> selectCharacteristicsByParentId(int parentId) { + SqlSession session = mybatis.openSession(false); + try { + return selectCharacteristicsByParentId(parentId, session); + } finally { + MyBatis.closeQuietly(session); + } + } + + public List<CharacteristicDto> selectCharacteristicsByParentId(int parentId, SqlSession session) { + return session.getMapper(CharacteristicMapper.class).selectCharacteristicsByParentId(parentId); + } + + public List<CharacteristicDto> selectCharacteristicsByIds(Collection<Integer> ids) { + SqlSession session = mybatis.openSession(false); + try { + return selectCharacteristicsByIds(ids, session); + } finally { + MyBatis.closeQuietly(session); + } + } + + public List<CharacteristicDto> selectCharacteristicsByIds(Collection<Integer> ids, SqlSession session) { + List<CharacteristicDto> dtos = newArrayList(); + List<List<Integer>> partitionList = Lists.partition(newArrayList(ids), 1000); + for (List<Integer> partition : partitionList) { + dtos.addAll(session.getMapper(CharacteristicMapper.class).selectCharacteristicsByIds(partition)); + } + return dtos; + } + + @CheckForNull + public CharacteristicDto selectByKey(String key) { + SqlSession session = mybatis.openSession(false); + try { + return selectByKey(key, session); + } finally { + MyBatis.closeQuietly(session); + } + } + + @CheckForNull + public CharacteristicDto selectByKey(String key, SqlSession session) { + return session.getMapper(CharacteristicMapper.class).selectByKey(key); + } + + @CheckForNull + public CharacteristicDto selectById(int id) { + SqlSession session = mybatis.openSession(false); + try { + return selectById(id, session); + } finally { + MyBatis.closeQuietly(session); + } + } + + @CheckForNull + public CharacteristicDto selectById(int id, SqlSession session) { + return session.getMapper(CharacteristicMapper.class).selectById(id); + } + + @CheckForNull + public CharacteristicDto selectByName(String name) { + SqlSession session = mybatis.openSession(false); + try { + return selectByName(name, session); + } finally { + MyBatis.closeQuietly(session); + } + } + + @CheckForNull + public CharacteristicDto selectByName(String name, SqlSession session) { + return session.getMapper(CharacteristicMapper.class).selectByName(name); + } + + public int selectMaxCharacteristicOrder() { + SqlSession session = mybatis.openSession(false); + try { + return selectMaxCharacteristicOrder(session); + } finally { + MyBatis.closeQuietly(session); + } + } + + public int selectMaxCharacteristicOrder(SqlSession session) { + Integer result = session.getMapper(CharacteristicMapper.class).selectMaxCharacteristicOrder(); + return result != null ? result : 0; + } + + public void insert(CharacteristicDto dto, SqlSession session) { + session.getMapper(CharacteristicMapper.class).insert(dto); + } + + public void insert(CharacteristicDto dto) { + SqlSession session = mybatis.openSession(false); + try { + insert(dto, session); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + public void insert(DbSession session, Collection<CharacteristicDto> items) { + for (CharacteristicDto item : items) { + insert(item, session); + } + } + + public void insert(DbSession session, CharacteristicDto item, CharacteristicDto... others) { + insert(session, Lists.asList(item, others)); + } + + public void update(CharacteristicDto dto, SqlSession session) { + session.getMapper(CharacteristicMapper.class).update(dto); + } + + public void update(CharacteristicDto dto) { + SqlSession session = mybatis.openSession(false); + try { + update(dto, session); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/debt/CharacteristicDto.java b/sonar-db/src/main/java/org/sonar/db/debt/CharacteristicDto.java new file mode 100644 index 00000000000..3cbaff45e81 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/debt/CharacteristicDto.java @@ -0,0 +1,138 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.debt; + +import java.io.Serializable; +import java.util.Date; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.sonar.api.technicaldebt.batch.internal.DefaultCharacteristic; + +public class CharacteristicDto implements Serializable { + + private Integer id; + private String kee; + private String name; + private Integer parentId; + private Integer characteristicOrder; + private Date createdAt; + private Date updatedAt; + private boolean enabled; + + public Integer getId() { + return id; + } + + public CharacteristicDto setId(Integer id) { + this.id = id; + return this; + } + + public String getKey() { + return kee; + } + + public CharacteristicDto setKey(String s) { + this.kee = s; + return this; + } + + public String getName() { + return name; + } + + public CharacteristicDto setName(String s) { + this.name = s; + return this; + } + + @CheckForNull + public Integer getParentId() { + return parentId; + } + + public CharacteristicDto setParentId(@Nullable Integer i) { + this.parentId = i; + return this; + } + + @CheckForNull + public Integer getOrder() { + return characteristicOrder; + } + + public CharacteristicDto setOrder(@Nullable Integer i) { + this.characteristicOrder = i; + return this; + } + + public Date getCreatedAt() { + return createdAt; + } + + public CharacteristicDto setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + return this; + } + + @CheckForNull + public Date getUpdatedAt() { + return updatedAt; + } + + public CharacteristicDto setUpdatedAt(@Nullable Date updatedAt) { + this.updatedAt = updatedAt; + return this; + } + + public boolean isEnabled() { + return enabled; + } + + public CharacteristicDto setEnabled(boolean enabled) { + this.enabled = enabled; + return this; + } + + public DefaultCharacteristic toCharacteristic(@Nullable DefaultCharacteristic parent) { + return new DefaultCharacteristic() + .setId(id) + .setKey(kee) + .setName(name) + .setOrder(characteristicOrder) + .setParent(parent) + .setRoot(parent) + .setCreatedAt(createdAt) + .setUpdatedAt(updatedAt); + } + + public static CharacteristicDto toDto(DefaultCharacteristic characteristic, @Nullable Integer parentId) { + return new CharacteristicDto() + .setKey(characteristic.key()) + .setName(characteristic.name()) + .setOrder(characteristic.order()) + .setParentId(parentId) + .setEnabled(true) + .setCreatedAt(characteristic.createdAt()) + .setUpdatedAt(characteristic.updatedAt()); + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/debt/CharacteristicMapper.java b/sonar-db/src/main/java/org/sonar/db/debt/CharacteristicMapper.java new file mode 100644 index 00000000000..20feb8641ab --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/debt/CharacteristicMapper.java @@ -0,0 +1,53 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.debt; + +import java.util.List; +import org.apache.ibatis.annotations.Param; + +public interface CharacteristicMapper { + + List<CharacteristicDto> selectEnabledCharacteristics(); + + List<CharacteristicDto> selectCharacteristics(); + + List<CharacteristicDto> selectEnabledRootCharacteristics(); + + List<CharacteristicDto> selectCharacteristicsByParentId(int parentId); + + List<CharacteristicDto> selectCharacteristicsByIds(@Param("ids") List<Integer> ids); + + CharacteristicDto selectByKey(String key); + + CharacteristicDto selectById(int id); + + CharacteristicDto selectByName(String name); + + Integer selectMaxCharacteristicOrder(); + + void insert(CharacteristicDto characteristic); + + int update(CharacteristicDto characteristic); + + void deleteRequirementsFromCharacteristicsTable(); + + List<RequirementMigrationDto> selectDeprecatedRequirements(); +} diff --git a/sonar-db/src/main/java/org/sonar/db/debt/RequirementMigrationDto.java b/sonar-db/src/main/java/org/sonar/db/debt/RequirementMigrationDto.java new file mode 100644 index 00000000000..f2dfe90d85d --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/debt/RequirementMigrationDto.java @@ -0,0 +1,159 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.debt; + +import java.io.Serializable; +import java.util.Date; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; + +/** + * Only used in {@link org.sonar.server.startup.CopyRequirementsFromCharacteristicsToRules} + */ +public class RequirementMigrationDto implements Serializable { + + private Integer id; + private Integer parentId; + private Integer rootId; + private Integer ruleId; + private String functionKey; + private Double coefficientValue; + private String coefficientUnit; + private Double offsetValue; + private String offsetUnit; + private Date createdAt; + private Date updatedAt; + private boolean enabled; + + public Integer getId() { + return id; + } + + public RequirementMigrationDto setId(Integer id) { + this.id = id; + return this; + } + + public Integer getParentId() { + return parentId; + } + + public RequirementMigrationDto setParentId(Integer i) { + this.parentId = i; + return this; + } + + public Integer getRootId() { + return rootId; + } + + public RequirementMigrationDto setRootId(Integer rootId) { + this.rootId = rootId; + return this; + } + + public Integer getRuleId() { + return ruleId; + } + + public RequirementMigrationDto setRuleId(Integer ruleId) { + this.ruleId = ruleId; + return this; + } + + public String getFunction() { + return functionKey; + } + + public RequirementMigrationDto setFunction(String function) { + this.functionKey = function; + return this; + } + + @CheckForNull + public Double getCoefficientValue() { + return coefficientValue; + } + + public RequirementMigrationDto setCoefficientValue(@Nullable Double coefficientValue) { + this.coefficientValue = coefficientValue; + return this; + } + + @CheckForNull + public String getCoefficientUnit() { + return coefficientUnit; + } + + public RequirementMigrationDto setCoefficientUnit(@Nullable String coefficientUnit) { + this.coefficientUnit = coefficientUnit; + return this; + } + + @CheckForNull + public Double getOffsetValue() { + return offsetValue; + } + + public RequirementMigrationDto setOffsetValue(@Nullable Double offset) { + this.offsetValue = offset; + return this; + } + + @CheckForNull + public String getOffsetUnit() { + return offsetUnit; + } + + public RequirementMigrationDto setOffsetUnit(@Nullable String offsetUnit) { + this.offsetUnit = offsetUnit; + return this; + } + + public Date getCreatedAt() { + return createdAt; + } + + public RequirementMigrationDto setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + return this; + } + + @CheckForNull + public Date getUpdatedAt() { + return updatedAt; + } + + public RequirementMigrationDto setUpdatedAt(@Nullable Date updatedAt) { + this.updatedAt = updatedAt; + return this; + } + + public boolean isEnabled() { + return enabled; + } + + public RequirementMigrationDto setEnabled(boolean enabled) { + this.enabled = enabled; + return this; + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/debt/package-info.java b/sonar-db/src/main/java/org/sonar/db/debt/package-info.java new file mode 100644 index 00000000000..b1e34d83234 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/debt/package-info.java @@ -0,0 +1,24 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.debt; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/sonar-db/src/main/java/org/sonar/db/deprecated/ClusterAction.java b/sonar-db/src/main/java/org/sonar/db/deprecated/ClusterAction.java new file mode 100644 index 00000000000..d6bfb3b30ab --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/deprecated/ClusterAction.java @@ -0,0 +1,28 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.deprecated; + +import java.util.concurrent.Callable; + +public interface ClusterAction<K> extends Callable<K> { + + @Override + public K call() throws Exception; +} diff --git a/sonar-db/src/main/java/org/sonar/db/deprecated/NullQueue.java b/sonar-db/src/main/java/org/sonar/db/deprecated/NullQueue.java new file mode 100644 index 00000000000..db002f476c0 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/deprecated/NullQueue.java @@ -0,0 +1,30 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.deprecated; + +import java.util.List; + +public class NullQueue implements WorkQueue<ClusterAction> { + + @Override + public void enqueue(List<ClusterAction> actions) { + // do nothing + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/deprecated/WorkQueue.java b/sonar-db/src/main/java/org/sonar/db/deprecated/WorkQueue.java new file mode 100644 index 00000000000..3b4e2077771 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/deprecated/WorkQueue.java @@ -0,0 +1,29 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.deprecated; + +import java.util.List; +import java.util.concurrent.Callable; + +public interface WorkQueue<K extends Callable> { + + void enqueue(List<K> actions); + +} diff --git a/sonar-db/src/main/java/org/sonar/db/dialect/AbstractDialect.java b/sonar-db/src/main/java/org/sonar/db/dialect/AbstractDialect.java new file mode 100644 index 00000000000..236c90acd1b --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/dialect/AbstractDialect.java @@ -0,0 +1,90 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.dialect; + +import java.util.Collections; +import java.util.List; + +/** + * @since 3.2 + */ +abstract class AbstractDialect implements Dialect { + private final String id; + private final String activeRecordDialectCode; + private final String defaultDriverClassName; + private final String trueSqlValue; + private final String falseSqlValue; + private final String validationQuery; + + protected AbstractDialect(String id, String activeRecordDialectCode, String defaultDriverClassName, String trueSqlValue, String falseSqlValue, + String validationQuery) { + this.id = id; + this.activeRecordDialectCode = activeRecordDialectCode; + this.defaultDriverClassName = defaultDriverClassName; + this.trueSqlValue = trueSqlValue; + this.falseSqlValue = falseSqlValue; + this.validationQuery = validationQuery; + } + + @Override + public String getId() { + return id; + } + + @Override + public String getActiveRecordDialectCode() { + return activeRecordDialectCode; + } + + @Override + public String getDefaultDriverClassName() { + return defaultDriverClassName; + } + + @Override + public final String getTrueSqlValue() { + return trueSqlValue; + } + + @Override + public final String getFalseSqlValue() { + return falseSqlValue; + } + + @Override + public final String getValidationQuery() { + return validationQuery; + } + + @Override + public List<String> getConnectionInitStatements() { + return Collections.emptyList(); + } + + @Override + public int getScrollDefaultFetchSize() { + return 200; + } + + @Override + public int getScrollSingleRowFetchSize() { + return 1; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/dialect/Dialect.java b/sonar-db/src/main/java/org/sonar/db/dialect/Dialect.java new file mode 100644 index 00000000000..3d0a0f6e730 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/dialect/Dialect.java @@ -0,0 +1,92 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.dialect; + +import java.util.List; + +/** + * @since 1.12 + */ +public interface Dialect { + + /** + * @return the sonar dialect Id to be matched with the sonar.jdbc.dialect property when provided + */ + String getId(); + + /** + * @return the activerecord dialect to be used + */ + String getActiveRecordDialectCode(); + + /** + * Used to autodetect a dialect for a given driver URL + * + * @param jdbcConnectionURL a jdbc driver url such as jdbc:mysql://localhost:3306/sonar + * @return true if the dialect supports surch url + */ + boolean matchesJdbcURL(String jdbcConnectionURL); + + /** + * @since 2.13 + */ + String getDefaultDriverClassName(); + + List<String> getConnectionInitStatements(); + + /** + * @since 2.14 + */ + String getTrueSqlValue(); + + /** + * @since 2.14 + */ + String getFalseSqlValue(); + + /** + * Query used to validate the jdbc connection. + * + * @since 3.2 + */ + String getValidationQuery(); + + /** + * Fetch size to be used when scrolling large result sets. + * + * @since 5.0 + */ + int getScrollDefaultFetchSize(); + + /** + * Fetch size to scroll one row at a time. It sounds strange because obviously value is 1 in most cases, + * but it's different on MySQL... + * + * @since 5.0 + */ + int getScrollSingleRowFetchSize(); + + /** + * Indicates whether DB migration can be perform on the DB vendor implementation associated with the current dialect. + * + * @return a boolean + */ + boolean supportsMigration(); +} diff --git a/sonar-db/src/main/java/org/sonar/db/dialect/DialectUtils.java b/sonar-db/src/main/java/org/sonar/db/dialect/DialectUtils.java new file mode 100644 index 00000000000..d000cc78151 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/dialect/DialectUtils.java @@ -0,0 +1,74 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.dialect; + +import com.google.common.base.Predicate; +import com.google.common.collect.Iterators; +import java.util.NoSuchElementException; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.apache.commons.lang.StringUtils; +import org.sonar.api.utils.MessageException; + +public final class DialectUtils { + + private DialectUtils() { + // only static stuff + } + + private static final Dialect[] DIALECTS = new Dialect[] {new H2(), new MySql(), new Oracle(), new PostgreSql(), new MsSql()}; + + public static Dialect find(final String dialectId, final String jdbcConnectionUrl) { + Dialect match = StringUtils.isNotBlank(dialectId) ? findById(dialectId) : findByJdbcUrl(jdbcConnectionUrl); + if (match == null) { + throw MessageException.of("Unable to determine database dialect to use within sonar with dialect " + dialectId + " jdbc url " + jdbcConnectionUrl); + } + return match; + } + + @CheckForNull + private static Dialect findByJdbcUrl(final String jdbcConnectionUrl) { + return findDialect(new Predicate<Dialect>() { + @Override + public boolean apply(@Nullable Dialect dialect) { + return dialect != null && dialect.matchesJdbcURL(StringUtils.trimToEmpty(jdbcConnectionUrl)); + } + }); + } + + @CheckForNull + private static Dialect findById(final String dialectId) { + return findDialect(new Predicate<Dialect>() { + @Override + public boolean apply(@Nullable Dialect dialect) { + return dialect != null && dialect.getId().equals(dialectId); + } + }); + } + + @CheckForNull + private static Dialect findDialect(Predicate<Dialect> predicate) { + try { + return Iterators.find(Iterators.forArray(DIALECTS), predicate); + } catch (NoSuchElementException ex) { + return null; + } + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/dialect/H2.java b/sonar-db/src/main/java/org/sonar/db/dialect/H2.java new file mode 100644 index 00000000000..aa9bd6fb881 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/dialect/H2.java @@ -0,0 +1,45 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.dialect; + +import org.apache.commons.lang.StringUtils; + +/** + * @since 1.12 + */ +public class H2 extends AbstractDialect { + + public static final String ID = "h2"; + + public H2() { + super(ID, ".h2.", "org.h2.Driver", "true", "false", "SELECT 1"); + } + + @Override + public boolean matchesJdbcURL(String jdbcConnectionURL) { + return StringUtils.startsWithIgnoreCase(jdbcConnectionURL, "jdbc:h2:"); + } + + @Override + public boolean supportsMigration() { + return false; + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/dialect/MsSql.java b/sonar-db/src/main/java/org/sonar/db/dialect/MsSql.java new file mode 100644 index 00000000000..d55139113c2 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/dialect/MsSql.java @@ -0,0 +1,42 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.dialect; + +import org.apache.commons.lang.StringUtils; + +public class MsSql extends AbstractDialect { + + public static final String ID = "mssql"; + + public MsSql() { + super(ID, "sqlserver", "net.sourceforge.jtds.jdbc.Driver", "1", "0", "SELECT 1"); + } + + @Override + public boolean matchesJdbcURL(String jdbcConnectionURL) { + return StringUtils.startsWithIgnoreCase(jdbcConnectionURL, "jdbc:microsoft:sqlserver:") + || StringUtils.startsWithIgnoreCase(jdbcConnectionURL, "jdbc:jtds:sqlserver:"); + } + + @Override + public boolean supportsMigration() { + return true; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/dialect/MySql.java b/sonar-db/src/main/java/org/sonar/db/dialect/MySql.java new file mode 100644 index 00000000000..66019cb785f --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/dialect/MySql.java @@ -0,0 +1,54 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.dialect; + +import org.apache.commons.lang.StringUtils; + +/** + * @since 1.12 + */ +public class MySql extends AbstractDialect { + + public static final String ID = "mysql"; + + public MySql() { + super(ID, "mysql", "com.mysql.jdbc.Driver", "true", "false", "SELECT 1"); + } + + @Override + public boolean matchesJdbcURL(String jdbcConnectionURL) { + return StringUtils.startsWithIgnoreCase(jdbcConnectionURL, "jdbc:mysql:"); + } + + @Override + public int getScrollDefaultFetchSize() { + return Integer.MIN_VALUE; + } + + @Override + public int getScrollSingleRowFetchSize() { + return Integer.MIN_VALUE; + } + + @Override + public boolean supportsMigration() { + return true; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/dialect/Oracle.java b/sonar-db/src/main/java/org/sonar/db/dialect/Oracle.java new file mode 100644 index 00000000000..dd5fccadf4b --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/dialect/Oracle.java @@ -0,0 +1,44 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.dialect; + +import org.apache.commons.lang.StringUtils; + +/** + * @since 1.12 + */ +public class Oracle extends AbstractDialect { + + public static final String ID = "oracle"; + + public Oracle() { + super(ID, "oracle", "oracle.jdbc.OracleDriver", "1", "0", "SELECT 1 FROM DUAL"); + } + + @Override + public boolean matchesJdbcURL(String jdbcConnectionURL) { + return StringUtils.startsWithIgnoreCase(jdbcConnectionURL, "jdbc:oracle:"); + } + + @Override + public boolean supportsMigration() { + return true; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/dialect/PostgreSql.java b/sonar-db/src/main/java/org/sonar/db/dialect/PostgreSql.java new file mode 100644 index 00000000000..d3aaadb92cb --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/dialect/PostgreSql.java @@ -0,0 +1,52 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.dialect; + +import com.google.common.collect.ImmutableList; +import java.util.List; +import org.apache.commons.lang.StringUtils; + +/** + * @since 1.12 + */ +public class PostgreSql extends AbstractDialect { + + public static final String ID = "postgresql"; + static final List<String> INIT_STATEMENTS = ImmutableList.of("SET standard_conforming_strings=on", "SET backslash_quote=off"); + + public PostgreSql() { + super(ID, "postgre", "org.postgresql.Driver", "true", "false", "SELECT 1"); + } + + @Override + public boolean matchesJdbcURL(String jdbcConnectionURL) { + return StringUtils.startsWithIgnoreCase(jdbcConnectionURL, "jdbc:postgresql:"); + } + + @Override + public List<String> getConnectionInitStatements() { + return INIT_STATEMENTS; + } + + @Override + public boolean supportsMigration() { + return true; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/dialect/package-info.java b/sonar-db/src/main/java/org/sonar/db/dialect/package-info.java new file mode 100644 index 00000000000..a28f4911544 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/dialect/package-info.java @@ -0,0 +1,24 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.dialect; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/sonar-db/src/main/java/org/sonar/db/duplication/DuplicationDao.java b/sonar-db/src/main/java/org/sonar/db/duplication/DuplicationDao.java new file mode 100644 index 00000000000..25690f35569 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/duplication/DuplicationDao.java @@ -0,0 +1,64 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.duplication; + +import java.util.Collection; +import java.util.List; +import org.apache.ibatis.session.SqlSession; +import org.sonar.db.DbSession; +import org.sonar.db.MyBatis; + +public class DuplicationDao { + + private final MyBatis mybatis; + + public DuplicationDao(MyBatis mybatis) { + this.mybatis = mybatis; + } + + public List<DuplicationUnitDto> selectCandidates(int resourceSnapshotId, Integer lastSnapshotId, String language) { + SqlSession session = mybatis.openSession(false); + try { + DuplicationMapper mapper = session.getMapper(DuplicationMapper.class); + return mapper.selectCandidates(resourceSnapshotId, lastSnapshotId, language); + } finally { + MyBatis.closeQuietly(session); + } + } + + /** + * Insert rows in the table DUPLICATIONS_INDEX. + * Note that generated ids are not returned. + */ + public void insert(Collection<DuplicationUnitDto> units) { + DbSession session = mybatis.openSession(true); + try { + DuplicationMapper mapper = session.getMapper(DuplicationMapper.class); + for (DuplicationUnitDto unit : units) { + mapper.batchInsert(unit); + } + session.commit(); + + } finally { + MyBatis.closeQuietly(session); + } + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/duplication/DuplicationMapper.java b/sonar-db/src/main/java/org/sonar/db/duplication/DuplicationMapper.java new file mode 100644 index 00000000000..fe366d9ffc0 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/duplication/DuplicationMapper.java @@ -0,0 +1,34 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.duplication; + +import java.util.List; +import org.apache.ibatis.annotations.Param; + +public interface DuplicationMapper { + + List<DuplicationUnitDto> selectCandidates( + @Param("resource_snapshot_id") int resourceSnapshotId, + @Param("last_project_snapshot_id") Integer lastSnapshotId, + @Param("language") String language); + + void batchInsert(DuplicationUnitDto unit); + +} diff --git a/sonar-db/src/main/java/org/sonar/db/duplication/DuplicationUnitDto.java b/sonar-db/src/main/java/org/sonar/db/duplication/DuplicationUnitDto.java new file mode 100644 index 00000000000..443782a63bd --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/duplication/DuplicationUnitDto.java @@ -0,0 +1,115 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.duplication; + +/** + * A simple DTO (Data Transfer Object) class that provides the mapping of data to a table. + */ +public final class DuplicationUnitDto { + + private Long id; + private Integer snapshotId; + private Integer projectSnapshotId; + + private String hash; + private int indexInFile; + private int startLine; + private int endLine; + + private String resourceKey; + + public DuplicationUnitDto() { + } + + public DuplicationUnitDto(Integer projectSnapshotId, Integer snapshotId, String hash, Integer indexInFile, Integer startLine, Integer endLine) { + this.projectSnapshotId = projectSnapshotId; + this.snapshotId = snapshotId; + this.hash = hash; + this.indexInFile = indexInFile; + this.startLine = startLine; + this.endLine = endLine; + } + + public Long getId() { + return id; + } + + public DuplicationUnitDto setId(Long id) { + this.id = id; + return this; + } + + public Integer getSnapshotId() { + return snapshotId; + } + + public void setSnapshotId(Integer snapshotId) { + this.snapshotId = snapshotId; + } + + public Integer getProjectSnapshotId() { + return projectSnapshotId; + } + + public void setProjectSnapshotId(Integer projectSnapshotId) { + this.projectSnapshotId = projectSnapshotId; + } + + public String getHash() { + return hash; + } + + public void setHash(String hash) { + this.hash = hash; + } + + public int getIndexInFile() { + return indexInFile; + } + + public void setIndexInFile(int indexInFile) { + this.indexInFile = indexInFile; + } + + public int getStartLine() { + return startLine; + } + + public void setStartLine(int startLine) { + this.startLine = startLine; + } + + public int getEndLine() { + return endLine; + } + + public void setEndLine(int endLine) { + this.endLine = endLine; + } + + public String getResourceKey() { + return resourceKey; + } + + public void setResourceKey(String resourceKey) { + this.resourceKey = resourceKey; + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/duplication/package-info.java b/sonar-db/src/main/java/org/sonar/db/duplication/package-info.java new file mode 100644 index 00000000000..54a5e199058 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/duplication/package-info.java @@ -0,0 +1,24 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.duplication; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/sonar-db/src/main/java/org/sonar/db/event/EventDto.java b/sonar-db/src/main/java/org/sonar/db/event/EventDto.java new file mode 100644 index 00000000000..884723ab408 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/event/EventDto.java @@ -0,0 +1,132 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.event; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; + +public class EventDto { + + public static final String CATEGORY_VERSION = "Version"; + public static final String CATEGORY_ALERT = "Alert"; + public static final String CATEGORY_PROFILE = "Profile"; + + private Long id; + + private String name; + + private String description; + + private String category; + + private Long date; + + private Long createdAt; + + private String data; + + private Long snapshotId; + + private String componentUuid; + + public Long getId() { + return id; + } + + public EventDto setId(Long id) { + this.id = id; + return this; + } + + public String getCategory() { + return category; + } + + public EventDto setCategory(String category) { + this.category = category; + return this; + } + + public String getComponentUuid() { + return componentUuid; + } + + public EventDto setComponentUuid(String componentUuid) { + this.componentUuid = componentUuid; + return this; + } + + public Long getCreatedAt() { + return createdAt; + } + + public EventDto setCreatedAt(Long createdAt) { + this.createdAt = createdAt; + return this; + } + + @CheckForNull + public String getData() { + return data; + } + + public EventDto setData(@Nullable String data) { + this.data = data; + return this; + } + + public Long getDate() { + return date; + } + + public EventDto setDate(Long date) { + this.date = date; + return this; + } + + @CheckForNull + public String getDescription() { + return description; + } + + public EventDto setDescription(@Nullable String description) { + this.description = description; + return this; + } + + public String getName() { + return name; + } + + public EventDto setName(String name) { + this.name = name; + return this; + } + + public Long getSnapshotId() { + return snapshotId; + } + + public EventDto setSnapshotId(Long snapshotId) { + this.snapshotId = snapshotId; + return this; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/event/EventMapper.java b/sonar-db/src/main/java/org/sonar/db/event/EventMapper.java new file mode 100644 index 00000000000..57dee6a9e68 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/event/EventMapper.java @@ -0,0 +1,41 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.event; + +import java.util.List; +import javax.annotation.CheckForNull; +import org.apache.ibatis.annotations.Param; + +public interface EventMapper { + + List<EventDto> selectByComponentUuid(String uuid); + + void insert(EventDto dto); + + void delete(long id); + + /** + * TODO Used by PastSnapshotFinderByVersion. Should be dropped soon. + */ + @CheckForNull + Long findSnapshotIdOfPreviousVersion(@Param("componentId") long componentId, @Param("currentVersion") String currentVersion); + +} diff --git a/sonar-db/src/main/java/org/sonar/db/event/package-info.java b/sonar-db/src/main/java/org/sonar/db/event/package-info.java new file mode 100644 index 00000000000..1e1d8997b92 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/event/package-info.java @@ -0,0 +1,25 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.event; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/sonar-db/src/main/java/org/sonar/db/issue/ActionPlanDao.java b/sonar-db/src/main/java/org/sonar/db/issue/ActionPlanDao.java new file mode 100644 index 00000000000..bb63a3c9b90 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/issue/ActionPlanDao.java @@ -0,0 +1,118 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.issue; + +import com.google.common.collect.Lists; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import org.apache.ibatis.session.SqlSession; +import org.sonar.api.server.ServerSide; +import org.sonar.db.Dao; +import org.sonar.db.MyBatis; + +import static com.google.common.collect.Lists.newArrayList; + +@ServerSide +public class ActionPlanDao implements Dao { + + private final MyBatis mybatis; + + public ActionPlanDao(MyBatis mybatis) { + this.mybatis = mybatis; + } + + public void save(ActionPlanDto actionPlanDto) { + SqlSession session = mybatis.openSession(false); + try { + session.getMapper(ActionPlanMapper.class).insert(actionPlanDto); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + public void update(ActionPlanDto actionPlanDto) { + SqlSession session = mybatis.openSession(false); + try { + session.getMapper(ActionPlanMapper.class).update(actionPlanDto); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + public void delete(String key) { + SqlSession session = mybatis.openSession(false); + try { + session.getMapper(ActionPlanMapper.class).delete(key); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + public ActionPlanDto findByKey(String key) { + SqlSession session = mybatis.openSession(false); + try { + return session.getMapper(ActionPlanMapper.class).findByKey(key); + } finally { + MyBatis.closeQuietly(session); + } + } + + public List<ActionPlanDto> findByKeys(Collection<String> keys) { + if (keys.isEmpty()) { + return Collections.emptyList(); + } + SqlSession session = mybatis.openSession(false); + try { + List<ActionPlanDto> dtosList = newArrayList(); + List<List<String>> keysPartition = Lists.partition(newArrayList(keys), 1000); + for (List<String> partition : keysPartition) { + List<ActionPlanDto> dtos = session.getMapper(ActionPlanMapper.class).findByKeys(partition); + dtosList.addAll(dtos); + } + return dtosList; + } finally { + MyBatis.closeQuietly(session); + } + } + + public List<ActionPlanDto> findOpenByProjectId(Long projectId) { + SqlSession session = mybatis.openSession(false); + try { + return session.getMapper(ActionPlanMapper.class).findOpenByProjectId(projectId); + } finally { + MyBatis.closeQuietly(session); + } + } + + public List<ActionPlanDto> findByNameAndProjectId(String name, Long projectId) { + SqlSession session = mybatis.openSession(false); + try { + return session.getMapper(ActionPlanMapper.class).findByNameAndProjectId(name, projectId); + } finally { + MyBatis.closeQuietly(session); + } + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/issue/ActionPlanDto.java b/sonar-db/src/main/java/org/sonar/db/issue/ActionPlanDto.java new file mode 100644 index 00000000000..f9cce188c07 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/issue/ActionPlanDto.java @@ -0,0 +1,201 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.issue; + +import java.util.Date; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; +import org.sonar.api.issue.ActionPlan; +import org.sonar.core.issue.DefaultActionPlan; + +/** + * @since 3.6 + */ +public class ActionPlanDto { + + private Long id; + private String kee; + private String name; + private String description; + private String userLogin; + private Long projectId; + private String status; + private Date deadLine; + private Date createdAt; + private Date updatedAt; + + // return by joins + private String projectKey; + + public Long getId() { + return id; + } + + public ActionPlanDto setId(Long id) { + this.id = id; + return this; + } + + public String getKey() { + return kee; + } + + public ActionPlanDto setKey(String kee) { + this.kee = kee; + return this; + } + + public String getName() { + return name; + } + + public ActionPlanDto setName(String name) { + this.name = name; + return this; + } + + @CheckForNull + public String getDescription() { + return description; + } + + public ActionPlanDto setDescription(@Nullable String description) { + this.description = description; + return this; + } + + public String getUserLogin() { + return userLogin; + } + + public ActionPlanDto setUserLogin(String userLogin) { + this.userLogin = userLogin; + return this; + } + + public Long getProjectId() { + return projectId; + } + + public ActionPlanDto setProjectId(Long projectId) { + this.projectId = projectId; + return this; + } + + public String getStatus() { + return status; + } + + public ActionPlanDto setStatus(String status) { + this.status = status; + return this; + } + + @CheckForNull + public Date getDeadLine() { + return deadLine; + } + + public ActionPlanDto setDeadLine(@Nullable Date deadLine) { + this.deadLine = deadLine; + return this; + } + + public Date getCreatedAt() { + return createdAt; + } + + public ActionPlanDto setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + return this; + } + + public Date getUpdatedAt() { + return updatedAt; + } + + public ActionPlanDto setUpdatedAt(Date updatedAt) { + this.updatedAt = updatedAt; + return this; + } + + public String getProjectKey() { + return projectKey; + } + + /** + * Only for unit tests + */ + public ActionPlanDto setProjectKey_unit_test_only(String projectKey) { + this.projectKey = projectKey; + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + ActionPlanDto actionPlanDto = (ActionPlanDto) o; + return !((id != null) ? !id.equals(actionPlanDto.id) : (actionPlanDto.id != null)); + } + + @Override + public int hashCode() { + return id != null ? id.hashCode() : 0; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); + } + + public DefaultActionPlan toActionPlan() { + return new DefaultActionPlan() + .setName(name) + .setKey(kee) + .setProjectKey(projectKey) + .setDescription(description) + .setStatus(status) + .setDeadLine(deadLine) + .setUserLogin(userLogin) + .setCreatedAt(createdAt) + .setUpdatedAt(updatedAt); + } + + public static ActionPlanDto toActionDto(ActionPlan actionPlan, Long projectId) { + return new ActionPlanDto().setKey(actionPlan.key()) + .setName(actionPlan.name()) + .setProjectId(projectId) + .setDescription(actionPlan.description()) + .setStatus(actionPlan.status()) + .setDeadLine(actionPlan.deadLine()) + .setUserLogin(actionPlan.userLogin()) + .setCreatedAt(actionPlan.createdAt()) + .setUpdatedAt(actionPlan.updatedAt()); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/issue/ActionPlanMapper.java b/sonar-db/src/main/java/org/sonar/db/issue/ActionPlanMapper.java new file mode 100644 index 00000000000..b8df2a11a58 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/issue/ActionPlanMapper.java @@ -0,0 +1,44 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.issue; + +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + * @since 3.6 + */ +public interface ActionPlanMapper { + + void insert(ActionPlanDto actionPlanDto); + + void update(ActionPlanDto actionPlanDto); + + void delete(@Param("key") String key); + + List<ActionPlanDto> findByKeys(@Param("keys") List<String> keys); + + ActionPlanDto findByKey(@Param("key") String key); + + List<ActionPlanDto> findOpenByProjectId(@Param("projectId") Long projectId); + + List<ActionPlanDto> findByNameAndProjectId(@Param("name") String name, @Param("projectId") Long projectId); +} diff --git a/sonar-db/src/main/java/org/sonar/db/issue/ActionPlanStatsDao.java b/sonar-db/src/main/java/org/sonar/db/issue/ActionPlanStatsDao.java new file mode 100644 index 00000000000..dfd4192922b --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/issue/ActionPlanStatsDao.java @@ -0,0 +1,44 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.issue; + +import java.util.List; +import org.apache.ibatis.session.SqlSession; +import org.sonar.db.MyBatis; + +public class ActionPlanStatsDao { + + private final MyBatis mybatis; + + public ActionPlanStatsDao(MyBatis mybatis) { + this.mybatis = mybatis; + } + + public List<ActionPlanStatsDto> findByProjectId(Long projectId) { + SqlSession session = mybatis.openSession(false); + try { + return session.getMapper(ActionPlanStatsMapper.class).findByProjectId(projectId); + } finally { + MyBatis.closeQuietly(session); + } + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/issue/ActionPlanStatsDto.java b/sonar-db/src/main/java/org/sonar/db/issue/ActionPlanStatsDto.java new file mode 100644 index 00000000000..d1aa6bc3797 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/issue/ActionPlanStatsDto.java @@ -0,0 +1,187 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.issue; + +import java.util.Date; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; +import org.sonar.core.issue.ActionPlanStats; + +/** + * @since 3.6 + */ +public class ActionPlanStatsDto { + + private Integer id; + private String kee; + private String name; + private String description; + private String userLogin; + private Integer projectId; + private String status; + private Date deadLine; + private Date createdAt; + private Date updatedAt; + private int totalIssues; + private int unresolvedIssues; + // return by joins + private String projectKey; + + public Integer getId() { + return id; + } + + public ActionPlanStatsDto setId(Integer id) { + this.id = id; + return this; + } + + public String getKee() { + return kee; + } + + public ActionPlanStatsDto setKee(String kee) { + this.kee = kee; + return this; + } + + public String getName() { + return name; + } + + public ActionPlanStatsDto setName(String name) { + this.name = name; + return this; + } + + public String getDescription() { + return description; + } + + public ActionPlanStatsDto setDescription(String description) { + this.description = description; + return this; + } + + public String getUserLogin() { + return userLogin; + } + + public ActionPlanStatsDto setUserLogin(String userLogin) { + this.userLogin = userLogin; + return this; + } + + public Integer getProjectId() { + return projectId; + } + + public ActionPlanStatsDto setProjectId(Integer projectId) { + this.projectId = projectId; + return this; + } + + public String getStatus() { + return status; + } + + public ActionPlanStatsDto setStatus(String status) { + this.status = status; + return this; + } + + public Date getDeadLine() { + return deadLine; + } + + public ActionPlanStatsDto setDeadLine(Date deadLine) { + this.deadLine = deadLine; + return this; + } + + public Date getCreatedAt() { + return createdAt; + } + + public ActionPlanStatsDto setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + return this; + } + + public Date getUpdatedAt() { + return updatedAt; + } + + public ActionPlanStatsDto setUpdatedAt(Date updatedAt) { + this.updatedAt = updatedAt; + return this; + } + + public int getTotalIssues() { + return totalIssues; + } + + public ActionPlanStatsDto setTotalIssues(int totalIssues) { + this.totalIssues = totalIssues; + return this; + } + + public int getUnresolvedIssues() { + return unresolvedIssues; + } + + public ActionPlanStatsDto setUnresolvedIssues(int unresolvedIssues) { + this.unresolvedIssues = unresolvedIssues; + return this; + } + + public String getProjectKey() { + return projectKey; + } + + /** + * Only for unit tests + */ + public ActionPlanStatsDto setProjectKey_unit_test_only(String projectKey) { + this.projectKey = projectKey; + return this; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); + } + + public ActionPlanStats toActionPlanStat() { + return ((ActionPlanStats) ActionPlanStats.create(name) + .setKey(kee) + .setProjectKey(projectKey) + .setDescription(description) + .setStatus(status) + .setDeadLine(deadLine) + .setUserLogin(userLogin) + .setCreatedAt(createdAt) + .setUpdatedAt(updatedAt)) + .setTotalIssues(totalIssues) + .setUnresolvedIssues(unresolvedIssues); + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/issue/ActionPlanStatsMapper.java b/sonar-db/src/main/java/org/sonar/db/issue/ActionPlanStatsMapper.java new file mode 100644 index 00000000000..26c3395a0f7 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/issue/ActionPlanStatsMapper.java @@ -0,0 +1,35 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.issue; + +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + * @since 3.6 + */ +public interface ActionPlanStatsMapper { + + /** + * @since3.6 + */ + List<ActionPlanStatsDto> findByProjectId(@Param("projectId") Long projectId); +} diff --git a/sonar-db/src/main/java/org/sonar/db/issue/IssueChangeDao.java b/sonar-db/src/main/java/org/sonar/db/issue/IssueChangeDao.java new file mode 100644 index 00000000000..076681365eb --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/issue/IssueChangeDao.java @@ -0,0 +1,135 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.issue; + +import com.google.common.collect.Lists; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import javax.annotation.CheckForNull; +import org.sonar.api.server.ServerSide; +import org.sonar.core.issue.DefaultIssueComment; +import org.sonar.core.issue.FieldDiffs; +import org.sonar.db.Dao; +import org.sonar.db.DbSession; +import org.sonar.db.MyBatis; + +import static com.google.common.collect.Lists.newArrayList; +import static java.util.Arrays.asList; + +@ServerSide +public class IssueChangeDao implements Dao { + + private final MyBatis mybatis; + + public IssueChangeDao(MyBatis mybatis) { + this.mybatis = mybatis; + } + + public List<DefaultIssueComment> selectCommentsByIssues(DbSession session, Collection<String> issueKeys) { + List<DefaultIssueComment> comments = Lists.newArrayList(); + for (IssueChangeDto dto : selectByIssuesAndType(session, issueKeys, IssueChangeDto.TYPE_COMMENT)) { + comments.add(dto.toComment()); + } + return comments; + } + + public List<FieldDiffs> selectChangelogByIssue(String issueKey) { + DbSession session = mybatis.openSession(false); + try { + List<FieldDiffs> result = Lists.newArrayList(); + for (IssueChangeDto dto : selectByIssuesAndType(session, asList(issueKey), IssueChangeDto.TYPE_FIELD_CHANGE)) { + result.add(dto.toFieldDiffs()); + } + return result; + } finally { + MyBatis.closeQuietly(session); + } + } + + public List<IssueChangeDto> selectChangelogOfNonClosedIssuesByComponent(String componentUuid) { + DbSession session = mybatis.openSession(false); + try { + IssueChangeMapper mapper = session.getMapper(IssueChangeMapper.class); + return mapper.selectChangelogOfNonClosedIssuesByComponent(componentUuid, IssueChangeDto.TYPE_FIELD_CHANGE); + + } finally { + MyBatis.closeQuietly(session); + } + } + + @CheckForNull + public DefaultIssueComment selectCommentByKey(String commentKey) { + DbSession session = mybatis.openSession(false); + try { + IssueChangeMapper mapper = session.getMapper(IssueChangeMapper.class); + IssueChangeDto dto = mapper.selectByKeyAndType(commentKey, IssueChangeDto.TYPE_COMMENT); + return dto != null ? dto.toComment() : null; + + } finally { + MyBatis.closeQuietly(session); + } + } + + List<IssueChangeDto> selectByIssuesAndType(DbSession session, Collection<String> issueKeys, String changeType) { + if (issueKeys.isEmpty()) { + return Collections.emptyList(); + } + IssueChangeMapper mapper = session.getMapper(IssueChangeMapper.class); + List<IssueChangeDto> dtosList = newArrayList(); + List<List<String>> keysPartition = Lists.partition(newArrayList(issueKeys), 1000); + for (List<String> partition : keysPartition) { + List<IssueChangeDto> dtos = mapper.selectByIssuesAndType(partition, changeType); + dtosList.addAll(dtos); + } + return dtosList; + } + + public void insert(DbSession session, IssueChangeDto change) { + session.getMapper(IssueChangeMapper.class).insert(change); + } + + public boolean delete(String key) { + DbSession session = mybatis.openSession(false); + try { + IssueChangeMapper mapper = session.getMapper(IssueChangeMapper.class); + int count = mapper.delete(key); + session.commit(); + return count == 1; + + } finally { + MyBatis.closeQuietly(session); + } + } + + public boolean update(IssueChangeDto change) { + DbSession session = mybatis.openSession(false); + try { + IssueChangeMapper mapper = session.getMapper(IssueChangeMapper.class); + int count = mapper.update(change); + session.commit(); + return count == 1; + + } finally { + MyBatis.closeQuietly(session); + } + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/issue/IssueChangeDto.java b/sonar-db/src/main/java/org/sonar/db/issue/IssueChangeDto.java new file mode 100644 index 00000000000..14bce70b26b --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/issue/IssueChangeDto.java @@ -0,0 +1,190 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.issue; + +import java.io.Serializable; +import java.util.Date; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; +import org.sonar.api.utils.System2; +import org.sonar.core.issue.DefaultIssueComment; +import org.sonar.core.issue.FieldDiffs; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * @since 3.6 + */ +public final class IssueChangeDto implements Serializable { + + public static final String TYPE_FIELD_CHANGE = "diff"; + public static final String TYPE_COMMENT = "comment"; + + private Long id; + private String kee; + private String issueKey; + private String userLogin; + private String changeType; + private String changeData; + + // technical dates + private Long createdAt; + private Long updatedAt; + + // functional date + private Long issueChangeCreationDate; + + public static IssueChangeDto of(DefaultIssueComment comment) { + IssueChangeDto dto = newDto(comment.issueKey()); + dto.setKey(comment.key()); + dto.setChangeType(IssueChangeDto.TYPE_COMMENT); + dto.setChangeData(comment.markdownText()); + dto.setUserLogin(comment.userLogin()); + dto.setIssueChangeCreationDate(comment.createdAt() == null ? null : comment.createdAt().getTime()); + return dto; + } + + public static IssueChangeDto of(String issueKey, FieldDiffs diffs) { + IssueChangeDto dto = newDto(issueKey); + dto.setChangeType(IssueChangeDto.TYPE_FIELD_CHANGE); + dto.setChangeData(diffs.toString()); + dto.setUserLogin(diffs.userLogin()); + dto.setIssueChangeCreationDate(diffs.creationDate() == null ? null : diffs.creationDate().getTime()); + return dto; + } + + private static IssueChangeDto newDto(String issueKey) { + IssueChangeDto dto = new IssueChangeDto(); + dto.setIssueKey(issueKey); + + // technical dates - do not use the context date + dto.setCreatedAt(System2.INSTANCE.now()); + dto.setUpdatedAt(System2.INSTANCE.now()); + return dto; + } + + public Long getId() { + return id; + } + + public IssueChangeDto setId(Long id) { + this.id = id; + return this; + } + + @CheckForNull + public String getKey() { + return kee; + } + + public IssueChangeDto setKey(@Nullable String key) { + this.kee = key; + return this; + } + + public String getIssueKey() { + return issueKey; + } + + public IssueChangeDto setIssueKey(String s) { + this.issueKey = s; + return this; + } + + public String getUserLogin() { + return userLogin; + } + + public IssueChangeDto setUserLogin(@Nullable String userLogin) { + this.userLogin = userLogin; + return this; + } + + public String getChangeType() { + return changeType; + } + + public IssueChangeDto setChangeType(String changeType) { + this.changeType = changeType; + return this; + } + + public String getChangeData() { + return changeData; + } + + public IssueChangeDto setChangeData(String changeData) { + this.changeData = changeData; + return this; + } + + public Long getCreatedAt() { + return createdAt; + } + + public IssueChangeDto setCreatedAt(Long createdAt) { + this.createdAt = checkNotNull(createdAt); + return this; + } + + public Long getUpdatedAt() { + return updatedAt; + } + + public IssueChangeDto setUpdatedAt(@Nullable Long updatedAt) { + this.updatedAt = updatedAt; + return this; + } + + public Long getIssueChangeCreationDate() { + return issueChangeCreationDate; + } + + public IssueChangeDto setIssueChangeCreationDate(@Nullable Long issueChangeCreationDate) { + this.issueChangeCreationDate = issueChangeCreationDate; + return this; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); + } + + public DefaultIssueComment toComment() { + return new DefaultIssueComment() + .setMarkdownText(changeData) + .setKey(kee) + .setCreatedAt(new Date(createdAt)) + .setUpdatedAt(updatedAt == null ? null : new Date(updatedAt)) + .setUserLogin(userLogin) + .setIssueKey(issueKey) + .setNew(false); + } + + public FieldDiffs toFieldDiffs() { + return FieldDiffs.parse(changeData) + .setUserLogin(userLogin) + // issueChangeCreationDate can be null as it has been introduced after createdAt + .setCreationDate(issueChangeCreationDate != null ? new Date(issueChangeCreationDate) : new Date(createdAt)) + .setIssueKey(issueKey); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/issue/IssueChangeMapper.java b/sonar-db/src/main/java/org/sonar/db/issue/IssueChangeMapper.java new file mode 100644 index 00000000000..1f0efcd0c31 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/issue/IssueChangeMapper.java @@ -0,0 +1,45 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.issue; + +import java.util.List; +import javax.annotation.CheckForNull; +import org.apache.ibatis.annotations.Param; + +public interface IssueChangeMapper { + + void insert(IssueChangeDto dto); + + int delete(String key); + + int update(IssueChangeDto change); + + @CheckForNull + IssueChangeDto selectByKeyAndType(@Param("key") String key, @Param("changeType") String type); + + /** + * Issue changes by chronological date of creation + */ + List<IssueChangeDto> selectByIssuesAndType(@Param("issueKeys") List<String> issueKeys, + @Param("changeType") String changeType); + + List<IssueChangeDto> selectChangelogOfNonClosedIssuesByComponent(@Param("componentUuid") String componentUuid, @Param("changeType") String changeType); +} diff --git a/sonar-db/src/main/java/org/sonar/db/issue/IssueDao.java b/sonar-db/src/main/java/org/sonar/db/issue/IssueDao.java new file mode 100644 index 00000000000..edc89f9c267 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/issue/IssueDao.java @@ -0,0 +1,50 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.issue; + +import org.apache.ibatis.session.ResultHandler; +import org.apache.ibatis.session.SqlSession; +import org.sonar.db.DbSession; +import org.sonar.db.MyBatis; + +public class IssueDao { + + private final MyBatis mybatis; + + public IssueDao(MyBatis mybatis) { + this.mybatis = mybatis; + } + + public void selectNonClosedIssuesByModule(long componentId, ResultHandler handler) { + SqlSession session = mybatis.openSession(false); + try { + session.select("org.sonar.db.issue.IssueMapper.selectNonClosedIssuesByModule", componentId, handler); + + } finally { + MyBatis.closeQuietly(session); + } + } + + protected IssueMapper mapper(DbSession session) { + return session.getMapper(IssueMapper.class); + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/issue/IssueDto.java b/sonar-db/src/main/java/org/sonar/db/issue/IssueDto.java new file mode 100644 index 00000000000..f5eff6e3095 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/issue/IssueDto.java @@ -0,0 +1,686 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.issue; + +import com.google.common.base.Joiner; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.base.Splitter; +import com.google.common.collect.ImmutableSet; +import java.io.Serializable; +import java.util.Collection; +import java.util.Date; +import java.util.Set; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; +import org.sonar.api.resources.Project; +import org.sonar.api.rule.RuleKey; +import org.sonar.api.utils.Duration; +import org.sonar.api.utils.KeyValueFormat; +import org.sonar.api.utils.internal.Uuids; +import org.sonar.core.issue.DefaultIssue; +import org.sonar.db.component.ComponentDto; +import org.sonar.db.rule.RuleDto; + +import static org.sonar.api.utils.DateUtils.dateToLong; +import static org.sonar.api.utils.DateUtils.longToDate; + +/** + * @since 3.6 + */ +public final class IssueDto implements Serializable { + + private static final char TAGS_SEPARATOR = ','; + private static final Joiner TAGS_JOINER = Joiner.on(TAGS_SEPARATOR).skipNulls(); + private static final Splitter TAGS_SPLITTER = Splitter.on(',').trimResults().omitEmptyStrings(); + + private Long id; + private String kee; + private String componentUuid; + private String projectUuid; + private Integer ruleId; + private String severity; + private boolean manualSeverity; + private String message; + private Integer line; + private Double effortToFix; + private Long debt; + private String status; + private String resolution; + private String checksum; + private String reporter; + private String assignee; + private String authorLogin; + private String actionPlanKey; + private String issueAttributes; + private long createdAt; + private long updatedAt; + + // functional dates stored as Long + private Long issueCreationDate; + private Long issueUpdateDate; + private Long issueCloseDate; + + /** + * Temporary date used only during scan + */ + private Long selectedAt; + + // joins + private String ruleKey; + private String ruleRepo; + private String language; + private String componentKey; + private String moduleUuid; + private String moduleUuidPath; + private String projectKey; + private String filePath; + private String tags; + + /** + * On batch side, component keys and uuid are useless + */ + public static IssueDto toDtoForComputationInsert(DefaultIssue issue, int ruleId, long now) { + return new IssueDto() + .setKee(issue.key()) + .setLine(issue.line()) + .setMessage(issue.message()) + .setEffortToFix(issue.effortToFix()) + .setDebt(issue.debtInMinutes()) + .setResolution(issue.resolution()) + .setStatus(issue.status()) + .setSeverity(issue.severity()) + .setManualSeverity(issue.manualSeverity()) + .setChecksum(issue.checksum()) + .setReporter(issue.reporter()) + .setAssignee(issue.assignee()) + .setRuleId(ruleId) + .setRuleKey(issue.ruleKey().repository(), issue.ruleKey().rule()) + .setTags(issue.tags()) + .setComponentUuid(issue.componentUuid()) + .setComponentKey(issue.componentKey()) + .setModuleUuid(issue.moduleUuid()) + .setModuleUuidPath(issue.moduleUuidPath()) + .setComponentUuid(issue.componentUuid()) + .setProjectUuid(issue.projectUuid()) + .setProjectKey(issue.projectKey()) + .setActionPlanKey(issue.actionPlanKey()) + .setIssueAttributes(KeyValueFormat.format(issue.attributes())) + .setAuthorLogin(issue.authorLogin()) + .setIssueCreationDate(issue.creationDate()) + .setIssueCloseDate(issue.closeDate()) + .setIssueUpdateDate(issue.updateDate()) + .setSelectedAt(issue.selectedAt()) + + // technical dates + .setCreatedAt(now) + .setUpdatedAt(now); + } + + /** + * On server side, we need component keys and uuid + */ + public static IssueDto toDtoForServerInsert(DefaultIssue issue, ComponentDto component, ComponentDto project, int ruleId, long now) { + return toDtoForComputationInsert(issue, ruleId, now) + .setComponent(component) + .setProject(project); + } + + public static IssueDto toDtoForUpdate(DefaultIssue issue, long now) { + // Invariant fields, like key and rule, can't be updated + return new IssueDto() + .setKee(issue.key()) + .setLine(issue.line()) + .setMessage(issue.message()) + .setEffortToFix(issue.effortToFix()) + .setDebt(issue.debtInMinutes()) + .setResolution(issue.resolution()) + .setStatus(issue.status()) + .setSeverity(issue.severity()) + .setChecksum(issue.checksum()) + .setManualSeverity(issue.manualSeverity()) + .setReporter(issue.reporter()) + .setAssignee(issue.assignee()) + .setActionPlanKey(issue.actionPlanKey()) + .setIssueAttributes(KeyValueFormat.format(issue.attributes())) + .setAuthorLogin(issue.authorLogin()) + .setRuleKey(issue.ruleKey().repository(), issue.ruleKey().rule()) + .setTags(issue.tags()) + .setComponentUuid(issue.componentUuid()) + .setComponentKey(issue.componentKey()) + .setModuleUuid(issue.moduleUuid()) + .setModuleUuidPath(issue.moduleUuidPath()) + .setProjectUuid(issue.projectUuid()) + .setProjectKey(issue.projectKey()) + .setIssueCreationDate(issue.creationDate()) + .setIssueCloseDate(issue.closeDate()) + .setIssueUpdateDate(issue.updateDate()) + .setSelectedAt(issue.selectedAt()) + + // technical date + .setUpdatedAt(now); + } + + public static IssueDto createFor(Project project, RuleDto rule) { + return new IssueDto() + .setProjectUuid(project.getUuid()) + .setRuleId(rule.getId()) + .setKee(Uuids.create()); + } + + public String getKey() { + return getKee(); + } + + public Long getId() { + return id; + } + + public IssueDto setId(@Nullable Long id) { + this.id = id; + return this; + } + + public String getKee() { + return kee; + } + + public IssueDto setKee(String s) { + this.kee = s; + return this; + } + + public IssueDto setComponent(ComponentDto component) { + this.componentKey = component.getKey(); + this.componentUuid = component.uuid(); + this.moduleUuid = component.moduleUuid(); + this.moduleUuidPath = component.moduleUuidPath(); + this.filePath = component.path(); + return this; + } + + public IssueDto setProject(ComponentDto project) { + this.projectKey = project.getKey(); + this.projectUuid = project.uuid(); + return this; + } + + public Integer getRuleId() { + return ruleId; + } + + /** + * please use setRule(RuleDto rule) + */ + public IssueDto setRuleId(Integer ruleId) { + this.ruleId = ruleId; + return this; + } + + @CheckForNull + public String getActionPlanKey() { + return actionPlanKey; + } + + public IssueDto setActionPlanKey(@Nullable String s) { + this.actionPlanKey = s; + return this; + } + + @CheckForNull + public String getSeverity() { + return severity; + } + + public IssueDto setSeverity(@Nullable String severity) { + this.severity = severity; + return this; + } + + public boolean isManualSeverity() { + return manualSeverity; + } + + public IssueDto setManualSeverity(boolean manualSeverity) { + this.manualSeverity = manualSeverity; + return this; + } + + @CheckForNull + public String getMessage() { + return message; + } + + public IssueDto setMessage(@Nullable String s) { + this.message = s; + return this; + } + + @CheckForNull + public Integer getLine() { + return line; + } + + public IssueDto setLine(@Nullable Integer line) { + this.line = line; + return this; + } + + @CheckForNull + public Double getEffortToFix() { + return effortToFix; + } + + public IssueDto setEffortToFix(@Nullable Double d) { + this.effortToFix = d; + return this; + } + + @CheckForNull + public Long getDebt() { + return debt; + } + + public IssueDto setDebt(@Nullable Long debt) { + this.debt = debt; + return this; + } + + public String getStatus() { + return status; + } + + public IssueDto setStatus(@Nullable String status) { + this.status = status; + return this; + } + + @CheckForNull + public String getResolution() { + return resolution; + } + + public IssueDto setResolution(@Nullable String s) { + this.resolution = s; + return this; + } + + @CheckForNull + public String getChecksum() { + return checksum; + } + + public IssueDto setChecksum(@Nullable String checksum) { + this.checksum = checksum; + return this; + } + + @CheckForNull + public String getReporter() { + return reporter; + } + + public IssueDto setReporter(@Nullable String s) { + this.reporter = s; + return this; + } + + public String getAssignee() { + return assignee; + } + + public IssueDto setAssignee(@Nullable String s) { + this.assignee = s; + return this; + } + + public String getAuthorLogin() { + return authorLogin; + } + + public IssueDto setAuthorLogin(@Nullable String authorLogin) { + this.authorLogin = authorLogin; + return this; + } + + public String getIssueAttributes() { + return issueAttributes; + } + + public IssueDto setIssueAttributes(@Nullable String s) { + Preconditions.checkArgument(s == null || s.length() <= 4000, + "Issue attributes must not exceed 4000 characters: " + s); + this.issueAttributes = s; + return this; + } + + /** + * Technical date + */ + public long getCreatedAt() { + return createdAt; + } + + public IssueDto setCreatedAt(long createdAt) { + this.createdAt = createdAt; + return this; + } + + /** + * Technical date + */ + public long getUpdatedAt() { + return updatedAt; + } + + public IssueDto setUpdatedAt(long updatedAt) { + this.updatedAt = updatedAt; + return this; + } + + public Long getIssueCreationTime() { + return issueCreationDate; + } + + public IssueDto setIssueCreationTime(Long time) { + this.issueCreationDate = time; + return this; + } + + public Date getIssueCreationDate() { + return longToDate(issueCreationDate); + } + + public IssueDto setIssueCreationDate(@Nullable Date d) { + this.issueCreationDate = dateToLong(d); + return this; + } + + public Long getIssueUpdateTime() { + return issueUpdateDate; + } + + public IssueDto setIssueUpdateTime(Long time) { + this.issueUpdateDate = time; + return this; + } + + public Date getIssueUpdateDate() { + return longToDate(issueUpdateDate); + } + + public IssueDto setIssueUpdateDate(@Nullable Date d) { + this.issueUpdateDate = dateToLong(d); + return this; + } + + public Long getIssueCloseTime() { + return issueCloseDate; + } + + public IssueDto setIssueCloseTime(Long time) { + this.issueCloseDate = time; + return this; + } + + public Date getIssueCloseDate() { + return longToDate(issueCloseDate); + } + + public IssueDto setIssueCloseDate(@Nullable Date d) { + this.issueCloseDate = dateToLong(d); + return this; + } + + public String getRule() { + return ruleKey; + } + + public IssueDto setRule(RuleDto rule) { + Preconditions.checkNotNull(rule.getId(), "Rule must be persisted."); + this.ruleId = rule.getId(); + this.ruleKey = rule.getRuleKey(); + this.ruleRepo = rule.getRepositoryKey(); + this.language = rule.getLanguage(); + return this; + } + + public String getRuleRepo() { + return ruleRepo; + } + + public RuleKey getRuleKey() { + return RuleKey.of(ruleRepo, ruleKey); + } + + public String getLanguage() { + return language; + } + + /** + * Should only be used to persist in E/S + * <p/> + * Please use {@link #setRule(RuleDto)} instead + */ + public IssueDto setLanguage(String language) { + this.language = language; + return this; + } + + public String getComponentKey() { + return componentKey; + } + + /** + * Should only be used to persist in E/S + * <p/> + * Please use {@link #setComponent(ComponentDto)} instead + */ + public IssueDto setComponentKey(String componentKey) { + this.componentKey = componentKey; + return this; + } + + /** + * Can be null on Views or Devs + */ + @CheckForNull + public String getComponentUuid() { + return componentUuid; + } + + /** + * Should only be used to persist in E/S + * <p/> + * Please use {@link #setComponent(ComponentDto)} instead + */ + public IssueDto setComponentUuid(@Nullable String componentUuid) { + this.componentUuid = componentUuid; + return this; + } + + @CheckForNull + public String getModuleUuid() { + return moduleUuid; + } + + /** + * Should only be used to persist in E/S + * <p/> + * Please use {@link #setComponent(ComponentDto)} instead + */ + public IssueDto setModuleUuid(@Nullable String moduleUuid) { + this.moduleUuid = moduleUuid; + return this; + } + + @CheckForNull + public String getModuleUuidPath() { + return moduleUuidPath; + } + + /** + * Should only be used to persist in E/S + * <p/> + * Please use {@link #setComponent(ComponentDto)} instead + */ + public IssueDto setModuleUuidPath(@Nullable String moduleUuidPath) { + this.moduleUuidPath = moduleUuidPath; + return this; + } + + /** + * Used by the issue tracking mechanism, but it should used the component uuid instead + */ + public String getProjectKey() { + return projectKey; + } + + /** + * Should only be used to persist in E/S + * <p/> + * Please use {@link #setProject(ComponentDto)} instead + */ + public IssueDto setProjectKey(String projectKey) { + this.projectKey = projectKey; + return this; + } + + /** + * Can be null on Views or Devs + */ + @CheckForNull + public String getProjectUuid() { + return projectUuid; + } + + /** + * Should only be used to persist in E/S + * <p/> + * Please use {@link #setProject(ComponentDto)} instead + */ + public IssueDto setProjectUuid(@Nullable String projectUuid) { + this.projectUuid = projectUuid; + return this; + } + + @CheckForNull + public Long getSelectedAt() { + return selectedAt; + } + + public IssueDto setSelectedAt(@Nullable Long d) { + this.selectedAt = d; + return this; + } + + /** + * Should only be used to persist in E/S + * <p/> + * Please use {@link #setRule(RuleDto)} instead + */ + public IssueDto setRuleKey(String repo, String rule) { + this.ruleRepo = repo; + this.ruleKey = rule; + return this; + } + + /** + * Should only be used to persist in E/S + * <p/> + * Please use {@link #setProject(ComponentDto)} instead + */ + public String getFilePath() { + return filePath; + } + + /** + * Should only be used to persist in E/S + * <p/> + * Please use {@link #setProject(ComponentDto)} instead + */ + public IssueDto setFilePath(String filePath) { + this.filePath = filePath; + return this; + } + + public Set<String> getTags() { + return ImmutableSet.copyOf(TAGS_SPLITTER.split(tags == null ? "" : tags)); + } + + public IssueDto setTags(Collection<String> tags) { + if (tags.isEmpty()) { + this.tags = null; + } else { + this.tags = TAGS_JOINER.join(tags); + } + return this; + } + + public String getTagsString() { + return tags; + } + + public IssueDto setTagsString(String tags) { + this.tags = tags; + return this; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); + } + + public DefaultIssue toDefaultIssue() { + DefaultIssue issue = new DefaultIssue(); + issue.setKey(kee); + issue.setStatus(status); + issue.setResolution(resolution); + issue.setMessage(message); + issue.setEffortToFix(effortToFix); + issue.setDebt(debt != null ? Duration.create(debt) : null); + issue.setLine(line); + issue.setChecksum(checksum); + issue.setSeverity(severity); + issue.setReporter(reporter); + issue.setAssignee(assignee); + issue.setAttributes(KeyValueFormat.parse(Objects.firstNonNull(issueAttributes, ""))); + issue.setComponentKey(componentKey); + issue.setComponentUuid(componentUuid); + issue.setModuleUuid(moduleUuid); + issue.setModuleUuidPath(moduleUuidPath); + issue.setProjectUuid(projectUuid); + issue.setProjectKey(projectKey); + issue.setManualSeverity(manualSeverity); + issue.setRuleKey(getRuleKey()); + issue.setTags(getTags()); + issue.setLanguage(language); + issue.setActionPlanKey(actionPlanKey); + issue.setAuthorLogin(authorLogin); + issue.setNew(false); + issue.setCreationDate(longToDate(issueCreationDate)); + issue.setCloseDate(longToDate(issueCloseDate)); + issue.setUpdateDate(longToDate(issueUpdateDate)); + issue.setSelectedAt(selectedAt); + return issue; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/issue/IssueFilterDao.java b/sonar-db/src/main/java/org/sonar/db/issue/IssueFilterDao.java new file mode 100644 index 00000000000..6d187866547 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/issue/IssueFilterDao.java @@ -0,0 +1,117 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.issue; + +import java.util.List; +import javax.annotation.CheckForNull; +import org.apache.ibatis.session.SqlSession; +import org.sonar.db.Dao; +import org.sonar.db.MyBatis; + +public class IssueFilterDao implements Dao { + + private final MyBatis mybatis; + + public IssueFilterDao(MyBatis mybatis) { + this.mybatis = mybatis; + } + + @CheckForNull + public IssueFilterDto selectById(long id) { + SqlSession session = mybatis.openSession(false); + try { + session.getMapper(IssueFilterMapper.class); + return getMapper(session).selectById(id); + } finally { + MyBatis.closeQuietly(session); + } + } + + public List<IssueFilterDto> selectByUser(String user) { + SqlSession session = mybatis.openSession(false); + try { + return getMapper(session).selectByUser(user); + } finally { + MyBatis.closeQuietly(session); + } + } + + public List<IssueFilterDto> selectFavoriteFiltersByUser(String user) { + SqlSession session = mybatis.openSession(false); + try { + return getMapper(session).selectFavoriteFiltersByUser(user); + } finally { + MyBatis.closeQuietly(session); + } + } + + public IssueFilterDto selectProvidedFilterByName(String name) { + SqlSession session = mybatis.openSession(false); + try { + return getMapper(session).selectProvidedFilterByName(name); + } finally { + MyBatis.closeQuietly(session); + } + } + + public List<IssueFilterDto> selectSharedFilters() { + SqlSession session = mybatis.openSession(false); + try { + return getMapper(session).selectSharedFilters(); + } finally { + MyBatis.closeQuietly(session); + } + } + + public void insert(IssueFilterDto filter) { + SqlSession session = mybatis.openSession(false); + try { + getMapper(session).insert(filter); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + public void update(IssueFilterDto filter) { + SqlSession session = mybatis.openSession(false); + try { + getMapper(session).update(filter); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + public void delete(long id) { + SqlSession session = mybatis.openSession(false); + try { + getMapper(session).delete(id); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + private IssueFilterMapper getMapper(SqlSession session) { + return session.getMapper(IssueFilterMapper.class); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/issue/IssueFilterDto.java b/sonar-db/src/main/java/org/sonar/db/issue/IssueFilterDto.java new file mode 100644 index 00000000000..d3552aae316 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/issue/IssueFilterDto.java @@ -0,0 +1,116 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.issue; + +import java.util.Date; +import javax.annotation.Nullable; + +/** + * @since 3.7 + */ +public class IssueFilterDto { + + private Long id; + private String name; + private String userLogin; + private boolean shared; + private String description; + private String data; + private Date createdAt; + private Date updatedAt; + + public IssueFilterDto() { + Date now = new Date(); + createdAt = updatedAt = now; + shared = false; + } + + public Long getId() { + return id; + } + + public IssueFilterDto setId(Long id) { + this.id = id; + return this; + } + + public String getName() { + return name; + } + + public IssueFilterDto setName(String name) { + this.name = name; + return this; + } + + public String getUserLogin() { + return userLogin; + } + + public IssueFilterDto setUserLogin(String userLogin) { + this.userLogin = userLogin; + return this; + } + + public boolean isShared() { + return shared; + } + + public IssueFilterDto setShared(boolean shared) { + this.shared = shared; + return this; + } + + public String getDescription() { + return description; + } + + public IssueFilterDto setDescription(@Nullable String description) { + this.description = description; + return this; + } + + public String getData() { + return data; + } + + public IssueFilterDto setData(String data) { + this.data = data; + return this; + } + + public Date getCreatedAt() { + return createdAt; + } + + public IssueFilterDto setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + return this; + } + + public Date getUpdatedAt() { + return updatedAt; + } + + public IssueFilterDto setUpdatedAt(Date updatedAt) { + this.updatedAt = updatedAt; + return this; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/issue/IssueFilterFavouriteDao.java b/sonar-db/src/main/java/org/sonar/db/issue/IssueFilterFavouriteDao.java new file mode 100644 index 00000000000..f9de1a19963 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/issue/IssueFilterFavouriteDao.java @@ -0,0 +1,86 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.issue; + +import java.util.List; +import org.apache.ibatis.session.SqlSession; +import org.sonar.db.MyBatis; + +public class IssueFilterFavouriteDao { + + private final MyBatis mybatis; + + public IssueFilterFavouriteDao(MyBatis mybatis) { + this.mybatis = mybatis; + } + + public IssueFilterFavouriteDto selectById(long id) { + SqlSession session = mybatis.openSession(false); + try { + return getMapper(session).selectById(id); + } finally { + MyBatis.closeQuietly(session); + } + } + + public List<IssueFilterFavouriteDto> selectByFilterId(long filterId) { + SqlSession session = mybatis.openSession(false); + try { + return getMapper(session).selectByFilterId(filterId); + } finally { + MyBatis.closeQuietly(session); + } + } + + public void insert(IssueFilterFavouriteDto filter) { + SqlSession session = mybatis.openSession(false); + try { + getMapper(session).insert(filter); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + public void delete(long id) { + SqlSession session = mybatis.openSession(false); + try { + getMapper(session).delete(id); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + public void deleteByFilterId(long filterId) { + SqlSession session = mybatis.openSession(false); + try { + getMapper(session).deleteByFilterId(filterId); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + private IssueFilterFavouriteMapper getMapper(SqlSession session) { + return session.getMapper(IssueFilterFavouriteMapper.class); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/issue/IssueFilterFavouriteDto.java b/sonar-db/src/main/java/org/sonar/db/issue/IssueFilterFavouriteDto.java new file mode 100644 index 00000000000..d86bd266bf4 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/issue/IssueFilterFavouriteDto.java @@ -0,0 +1,70 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.issue; + +import java.util.Date; + +/** + * @since 3.7 + */ +public class IssueFilterFavouriteDto { + + private Long id; + private String userLogin; + private Long issueFilterId; + private Date createdAt; + + public Long getId() { + return id; + } + + public IssueFilterFavouriteDto setId(Long id) { + this.id = id; + return this; + } + + public String getUserLogin() { + return userLogin; + } + + public IssueFilterFavouriteDto setUserLogin(String userLogin) { + this.userLogin = userLogin; + return this; + } + + public Long getIssueFilterId() { + return issueFilterId; + } + + public IssueFilterFavouriteDto setIssueFilterId(Long issueFilterId) { + this.issueFilterId = issueFilterId; + return this; + } + + public Date getCreatedAt() { + return createdAt; + } + + public IssueFilterFavouriteDto setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + return this; + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/issue/IssueFilterFavouriteMapper.java b/sonar-db/src/main/java/org/sonar/db/issue/IssueFilterFavouriteMapper.java new file mode 100644 index 00000000000..62bd124174b --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/issue/IssueFilterFavouriteMapper.java @@ -0,0 +1,41 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.issue; + +import java.util.List; +import javax.annotation.CheckForNull; +import org.apache.ibatis.annotations.Param; + +/** + * @since 3.7 + */ +public interface IssueFilterFavouriteMapper { + + @CheckForNull + IssueFilterFavouriteDto selectById(long id); + + List<IssueFilterFavouriteDto> selectByFilterId(@Param("filterId") long filterId); + + void insert(IssueFilterFavouriteDto filterFavourite); + + void delete(long id); + + void deleteByFilterId(long filterId); +} diff --git a/sonar-db/src/main/java/org/sonar/db/issue/IssueFilterMapper.java b/sonar-db/src/main/java/org/sonar/db/issue/IssueFilterMapper.java new file mode 100644 index 00000000000..50c7cc8912d --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/issue/IssueFilterMapper.java @@ -0,0 +1,47 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.issue; + +import java.util.List; +import javax.annotation.CheckForNull; + +/** + * @since 3.7 + */ +public interface IssueFilterMapper { + + @CheckForNull + IssueFilterDto selectById(long id); + + List<IssueFilterDto> selectByUser(String user); + + List<IssueFilterDto> selectFavoriteFiltersByUser(String user); + + List<IssueFilterDto> selectSharedFilters(); + + IssueFilterDto selectProvidedFilterByName(String name); + + void insert(IssueFilterDto filter); + + void update(IssueFilterDto filter); + + void delete(long id); + +} diff --git a/sonar-db/src/main/java/org/sonar/db/issue/IssueMapper.java b/sonar-db/src/main/java/org/sonar/db/issue/IssueMapper.java new file mode 100644 index 00000000000..eda8b2ef7ba --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/issue/IssueMapper.java @@ -0,0 +1,42 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.issue; + +import java.util.List; +import java.util.Set; + +public interface IssueMapper { + + IssueDto selectByKey(String key); + + List<IssueDto> selectNonClosedByComponentUuid(String componentUuid); + + Set<String> selectComponentUuidsOfOpenIssuesForProjectUuid(String projectUuid); + + List<IssueDto> selectByKeys(List<String> keys); + + List<IssueDto> selectByActionPlan(String actionPlan); + + void insert(IssueDto issue); + + int update(IssueDto issue); + + int updateIfBeforeSelectedDate(IssueDto issue); +} diff --git a/sonar-db/src/main/java/org/sonar/db/issue/package-info.java b/sonar-db/src/main/java/org/sonar/db/issue/package-info.java new file mode 100644 index 00000000000..472eca27cae --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/issue/package-info.java @@ -0,0 +1,24 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.issue; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/sonar-db/src/main/java/org/sonar/db/loadedtemplate/LoadedTemplateDao.java b/sonar-db/src/main/java/org/sonar/db/loadedtemplate/LoadedTemplateDao.java new file mode 100644 index 00000000000..ccdb5c45101 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/loadedtemplate/LoadedTemplateDao.java @@ -0,0 +1,65 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.loadedtemplate; + +import org.apache.ibatis.session.SqlSession; +import org.sonar.db.Dao; +import org.sonar.db.DbSession; +import org.sonar.db.MyBatis; + +public class LoadedTemplateDao implements Dao { + + private MyBatis mybatis; + + public LoadedTemplateDao(MyBatis mybatis) { + this.mybatis = mybatis; + } + + public int countByTypeAndKey(String type, String key) { + SqlSession session = mybatis.openSession(false); + try { + return countByTypeAndKey(type, key, session); + } finally { + MyBatis.closeQuietly(session); + } + } + + public int countByTypeAndKey(String type, String key, SqlSession session) { + return session.getMapper(LoadedTemplateMapper.class).countByTypeAndKey(type, key); + } + + public void insert(LoadedTemplateDto loadedTemplateDto) { + SqlSession session = mybatis.openSession(false); + try { + insert(loadedTemplateDto, session); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + public void insert(LoadedTemplateDto loadedTemplateDto, SqlSession session) { + session.getMapper(LoadedTemplateMapper.class).insert(loadedTemplateDto); + } + + public void delete(DbSession session, String type, String key) { + session.getMapper(LoadedTemplateMapper.class).delete(type, key); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/loadedtemplate/LoadedTemplateDto.java b/sonar-db/src/main/java/org/sonar/db/loadedtemplate/LoadedTemplateDto.java new file mode 100644 index 00000000000..36300281c96 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/loadedtemplate/LoadedTemplateDto.java @@ -0,0 +1,89 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.loadedtemplate; + +import com.google.common.base.Objects; + +public final class LoadedTemplateDto { + + public static final String DASHBOARD_TYPE = "DASHBOARD"; + public static final String FILTER_TYPE = "FILTER"; + public static final String QUALITY_PROFILE_TYPE = "QUALITY_PROFILE"; + public static final String PERMISSION_TEMPLATE_TYPE = "PERM_TEMPLATE"; + public static final String QUALITY_GATE_TYPE = "QUALITY_GATE"; + public static final String ONE_SHOT_TASK_TYPE = "ONE_SHOT_TASK"; + public static final String ISSUE_FILTER_TYPE = "ISSUE_FILTER"; + + private Long id; + private String key; + private String type; + + public LoadedTemplateDto() { + } + + public LoadedTemplateDto(String key, String type) { + this.key = key; + this.type = type; + } + + public Long getId() { + return id; + } + + public LoadedTemplateDto setId(Long l) { + this.id = l; + return this; + } + + public String getKey() { + return key; + } + + public LoadedTemplateDto setKey(String key) { + this.key = key; + return this; + } + + public String getType() { + return type; + } + + public LoadedTemplateDto setType(String type) { + this.type = type; + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + LoadedTemplateDto other = (LoadedTemplateDto) o; + return Objects.equal(id, other.id) && Objects.equal(key, other.key) && Objects.equal(type, other.type); + } + + @Override + public int hashCode() { + return id != null ? id.hashCode() : 0; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/loadedtemplate/LoadedTemplateMapper.java b/sonar-db/src/main/java/org/sonar/db/loadedtemplate/LoadedTemplateMapper.java new file mode 100644 index 00000000000..af8ace065bd --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/loadedtemplate/LoadedTemplateMapper.java @@ -0,0 +1,31 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.loadedtemplate; + +import org.apache.ibatis.annotations.Param; + +public interface LoadedTemplateMapper { + + int countByTypeAndKey(@Param("type") String type, @Param("key") String key); + + void insert(LoadedTemplateDto template); + + void delete(@Param("type") String type, @Param("key") String key); +} diff --git a/sonar-db/src/main/java/org/sonar/db/loadedtemplate/package-info.java b/sonar-db/src/main/java/org/sonar/db/loadedtemplate/package-info.java new file mode 100644 index 00000000000..2dff941c724 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/loadedtemplate/package-info.java @@ -0,0 +1,24 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.loadedtemplate; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/sonar-db/src/main/java/org/sonar/db/measure/CustomMeasureDto.java b/sonar-db/src/main/java/org/sonar/db/measure/CustomMeasureDto.java new file mode 100644 index 00000000000..e7387d34cb9 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/measure/CustomMeasureDto.java @@ -0,0 +1,114 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.measure; + +public class CustomMeasureDto { + private long id; + private int metricId; + private String componentUuid; + private double value; + private String textValue; + private String userLogin; + private String description; + private long createdAt; + private long updatedAt; + + public String getDescription() { + return description; + } + + public CustomMeasureDto setDescription(String description) { + this.description = description; + return this; + } + + public String getUserLogin() { + return userLogin; + } + + public CustomMeasureDto setUserLogin(String userLogin) { + this.userLogin = userLogin; + return this; + } + + public String getTextValue() { + return textValue; + } + + public CustomMeasureDto setTextValue(String textValue) { + this.textValue = textValue; + return this; + } + + public double getValue() { + return value; + } + + public CustomMeasureDto setValue(double value) { + this.value = value; + return this; + } + + public int getMetricId() { + return metricId; + } + + public CustomMeasureDto setMetricId(int metricId) { + this.metricId = metricId; + return this; + } + + public long getId() { + return id; + } + + public CustomMeasureDto setId(long id) { + this.id = id; + return this; + } + + public long getUpdatedAt() { + return updatedAt; + } + + public CustomMeasureDto setUpdatedAt(long updatedAt) { + this.updatedAt = updatedAt; + return this; + } + + public long getCreatedAt() { + return createdAt; + } + + public CustomMeasureDto setCreatedAt(long createdAt) { + this.createdAt = createdAt; + return this; + } + + public String getComponentUuid() { + return componentUuid; + } + + public CustomMeasureDto setComponentUuid(String componentUuid) { + this.componentUuid = componentUuid; + return this; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/measure/CustomMeasureMapper.java b/sonar-db/src/main/java/org/sonar/db/measure/CustomMeasureMapper.java new file mode 100644 index 00000000000..e5f46294633 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/measure/CustomMeasureMapper.java @@ -0,0 +1,47 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.measure; + +import java.util.List; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.session.RowBounds; + +public interface CustomMeasureMapper { + void insert(CustomMeasureDto customMeasure); + + void update(CustomMeasureDto customMeasure); + + void delete(long id); + + void deleteByMetricIds(@Param("metricIds") List<Integer> metricIds); + + CustomMeasureDto selectById(long id); + + List<CustomMeasureDto> selectByMetricId(int id); + + List<CustomMeasureDto> selectByComponentUuid(String s); + + List<CustomMeasureDto> selectByComponentUuid(String s, RowBounds rowBounds); + + int countByComponentUuid(String componentUuid); + + int countByComponentIdAndMetricId(@Param("componentUuid") String componentUuid, @Param("metricId") int metricId); +} diff --git a/sonar-db/src/main/java/org/sonar/db/measure/MeasureDto.java b/sonar-db/src/main/java/org/sonar/db/measure/MeasureDto.java new file mode 100644 index 00000000000..0ba16182f0e --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/measure/MeasureDto.java @@ -0,0 +1,268 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.measure; + +import com.google.common.base.Objects; +import java.nio.charset.StandardCharsets; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; + +public class MeasureDto { + private static final String INDEX_SHOULD_BE_IN_RANGE_FROM_1_TO_5 = "Index should be in range from 1 to 5"; + private static final int MAX_TEXT_VALUE_LENGTH = 4000; + + private Long id; + private Double value; + private String textValue; + private byte[] dataValue; + private Double variation1; + private Double variation2; + private Double variation3; + private Double variation4; + private Double variation5; + private String alertStatus; + private String alertText; + private String description; + + private Long componentId; + private Long snapshotId; + private Integer metricId; + private Integer ruleId; + private Integer characteristicId; + private Integer personId; + + // TODO to delete – not in db + private String metricKey; + private String componentKey; + + public Long getId() { + return id; + } + + public MeasureDto setId(Long id) { + this.id = id; + return this; + } + + @CheckForNull + public Double getValue() { + return value; + } + + public MeasureDto setValue(@Nullable Double value) { + this.value = value; + return this; + } + + @CheckForNull + public String getData() { + if (dataValue != null) { + return new String(dataValue, StandardCharsets.UTF_8); + } + return textValue; + } + + public MeasureDto setData(@Nullable String data) { + if (data == null) { + this.textValue = null; + this.dataValue = null; + } else if (data.length() > MAX_TEXT_VALUE_LENGTH) { + this.textValue = null; + this.dataValue = data.getBytes(StandardCharsets.UTF_8); + } else { + this.textValue = data; + this.dataValue = null; + } + + return this; + } + + @CheckForNull + public Double getVariation(int index) { + switch (index) { + case 1: + return variation1; + case 2: + return variation2; + case 3: + return variation3; + case 4: + return variation4; + case 5: + return variation5; + default: + throw new IndexOutOfBoundsException(INDEX_SHOULD_BE_IN_RANGE_FROM_1_TO_5); + } + } + + public MeasureDto setVariation(int index, @Nullable Double d) { + switch (index) { + case 1: + variation1 = d; + break; + case 2: + variation2 = d; + break; + case 3: + variation3 = d; + break; + case 4: + variation4 = d; + break; + case 5: + variation5 = d; + break; + default: + throw new IndexOutOfBoundsException(INDEX_SHOULD_BE_IN_RANGE_FROM_1_TO_5); + } + return this; + } + + @CheckForNull + public String getAlertStatus() { + return alertStatus; + } + + public MeasureDto setAlertStatus(@Nullable String alertStatus) { + this.alertStatus = alertStatus; + return this; + } + + @CheckForNull + public String getAlertText() { + return alertText; + } + + public MeasureDto setAlertText(@Nullable String alertText) { + this.alertText = alertText; + return this; + } + + @CheckForNull + public String getDescription() { + return description; + } + + public MeasureDto setDescription(@Nullable String description) { + this.description = description; + return this; + } + + public Long getComponentId() { + return componentId; + } + + public MeasureDto setComponentId(Long componentId) { + this.componentId = componentId; + return this; + } + + public Integer getMetricId() { + return metricId; + } + + public MeasureDto setMetricId(Integer metricId) { + this.metricId = metricId; + return this; + } + + public Long getSnapshotId() { + return snapshotId; + } + + public MeasureDto setSnapshotId(Long snapshotId) { + this.snapshotId = snapshotId; + return this; + } + + @CheckForNull + public Integer getRuleId() { + return ruleId; + } + + public MeasureDto setRuleId(@Nullable Integer ruleId) { + this.ruleId = ruleId; + return this; + } + + public Integer getCharacteristicId() { + return characteristicId; + } + + public MeasureDto setCharacteristicId(@Nullable Integer characteristicId) { + this.characteristicId = characteristicId; + return this; + } + + @CheckForNull + public Integer getPersonId() { + return personId; + } + + public MeasureDto setPersonId(@Nullable Integer personId) { + this.personId = personId; + return this; + } + + public String getMetricKey() { + return metricKey; + } + + public MeasureDto setMetricKey(String metricKey) { + this.metricKey = metricKey; + return this; + } + + public String getComponentKey() { + return componentKey; + } + + public MeasureDto setComponentKey(String componentKey) { + this.componentKey = componentKey; + return this; + } + + @Override + public String toString() { + return Objects.toStringHelper(this) + .add("id", id) + .add("value", value) + .add("textValue", textValue) + .add("dataValue", dataValue) + .add("variation1", variation1) + .add("variation2", variation2) + .add("variation3", variation3) + .add("variation4", variation4) + .add("variation5", variation5) + .add("alertStatus", alertStatus) + .add("alertText", alertText) + .add("description", description) + .add("componentId", componentId) + .add("snapshotId", snapshotId) + .add("metricId", metricId) + .add("ruleId", ruleId) + .add("characteristicId", characteristicId) + .add("personId", personId) + .add("metricKey", metricKey) + .add("componentKey", componentKey) + .toString(); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/measure/MeasureFilterDao.java b/sonar-db/src/main/java/org/sonar/db/measure/MeasureFilterDao.java new file mode 100644 index 00000000000..50d0bad2f53 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/measure/MeasureFilterDao.java @@ -0,0 +1,52 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.measure; + +import org.apache.ibatis.session.SqlSession; +import org.sonar.db.MyBatis; + +public class MeasureFilterDao { + private MyBatis mybatis; + + public MeasureFilterDao(MyBatis mybatis) { + this.mybatis = mybatis; + } + + public MeasureFilterDto findSystemFilterByName(String name) { + SqlSession session = mybatis.openSession(false); + try { + MeasureFilterMapper mapper = session.getMapper(MeasureFilterMapper.class); + return mapper.findSystemFilterByName(name); + } finally { + MyBatis.closeQuietly(session); + } + } + + public void insert(MeasureFilterDto filter) { + SqlSession session = mybatis.openSession(false); + MeasureFilterMapper mapper = session.getMapper(MeasureFilterMapper.class); + try { + mapper.insert(filter); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/measure/MeasureFilterDto.java b/sonar-db/src/main/java/org/sonar/db/measure/MeasureFilterDto.java new file mode 100644 index 00000000000..f693d815790 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/measure/MeasureFilterDto.java @@ -0,0 +1,109 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.measure; + +import java.util.Date; +import javax.annotation.Nullable; + +/** + * @since 3.4 + */ +public class MeasureFilterDto { + private Long id; + private String name; + private Long userId; + private Boolean shared; + private String description; + private String data; + private Date createdAt; + private Date updatedAt; + + public Long getId() { + return id; + } + + public MeasureFilterDto setId(Long id) { + this.id = id; + return this; + } + + public String getName() { + return name; + } + + public MeasureFilterDto setName(String name) { + this.name = name; + return this; + } + + public Long getUserId() { + return userId; + } + + public MeasureFilterDto setUserId(@Nullable Long userId) { + this.userId = userId; + return this; + } + + public Boolean isShared() { + return shared; + } + + public MeasureFilterDto setShared(@Nullable Boolean shared) { + this.shared = shared; + return this; + } + + public String getDescription() { + return description; + } + + public MeasureFilterDto setDescription(@Nullable String description) { + this.description = description; + return this; + } + + public String getData() { + return data; + } + + public MeasureFilterDto setData(String data) { + this.data = data; + return this; + } + + public Date getCreatedAt() { + return createdAt; + } + + public MeasureFilterDto setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + return this; + } + + public Date getUpdatedAt() { + return updatedAt; + } + + public MeasureFilterDto setUpdatedAt(Date updatedAt) { + this.updatedAt = updatedAt; + return this; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/measure/MeasureFilterMapper.java b/sonar-db/src/main/java/org/sonar/db/measure/MeasureFilterMapper.java new file mode 100644 index 00000000000..ed0c51d3dc2 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/measure/MeasureFilterMapper.java @@ -0,0 +1,29 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.measure; + +/** + * @since 3.4 + */ +public interface MeasureFilterMapper { + MeasureFilterDto findSystemFilterByName(String name); + + void insert(MeasureFilterDto filter); +} diff --git a/sonar-db/src/main/java/org/sonar/db/measure/MeasureMapper.java b/sonar-db/src/main/java/org/sonar/db/measure/MeasureMapper.java new file mode 100644 index 00000000000..8abcea4d7cf --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/measure/MeasureMapper.java @@ -0,0 +1,44 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.measure; + +import java.util.List; +import javax.annotation.CheckForNull; +import org.apache.ibatis.annotations.Param; + +public interface MeasureMapper { + + MeasureDto selectByKey(@Param("componentKey") String componentKey, @Param("metricKey") String metricKey); + + List<MeasureDto> selectByComponentAndMetrics(@Param("componentKey") String componentKey, @Param("metricKeys") List<String> metricKeys); + + @CheckForNull + MeasureDto selectByComponentAndMetric(@Param("componentKey") String componentKey, @Param("metricKey") String metricKey); + + List<PastMeasureDto> selectByComponentUuidAndProjectSnapshotIdAndStatusAndMetricIds(@Param("componentUuid") String componentuuid, @Param("rootSnapshotId") long rootSnapshotId, + @Param("metricIds") List<Integer> metricIds, @Param("status") String status); + + long countByComponentAndMetric(@Param("componentKey") String componentKey, @Param("metricKey") String metricKey); + + void insert(MeasureDto measureDto); + + List<String> selectMetricKeysForSnapshot(@Param("snapshotId") long snapshotId); +} diff --git a/sonar-db/src/main/java/org/sonar/db/measure/PastMeasureDto.java b/sonar-db/src/main/java/org/sonar/db/measure/PastMeasureDto.java new file mode 100644 index 00000000000..f82099b6e03 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/measure/PastMeasureDto.java @@ -0,0 +1,97 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.measure; + +import java.util.Objects; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; + +public class PastMeasureDto { + + private Long id; + private Double value; + private Integer metricId; + private Integer ruleId; + private Integer characteristicId; + private Integer personId; + + public Long getId() { + return id; + } + + public PastMeasureDto setId(Long id) { + this.id = id; + return this; + } + + public double getValue() { + Objects.requireNonNull(value); + return value; + } + + public PastMeasureDto setValue(@Nullable Double value) { + this.value = value; + return this; + } + + public boolean hasValue() { + return value != null; + } + + public Integer getMetricId() { + return metricId; + } + + public PastMeasureDto setMetricId(Integer metricId) { + this.metricId = metricId; + return this; + } + + @CheckForNull + public Integer getCharacteristicId() { + return characteristicId; + } + + public PastMeasureDto setCharacteristicId(@Nullable Integer characteristicId) { + this.characteristicId = characteristicId; + return this; + } + + @CheckForNull + public Integer getPersonId() { + return personId; + } + + public PastMeasureDto setPersonId(@Nullable Integer personId) { + this.personId = personId; + return this; + } + + @CheckForNull + public Integer getRuleId() { + return ruleId; + } + + public PastMeasureDto setRuleId(@Nullable Integer ruleId) { + this.ruleId = ruleId; + return this; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/measure/package-info.java b/sonar-db/src/main/java/org/sonar/db/measure/package-info.java new file mode 100644 index 00000000000..4485a31899b --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/measure/package-info.java @@ -0,0 +1,24 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.measure; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/sonar-db/src/main/java/org/sonar/db/metric/MetricDto.java b/sonar-db/src/main/java/org/sonar/db/metric/MetricDto.java new file mode 100644 index 00000000000..9822dabaa84 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/metric/MetricDto.java @@ -0,0 +1,199 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.metric; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; + +public class MetricDto { + + private Integer id; + + private String kee; + + private String shortName; + + private String valueType; + + private String description; + + private String domain; + + private int direction; + + private boolean qualitative; + + private boolean userManaged; + + private Double worstValue; + + private Double bestValue; + + private boolean optimizedBestValue; + + private boolean hidden; + + private boolean deleteHistoricalData; + + private boolean enabled; + + public Integer getId() { + return id; + } + + public MetricDto setId(Integer id) { + this.id = id; + return this; + } + + public String getKey() { + return kee; + } + + public MetricDto setKey(String name) { + this.kee = name; + return this; + } + + public String getShortName() { + return shortName; + } + + public MetricDto setShortName(String shortName) { + this.shortName = shortName; + return this; + } + + public String getValueType() { + return valueType; + } + + public MetricDto setValueType(String valueType) { + this.valueType = valueType; + return this; + } + + /** + * @return null for manual metrics + */ + @CheckForNull + public String getDescription() { + return description; + } + + public MetricDto setDescription(@Nullable String description) { + this.description = description; + return this; + } + + public String getDomain() { + return domain; + } + + public MetricDto setDomain(String domain) { + this.domain = domain; + return this; + } + + public int getDirection() { + return direction; + } + + public MetricDto setDirection(int direction) { + this.direction = direction; + return this; + } + + public boolean isQualitative() { + return qualitative; + } + + public MetricDto setQualitative(boolean qualitative) { + this.qualitative = qualitative; + return this; + } + + public boolean isUserManaged() { + return userManaged; + } + + public MetricDto setUserManaged(boolean userManaged) { + this.userManaged = userManaged; + return this; + } + + @CheckForNull + public Double getWorstValue() { + return worstValue; + } + + public MetricDto setWorstValue(@Nullable Double worstValue) { + this.worstValue = worstValue; + return this; + } + + @CheckForNull + public Double getBestValue() { + return bestValue; + } + + public MetricDto setBestValue(@Nullable Double bestValue) { + this.bestValue = bestValue; + return this; + } + + public boolean isOptimizedBestValue() { + return optimizedBestValue; + } + + public MetricDto setOptimizedBestValue(boolean optimizedBestValue) { + this.optimizedBestValue = optimizedBestValue; + return this; + } + + public boolean isHidden() { + return hidden; + } + + public MetricDto setHidden(boolean hidden) { + this.hidden = hidden; + return this; + } + + public boolean isDeleteHistoricalData() { + return deleteHistoricalData; + } + + public MetricDto setDeleteHistoricalData(boolean deleteHistoricalData) { + this.deleteHistoricalData = deleteHistoricalData; + return this; + } + + public boolean isEnabled() { + return enabled; + } + + public MetricDto setEnabled(boolean enabled) { + this.enabled = enabled; + return this; + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/metric/MetricMapper.java b/sonar-db/src/main/java/org/sonar/db/metric/MetricMapper.java new file mode 100644 index 00000000000..68ff2ccf0b4 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/metric/MetricMapper.java @@ -0,0 +1,58 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.metric; + +import java.util.List; +import java.util.Map; +import javax.annotation.Nullable; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.session.RowBounds; + +public interface MetricMapper { + + MetricDto selectById(long id); + + List<MetricDto> selectByIds(@Param("ids") List<Integer> ids); + + MetricDto selectByKey(@Param("key") String key); + + List<MetricDto> selectByKeys(@Param("keys") List<String> keys); + + List<MetricDto> selectAllEnabled(); + + List<MetricDto> selectAllEnabled(Map<String, Object> properties, RowBounds rowBounds); + + void insert(MetricDto dto); + + List<String> selectDomains(); + + void disableByIds(@Param("ids") List<Integer> ids); + + void disableByKey(@Param("key") String key); + + int countEnabled(@Param("isCustom") @Nullable Boolean isCustom); + + void update(MetricDto metric); + + List<MetricDto> selectAvailableCustomMetricsByComponentUuid(String projectUuid); + + List<MetricDto> selectAvailableCustomMetricsByComponentKey(String projectKey); +} diff --git a/sonar-db/src/main/java/org/sonar/db/metric/package-info.java b/sonar-db/src/main/java/org/sonar/db/metric/package-info.java new file mode 100644 index 00000000000..b0c6b63660b --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/metric/package-info.java @@ -0,0 +1,24 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.metric; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/sonar-db/src/main/java/org/sonar/db/notification/NotificationQueueDao.java b/sonar-db/src/main/java/org/sonar/db/notification/NotificationQueueDao.java new file mode 100644 index 00000000000..b82ba01dd09 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/notification/NotificationQueueDao.java @@ -0,0 +1,83 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.notification; + +import java.util.Collections; +import java.util.List; +import org.apache.ibatis.session.SqlSession; +import org.sonar.db.DbSession; +import org.sonar.db.MyBatis; + +public class NotificationQueueDao { + + private final MyBatis mybatis; + + public NotificationQueueDao(MyBatis mybatis) { + this.mybatis = mybatis; + } + + public void insert(List<NotificationQueueDto> dtos) { + DbSession session = mybatis.openSession(true); + NotificationQueueMapper mapper = session.getMapper(NotificationQueueMapper.class); + try { + for (NotificationQueueDto dto : dtos) { + mapper.insert(dto); + } + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + public void delete(List<NotificationQueueDto> dtos) { + DbSession session = mybatis.openSession(true); + NotificationQueueMapper mapper = session.getMapper(NotificationQueueMapper.class); + try { + for (NotificationQueueDto dto : dtos) { + mapper.delete(dto.getId()); + } + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + public List<NotificationQueueDto> findOldest(int count) { + if (count < 1) { + return Collections.emptyList(); + } + SqlSession session = mybatis.openSession(false); + try { + return session.getMapper(NotificationQueueMapper.class).findOldest(count); + } finally { + MyBatis.closeQuietly(session); + } + } + + public long count() { + SqlSession session = mybatis.openSession(false); + try { + return session.getMapper(NotificationQueueMapper.class).count(); + } finally { + MyBatis.closeQuietly(session); + } + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/notification/NotificationQueueDto.java b/sonar-db/src/main/java/org/sonar/db/notification/NotificationQueueDto.java new file mode 100644 index 00000000000..44a5602bb64 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/notification/NotificationQueueDto.java @@ -0,0 +1,97 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.notification; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; +import org.sonar.api.notifications.Notification; +import org.sonar.api.utils.SonarException; + +/** + * @since 3.7.1 + */ +public class NotificationQueueDto { + + private Long id; + private byte[] data; + + public Long getId() { + return id; + } + + public NotificationQueueDto setId(Long id) { + this.id = id; + return this; + } + + public byte[] getData() { + return data; + } + + public NotificationQueueDto setData(byte[] data) { + this.data = data; + return this; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); + } + + public static NotificationQueueDto toNotificationQueueDto(Notification notification) { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + try { + ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); + objectOutputStream.writeObject(notification); + objectOutputStream.close(); + return new NotificationQueueDto().setData(byteArrayOutputStream.toByteArray()); + + } catch (IOException e) { + throw new SonarException("Unable to write notification", e); + + } finally { + IOUtils.closeQuietly(byteArrayOutputStream); + } + } + + public Notification toNotification() throws IOException, ClassNotFoundException { + if (this.data == null) { + return null; + } + ByteArrayInputStream byteArrayInputStream = null; + try { + byteArrayInputStream = new ByteArrayInputStream(this.data); + ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream); + Object result = objectInputStream.readObject(); + objectInputStream.close(); + return (Notification) result; + } finally { + IOUtils.closeQuietly(byteArrayInputStream); + } + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/notification/NotificationQueueMapper.java b/sonar-db/src/main/java/org/sonar/db/notification/NotificationQueueMapper.java new file mode 100644 index 00000000000..dead94fc4ea --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/notification/NotificationQueueMapper.java @@ -0,0 +1,38 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.notification; + +import java.util.List; + +/** + * @since 3.7.1 + */ +public interface NotificationQueueMapper { + + void insert(NotificationQueueDto actionPlanDto); + + void delete(long id); + + List<NotificationQueueDto> findOldest(int count); + + long count(); + +} diff --git a/sonar-db/src/main/java/org/sonar/db/notification/package-info.java b/sonar-db/src/main/java/org/sonar/db/notification/package-info.java new file mode 100644 index 00000000000..a6d74836ec6 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/notification/package-info.java @@ -0,0 +1,24 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.notification; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/sonar-db/src/main/java/org/sonar/db/package-info.java b/sonar-db/src/main/java/org/sonar/db/package-info.java new file mode 100644 index 00000000000..d2f73de8eb1 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/package-info.java @@ -0,0 +1,24 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/sonar-db/src/main/java/org/sonar/db/permission/GroupWithPermissionDto.java b/sonar-db/src/main/java/org/sonar/db/permission/GroupWithPermissionDto.java new file mode 100644 index 00000000000..2dbcd04203c --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/permission/GroupWithPermissionDto.java @@ -0,0 +1,68 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.permission; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.sonar.core.permission.GroupWithPermission; + +public class GroupWithPermissionDto { + + private String name; + private String permission; + private String description; + + public String getName() { + return name; + } + + public GroupWithPermissionDto setName(String name) { + this.name = name; + return this; + } + + @CheckForNull + public String getPermission() { + return permission; + } + + public GroupWithPermissionDto setPermission(@Nullable String permission) { + this.permission = permission; + return this; + } + + @CheckForNull + public String getDescription() { + return description; + } + + public GroupWithPermissionDto setDescription(@Nullable String description) { + this.description = description; + return this; + } + + public GroupWithPermission toGroupWithPermission() { + return new GroupWithPermission() + .setName(name) + .setDescription(description) + .hasPermission(permission != null); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/permission/PermissionDao.java b/sonar-db/src/main/java/org/sonar/db/permission/PermissionDao.java new file mode 100644 index 00000000000..e6a1508e222 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/permission/PermissionDao.java @@ -0,0 +1,91 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.permission; + +import com.google.common.annotations.VisibleForTesting; +import java.util.List; +import java.util.Map; +import javax.annotation.Nullable; +import org.apache.ibatis.session.RowBounds; +import org.apache.ibatis.session.SqlSession; +import org.sonar.api.security.DefaultGroups; +import org.sonar.api.server.ServerSide; +import org.sonar.db.MyBatis; + +import static com.google.common.collect.Maps.newHashMap; + +@ServerSide +public class PermissionDao { + + private static final String QUERY_PARAMETER = "query"; + private static final String COMPONENT_ID_PARAMETER = "componentId"; + + private final MyBatis myBatis; + + public PermissionDao(MyBatis myBatis) { + this.myBatis = myBatis; + } + + /** + * @return a paginated list of users. + */ + public List<UserWithPermissionDto> selectUsers(PermissionQuery query, @Nullable Long componentId, int offset, int limit) { + SqlSession session = myBatis.openSession(false); + try { + Map<String, Object> params = newHashMap(); + params.put(QUERY_PARAMETER, query); + params.put(COMPONENT_ID_PARAMETER, componentId); + + return mapper(session).selectUsers(params, new RowBounds(offset, limit)); + } finally { + MyBatis.closeQuietly(session); + } + } + + @VisibleForTesting + List<UserWithPermissionDto> selectUsers(PermissionQuery query, @Nullable Long componentId) { + return selectUsers(query, componentId, 0, Integer.MAX_VALUE); + } + + /** + * 'Anyone' group is not returned when it has not the asked permission. + * Membership parameter from query is not taking into account in order to deal more easily with the 'Anyone' group + * @return a non paginated list of groups. + */ + public List<GroupWithPermissionDto> selectGroups(PermissionQuery query, @Nullable Long componentId) { + SqlSession session = myBatis.openSession(false); + try { + Map<String, Object> params = newHashMap(); + params.put(QUERY_PARAMETER, query); + params.put(COMPONENT_ID_PARAMETER, componentId); + params.put("anyoneGroup", DefaultGroups.ANYONE); + + return mapper(session).selectGroups(params); + } finally { + MyBatis.closeQuietly(session); + } + } + + private PermissionMapper mapper(SqlSession session) { + return session.getMapper(PermissionMapper.class); + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/permission/PermissionFacade.java b/sonar-db/src/main/java/org/sonar/db/permission/PermissionFacade.java new file mode 100644 index 00000000000..116e2e2634f --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/permission/PermissionFacade.java @@ -0,0 +1,248 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.permission; + +import com.google.common.annotations.VisibleForTesting; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import javax.annotation.Nullable; +import org.apache.commons.lang.StringUtils; +import org.sonar.api.config.Settings; +import org.sonar.api.security.DefaultGroups; +import org.sonar.api.server.ServerSide; +import org.sonar.db.DbSession; +import org.sonar.db.component.ResourceDao; +import org.sonar.db.component.ResourceDto; +import org.sonar.db.user.GroupDto; +import org.sonar.db.user.GroupRoleDto; +import org.sonar.db.user.RoleDao; +import org.sonar.db.user.UserDao; +import org.sonar.db.user.UserRoleDto; + +/** + * This facade wraps db operations related to permissions + * + * Should be removed when batch will no more create permission, and be replaced by a new PermissionService in module server (probably be a merge with InternalPermissionService) + * + * WARNING, this class is called by Views to apply default permission template on new views + */ +@ServerSide +public class PermissionFacade { + + private final RoleDao roleDao; + private final UserDao userDao; + private final PermissionTemplateDao permissionTemplateDao; + private final Settings settings; + private final ResourceDao resourceDao; + + public PermissionFacade(RoleDao roleDao, UserDao userDao, ResourceDao resourceDao, PermissionTemplateDao permissionTemplateDao, Settings settings) { + this.roleDao = roleDao; + this.userDao = userDao; + this.resourceDao = resourceDao; + this.permissionTemplateDao = permissionTemplateDao; + this.settings = settings; + } + + /** + * @param updateProjectAuthorizationDate is false when doing bulk action in order to not update the same project multiple times for nothing + */ + private void insertUserPermission(@Nullable Long resourceId, Long userId, String permission, boolean updateProjectAuthorizationDate, DbSession session) { + UserRoleDto userRoleDto = new UserRoleDto() + .setRole(permission) + .setUserId(userId) + .setResourceId(resourceId); + if (updateProjectAuthorizationDate) { + updateProjectAuthorizationDate(resourceId, session); + } + roleDao.insertUserRole(userRoleDto, session); + } + + public void insertUserPermission(@Nullable Long resourceId, Long userId, String permission, DbSession session) { + insertUserPermission(resourceId, userId, permission, true, session); + } + + public void deleteUserPermission(@Nullable Long resourceId, Long userId, String permission, DbSession session) { + UserRoleDto userRoleDto = new UserRoleDto() + .setRole(permission) + .setUserId(userId) + .setResourceId(resourceId); + updateProjectAuthorizationDate(resourceId, session); + roleDao.deleteUserRole(userRoleDto, session); + } + + private void insertGroupPermission(@Nullable Long resourceId, @Nullable Long groupId, String permission, boolean updateProjectAuthorizationDate, DbSession session) { + GroupRoleDto groupRole = new GroupRoleDto() + .setRole(permission) + .setGroupId(groupId) + .setResourceId(resourceId); + updateProjectAuthorizationDate(resourceId, session); + roleDao.insertGroupRole(groupRole, session); + } + + public void insertGroupPermission(@Nullable Long resourceId, @Nullable Long groupId, String permission, DbSession session) { + insertGroupPermission(resourceId, groupId, permission, true, session); + } + + public void insertGroupPermission(@Nullable Long resourceId, String groupName, String permission, DbSession session) { + if (DefaultGroups.isAnyone(groupName)) { + insertGroupPermission(resourceId, (Long) null, permission, session); + } else { + GroupDto group = userDao.selectGroupByName(groupName, session); + if (group != null) { + insertGroupPermission(resourceId, group.getId(), permission, session); + } + } + } + + public void deleteGroupPermission(@Nullable Long resourceId, @Nullable Long groupId, String permission, DbSession session) { + GroupRoleDto groupRole = new GroupRoleDto() + .setRole(permission) + .setGroupId(groupId) + .setResourceId(resourceId); + updateProjectAuthorizationDate(resourceId, session); + roleDao.deleteGroupRole(groupRole, session); + } + + public void deleteGroupPermission(@Nullable Long resourceId, String groupName, String permission, DbSession session) { + if (DefaultGroups.isAnyone(groupName)) { + deleteGroupPermission(resourceId, (Long) null, permission, session); + } else { + GroupDto group = userDao.selectGroupByName(groupName, session); + if (group != null) { + deleteGroupPermission(resourceId, group.getId(), permission, session); + } + } + } + + /** + * For each modification of permission on a project, update the authorization_updated_at to help ES reindex only relevant changes + */ + private void updateProjectAuthorizationDate(@Nullable Long projectId, DbSession session) { + if (projectId != null) { + resourceDao.updateAuthorizationDate(projectId, session); + } + } + + /** + * Load permission template and load associated collections of users and groups permissions + */ + @VisibleForTesting + PermissionTemplateDto getPermissionTemplateWithPermissions(DbSession session, String templateKey) { + PermissionTemplateDto permissionTemplateDto = permissionTemplateDao.selectTemplateByKey(session, templateKey); + if (permissionTemplateDto == null) { + throw new IllegalArgumentException("Could not retrieve permission template with key " + templateKey); + } + PermissionTemplateDto templateWithPermissions = permissionTemplateDao.selectPermissionTemplate(session, permissionTemplateDto.getKee()); + if (templateWithPermissions == null) { + throw new IllegalArgumentException("Could not retrieve permissions for template with key " + templateKey); + } + return templateWithPermissions; + } + + public void applyPermissionTemplate(DbSession session, String templateKey, Long resourceId) { + PermissionTemplateDto permissionTemplate = getPermissionTemplateWithPermissions(session, templateKey); + updateProjectAuthorizationDate(resourceId, session); + removeAllPermissions(resourceId, session); + List<PermissionTemplateUserDto> usersPermissions = permissionTemplate.getUsersPermissions(); + if (usersPermissions != null) { + for (PermissionTemplateUserDto userPermission : usersPermissions) { + insertUserPermission(resourceId, userPermission.getUserId(), userPermission.getPermission(), false, session); + } + } + List<PermissionTemplateGroupDto> groupsPermissions = permissionTemplate.getGroupsPermissions(); + if (groupsPermissions != null) { + for (PermissionTemplateGroupDto groupPermission : groupsPermissions) { + Long groupId = groupPermission.getGroupId() == null ? null : groupPermission.getGroupId(); + insertGroupPermission(resourceId, groupId, groupPermission.getPermission(), false, session); + } + } + } + + public int countComponentPermissions(DbSession session, Long resourceId) { + return roleDao.countResourceGroupRoles(session, resourceId) + roleDao.countResourceUserRoles(session, resourceId); + } + + protected void removeAllPermissions(Long resourceId, DbSession session) { + roleDao.deleteGroupRolesByResourceId(resourceId, session); + roleDao.deleteUserRolesByResourceId(resourceId, session); + } + + public List<String> selectGroupPermissions(DbSession session, String group, @Nullable Long componentId) { + return roleDao.selectGroupPermissions(session, group, componentId); + } + + public List<String> selectUserPermissions(DbSession session, String user, @Nullable Long componentId) { + return roleDao.selectUserPermissions(session, user, componentId); + } + + public void grantDefaultRoles(DbSession session, Long componentId, String qualifier) { + ResourceDto resource = resourceDao.getResource(componentId, session); + String applicablePermissionTemplateKey = getApplicablePermissionTemplateKey(session, resource.getKey(), qualifier); + applyPermissionTemplate(session, applicablePermissionTemplateKey, componentId); + } + + /** + * Return the permission template for the given componentKey. If no template key pattern match then consider default + * permission template for the resource qualifier. + */ + private String getApplicablePermissionTemplateKey(DbSession session, final String componentKey, String qualifier) { + List<PermissionTemplateDto> allPermissionTemplates = permissionTemplateDao.selectAllPermissionTemplates(session); + List<PermissionTemplateDto> matchingTemplates = new ArrayList<>(); + for (PermissionTemplateDto permissionTemplateDto : allPermissionTemplates) { + String keyPattern = permissionTemplateDto.getKeyPattern(); + if (StringUtils.isNotBlank(keyPattern) && componentKey.matches(keyPattern)) { + matchingTemplates.add(permissionTemplateDto); + } + } + checkAtMostOneMatchForComponentKey(componentKey, matchingTemplates); + if (matchingTemplates.size() == 1) { + return matchingTemplates.get(0).getKee(); + } + String qualifierTemplateKey = settings.getString("sonar.permission.template." + qualifier + ".default"); + if (!StringUtils.isBlank(qualifierTemplateKey)) { + return qualifierTemplateKey; + } + + String defaultTemplateKey = settings.getString("sonar.permission.template.default"); + if (StringUtils.isBlank(defaultTemplateKey)) { + throw new IllegalStateException("At least one default permission template should be defined"); + } + return defaultTemplateKey; + } + + private void checkAtMostOneMatchForComponentKey(final String componentKey, List<PermissionTemplateDto> matchingTemplates) { + if (matchingTemplates.size() > 1) { + StringBuilder templatesNames = new StringBuilder(); + for (Iterator<PermissionTemplateDto> it = matchingTemplates.iterator(); it.hasNext();) { + templatesNames.append("\"").append(it.next().getName()).append("\""); + if (it.hasNext()) { + templatesNames.append(", "); + } + } + throw new IllegalStateException(MessageFormat.format( + "The \"{0}\" key matches multiple permission templates: {1}." + + " A system administrator must update these templates so that only one of them matches the key.", componentKey, + templatesNames.toString())); + } + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/permission/PermissionMapper.java b/sonar-db/src/main/java/org/sonar/db/permission/PermissionMapper.java new file mode 100644 index 00000000000..08c7b3e07c0 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/permission/PermissionMapper.java @@ -0,0 +1,32 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.permission; + +import java.util.List; +import java.util.Map; +import org.apache.ibatis.session.RowBounds; + +public interface PermissionMapper { + + List<UserWithPermissionDto> selectUsers(Map<String, Object> parameters, RowBounds rowBounds); + + List<GroupWithPermissionDto> selectGroups(Map<String, Object> parameters); +} diff --git a/sonar-db/src/main/java/org/sonar/db/permission/PermissionQuery.java b/sonar-db/src/main/java/org/sonar/db/permission/PermissionQuery.java new file mode 100644 index 00000000000..6d1a04a66bb --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/permission/PermissionQuery.java @@ -0,0 +1,199 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.permission; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableSet; +import java.util.Set; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.apache.commons.lang.StringUtils; + +/** + * Query used to get users and groups from a permission + */ +public class PermissionQuery { + + public static final int DEFAULT_PAGE_INDEX = 1; + public static final int DEFAULT_PAGE_SIZE = 100; + + public static final String ANY = "ANY"; + public static final String IN = "IN"; + public static final String OUT = "OUT"; + public static final Set<String> AVAILABLE_MEMBERSHIP = ImmutableSet.of(ANY, IN, OUT); + + private final String permission; + private final String component; + private final String template; + private final String membership; + private final String search; + + // for internal use in MyBatis + final String searchSql; + + // max results per page + private final int pageSize; + + // index of selected page. Start with 1. + private final int pageIndex; + + private PermissionQuery(Builder builder) { + this.permission = builder.permission; + this.component = builder.component; + this.template = builder.template; + this.membership = builder.membership; + this.search = builder.search; + this.searchSql = searchToSql(search); + + this.pageSize = builder.pageSize; + this.pageIndex = builder.pageIndex; + } + + private static String searchToSql(@Nullable String s) { + String sql = null; + if (s != null) { + sql = StringUtils.replace(StringUtils.upperCase(s), "%", "/%"); + sql = StringUtils.replace(sql, "_", "/_"); + sql = "%" + sql + "%"; + } + return sql; + } + + public String permission() { + return permission; + } + + /** + * Used only for permission template + */ + public String template() { + return template; + } + + /** + * Used on project permission + */ + @CheckForNull + public String component() { + return component; + } + + @CheckForNull + public String membership() { + return membership; + } + + @CheckForNull + public String search() { + return search; + } + + public int pageSize() { + return pageSize; + } + + public int pageIndex() { + return pageIndex; + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private String permission; + private String component; + private String template; + private String membership; + private String search; + + private Integer pageIndex = DEFAULT_PAGE_INDEX; + private Integer pageSize = DEFAULT_PAGE_SIZE; + + private Builder() { + } + + public Builder permission(String permission) { + this.permission = permission; + return this; + } + + public Builder template(String template) { + this.template = template; + return this; + } + + public Builder component(@Nullable String component) { + this.component = component; + return this; + } + + public Builder membership(@Nullable String membership) { + this.membership = membership; + return this; + } + + public Builder search(@Nullable String s) { + this.search = StringUtils.defaultIfBlank(s, null); + return this; + } + + public Builder pageSize(@Nullable Integer i) { + this.pageSize = i; + return this; + } + + public Builder pageIndex(@Nullable Integer i) { + this.pageIndex = i; + return this; + } + + private void initMembership() { + if (membership == null) { + membership = PermissionQuery.ANY; + } else { + Preconditions.checkArgument(AVAILABLE_MEMBERSHIP.contains(membership), + "Membership is not valid (got " + membership + "). Availables values are " + AVAILABLE_MEMBERSHIP); + } + } + + private void initPageSize() { + if (pageSize == null) { + pageSize = DEFAULT_PAGE_SIZE; + } + } + + private void initPageIndex() { + if (pageIndex == null) { + pageIndex = DEFAULT_PAGE_INDEX; + } + Preconditions.checkArgument(pageIndex > 0, "Page index must be greater than 0 (got " + pageIndex + ")"); + } + + public PermissionQuery build() { + Preconditions.checkNotNull(permission, "Permission cant be null."); + initMembership(); + initPageIndex(); + initPageSize(); + return new PermissionQuery(this); + } + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateDao.java b/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateDao.java new file mode 100644 index 00000000000..050f19c1cb4 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateDao.java @@ -0,0 +1,275 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.permission; + +import com.google.common.annotations.VisibleForTesting; +import java.text.Normalizer; +import java.util.Date; +import java.util.List; +import java.util.Map; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.apache.commons.lang.time.DateFormatUtils; +import org.apache.ibatis.session.RowBounds; +import org.apache.ibatis.session.SqlSession; +import org.sonar.api.security.DefaultGroups; +import org.sonar.api.utils.System2; +import org.sonar.db.Dao; +import org.sonar.db.DbSession; +import org.sonar.db.MyBatis; + +import static com.google.common.collect.Maps.newHashMap; + +public class PermissionTemplateDao implements Dao { + + public static final String QUERY_PARAMETER = "query"; + public static final String TEMPLATE_ID_PARAMETER = "templateId"; + private final MyBatis myBatis; + private final System2 system; + + public PermissionTemplateDao(MyBatis myBatis, System2 system) { + this.myBatis = myBatis; + this.system = system; + } + + /** + * @return a paginated list of users. + */ + public List<UserWithPermissionDto> selectUsers(PermissionQuery query, Long templateId, int offset, int limit) { + SqlSession session = myBatis.openSession(false); + try { + Map<String, Object> params = newHashMap(); + params.put(QUERY_PARAMETER, query); + params.put(TEMPLATE_ID_PARAMETER, templateId); + return mapper(session).selectUsers(params, new RowBounds(offset, limit)); + } finally { + MyBatis.closeQuietly(session); + } + } + + @VisibleForTesting + List<UserWithPermissionDto> selectUsers(PermissionQuery query, Long templateId) { + return selectUsers(query, templateId, 0, Integer.MAX_VALUE); + } + + /** + * 'Anyone' group is not returned when it has not the asked permission. + * Membership parameter from query is not taking into account in order to deal more easily with the 'Anyone' group. + * @return a non paginated list of groups. + */ + public List<GroupWithPermissionDto> selectGroups(PermissionQuery query, Long templateId) { + SqlSession session = myBatis.openSession(false); + try { + Map<String, Object> params = newHashMap(); + params.put(QUERY_PARAMETER, query); + params.put(TEMPLATE_ID_PARAMETER, templateId); + params.put("anyoneGroup", DefaultGroups.ANYONE); + return mapper(session).selectGroups(params); + } finally { + MyBatis.closeQuietly(session); + } + } + + @CheckForNull + public PermissionTemplateDto selectTemplateByKey(DbSession session, String templateKey) { + return mapper(session).selectByKey(templateKey); + } + + @CheckForNull + public PermissionTemplateDto selectTemplateByKey(String templateKey) { + DbSession session = myBatis.openSession(false); + try { + return selectTemplateByKey(session, templateKey); + } finally { + MyBatis.closeQuietly(session); + } + } + + @CheckForNull + public PermissionTemplateDto selectPermissionTemplate(DbSession session, String templateKey) { + PermissionTemplateDto permissionTemplate = null; + PermissionTemplateMapper mapper = mapper(session); + permissionTemplate = mapper.selectByKey(templateKey); + PermissionTemplateDto templateUsersPermissions = mapper.selectTemplateUsersPermissions(templateKey); + if (templateUsersPermissions != null) { + permissionTemplate.setUsersPermissions(templateUsersPermissions.getUsersPermissions()); + } + PermissionTemplateDto templateGroupsPermissions = mapper.selectTemplateGroupsPermissions(templateKey); + if (templateGroupsPermissions != null) { + permissionTemplate.setGroupsByPermission(templateGroupsPermissions.getGroupsPermissions()); + } + return permissionTemplate; + } + + @CheckForNull + public PermissionTemplateDto selectPermissionTemplate(String templateKey) { + DbSession session = myBatis.openSession(false); + try { + return selectPermissionTemplate(session, templateKey); + } finally { + MyBatis.closeQuietly(session); + } + } + + public List<PermissionTemplateDto> selectAllPermissionTemplates(DbSession session) { + return session.selectList("selectAllPermissionTemplates"); + } + + public List<PermissionTemplateDto> selectAllPermissionTemplates() { + DbSession session = myBatis.openSession(false); + try { + return selectAllPermissionTemplates(session); + } finally { + MyBatis.closeQuietly(session); + } + } + + public PermissionTemplateDto createPermissionTemplate(String templateName, @Nullable String description, @Nullable String keyPattern) { + Date creationDate = now(); + PermissionTemplateDto permissionTemplate = new PermissionTemplateDto() + .setName(templateName) + .setKee(generateTemplateKee(templateName, creationDate)) + .setDescription(description) + .setKeyPattern(keyPattern) + .setCreatedAt(creationDate) + .setUpdatedAt(creationDate); + SqlSession session = myBatis.openSession(false); + try { + mapper(session).insert(permissionTemplate); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + return permissionTemplate; + } + + public void deletePermissionTemplate(Long templateId) { + SqlSession session = myBatis.openSession(false); + try { + PermissionTemplateMapper mapper = mapper(session); + mapper.deleteUsersPermissions(templateId); + mapper.deleteGroupsPermissions(templateId); + mapper.delete(templateId); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + public void updatePermissionTemplate(Long templateId, String templateName, @Nullable String description, @Nullable String keyPattern) { + PermissionTemplateDto permissionTemplate = new PermissionTemplateDto() + .setId(templateId) + .setName(templateName) + .setDescription(description) + .setKeyPattern(keyPattern) + .setUpdatedAt(now()); + SqlSession session = myBatis.openSession(false); + try { + mapper(session).update(permissionTemplate); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + public void addUserPermission(Long templateId, Long userId, String permission) { + PermissionTemplateUserDto permissionTemplateUser = new PermissionTemplateUserDto() + .setTemplateId(templateId) + .setUserId(userId) + .setPermission(permission) + .setCreatedAt(now()) + .setUpdatedAt(now()); + SqlSession session = myBatis.openSession(false); + try { + mapper(session).insertUserPermission(permissionTemplateUser); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + public void removeUserPermission(Long templateId, Long userId, String permission) { + PermissionTemplateUserDto permissionTemplateUser = new PermissionTemplateUserDto() + .setTemplateId(templateId) + .setPermission(permission) + .setUserId(userId); + SqlSession session = myBatis.openSession(false); + try { + mapper(session).deleteUserPermission(permissionTemplateUser); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + public void addGroupPermission(Long templateId, @Nullable Long groupId, String permission) { + PermissionTemplateGroupDto permissionTemplateGroup = new PermissionTemplateGroupDto() + .setTemplateId(templateId) + .setPermission(permission) + .setGroupId(groupId) + .setCreatedAt(now()) + .setUpdatedAt(now()); + SqlSession session = myBatis.openSession(false); + try { + mapper(session).insertGroupPermission(permissionTemplateGroup); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + public void removeGroupPermission(Long templateId, @Nullable Long groupId, String permission) { + PermissionTemplateGroupDto permissionTemplateGroup = new PermissionTemplateGroupDto() + .setTemplateId(templateId) + .setPermission(permission) + .setGroupId(groupId); + SqlSession session = myBatis.openSession(false); + try { + mapper(session).deleteGroupPermission(permissionTemplateGroup); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + /** + * Remove a group from all templates (used when removing a group) + */ + public void removeByGroup(Long groupId, SqlSession session) { + session.getMapper(PermissionTemplateMapper.class).deleteByGroupId(groupId); + } + + private String generateTemplateKee(String name, Date timeStamp) { + if (PermissionTemplateDto.DEFAULT.getName().equals(name)) { + return PermissionTemplateDto.DEFAULT.getKee(); + } + String normalizedName = Normalizer.normalize(name, Normalizer.Form.NFD).replaceAll("[^\\p{ASCII}]", "").replace(" ", "_"); + return normalizedName.toLowerCase() + "_" + DateFormatUtils.format(timeStamp, "yyyyMMdd_HHmmss"); + } + + private Date now() { + return new Date(system.now()); + } + + private PermissionTemplateMapper mapper(SqlSession session) { + return session.getMapper(PermissionTemplateMapper.class); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateDto.java b/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateDto.java new file mode 100644 index 00000000000..68f7c1da41c --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateDto.java @@ -0,0 +1,129 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.permission; + +import java.util.Date; +import java.util.List; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; + +public class PermissionTemplateDto { + + public static final PermissionTemplateDto DEFAULT = new PermissionTemplateDto() + .setName("Default template") + .setKee("default_template") + .setDescription("This permission template will be used as default when no other permission configuration is available"); + + private Long id; + private String name; + private String kee; + private String description; + private String keyPattern; + private List<PermissionTemplateUserDto> usersPermissions; + private List<PermissionTemplateGroupDto> groupsPermissions; + private Date createdAt; + private Date updatedAt; + + public Long getId() { + return id; + } + + public PermissionTemplateDto setId(Long id) { + this.id = id; + return this; + } + + public String getName() { + return name; + } + + public PermissionTemplateDto setName(String name) { + this.name = name; + return this; + } + + public String getKee() { + return kee; + } + + public PermissionTemplateDto setKee(String kee) { + this.kee = kee; + return this; + } + + @CheckForNull + public String getDescription() { + return description; + } + + public PermissionTemplateDto setDescription(@Nullable String description) { + this.description = description; + return this; + } + + @CheckForNull + public String getKeyPattern() { + return keyPattern; + } + + public PermissionTemplateDto setKeyPattern(@Nullable String regexp) { + this.keyPattern = regexp; + return this; + } + + @CheckForNull + public List<PermissionTemplateUserDto> getUsersPermissions() { + return usersPermissions; + } + + public PermissionTemplateDto setUsersPermissions(@Nullable List<PermissionTemplateUserDto> usersPermissions) { + this.usersPermissions = usersPermissions; + return this; + } + + @CheckForNull + public List<PermissionTemplateGroupDto> getGroupsPermissions() { + return groupsPermissions; + } + + public PermissionTemplateDto setGroupsByPermission(@Nullable List<PermissionTemplateGroupDto> groupsPermissions) { + this.groupsPermissions = groupsPermissions; + return this; + } + + public Date getCreatedAt() { + return createdAt; + } + + public PermissionTemplateDto setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + return this; + } + + public Date getUpdatedAt() { + return updatedAt; + } + + public PermissionTemplateDto setUpdatedAt(Date updatedAt) { + this.updatedAt = updatedAt; + return this; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateGroupDto.java b/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateGroupDto.java new file mode 100644 index 00000000000..dc1e11dd2c5 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateGroupDto.java @@ -0,0 +1,98 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.permission; + +import java.util.Date; +import javax.annotation.Nullable; + +public class PermissionTemplateGroupDto { + + private Long id; + private Long templateId; + private Long groupId; + private String permission; + private String groupName; + private Date createdAt; + private Date updatedAt; + + public Long getId() { + return id; + } + + public PermissionTemplateGroupDto setId(Long id) { + this.id = id; + return this; + } + + public Long getTemplateId() { + return templateId; + } + + public PermissionTemplateGroupDto setTemplateId(Long templateId) { + this.templateId = templateId; + return this; + } + + public Long getGroupId() { + return groupId; + } + + public PermissionTemplateGroupDto setGroupId(@Nullable Long groupId) { + this.groupId = groupId; + return this; + } + + public String getPermission() { + return permission; + } + + public PermissionTemplateGroupDto setPermission(String permission) { + this.permission = permission; + return this; + } + + public String getGroupName() { + return groupName; + } + + public PermissionTemplateGroupDto setGroupName(String groupName) { + this.groupName = groupName; + return this; + } + + public Date getCreatedAt() { + return createdAt; + } + + public PermissionTemplateGroupDto setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + return this; + } + + public Date getUpdatedAt() { + return updatedAt; + } + + public PermissionTemplateGroupDto setUpdatedAt(Date updatedAt) { + this.updatedAt = updatedAt; + return this; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateMapper.java b/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateMapper.java new file mode 100644 index 00000000000..1277462b14d --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateMapper.java @@ -0,0 +1,61 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.permission; + +import java.util.List; +import java.util.Map; +import org.apache.ibatis.session.RowBounds; + +/** + * @since 3.7 + */ +public interface PermissionTemplateMapper { + + void insert(PermissionTemplateDto permissionTemplate); + + void update(PermissionTemplateDto permissionTemplate); + + void delete(long templateId); + + void deleteUsersPermissions(long templateId); + + void deleteGroupsPermissions(long templateId); + + PermissionTemplateDto selectByKey(String templateKey); + + PermissionTemplateDto selectTemplateUsersPermissions(String templateKey); + + PermissionTemplateDto selectTemplateGroupsPermissions(String templateKey); + + void insertUserPermission(PermissionTemplateUserDto permissionTemplateUser); + + void deleteUserPermission(PermissionTemplateUserDto permissionTemplateUser); + + void insertGroupPermission(PermissionTemplateGroupDto permissionTemplateGroup); + + void deleteGroupPermission(PermissionTemplateGroupDto permissionTemplateGroup); + + void deleteByGroupId(long groupId); + + List<GroupWithPermissionDto> selectGroups(Map<String, Object> params); + + List<UserWithPermissionDto> selectUsers(Map<String, Object> params, RowBounds rowBounds); +} diff --git a/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateUserDto.java b/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateUserDto.java new file mode 100644 index 00000000000..a1f6aaacb2f --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateUserDto.java @@ -0,0 +1,107 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.permission; + +import java.util.Date; + +public class PermissionTemplateUserDto { + + private Long id; + private Long templateId; + private Long userId; + private String permission; + private String userName; + private String userLogin; + private Date createdAt; + private Date updatedAt; + + public Long getId() { + return id; + } + + public PermissionTemplateUserDto setId(Long id) { + this.id = id; + return this; + } + + public Long getTemplateId() { + return templateId; + } + + public PermissionTemplateUserDto setTemplateId(Long templateId) { + this.templateId = templateId; + return this; + } + + public Long getUserId() { + return userId; + } + + public PermissionTemplateUserDto setUserId(Long userId) { + this.userId = userId; + return this; + } + + public String getUserName() { + return userName; + } + + public PermissionTemplateUserDto setUserName(String userName) { + this.userName = userName; + return this; + } + + public String getUserLogin() { + return userLogin; + } + + public PermissionTemplateUserDto setUserLogin(String userLogin) { + this.userLogin = userLogin; + return this; + } + + public String getPermission() { + return permission; + } + + public PermissionTemplateUserDto setPermission(String permission) { + this.permission = permission; + return this; + } + + public Date getCreatedAt() { + return createdAt; + } + + public PermissionTemplateUserDto setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + return this; + } + + public Date getUpdatedAt() { + return updatedAt; + } + + public PermissionTemplateUserDto setUpdatedAt(Date updatedAt) { + this.updatedAt = updatedAt; + return this; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/permission/UserWithPermissionDto.java b/sonar-db/src/main/java/org/sonar/db/permission/UserWithPermissionDto.java new file mode 100644 index 00000000000..66c7d176c96 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/permission/UserWithPermissionDto.java @@ -0,0 +1,67 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.permission; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.sonar.core.permission.UserWithPermission; + +public class UserWithPermissionDto { + + private String login; + private String name; + private String permission; + + public String getLogin() { + return login; + } + + public UserWithPermissionDto setLogin(String login) { + this.login = login; + return this; + } + + public String getName() { + return name; + } + + public UserWithPermissionDto setName(String name) { + this.name = name; + return this; + } + + @CheckForNull + public String getPermission() { + return permission; + } + + public UserWithPermissionDto setPermission(@Nullable String permission) { + this.permission = permission; + return this; + } + + public UserWithPermission toUserWithPermission() { + return new UserWithPermission() + .setLogin(login) + .setName(name) + .hasPermission(permission != null); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/permission/package-info.java b/sonar-db/src/main/java/org/sonar/db/permission/package-info.java new file mode 100644 index 00000000000..bb23b9cf500 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/permission/package-info.java @@ -0,0 +1,24 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.permission; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/sonar-db/src/main/java/org/sonar/db/profiling/InvocationUtils.java b/sonar-db/src/main/java/org/sonar/db/profiling/InvocationUtils.java new file mode 100644 index 00000000000..a4c5ac1cdc0 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/profiling/InvocationUtils.java @@ -0,0 +1,46 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.profiling; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +class InvocationUtils { + + private InvocationUtils() { + // Only private stuff + } + + static Object invokeQuietly(Object target, Method method, Object[] params) throws Throwable { + Object result = null; + try { + result = method.invoke(target, params); + } catch (InvocationTargetException invocationException) { + for (Class<?> exceptionClass : method.getExceptionTypes()) { + if (exceptionClass.isInstance(invocationException.getCause())) { + throw invocationException.getCause(); + } + throw new IllegalStateException(invocationException.getCause()); + } + } + return result; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/profiling/ProfiledDataSource.java b/sonar-db/src/main/java/org/sonar/db/profiling/ProfiledDataSource.java new file mode 100644 index 00000000000..2b2136a1ef8 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/profiling/ProfiledDataSource.java @@ -0,0 +1,407 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.profiling; + +import java.io.PrintWriter; +import java.lang.reflect.Proxy; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.Collection; +import org.apache.commons.dbcp.BasicDataSource; +import org.sonar.api.utils.log.Logger; +import org.sonar.api.utils.log.Loggers; + +public class ProfiledDataSource extends BasicDataSource { + + static final Logger SQL_LOGGER = Loggers.get("sql"); + + private final BasicDataSource delegate; + + public ProfiledDataSource(BasicDataSource delegate) { + this.delegate = delegate; + } + + @Override + public boolean getDefaultAutoCommit() { + return delegate.getDefaultAutoCommit(); + } + + @Override + public void setDefaultAutoCommit(boolean defaultAutoCommit) { + delegate.setDefaultAutoCommit(defaultAutoCommit); + } + + @Override + public boolean getDefaultReadOnly() { + return delegate.getDefaultReadOnly(); + } + + @Override + public void setDefaultReadOnly(boolean defaultReadOnly) { + delegate.setDefaultReadOnly(defaultReadOnly); + } + + @Override + public int getDefaultTransactionIsolation() { + return delegate.getDefaultTransactionIsolation(); + } + + @Override + public void setDefaultTransactionIsolation(int defaultTransactionIsolation) { + delegate.setDefaultTransactionIsolation(defaultTransactionIsolation); + } + + @Override + public String getDefaultCatalog() { + return delegate.getDefaultCatalog(); + } + + @Override + public void setDefaultCatalog(String defaultCatalog) { + delegate.setDefaultCatalog(defaultCatalog); + } + + @Override + public synchronized String getDriverClassName() { + return delegate.getDriverClassName(); + } + + @Override + public synchronized void setDriverClassName(String driverClassName) { + delegate.setDriverClassName(driverClassName); + } + + @Override + public synchronized ClassLoader getDriverClassLoader() { + return delegate.getDriverClassLoader(); + } + + @Override + public synchronized void setDriverClassLoader(ClassLoader driverClassLoader) { + delegate.setDriverClassLoader(driverClassLoader); + } + + @Override + public synchronized int getMaxActive() { + return delegate.getMaxActive(); + } + + @Override + public synchronized void setMaxActive(int maxActive) { + delegate.setMaxActive(maxActive); + } + + @Override + public synchronized int getMaxIdle() { + return delegate.getMaxIdle(); + } + + @Override + public synchronized void setMaxIdle(int maxIdle) { + delegate.setMaxIdle(maxIdle); + } + + @Override + public synchronized int getMinIdle() { + return delegate.getMinIdle(); + } + + @Override + public synchronized void setMinIdle(int minIdle) { + delegate.setMinIdle(minIdle); + } + + @Override + public synchronized int getInitialSize() { + return delegate.getInitialSize(); + } + + @Override + public synchronized void setInitialSize(int initialSize) { + delegate.setInitialSize(initialSize); + } + + @Override + public synchronized long getMaxWait() { + return delegate.getMaxWait(); + } + + @Override + public synchronized void setMaxWait(long maxWait) { + delegate.setMaxWait(maxWait); + } + + @Override + public synchronized boolean isPoolPreparedStatements() { + return delegate.isPoolPreparedStatements(); + } + + @Override + public synchronized void setPoolPreparedStatements(boolean poolingStatements) { + delegate.setPoolPreparedStatements(poolingStatements); + } + + @Override + public synchronized int getMaxOpenPreparedStatements() { + return delegate.getMaxOpenPreparedStatements(); + } + + @Override + public synchronized void setMaxOpenPreparedStatements(int maxOpenStatements) { + delegate.setMaxOpenPreparedStatements(maxOpenStatements); + } + + @Override + public synchronized boolean getTestOnBorrow() { + return delegate.getTestOnBorrow(); + } + + @Override + public synchronized void setTestOnBorrow(boolean testOnBorrow) { + delegate.setTestOnBorrow(testOnBorrow); + } + + @Override + public synchronized boolean getTestOnReturn() { + return delegate.getTestOnReturn(); + } + + @Override + public synchronized void setTestOnReturn(boolean testOnReturn) { + delegate.setTestOnReturn(testOnReturn); + } + + @Override + public synchronized long getTimeBetweenEvictionRunsMillis() { + return delegate.getTimeBetweenEvictionRunsMillis(); + } + + @Override + public synchronized void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) { + delegate.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); + } + + @Override + public synchronized int getNumTestsPerEvictionRun() { + return delegate.getNumTestsPerEvictionRun(); + } + + @Override + public synchronized void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) { + delegate.setNumTestsPerEvictionRun(numTestsPerEvictionRun); + } + + @Override + public synchronized long getMinEvictableIdleTimeMillis() { + return delegate.getMinEvictableIdleTimeMillis(); + } + + @Override + public synchronized void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) { + delegate.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); + } + + @Override + public synchronized boolean getTestWhileIdle() { + return delegate.getTestWhileIdle(); + } + + @Override + public synchronized void setTestWhileIdle(boolean testWhileIdle) { + delegate.setTestWhileIdle(testWhileIdle); + } + + @Override + public synchronized int getNumActive() { + return delegate.getNumActive(); + } + + @Override + public synchronized int getNumIdle() { + return delegate.getNumIdle(); + } + + @Override + public String getPassword() { + return delegate.getPassword(); + } + + @Override + public void setPassword(String password) { + delegate.setPassword(password); + } + + @Override + public synchronized String getUrl() { + return delegate.getUrl(); + } + + @Override + public synchronized void setUrl(String url) { + delegate.setUrl(url); + } + + @Override + public String getUsername() { + return delegate.getUsername(); + } + + @Override + public void setUsername(String username) { + delegate.setUsername(username); + } + + @Override + public String getValidationQuery() { + return delegate.getValidationQuery(); + } + + @Override + public void setValidationQuery(String validationQuery) { + delegate.setValidationQuery(validationQuery); + } + + @Override + public int getValidationQueryTimeout() { + return delegate.getValidationQueryTimeout(); + } + + @Override + public void setValidationQueryTimeout(int timeout) { + delegate.setValidationQueryTimeout(timeout); + } + + @Override + public Collection getConnectionInitSqls() { + return delegate.getConnectionInitSqls(); + } + + @Override + public void setConnectionInitSqls(Collection connectionInitSqls) { + delegate.setConnectionInitSqls(connectionInitSqls); + } + + @Override + public synchronized boolean isAccessToUnderlyingConnectionAllowed() { + return delegate.isAccessToUnderlyingConnectionAllowed(); + } + + @Override + public synchronized void setAccessToUnderlyingConnectionAllowed(boolean allow) { + delegate.setAccessToUnderlyingConnectionAllowed(allow); + } + + @Override + public Connection getConnection() throws SQLException { + return (Connection) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[] {Connection.class}, + new ProfilingConnectionHandler(delegate.getConnection())); + } + + @Override + public Connection getConnection(String user, String pass) throws SQLException { + return (Connection) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[] {Connection.class}, + new ProfilingConnectionHandler(delegate.getConnection(user, pass))); + } + + @Override + public int getLoginTimeout() throws SQLException { + return delegate.getLoginTimeout(); + } + + @Override + public PrintWriter getLogWriter() throws SQLException { + return delegate.getLogWriter(); + } + + @Override + public void setLoginTimeout(int loginTimeout) throws SQLException { + delegate.setLoginTimeout(loginTimeout); + } + + @Override + public void setLogWriter(PrintWriter logWriter) throws SQLException { + delegate.setLogWriter(logWriter); + } + + @Override + public boolean getRemoveAbandoned() { + return delegate.getRemoveAbandoned(); + } + + @Override + public void setRemoveAbandoned(boolean removeAbandoned) { + delegate.setRemoveAbandoned(removeAbandoned); + } + + @Override + public int getRemoveAbandonedTimeout() { + return delegate.getRemoveAbandonedTimeout(); + } + + @Override + public void setRemoveAbandonedTimeout(int removeAbandonedTimeout) { + delegate.setRemoveAbandonedTimeout(removeAbandonedTimeout); + } + + @Override + public boolean getLogAbandoned() { + return delegate.getLogAbandoned(); + } + + @Override + public void setLogAbandoned(boolean logAbandoned) { + delegate.setLogAbandoned(logAbandoned); + } + + @Override + public void addConnectionProperty(String name, String value) { + delegate.addConnectionProperty(name, value); + } + + @Override + public void removeConnectionProperty(String name) { + delegate.removeConnectionProperty(name); + } + + @Override + public void setConnectionProperties(String connectionProperties) { + delegate.setConnectionProperties(connectionProperties); + } + + @Override + public synchronized void close() throws SQLException { + delegate.close(); + } + + @Override + public synchronized boolean isClosed() { + return delegate.isClosed(); + } + + @Override + public boolean isWrapperFor(Class<?> iface) throws SQLException { + return delegate.isWrapperFor(iface); + } + + @Override + public <T> T unwrap(Class<T> iface) throws SQLException { + return delegate.unwrap(iface); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/profiling/ProfilingConnectionHandler.java b/sonar-db/src/main/java/org/sonar/db/profiling/ProfilingConnectionHandler.java new file mode 100644 index 00000000000..4446a47e7ee --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/profiling/ProfilingConnectionHandler.java @@ -0,0 +1,56 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.profiling; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.Statement; + +class ProfilingConnectionHandler implements InvocationHandler { + + private final Connection connection; + + ProfilingConnectionHandler(Connection connection) { + this.connection = connection; + } + + @Override + public Object invoke(Object target, Method method, Object[] args) throws Throwable { + Object result = InvocationUtils.invokeQuietly(connection, method, args); + if ("prepareStatement".equals(method.getName())) { + PreparedStatement statement = (PreparedStatement) result; + String sql = (String) args[0]; + return Proxy.newProxyInstance(ProfilingConnectionHandler.class.getClassLoader(), new Class[] {PreparedStatement.class}, + new ProfilingPreparedStatementHandler(statement, sql)); + + } else if ("createStatement".equals(method.getName())) { + Statement statement = (Statement) result; + return Proxy.newProxyInstance(ProfilingConnectionHandler.class.getClassLoader(), new Class[] {Statement.class}, + new ProfilingStatementHandler(statement)); + + } else { + return result; + } + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/profiling/ProfilingPreparedStatementHandler.java b/sonar-db/src/main/java/org/sonar/db/profiling/ProfilingPreparedStatementHandler.java new file mode 100644 index 00000000000..9c451f13a30 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/profiling/ProfilingPreparedStatementHandler.java @@ -0,0 +1,65 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.profiling; + +import com.google.common.collect.Lists; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.sql.PreparedStatement; +import java.util.List; +import org.apache.commons.lang.StringUtils; +import org.sonar.api.utils.log.Profiler; + +class ProfilingPreparedStatementHandler implements InvocationHandler { + + private final PreparedStatement statement; + private final List<Object> arguments; + private final String sql; + + ProfilingPreparedStatementHandler(PreparedStatement statement, String sql) { + this.statement = statement; + this.sql = sql; + this.arguments = Lists.newArrayList(); + for (int argCount = 0; argCount < StringUtils.countMatches(sql, "?"); argCount++) { + arguments.add("!"); + } + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + if (method.getName().startsWith("execute")) { + Profiler profiler = Profiler.create(ProfiledDataSource.SQL_LOGGER).start(); + Object result = null; + try { + result = InvocationUtils.invokeQuietly(statement, method, args); + } finally { + profiler.addContext("sql", StringUtils.remove(sql, '\n')); + profiler.stopTrace(""); + } + return result; + } else if (method.getName().startsWith("set") && args.length > 1) { + arguments.set((Integer) args[0] - 1, args[1]); + return InvocationUtils.invokeQuietly(statement, method, args); + } else { + return InvocationUtils.invokeQuietly(statement, method, args); + } + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/profiling/ProfilingStatementHandler.java b/sonar-db/src/main/java/org/sonar/db/profiling/ProfilingStatementHandler.java new file mode 100644 index 00000000000..994f1a823c0 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/profiling/ProfilingStatementHandler.java @@ -0,0 +1,52 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.profiling; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.sql.Statement; +import org.apache.commons.lang.StringUtils; +import org.sonar.api.utils.log.Profiler; + +class ProfilingStatementHandler implements InvocationHandler { + + private final Statement statement; + + ProfilingStatementHandler(Statement statement) { + this.statement = statement; + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + if (method.getName().startsWith("execute")) { + Profiler profiler = Profiler.create(ProfiledDataSource.SQL_LOGGER).start(); + Object result = null; + try { + result = InvocationUtils.invokeQuietly(statement, method, args); + } finally { + profiler.addContext("sql", StringUtils.remove((String) args[0], '\n')); + profiler.stopTrace(""); + } + return result; + } else { + return InvocationUtils.invokeQuietly(statement, method, args); + } + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/profiling/package-info.java b/sonar-db/src/main/java/org/sonar/db/profiling/package-info.java new file mode 100644 index 00000000000..99f88d56e77 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/profiling/package-info.java @@ -0,0 +1,24 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.profiling; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/sonar-db/src/main/java/org/sonar/db/property/PropertiesDao.java b/sonar-db/src/main/java/org/sonar/db/property/PropertiesDao.java new file mode 100644 index 00000000000..cb1a63adbe3 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/property/PropertiesDao.java @@ -0,0 +1,302 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.property; + +import com.google.common.base.Preconditions; +import com.google.common.base.Strings; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import javax.annotation.Nullable; +import org.apache.commons.dbutils.DbUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.ibatis.session.SqlSession; +import org.sonar.api.resources.Scopes; +import org.sonar.db.Dao; +import org.sonar.db.DaoUtils; +import org.sonar.db.DbSession; +import org.sonar.db.MyBatis; + +public class PropertiesDao implements Dao { + + private static final String NOTIFICATION_PREFIX = "notification."; + private MyBatis mybatis; + + public PropertiesDao(MyBatis mybatis) { + this.mybatis = mybatis; + } + + /** + * Returns the logins of users who have subscribed to the given notification dispatcher with the given notification channel. + * If a resource ID is passed, the search is made on users who have specifically subscribed for the given resource. + * + * @return the list of logins (maybe be empty - obviously) + */ + public List<String> findUsersForNotification(String notificationDispatcherKey, String notificationChannelKey, + @Nullable String projectUuid) { + SqlSession session = mybatis.openSession(false); + PropertiesMapper mapper = session.getMapper(PropertiesMapper.class); + try { + return mapper.findUsersForNotification(NOTIFICATION_PREFIX + notificationDispatcherKey + "." + notificationChannelKey, projectUuid); + } finally { + MyBatis.closeQuietly(session); + } + } + + public List<String> findNotificationSubscribers(String notificationDispatcherKey, String notificationChannelKey, @Nullable String componentKey) { + SqlSession session = mybatis.openSession(false); + PropertiesMapper mapper = session.getMapper(PropertiesMapper.class); + try { + return mapper.findNotificationSubscribers(NOTIFICATION_PREFIX + notificationDispatcherKey + "." + notificationChannelKey, componentKey); + } finally { + MyBatis.closeQuietly(session); + } + } + + public boolean hasProjectNotificationSubscribersForDispatchers(String projectUuid, Collection<String> dispatcherKeys) { + DbSession session = mybatis.openSession(false); + Connection connection = session.getConnection(); + PreparedStatement pstmt = null; + ResultSet rs = null; + String sql = "SELECT count(*) FROM properties pp " + + "left outer join projects pj on pp.resource_id = pj.id " + + "where pp.user_id is not null and (pp.resource_id is null or pj.uuid=?) " + + "and (" + DaoUtils.repeatCondition("pp.prop_key like ?", dispatcherKeys.size(), "or") + ")"; + try { + pstmt = connection.prepareStatement(sql); + pstmt.setString(1, projectUuid); + int index = 2; + for (String dispatcherKey : dispatcherKeys) { + pstmt.setString(index, "notification." + dispatcherKey + ".%"); + index++; + } + rs = pstmt.executeQuery(); + return rs.next() && rs.getInt(1) > 0; + } catch (SQLException e) { + throw new IllegalStateException("Fail to execute SQL request: " + sql, e); + } finally { + DbUtils.closeQuietly(connection, pstmt, rs); + MyBatis.closeQuietly(session); + } + } + + public List<PropertyDto> selectGlobalProperties() { + SqlSession session = mybatis.openSession(false); + try { + return selectGlobalProperties(session); + } finally { + MyBatis.closeQuietly(session); + } + } + + public List<PropertyDto> selectGlobalProperties(SqlSession session) { + return session.getMapper(PropertiesMapper.class).selectGlobalProperties(); + } + + public PropertyDto selectGlobalProperty(String propertyKey) { + SqlSession session = mybatis.openSession(false); + PropertiesMapper mapper = session.getMapper(PropertiesMapper.class); + try { + return mapper.selectByKey(new PropertyDto().setKey(propertyKey)); + } finally { + MyBatis.closeQuietly(session); + } + } + + public List<PropertyDto> selectProjectProperties(DbSession session, String projectKey) { + return session.getMapper(PropertiesMapper.class).selectProjectProperties(projectKey); + } + + public List<PropertyDto> selectProjectProperties(String resourceKey) { + DbSession session = mybatis.openSession(false); + try { + return selectProjectProperties(session, resourceKey); + } finally { + MyBatis.closeQuietly(session); + } + } + + public List<PropertyDto> selectEnabledDescendantModuleProperties(String moduleUuid, SqlSession session) { + return session.getMapper(PropertiesMapper.class).selectDescendantModuleProperties(moduleUuid, Scopes.PROJECT, true); + } + + public PropertyDto selectProjectProperty(long resourceId, String propertyKey) { + SqlSession session = mybatis.openSession(false); + PropertiesMapper mapper = session.getMapper(PropertiesMapper.class); + try { + return mapper.selectByKey(new PropertyDto().setKey(propertyKey).setResourceId(resourceId)); + } finally { + MyBatis.closeQuietly(session); + } + } + + public List<PropertyDto> selectByQuery(PropertyQuery query, DbSession session) { + return session.getMapper(PropertiesMapper.class).selectByQuery(query); + } + + public void setProperty(PropertyDto property, SqlSession session) { + PropertiesMapper mapper = session.getMapper(PropertiesMapper.class); + PropertyDto persistedProperty = mapper.selectByKey(property); + if (persistedProperty != null && !StringUtils.equals(persistedProperty.getValue(), property.getValue())) { + persistedProperty.setValue(property.getValue()); + mapper.update(persistedProperty); + } else if (persistedProperty == null) { + mapper.insert(property); + } + } + + public void setProperty(PropertyDto property) { + SqlSession session = mybatis.openSession(false); + try { + setProperty(property, session); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + public void deleteProjectProperty(String key, Long projectId) { + SqlSession session = mybatis.openSession(false); + try { + deleteProjectProperty(key, projectId, session); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + public void deleteProjectProperty(String key, Long projectId, SqlSession session) { + PropertiesMapper mapper = session.getMapper(PropertiesMapper.class); + mapper.deleteProjectProperty(key, projectId); + } + + public void deleteProjectProperties(String key, String value, SqlSession session) { + PropertiesMapper mapper = session.getMapper(PropertiesMapper.class); + mapper.deleteProjectProperties(key, value); + } + + public void deleteProjectProperties(String key, String value) { + SqlSession session = mybatis.openSession(false); + try { + deleteProjectProperties(key, value, session); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + public void deleteGlobalProperties() { + SqlSession session = mybatis.openSession(false); + PropertiesMapper mapper = session.getMapper(PropertiesMapper.class); + try { + mapper.deleteGlobalProperties(); + session.commit(); + + } finally { + MyBatis.closeQuietly(session); + } + } + + public void deleteGlobalProperty(String key, SqlSession session) { + PropertiesMapper mapper = session.getMapper(PropertiesMapper.class); + mapper.deleteGlobalProperty(key); + } + + public void deleteGlobalProperty(String key) { + SqlSession session = mybatis.openSession(false); + try { + deleteGlobalProperty(key, session); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + public void deleteAllProperties(String key) { + SqlSession session = mybatis.openSession(false); + PropertiesMapper mapper = session.getMapper(PropertiesMapper.class); + try { + mapper.deleteAllProperties(key); + session.commit(); + + } finally { + MyBatis.closeQuietly(session); + } + } + + public void saveGlobalProperties(Map<String, String> properties) { + DbSession session = mybatis.openSession(true); + PropertiesMapper mapper = session.getMapper(PropertiesMapper.class); + try { + for (Map.Entry<String, String> entry : properties.entrySet()) { + mapper.deleteGlobalProperty(entry.getKey()); + } + for (Map.Entry<String, String> entry : properties.entrySet()) { + mapper.insert(new PropertyDto().setKey(entry.getKey()).setValue(entry.getValue())); + } + session.commit(); + + } finally { + MyBatis.closeQuietly(session); + } + } + + public void renamePropertyKey(String oldKey, String newKey) { + Preconditions.checkArgument(!Strings.isNullOrEmpty(oldKey), "Old property key must not be empty"); + Preconditions.checkArgument(!Strings.isNullOrEmpty(newKey), "New property key must not be empty"); + + if (!newKey.equals(oldKey)) { + SqlSession session = mybatis.openSession(false); + PropertiesMapper mapper = session.getMapper(PropertiesMapper.class); + try { + mapper.renamePropertyKey(oldKey, newKey); + session.commit(); + + } finally { + MyBatis.closeQuietly(session); + } + } + } + + /** + * Update all properties (global and projects ones) with a given key and value to a new value + */ + public void updateProperties(String key, String oldValue, String newValue) { + SqlSession session = mybatis.openSession(false); + try { + updateProperties(key, oldValue, newValue, session); + session.commit(); + + } finally { + MyBatis.closeQuietly(session); + } + } + + public void updateProperties(String key, String oldValue, String newValue, SqlSession session) { + PropertiesMapper mapper = session.getMapper(PropertiesMapper.class); + mapper.updateProperties(key, oldValue, newValue); + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/property/PropertiesMapper.java b/sonar-db/src/main/java/org/sonar/db/property/PropertiesMapper.java new file mode 100644 index 00000000000..34c03e2e9b8 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/property/PropertiesMapper.java @@ -0,0 +1,65 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.property; + +import java.util.List; +import javax.annotation.Nullable; +import org.apache.ibatis.annotations.Param; + +public interface PropertiesMapper { + + List<String> findUsersForNotification(@Param("notifKey") String notificationKey, @Nullable @Param("projectUuid") String projectUuid); + + List<String> findNotificationSubscribers(@Param("propKey") String propertyKey, @Nullable @Param("componentKey") String componentKey); + + List<PropertyDto> selectGlobalProperties(); + + List<PropertyDto> selectProjectProperties(String resourceKey); + + List<PropertyDto> selectProjectPropertiesByResourceId(Long resourceId); + + List<PropertyDto> selectSetOfResourceProperties(@Param("rId") Long projectId, @Param("propKeys") List<String> propertyKeys); + + PropertyDto selectByKey(PropertyDto key); + + List<PropertyDto> selectByQuery(@Param("query") PropertyQuery query); + + List<PropertyDto> selectDescendantModuleProperties(@Param("moduleUuid") String moduleUuid, @Param(value = "scope") String scope, + @Param(value = "excludeDisabled") boolean excludeDisabled); + + void update(PropertyDto property); + + void insert(PropertyDto property); + + void deleteProjectProperty(@Param("key") String key, @Param("rId") Long resourceId); + + void deleteProjectProperties(@Param("key") String key, @Param("value") String value); + + void deleteGlobalProperty(String key); + + void deleteAllProperties(String key); + + void deleteGlobalProperties(); + + void renamePropertyKey(@Param("oldKey") String oldKey, @Param("newKey") String newKey); + + void updateProperties(@Param("key") String key, @Param("oldValue") String oldValue, @Param("newValue") String newValue); +} diff --git a/sonar-db/src/main/java/org/sonar/db/property/PropertyDto.java b/sonar-db/src/main/java/org/sonar/db/property/PropertyDto.java new file mode 100644 index 00000000000..10456ace24c --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/property/PropertyDto.java @@ -0,0 +1,106 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.property; + +import com.google.common.base.Objects; + +public final class PropertyDto { + private Long id; + private String key; + private String value; + private Long resourceId; + private Long userId; + + public Long getId() { + return id; + } + + public PropertyDto setId(Long id) { + this.id = id; + return this; + } + + public String getKey() { + return key; + } + + public PropertyDto setKey(String key) { + this.key = key; + return this; + } + + public String getValue() { + return value; + } + + public PropertyDto setValue(String value) { + this.value = value; + return this; + } + + public Long getResourceId() { + return resourceId; + } + + public PropertyDto setResourceId(Long resourceId) { + this.resourceId = resourceId; + return this; + } + + public Long getUserId() { + return userId; + } + + public PropertyDto setUserId(Long userId) { + this.userId = userId; + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final PropertyDto other = (PropertyDto) obj; + + return Objects.equal(this.key, other.key) + && Objects.equal(this.value, other.value) + && Objects.equal(this.userId, other.userId) + && Objects.equal(this.resourceId, other.resourceId); + } + + @Override + public int hashCode() { + return Objects.hashCode(this.key, this.value, this.resourceId, this.userId); + } + + @Override + public String toString() { + return Objects.toStringHelper(this) + .addValue(this.key) + .addValue(this.value) + .addValue(this.resourceId) + .addValue(this.userId) + .toString(); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/property/PropertyQuery.java b/sonar-db/src/main/java/org/sonar/db/property/PropertyQuery.java new file mode 100644 index 00000000000..108fb2e2742 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/property/PropertyQuery.java @@ -0,0 +1,76 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.property; + +public class PropertyQuery { + + private final String key; + private final Long componentId; + private final Integer userId; + + private PropertyQuery(Builder builder) { + this.key = builder.key; + this.componentId = builder.componentId; + this.userId = builder.userId; + } + + public String key() { + return key; + } + + public Long componentId() { + return componentId; + } + + public Integer userId() { + return userId; + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private String key; + private Long componentId; + private Integer userId; + + public Builder setKey(String key) { + this.key = key; + return this; + } + + public Builder setComponentId(Long componentId) { + this.componentId = componentId; + return this; + } + + public Builder setUserId(Integer userId) { + this.userId = userId; + return this; + } + + public PropertyQuery build() { + return new PropertyQuery(this); + } + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/purge/IdUuidPair.java b/sonar-db/src/main/java/org/sonar/db/purge/IdUuidPair.java new file mode 100644 index 00000000000..642a6fbda55 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/purge/IdUuidPair.java @@ -0,0 +1,50 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.purge; + +public class IdUuidPair { + private Long id; + private String uuid; + + public IdUuidPair() { + } + + public IdUuidPair(long id, String uuid) { + this.id = id; + this.uuid = uuid; + } + + public Long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/purge/IdUuidPairs.java b/sonar-db/src/main/java/org/sonar/db/purge/IdUuidPairs.java new file mode 100644 index 00000000000..12bfbab8f09 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/purge/IdUuidPairs.java @@ -0,0 +1,53 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.purge; + +import com.google.common.base.Function; +import com.google.common.collect.Lists; +import java.util.List; +import javax.annotation.Nonnull; + +public class IdUuidPairs { + private IdUuidPairs() { + } + + public static List<Long> ids(List<IdUuidPair> pairs) { + return Lists.transform(pairs, new IdUuidPairToIdFunction()); + } + + public static List<String> uuids(List<IdUuidPair> pairs) { + return Lists.transform(pairs, new IdUuidPairToUuidFunction()); + } + + private static class IdUuidPairToIdFunction implements Function<IdUuidPair, Long> { + @Override + public Long apply(@Nonnull IdUuidPair pair) { + return pair.getId(); + } + } + + private static class IdUuidPairToUuidFunction implements Function<IdUuidPair, String> { + @Override + public String apply(@Nonnull IdUuidPair pair) { + return pair.getUuid(); + } + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/purge/PurgeCommands.java b/sonar-db/src/main/java/org/sonar/db/purge/PurgeCommands.java new file mode 100644 index 00000000000..8e93918e780 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/purge/PurgeCommands.java @@ -0,0 +1,224 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.purge; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.Lists; +import java.util.List; +import org.apache.ibatis.session.SqlSession; + +class PurgeCommands { + + private static final int MAX_SNAPSHOTS_PER_QUERY = 1000; + private static final int MAX_RESOURCES_PER_QUERY = 1000; + + private final SqlSession session; + private final PurgeMapper purgeMapper; + private final PurgeProfiler profiler; + + PurgeCommands(SqlSession session, PurgeMapper purgeMapper, PurgeProfiler profiler) { + this.session = session; + this.purgeMapper = purgeMapper; + this.profiler = profiler; + } + + @VisibleForTesting + PurgeCommands(SqlSession session, PurgeProfiler profiler) { + this(session, session.getMapper(PurgeMapper.class), profiler); + } + + List<Long> selectSnapshotIds(PurgeSnapshotQuery query) { + return purgeMapper.selectSnapshotIds(query); + } + + void deleteResources(List<IdUuidPair> componentIdUuids) { + List<List<Long>> componentIdPartitions = Lists.partition(IdUuidPairs.ids(componentIdUuids), MAX_RESOURCES_PER_QUERY); + List<List<String>> componentUuidsPartitions = Lists.partition(IdUuidPairs.uuids(componentIdUuids), MAX_RESOURCES_PER_QUERY); + // Note : do not merge the delete statements into a single loop of resource ids. It's + // voluntarily grouped by tables in order to benefit from JDBC batch mode. + // Batch requests can only relate to the same PreparedStatement. + + for (List<Long> partResourceIds : componentIdPartitions) { + deleteSnapshots(purgeMapper.selectSnapshotIdsByResource(partResourceIds)); + } + + // possible missing optimization: filter requests according to resource scope + + profiler.start("deleteResourceLinks (project_links)"); + for (List<String> componentUuidPartition : componentUuidsPartitions) { + purgeMapper.deleteResourceLinks(componentUuidPartition); + } + session.commit(); + profiler.stop(); + + profiler.start("deleteResourceProperties (properties)"); + for (List<Long> partResourceIds : componentIdPartitions) { + purgeMapper.deleteResourceProperties(partResourceIds); + } + session.commit(); + profiler.stop(); + + profiler.start("deleteResourceIndex (resource_index)"); + for (List<Long> partResourceIds : componentIdPartitions) { + purgeMapper.deleteResourceIndex(partResourceIds); + } + session.commit(); + profiler.stop(); + + profiler.start("deleteResourceGroupRoles (group_roles)"); + for (List<Long> partResourceIds : componentIdPartitions) { + purgeMapper.deleteResourceGroupRoles(partResourceIds); + } + session.commit(); + profiler.stop(); + + profiler.start("deleteResourceUserRoles (user_roles)"); + for (List<Long> partResourceIds : componentIdPartitions) { + purgeMapper.deleteResourceUserRoles(partResourceIds); + } + session.commit(); + profiler.stop(); + + profiler.start("deleteResourceManualMeasures (manual_measures)"); + for (List<String> componentUuidPartition : componentUuidsPartitions) { + purgeMapper.deleteResourceManualMeasures(componentUuidPartition); + } + session.commit(); + profiler.stop(); + + profiler.start("deleteComponentIssueChanges (issue_changes)"); + for (List<String> componentUuidPartition : componentUuidsPartitions) { + purgeMapper.deleteComponentIssueChanges(componentUuidPartition); + } + session.commit(); + profiler.stop(); + + profiler.start("deleteComponentIssues (issues)"); + for (List<String> componentUuidPartition : componentUuidsPartitions) { + purgeMapper.deleteComponentIssues(componentUuidPartition); + } + session.commit(); + profiler.stop(); + + profiler.start("deleteResourceActionPlans (action_plans)"); + for (List<Long> partResourceIds : componentIdPartitions) { + purgeMapper.deleteResourceActionPlans(partResourceIds); + } + session.commit(); + profiler.stop(); + + profiler.start("deleteComponentEvents (events)"); + for (List<String> componentUuidPartition : componentUuidsPartitions) { + purgeMapper.deleteComponentEvents(componentUuidPartition); + } + session.commit(); + profiler.stop(); + + profiler.start("deleteResource (projects)"); + for (List<Long> partResourceIds : componentIdPartitions) { + purgeMapper.deleteResource(partResourceIds); + } + session.commit(); + profiler.stop(); + + profiler.start("deleteAuthors (authors)"); + for (List<Long> partResourceIds : componentIdPartitions) { + purgeMapper.deleteAuthors(partResourceIds); + } + session.commit(); + profiler.stop(); + } + + void deleteSnapshots(final PurgeSnapshotQuery query) { + deleteSnapshots(purgeMapper.selectSnapshotIds(query)); + } + + @VisibleForTesting + protected void deleteSnapshots(final List<Long> snapshotIds) { + + List<List<Long>> snapshotIdsPartition = Lists.partition(snapshotIds, MAX_SNAPSHOTS_PER_QUERY); + + deleteSnapshotDuplications(snapshotIdsPartition); + + profiler.start("deleteSnapshotEvents (events)"); + for (List<Long> partSnapshotIds : snapshotIdsPartition) { + purgeMapper.deleteSnapshotEvents(partSnapshotIds); + } + session.commit(); + profiler.stop(); + + profiler.start("deleteSnapshotMeasures (project_measures)"); + for (List<Long> partSnapshotIds : snapshotIdsPartition) { + purgeMapper.deleteSnapshotMeasures(partSnapshotIds); + } + session.commit(); + profiler.stop(); + + profiler.start("deleteSnapshot (snapshots)"); + for (List<Long> partSnapshotIds : snapshotIdsPartition) { + purgeMapper.deleteSnapshot(partSnapshotIds); + } + session.commit(); + profiler.stop(); + } + + void purgeSnapshots(final PurgeSnapshotQuery query) { + purgeSnapshots(purgeMapper.selectSnapshotIds(query)); + } + + @VisibleForTesting + protected void purgeSnapshots(final List<Long> snapshotIds) { + // note that events are not deleted + List<List<Long>> snapshotIdsPartition = Lists.partition(snapshotIds, MAX_SNAPSHOTS_PER_QUERY); + + deleteSnapshotDuplications(snapshotIdsPartition); + + profiler.start("deleteSnapshotWastedMeasures (project_measures)"); + List<Long> metricIdsWithoutHistoricalData = purgeMapper.selectMetricIdsWithoutHistoricalData(); + for (List<Long> partSnapshotIds : snapshotIdsPartition) { + purgeMapper.deleteSnapshotWastedMeasures(partSnapshotIds, metricIdsWithoutHistoricalData); + } + session.commit(); + profiler.stop(); + + profiler.start("updatePurgeStatusToOne (snapshots)"); + for (Long snapshotId : snapshotIds) { + purgeMapper.updatePurgeStatusToOne(snapshotId); + } + session.commit(); + profiler.stop(); + } + + private void deleteSnapshotDuplications(final List<List<Long>> snapshotIdsPartition) { + profiler.start("deleteSnapshotDuplications (duplications_index)"); + for (List<Long> partSnapshotIds : snapshotIdsPartition) { + purgeMapper.deleteSnapshotDuplications(partSnapshotIds); + } + session.commit(); + profiler.stop(); + } + + public void deleteFileSources(String rootUuid) { + profiler.start("deleteFileSources (file_sources)"); + purgeMapper.deleteFileSourcesByProjectUuid(rootUuid); + session.commit(); + profiler.stop(); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/purge/PurgeConfiguration.java b/sonar-db/src/main/java/org/sonar/db/purge/PurgeConfiguration.java new file mode 100644 index 00000000000..65bc6c0ca0e --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/purge/PurgeConfiguration.java @@ -0,0 +1,81 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.purge; + +import com.google.common.annotations.VisibleForTesting; +import java.util.Date; +import javax.annotation.CheckForNull; +import org.apache.commons.lang.time.DateUtils; +import org.sonar.api.config.Settings; +import org.sonar.api.resources.Scopes; +import org.sonar.api.utils.System2; +import org.sonar.core.config.PurgeConstants; + +public class PurgeConfiguration { + + private final IdUuidPair rootProjectIdUuid; + private final String[] scopesWithoutHistoricalData; + private final int maxAgeInDaysOfClosedIssues; + private final System2 system2; + + public PurgeConfiguration(IdUuidPair rootProjectId, String[] scopesWithoutHistoricalData, int maxAgeInDaysOfClosedIssues) { + this(rootProjectId, scopesWithoutHistoricalData, maxAgeInDaysOfClosedIssues, System2.INSTANCE); + } + + @VisibleForTesting + PurgeConfiguration(IdUuidPair rootProjectId, String[] scopesWithoutHistoricalData, int maxAgeInDaysOfClosedIssues, System2 system2) { + this.rootProjectIdUuid = rootProjectId; + this.scopesWithoutHistoricalData = scopesWithoutHistoricalData; + this.maxAgeInDaysOfClosedIssues = maxAgeInDaysOfClosedIssues; + this.system2 = system2; + } + + public static PurgeConfiguration newDefaultPurgeConfiguration(Settings settings, IdUuidPair idUuidPair) { + String[] scopes = new String[] {Scopes.FILE}; + if (settings.getBoolean(PurgeConstants.PROPERTY_CLEAN_DIRECTORY)) { + scopes = new String[] {Scopes.DIRECTORY, Scopes.FILE}; + } + return new PurgeConfiguration(idUuidPair, scopes, settings.getInt(PurgeConstants.DAYS_BEFORE_DELETING_CLOSED_ISSUES)); + } + + public IdUuidPair rootProjectIdUuid() { + return rootProjectIdUuid; + } + + public String[] scopesWithoutHistoricalData() { + return scopesWithoutHistoricalData; + } + + @CheckForNull + public Date maxLiveDateOfClosedIssues() { + return maxLiveDateOfClosedIssues(new Date(system2.now())); + } + + @VisibleForTesting + @CheckForNull + Date maxLiveDateOfClosedIssues(Date now) { + if (maxAgeInDaysOfClosedIssues > 0) { + return DateUtils.addDays(now, -maxAgeInDaysOfClosedIssues); + } + + // delete all closed issues + return null; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/purge/PurgeDao.java b/sonar-db/src/main/java/org/sonar/db/purge/PurgeDao.java new file mode 100644 index 00000000000..a06767ab51c --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/purge/PurgeDao.java @@ -0,0 +1,244 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.purge; + +import com.google.common.collect.Lists; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import org.apache.commons.lang.ArrayUtils; +import org.apache.ibatis.session.ResultContext; +import org.apache.ibatis.session.ResultHandler; +import org.apache.ibatis.session.SqlSession; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.utils.System2; +import org.sonar.db.Dao; +import org.sonar.db.DbSession; +import org.sonar.db.MyBatis; +import org.sonar.db.component.ResourceDao; +import org.sonar.db.component.ResourceDto; + +import static org.sonar.api.utils.DateUtils.dateToLong; + +/** + * @since 2.14 + */ +public class PurgeDao implements Dao { + private static final Logger LOG = LoggerFactory.getLogger(PurgeDao.class); + private final MyBatis mybatis; + private final ResourceDao resourceDao; + private final System2 system2; + private final PurgeProfiler profiler; + + public PurgeDao(MyBatis mybatis, ResourceDao resourceDao, PurgeProfiler profiler, System2 system2) { + this.mybatis = mybatis; + this.resourceDao = resourceDao; + this.profiler = profiler; + this.system2 = system2; + } + + public PurgeDao purge(PurgeConfiguration conf, PurgeListener purgeListener) { + DbSession session = mybatis.openSession(true); + try { + purge(session, conf, purgeListener); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + return this; + } + + public void purge(DbSession session, PurgeConfiguration conf, PurgeListener purgeListener) { + PurgeMapper mapper = session.getMapper(PurgeMapper.class); + PurgeCommands commands = new PurgeCommands(session, mapper, profiler); + List<ResourceDto> projects = getProjects(conf.rootProjectIdUuid().getId(), session); + for (ResourceDto project : projects) { + LOG.debug("-> Clean " + project.getLongName() + " [id=" + project.getId() + "]"); + deleteAbortedBuilds(project, commands); + purge(project, conf.scopesWithoutHistoricalData(), commands); + } + for (ResourceDto project : projects) { + disableOrphanResources(project, session, mapper, purgeListener); + } + deleteOldClosedIssues(conf, mapper); + } + + private void deleteOldClosedIssues(PurgeConfiguration conf, PurgeMapper mapper) { + Date toDate = conf.maxLiveDateOfClosedIssues(); + mapper.deleteOldClosedIssueChanges(conf.rootProjectIdUuid().getUuid(), dateToLong(toDate)); + mapper.deleteOldClosedIssues(conf.rootProjectIdUuid().getUuid(), dateToLong(toDate)); + } + + private void deleteAbortedBuilds(ResourceDto project, PurgeCommands commands) { + if (hasAbortedBuilds(project.getId(), commands)) { + LOG.debug("<- Delete aborted builds"); + PurgeSnapshotQuery query = PurgeSnapshotQuery.create() + .setIslast(false) + .setStatus(new String[] {"U"}) + .setRootProjectId(project.getId()); + commands.deleteSnapshots(query); + } + } + + private boolean hasAbortedBuilds(Long projectId, PurgeCommands commands) { + PurgeSnapshotQuery query = PurgeSnapshotQuery.create() + .setIslast(false) + .setStatus(new String[] {"U"}) + .setResourceId(projectId); + return !commands.selectSnapshotIds(query).isEmpty(); + } + + private void purge(ResourceDto project, String[] scopesWithoutHistoricalData, PurgeCommands purgeCommands) { + List<Long> projectSnapshotIds = purgeCommands.selectSnapshotIds( + PurgeSnapshotQuery.create() + .setResourceId(project.getId()) + .setIslast(false) + .setNotPurged(true) + ); + for (final Long projectSnapshotId : projectSnapshotIds) { + LOG.debug("<- Clean snapshot " + projectSnapshotId); + if (!ArrayUtils.isEmpty(scopesWithoutHistoricalData)) { + PurgeSnapshotQuery query = PurgeSnapshotQuery.create() + .setIslast(false) + .setScopes(scopesWithoutHistoricalData) + .setRootSnapshotId(projectSnapshotId); + purgeCommands.deleteSnapshots(query); + } + + PurgeSnapshotQuery query = PurgeSnapshotQuery.create().setRootSnapshotId(projectSnapshotId).setNotPurged(true); + purgeCommands.purgeSnapshots(query); + + // must be executed at the end for reentrance + purgeCommands.purgeSnapshots(PurgeSnapshotQuery.create().setId(projectSnapshotId).setNotPurged(true)); + } + } + + private void disableOrphanResources(final ResourceDto project, final SqlSession session, final PurgeMapper purgeMapper, final PurgeListener purgeListener) { + final List<IdUuidPair> componentIdUuids = new ArrayList<>(); + session.select("org.sonar.db.purge.PurgeMapper.selectComponentIdUuidsToDisable", project.getId(), new ResultHandler() { + @Override + public void handleResult(ResultContext resultContext) { + IdUuidPair componentIdUuid = (IdUuidPair) resultContext.getResultObject(); + if (componentIdUuid.getId() != null) { + componentIdUuids.add(componentIdUuid); + } + } + }); + + for (IdUuidPair componentIdUuid : componentIdUuids) { + disableResource(componentIdUuid, purgeMapper); + purgeListener.onComponentDisabling(componentIdUuid.getUuid()); + } + + session.commit(); + } + + public List<PurgeableSnapshotDto> selectPurgeableSnapshots(long resourceId) { + DbSession session = mybatis.openSession(true); + try { + return selectPurgeableSnapshots(resourceId, session); + } finally { + MyBatis.closeQuietly(session); + } + } + + public List<PurgeableSnapshotDto> selectPurgeableSnapshots(long resourceId, DbSession session) { + List<PurgeableSnapshotDto> result = Lists.newArrayList(); + result.addAll(mapper(session).selectPurgeableSnapshotsWithEvents(resourceId)); + result.addAll(mapper(session).selectPurgeableSnapshotsWithoutEvents(resourceId)); + // sort by date + Collections.sort(result); + return result; + } + + public PurgeDao deleteResourceTree(IdUuidPair rootIdUuid) { + DbSession session = mybatis.openSession(true); + try { + return deleteResourceTree(session, rootIdUuid); + } finally { + MyBatis.closeQuietly(session); + } + } + + public PurgeDao deleteResourceTree(DbSession session, IdUuidPair rootIdUuid) { + deleteProject(rootIdUuid, mapper(session), new PurgeCommands(session, profiler)); + deleteFileSources(rootIdUuid.getUuid(), new PurgeCommands(session, profiler)); + return this; + } + + private static void deleteFileSources(String rootUuid, PurgeCommands commands) { + commands.deleteFileSources(rootUuid); + } + + private static void deleteProject(IdUuidPair rootProjectId, PurgeMapper mapper, PurgeCommands commands) { + List<IdUuidPair> childrenIdUuid = mapper.selectProjectIdUuidsByRootId(rootProjectId.getId()); + for (IdUuidPair childId : childrenIdUuid) { + deleteProject(childId, mapper, commands); + } + + List<IdUuidPair> componentIdUuids = mapper.selectComponentIdUuidsByRootId(rootProjectId.getId()); + commands.deleteResources(componentIdUuids); + } + + private void disableResource(IdUuidPair componentIdUuid, PurgeMapper mapper) { + long componentId = componentIdUuid.getId(); + mapper.deleteResourceIndex(Arrays.asList(componentId)); + mapper.setSnapshotIsLastToFalse(componentId); + mapper.deleteFileSourcesByUuid(componentIdUuid.getUuid()); + mapper.disableResource(componentId); + mapper.resolveResourceIssuesNotAlreadyResolved(componentIdUuid.getUuid(), system2.now()); + } + + public PurgeDao deleteSnapshots(PurgeSnapshotQuery query) { + final DbSession session = mybatis.openSession(true); + try { + return deleteSnapshots(query, session); + + } finally { + MyBatis.closeQuietly(session); + } + } + + public PurgeDao deleteSnapshots(PurgeSnapshotQuery query, final DbSession session) { + new PurgeCommands(session, profiler).deleteSnapshots(query); + return this; + } + + /** + * Load the whole tree of projects, including the project given in parameter. + */ + private List<ResourceDto> getProjects(long rootProjectId, SqlSession session) { + List<ResourceDto> projects = Lists.newArrayList(); + projects.add(resourceDao.getResource(rootProjectId, session)); + projects.addAll(resourceDao.getDescendantProjects(rootProjectId, session)); + return projects; + } + + public List<String> selectPurgeableFiles(DbSession dbSession, Long projectId) { + return mapper(dbSession).selectPurgeableFileUuids(projectId); + } + + private PurgeMapper mapper(DbSession session) { + return session.getMapper(PurgeMapper.class); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/purge/PurgeListener.java b/sonar-db/src/main/java/org/sonar/db/purge/PurgeListener.java new file mode 100644 index 00000000000..e1e90ccf714 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/purge/PurgeListener.java @@ -0,0 +1,33 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.purge; + +public interface PurgeListener { + + PurgeListener EMPTY = new PurgeListener() { + @Override + public void onComponentDisabling(String uuid) { + // do nothing + } + }; + + void onComponentDisabling(String uuid); +} diff --git a/sonar-db/src/main/java/org/sonar/db/purge/PurgeMapper.java b/sonar-db/src/main/java/org/sonar/db/purge/PurgeMapper.java new file mode 100644 index 00000000000..b1f84d0925f --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/purge/PurgeMapper.java @@ -0,0 +1,95 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.purge; + +import java.util.List; +import javax.annotation.Nullable; +import org.apache.ibatis.annotations.Param; + +public interface PurgeMapper { + + List<Long> selectSnapshotIds(PurgeSnapshotQuery query); + + List<Long> selectSnapshotIdsByResource(@Param("resourceIds") List<Long> resourceIds); + + List<IdUuidPair> selectProjectIdUuidsByRootId(long rootResourceId); + + List<IdUuidPair> selectComponentIdUuidsByRootId(long rootProjectId); + + void deleteSnapshot(@Param("snapshotIds") List<Long> snapshotIds); + + void deleteSnapshotDuplications(@Param("snapshotIds") List<Long> snapshotIds); + + void deleteSnapshotEvents(@Param("snapshotIds") List<Long> snapshotIds); + + void deleteSnapshotMeasures(@Param("snapshotIds") List<Long> snapshotIds); + + List<Long> selectMetricIdsWithoutHistoricalData(); + + void deleteSnapshotWastedMeasures(@Param("snapshotIds") List<Long> snapshotIds, @Param("mids") List<Long> metricIds); + + void updatePurgeStatusToOne(long snapshotId); + + void disableResource(long resourceId); + + void resolveResourceIssuesNotAlreadyResolved(@Param("componentUuid") String componentUuid, @Param("dateAsLong") Long dateAsLong); + + void deleteResourceIndex(@Param("resourceIds") List<Long> resourceIds); + + void deleteEvent(long eventId); + + void setSnapshotIsLastToFalse(long resourceId); + + void deleteResourceLinks(@Param("componentUuids") List<String> componentUuids); + + void deleteResourceProperties(@Param("resourceIds") List<Long> resourceIds); + + void deleteResource(@Param("resourceIds") List<Long> resourceIds); + + void deleteResourceGroupRoles(@Param("resourceIds") List<Long> resourceIds); + + void deleteResourceUserRoles(@Param("resourceIds") List<Long> resourceIds); + + void deleteResourceManualMeasures(@Param("componentUuids") List<String> componentUuids); + + void deleteComponentEvents(@Param("componentUuids") List<String> componentUuids); + + void deleteResourceActionPlans(@Param("resourceIds") List<Long> resourceIds); + + void deleteAuthors(@Param("resourceIds") List<Long> resourceIds); + + List<PurgeableSnapshotDto> selectPurgeableSnapshotsWithEvents(long resourceId); + + List<PurgeableSnapshotDto> selectPurgeableSnapshotsWithoutEvents(long resourceId); + + void deleteComponentIssueChanges(@Param("componentUuids") List<String> componentUuids); + + void deleteComponentIssues(@Param("componentUuids") List<String> componentUuids); + + void deleteOldClosedIssueChanges(@Param("projectUuid") String projectUuid, @Nullable @Param("toDate") Long toDate); + + void deleteOldClosedIssues(@Param("projectUuid") String projectUuid, @Nullable @Param("toDate") Long toDate); + + void deleteFileSourcesByProjectUuid(String rootProjectUuid); + + void deleteFileSourcesByUuid(String fileUuid); + + List<String> selectPurgeableFileUuids(Long projectId); +} diff --git a/sonar-db/src/main/java/org/sonar/db/purge/PurgeProfiler.java b/sonar-db/src/main/java/org/sonar/db/purge/PurgeProfiler.java new file mode 100644 index 00000000000..c68c8dfa2cc --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/purge/PurgeProfiler.java @@ -0,0 +1,104 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.purge; + +import com.google.common.annotations.VisibleForTesting; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import org.sonar.api.utils.TimeUtils; +import org.sonar.api.utils.log.Logger; + +public class PurgeProfiler { + + private Map<String, Long> durations = new HashMap<>(); + private long startTime; + private String currentTable; + private final Clock clock; + + public PurgeProfiler() { + this(new Clock()); + } + + @VisibleForTesting + PurgeProfiler(Clock clock) { + this.clock = clock; + } + + public void reset() { + durations.clear(); + } + + void start(String table) { + this.startTime = clock.now(); + this.currentTable = table; + } + + void stop() { + final Long cumulatedDuration; + if (durations.containsKey(currentTable)) { + cumulatedDuration = durations.get(currentTable); + } else { + cumulatedDuration = 0L; + } + durations.put(currentTable, cumulatedDuration + (clock.now() - startTime)); + } + + public void dump(long totalTime, Logger logger) { + List<Entry<String, Long>> data = new ArrayList<>(durations.entrySet()); + Collections.sort(data, new Comparator<Entry<String, Long>>() { + @Override + public int compare(Entry<String, Long> o1, Entry<String, Long> o2) { + return o2.getValue().compareTo(o1.getValue()); + } + }); + double percent = totalTime / 100.0; + for (Entry<String, Long> entry : truncateList(data)) { + StringBuilder sb = new StringBuilder(); + sb.append(" o ").append(entry.getKey()).append(": ").append(TimeUtils.formatDuration(entry.getValue())) + .append(" (").append((int) (entry.getValue() / percent)).append("%)"); + logger.info(sb.toString()); + } + } + + private List<Entry<String, Long>> truncateList(List<Entry<String, Long>> sortedFullList) { + int maxSize = 10; + List<Entry<String, Long>> result = new ArrayList<>(maxSize); + int i = 0; + for (Entry<String, Long> item : sortedFullList) { + if (i++ >= maxSize || item.getValue() == 0) { + return result; + } + result.add(item); + } + return result; + } + + static class Clock { + public long now() { + return System.currentTimeMillis(); + } + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/purge/PurgeSnapshotQuery.java b/sonar-db/src/main/java/org/sonar/db/purge/PurgeSnapshotQuery.java new file mode 100644 index 00000000000..2e44e1033ee --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/purge/PurgeSnapshotQuery.java @@ -0,0 +1,130 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.purge; + +public final class PurgeSnapshotQuery { + private Long id; + private Long rootProjectId; + private Long rootSnapshotId; + private Long resourceId; + private String[] scopes; + private String[] qualifiers; + private String[] status; + private Boolean islast; + private Boolean notPurged; + private Boolean withVersionEvent; + + private PurgeSnapshotQuery() { + } + + public static PurgeSnapshotQuery create() { + return new PurgeSnapshotQuery(); + } + + public Long getId() { + return id; + } + + public PurgeSnapshotQuery setId(Long l) { + this.id = l; + return this; + } + + public Long getRootProjectId() { + return rootProjectId; + } + + public PurgeSnapshotQuery setRootProjectId(Long rootProjectId) { + this.rootProjectId = rootProjectId; + return this; + } + + public String[] getScopes() { + return scopes;// NOSONAR May expose internal representation by returning reference to mutable object + } + + public PurgeSnapshotQuery setScopes(String[] scopes) { + this.scopes = scopes; // NOSONAR May expose internal representation by incorporating reference to mutable object + return this; + } + + public String[] getQualifiers() { + return qualifiers;// NOSONAR May expose internal representation by returning reference to mutable object + } + + public PurgeSnapshotQuery setQualifiers(String[] qualifiers) { + this.qualifiers = qualifiers;// NOSONAR May expose internal representation by incorporating reference to mutable object + return this; + } + + public String[] getStatus() { + return status;// NOSONAR May expose internal representation by returning reference to mutable object + } + + public PurgeSnapshotQuery setStatus(String[] status) { + this.status = status; // NOSONAR org.sonar.db.purge.PurgeSnapshotQuery.setStatus(String[]) may expose internal representation + return this; + } + + public Boolean getIslast() { + return islast; + } + + public PurgeSnapshotQuery setIslast(Boolean islast) { + this.islast = islast; + return this; + } + + public Boolean getNotPurged() { + return notPurged; + } + + public PurgeSnapshotQuery setNotPurged(Boolean notPurged) { + this.notPurged = notPurged; + return this; + } + + public Long getRootSnapshotId() { + return rootSnapshotId; + } + + public PurgeSnapshotQuery setRootSnapshotId(Long rootSnapshotId) { + this.rootSnapshotId = rootSnapshotId; + return this; + } + + public Long getResourceId() { + return resourceId; + } + + public PurgeSnapshotQuery setResourceId(Long l) { + this.resourceId = l; + return this; + } + + public Boolean getWithVersionEvent() { + return withVersionEvent; + } + + public PurgeSnapshotQuery setWithVersionEvent(Boolean withVersionEvent) { + this.withVersionEvent = withVersionEvent; + return this; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/purge/PurgeableSnapshotDto.java b/sonar-db/src/main/java/org/sonar/db/purge/PurgeableSnapshotDto.java new file mode 100644 index 00000000000..b879738b04d --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/purge/PurgeableSnapshotDto.java @@ -0,0 +1,94 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.purge; + +import java.util.Date; +import org.apache.commons.lang.builder.ReflectionToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; + +public class PurgeableSnapshotDto implements Comparable<PurgeableSnapshotDto> { + private Date date; + private long snapshotId; + private boolean hasEvents; + private boolean isLast; + + public Date getDate() { + return date; + } + + public long getSnapshotId() { + return snapshotId; + } + + public boolean hasEvents() { + return hasEvents; + } + + public boolean isLast() { + return isLast; + } + + public PurgeableSnapshotDto setDate(Long aLong) { + this.date = new Date(aLong); + return this; + } + + public PurgeableSnapshotDto setSnapshotId(long snapshotId) { + this.snapshotId = snapshotId; + return this; + } + + public PurgeableSnapshotDto setHasEvents(boolean b) { + this.hasEvents = b; + return this; + } + + public PurgeableSnapshotDto setLast(boolean last) { + isLast = last; + return this; + } + + @Override + public int compareTo(PurgeableSnapshotDto other) { + return date.compareTo(other.date); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + PurgeableSnapshotDto that = (PurgeableSnapshotDto) o; + return snapshotId == that.snapshotId; + } + + @Override + public int hashCode() { + return (int) snapshotId; + } + + @Override + public String toString() { + return new ReflectionToStringBuilder(this, ToStringStyle.SIMPLE_STYLE).toString(); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/purge/package-info.java b/sonar-db/src/main/java/org/sonar/db/purge/package-info.java new file mode 100644 index 00000000000..890b581cc1c --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/purge/package-info.java @@ -0,0 +1,25 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.purge; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/sonar-db/src/main/java/org/sonar/db/purge/period/DefaultPeriodCleaner.java b/sonar-db/src/main/java/org/sonar/db/purge/period/DefaultPeriodCleaner.java new file mode 100644 index 00000000000..ac7bad54d1a --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/purge/period/DefaultPeriodCleaner.java @@ -0,0 +1,69 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.purge.period; + +import com.google.common.annotations.VisibleForTesting; +import java.util.List; +import org.sonar.api.config.Settings; +import org.sonar.api.server.ServerSide; +import org.sonar.api.utils.DateUtils; +import org.sonar.api.utils.log.Logger; +import org.sonar.api.utils.log.Loggers; +import org.sonar.db.DbSession; +import org.sonar.db.purge.PurgeDao; +import org.sonar.db.purge.PurgeSnapshotQuery; +import org.sonar.db.purge.PurgeableSnapshotDto; + +@ServerSide +public class DefaultPeriodCleaner { + + private static final Logger LOG = Loggers.get(DefaultPeriodCleaner.class); + private PurgeDao purgeDao; + + public DefaultPeriodCleaner(PurgeDao purgeDao) { + this.purgeDao = purgeDao; + } + + public void clean(DbSession session, long projectId, Settings settings) { + doClean(projectId, new Filters(settings).all(), session); + } + + @VisibleForTesting + void doClean(long projectId, List<Filter> filters, DbSession session) { + List<PurgeableSnapshotDto> history = selectProjectSnapshots(projectId, session); + for (Filter filter : filters) { + filter.log(); + delete(filter.filter(history), session); + } + } + + private void delete(List<PurgeableSnapshotDto> snapshots, DbSession session) { + for (PurgeableSnapshotDto snapshot : snapshots) { + LOG.debug("<- Delete snapshot: {} [{}]", DateUtils.formatDateTime(snapshot.getDate()), snapshot.getSnapshotId()); + purgeDao.deleteSnapshots(PurgeSnapshotQuery.create().setRootSnapshotId(snapshot.getSnapshotId()), session); + purgeDao.deleteSnapshots(PurgeSnapshotQuery.create().setId(snapshot.getSnapshotId()), session); + } + } + + private List<PurgeableSnapshotDto> selectProjectSnapshots(long resourceId, DbSession session) { + return purgeDao.selectPurgeableSnapshots(resourceId, session); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/purge/period/DeleteAllFilter.java b/sonar-db/src/main/java/org/sonar/db/purge/period/DeleteAllFilter.java new file mode 100644 index 00000000000..9cd9275eaad --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/purge/period/DeleteAllFilter.java @@ -0,0 +1,52 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.purge.period; + +import com.google.common.collect.Lists; +import java.util.Date; +import java.util.List; +import org.sonar.api.utils.DateUtils; +import org.sonar.api.utils.log.Loggers; +import org.sonar.db.purge.PurgeableSnapshotDto; + +class DeleteAllFilter implements Filter { + private final Date before; + + public DeleteAllFilter(Date before) { + this.before = before; + } + + @Override + public List<PurgeableSnapshotDto> filter(List<PurgeableSnapshotDto> history) { + List<PurgeableSnapshotDto> result = Lists.newArrayList(); + for (PurgeableSnapshotDto snapshot : history) { + if (snapshot.getDate().before(before)) { + result.add(snapshot); + } + } + return result; + } + + @Override + public void log() { + Loggers.get(getClass()).debug("-> Delete data prior to: {}", DateUtils.formatDate(before)); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/purge/period/Filter.java b/sonar-db/src/main/java/org/sonar/db/purge/period/Filter.java new file mode 100644 index 00000000000..b10fb4cd342 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/purge/period/Filter.java @@ -0,0 +1,30 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.purge.period; + +import java.util.List; +import org.sonar.db.purge.PurgeableSnapshotDto; + +interface Filter { + List<PurgeableSnapshotDto> filter(List<PurgeableSnapshotDto> snapshots); + + void log(); +} diff --git a/sonar-db/src/main/java/org/sonar/db/purge/period/Filters.java b/sonar-db/src/main/java/org/sonar/db/purge/period/Filters.java new file mode 100644 index 00000000000..08b9bf04648 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/purge/period/Filters.java @@ -0,0 +1,59 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.purge.period; + +import com.google.common.collect.Lists; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import org.apache.commons.lang.time.DateUtils; +import org.sonar.api.config.Settings; +import org.sonar.core.config.PurgeConstants; + +class Filters { + private final List<Filter> all = Lists.newArrayList(); + + Filters(Settings settings) { + Date dateToStartKeepingOneSnapshotByDay = getDateFromHours(settings, PurgeConstants.HOURS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_DAY); + Date dateToStartKeepingOneSnapshotByWeek = getDateFromWeeks(settings, PurgeConstants.WEEKS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_WEEK); + Date dateToStartKeepingOneSnapshotByMonth = getDateFromWeeks(settings, PurgeConstants.WEEKS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_MONTH); + Date dateToStartDeletingAllSnapshots = getDateFromWeeks(settings, PurgeConstants.WEEKS_BEFORE_DELETING_ALL_SNAPSHOTS); + + all.add(new KeepOneFilter(dateToStartKeepingOneSnapshotByWeek, dateToStartKeepingOneSnapshotByDay, Calendar.DAY_OF_YEAR, "day")); + all.add(new KeepOneFilter(dateToStartKeepingOneSnapshotByMonth, dateToStartKeepingOneSnapshotByWeek, Calendar.WEEK_OF_YEAR, "week")); + all.add(new KeepOneFilter(dateToStartDeletingAllSnapshots, dateToStartKeepingOneSnapshotByMonth, Calendar.MONTH, "month")); + all.add(new DeleteAllFilter(dateToStartDeletingAllSnapshots)); + } + + static Date getDateFromWeeks(Settings settings, String propertyKey) { + int weeks = settings.getInt(propertyKey); + return DateUtils.addWeeks(new Date(), -weeks); + } + + static Date getDateFromHours(Settings settings, String propertyKey) { + int hours = settings.getInt(propertyKey); + return DateUtils.addHours(new Date(), -hours); + } + + List<Filter> all() { + return all; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/purge/period/Interval.java b/sonar-db/src/main/java/org/sonar/db/purge/period/Interval.java new file mode 100644 index 00000000000..2014d3fbecc --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/purge/period/Interval.java @@ -0,0 +1,73 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.purge.period; + +import com.google.common.collect.Lists; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.List; +import org.apache.commons.lang.time.DateUtils; +import org.sonar.db.purge.PurgeableSnapshotDto; + +final class Interval { + List<PurgeableSnapshotDto> snapshots = Lists.newArrayList(); + + void add(PurgeableSnapshotDto snapshot) { + snapshots.add(snapshot); + } + + List<PurgeableSnapshotDto> get() { + return snapshots; + } + + int count() { + return snapshots.size(); + } + + static List<Interval> group(List<PurgeableSnapshotDto> snapshots, Date start, Date end, int calendarField) { + List<Interval> intervals = Lists.newArrayList(); + + GregorianCalendar calendar = new GregorianCalendar(); + int lastYear = -1; + int lastFieldValue = -1; + Interval currentInterval = null; + + for (PurgeableSnapshotDto snapshot : snapshots) { + if (!DateUtils.isSameDay(start, snapshot.getDate()) && snapshot.getDate().after(start) && + (snapshot.getDate().before(end) || DateUtils.isSameDay(end, snapshot.getDate()))) { + calendar.setTime(snapshot.getDate()); + int currentFieldValue = calendar.get(calendarField); + int currentYear = calendar.get(Calendar.YEAR); + if (lastYear != currentYear || lastFieldValue != currentFieldValue) { + currentInterval = new Interval(); + intervals.add(currentInterval); + } + lastFieldValue = currentFieldValue; + lastYear = currentYear; + if (currentInterval != null) { + currentInterval.add(snapshot); + } + } + } + return intervals; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/purge/period/KeepOneFilter.java b/sonar-db/src/main/java/org/sonar/db/purge/period/KeepOneFilter.java new file mode 100644 index 00000000000..7335e7c1981 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/purge/period/KeepOneFilter.java @@ -0,0 +1,88 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.purge.period; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.Lists; +import java.util.Date; +import java.util.List; +import org.sonar.api.utils.DateUtils; +import org.sonar.api.utils.log.Loggers; +import org.sonar.db.purge.PurgeableSnapshotDto; + +class KeepOneFilter implements Filter { + + private final Date start; + private final Date end; + private final int dateField; + private final String label; + + KeepOneFilter(Date start, Date end, int calendarField, String label) { + this.start = start; + this.end = end; + this.dateField = calendarField; + this.label = label; + } + + @Override + public List<PurgeableSnapshotDto> filter(List<PurgeableSnapshotDto> history) { + List<Interval> intervals = Interval.group(history, start, end, dateField); + List<PurgeableSnapshotDto> result = Lists.newArrayList(); + for (Interval interval : intervals) { + appendSnapshotsToDelete(interval, result); + } + + return result; + } + + @Override + public void log() { + Loggers.get(getClass()).debug("-> Keep one snapshot per {} between {} and {}", label, DateUtils.formatDate(start), DateUtils.formatDate(end)); + } + + private void appendSnapshotsToDelete(Interval interval, List<PurgeableSnapshotDto> toDelete) { + if (interval.count() > 1) { + List<PurgeableSnapshotDto> deletables = Lists.newArrayList(); + List<PurgeableSnapshotDto> toKeep = Lists.newArrayList(); + for (PurgeableSnapshotDto snapshot : interval.get()) { + if (isDeletable(snapshot)) { + deletables.add(snapshot); + } else { + toKeep.add(snapshot); + } + } + + if (!toKeep.isEmpty()) { + toDelete.addAll(deletables); + + } else if (deletables.size() > 1) { + // keep one snapshot + toDelete.addAll(deletables.subList(1, deletables.size())); + } + } + } + + @VisibleForTesting + static boolean isDeletable(PurgeableSnapshotDto snapshot) { + return !snapshot.isLast() && !snapshot.hasEvents(); + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/purge/period/package-info.java b/sonar-db/src/main/java/org/sonar/db/purge/period/package-info.java new file mode 100644 index 00000000000..462f8f07e52 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/purge/period/package-info.java @@ -0,0 +1,25 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.purge.period; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/sonar-db/src/main/java/org/sonar/db/qualitygate/ProjectQgateAssociation.java b/sonar-db/src/main/java/org/sonar/db/qualitygate/ProjectQgateAssociation.java new file mode 100644 index 00000000000..5aafbde3669 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/qualitygate/ProjectQgateAssociation.java @@ -0,0 +1,79 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.qualitygate; + +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; + +public class ProjectQgateAssociation { + + private Long id; + private String name; + private boolean isMember; + + public Long id() { + return id; + } + + public ProjectQgateAssociation setId(Long id) { + this.id = id; + return this; + } + + public String name() { + return name; + } + + public ProjectQgateAssociation setName(String name) { + this.name = name; + return this; + } + + public boolean isMember() { + return isMember; + } + + public ProjectQgateAssociation setMember(boolean isMember) { + this.isMember = isMember; + return this; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ProjectQgateAssociation that = (ProjectQgateAssociation) o; + return name.equals(that.name); + } + + @Override + public int hashCode() { + return name.hashCode(); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/qualitygate/ProjectQgateAssociationDao.java b/sonar-db/src/main/java/org/sonar/db/qualitygate/ProjectQgateAssociationDao.java new file mode 100644 index 00000000000..e5c03caa515 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/qualitygate/ProjectQgateAssociationDao.java @@ -0,0 +1,58 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.qualitygate; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.ImmutableMap; +import java.util.List; +import java.util.Map; +import org.apache.ibatis.session.RowBounds; +import org.apache.ibatis.session.SqlSession; +import org.sonar.db.MyBatis; + +public class ProjectQgateAssociationDao { + + private final MyBatis mybatis; + + public ProjectQgateAssociationDao(MyBatis mybatis) { + this.mybatis = mybatis; + } + + public List<ProjectQgateAssociationDto> selectProjects(ProjectQgateAssociationQuery query, Long gateId, int offset, int limit) { + SqlSession session = mybatis.openSession(false); + try { + Map<String, Object> params = ImmutableMap.of("query", query, "gateId", gateId.toString()); + return mapper(session).selectProjects(params, new RowBounds(offset, limit)); + } finally { + MyBatis.closeQuietly(session); + } + } + + @VisibleForTesting + List<ProjectQgateAssociationDto> selectProjects(ProjectQgateAssociationQuery query, Long gateId) { + return selectProjects(query, gateId, 0, Integer.MAX_VALUE); + } + + private ProjectQgateAssociationMapper mapper(SqlSession session) { + return session.getMapper(ProjectQgateAssociationMapper.class); + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/qualitygate/ProjectQgateAssociationDto.java b/sonar-db/src/main/java/org/sonar/db/qualitygate/ProjectQgateAssociationDto.java new file mode 100644 index 00000000000..18b3d7f0e19 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/qualitygate/ProjectQgateAssociationDto.java @@ -0,0 +1,68 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.qualitygate; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; + +/** + * @since 4.3 + */ +public class ProjectQgateAssociationDto { + + private Long id; + private String name; + private String gateId; + + public Long getId() { + return id; + } + + public ProjectQgateAssociationDto setId(Long id) { + this.id = id; + return this; + } + + public String getName() { + return name; + } + + public ProjectQgateAssociationDto setName(String name) { + this.name = name; + return this; + } + + @CheckForNull + public String getGateId() { + return gateId; + } + + public ProjectQgateAssociationDto setGateId(@Nullable String gateId) { + this.gateId = gateId; + return this; + } + + public ProjectQgateAssociation toQgateAssociation() { + return new ProjectQgateAssociation() + .setId(id) + .setName(name) + .setMember(gateId != null); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/qualitygate/ProjectQgateAssociationMapper.java b/sonar-db/src/main/java/org/sonar/db/qualitygate/ProjectQgateAssociationMapper.java new file mode 100644 index 00000000000..1472fe7199a --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/qualitygate/ProjectQgateAssociationMapper.java @@ -0,0 +1,31 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.qualitygate; + +import java.util.List; +import java.util.Map; +import org.apache.ibatis.session.RowBounds; + +public interface ProjectQgateAssociationMapper { + + List<ProjectQgateAssociationDto> selectProjects(ProjectQgateAssociationQuery query); + + List<ProjectQgateAssociationDto> selectProjects(Map<String, Object> params, RowBounds rowBounds); +} diff --git a/sonar-db/src/main/java/org/sonar/db/qualitygate/ProjectQgateAssociationQuery.java b/sonar-db/src/main/java/org/sonar/db/qualitygate/ProjectQgateAssociationQuery.java new file mode 100644 index 00000000000..7a96fe57b05 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/qualitygate/ProjectQgateAssociationQuery.java @@ -0,0 +1,168 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.qualitygate; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableSet; +import java.util.Set; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.apache.commons.lang.StringUtils; + +public class ProjectQgateAssociationQuery { + + public static final int DEFAULT_PAGE_INDEX = 1; + public static final int DEFAULT_PAGE_SIZE = 100; + + public static final String ANY = "all"; + public static final String IN = "selected"; + public static final String OUT = "deselected"; + public static final Set<String> AVAILABLE_MEMBERSHIP = ImmutableSet.of(ANY, IN, OUT); + + private final String gateId; + private final String membership; + + private final String projectSearch; + + // for internal use in MyBatis + final String projectSearchSql; + + // max results per page + private final int pageSize; + + // index of selected page. Start with 1. + private final int pageIndex; + + private ProjectQgateAssociationQuery(Builder builder) { + this.gateId = builder.gateId; + this.membership = builder.membership; + this.projectSearch = builder.projectSearch; + this.projectSearchSql = projectSearchToSql(projectSearch); + + this.pageSize = builder.pageSize; + this.pageIndex = builder.pageIndex; + } + + private String projectSearchToSql(@Nullable String s) { + String sql = null; + if (s != null) { + sql = StringUtils.replace(StringUtils.lowerCase(s), "%", "/%"); + sql = StringUtils.replace(sql, "_", "/_"); + sql = sql + "%"; + } + return sql; + } + + public String gateId() { + return gateId; + } + + @CheckForNull + public String membership() { + return membership; + } + + /** + * Search for projects containing a given string + */ + @CheckForNull + public String projectSearch() { + return projectSearch; + } + + public int pageSize() { + return pageSize; + } + + public int pageIndex() { + return pageIndex; + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private String gateId; + private String membership; + private String projectSearch; + + private Integer pageIndex = DEFAULT_PAGE_INDEX; + private Integer pageSize = DEFAULT_PAGE_SIZE; + + private Builder() { + } + + public Builder gateId(String gateId) { + this.gateId = gateId; + return this; + } + + public Builder membership(@Nullable String membership) { + this.membership = membership; + return this; + } + + public Builder projectSearch(@Nullable String s) { + this.projectSearch = StringUtils.defaultIfBlank(s, null); + return this; + } + + public Builder pageSize(@Nullable Integer i) { + this.pageSize = i; + return this; + } + + public Builder pageIndex(@Nullable Integer i) { + this.pageIndex = i; + return this; + } + + private void initMembership() { + if (membership == null) { + membership = ProjectQgateAssociationQuery.ANY; + } else { + Preconditions.checkArgument(AVAILABLE_MEMBERSHIP.contains(membership), + "Membership is not valid (got " + membership + "). Availables values are " + AVAILABLE_MEMBERSHIP); + } + } + + private void initPageSize() { + if (pageSize == null) { + pageSize = DEFAULT_PAGE_SIZE; + } + } + + private void initPageIndex() { + if (pageIndex == null) { + pageIndex = DEFAULT_PAGE_INDEX; + } + Preconditions.checkArgument(pageIndex > 0, "Page index must be greater than 0 (got " + pageIndex + ")"); + } + + public ProjectQgateAssociationQuery build() { + Preconditions.checkNotNull(gateId, "Gate ID cant be null."); + initMembership(); + initPageIndex(); + initPageSize(); + return new ProjectQgateAssociationQuery(this); + } + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/qualitygate/QualityGateConditionDao.java b/sonar-db/src/main/java/org/sonar/db/qualitygate/QualityGateConditionDao.java new file mode 100644 index 00000000000..df5f6886f25 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/qualitygate/QualityGateConditionDao.java @@ -0,0 +1,124 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.qualitygate; + +import java.util.Collection; +import java.util.Date; +import org.apache.ibatis.session.SqlSession; +import org.sonar.db.Dao; +import org.sonar.db.MyBatis; + +/** + * @since 4.3 + */ +public class QualityGateConditionDao implements Dao { + + private final MyBatis myBatis; + + public QualityGateConditionDao(MyBatis myBatis) { + this.myBatis = myBatis; + } + + public void insert(QualityGateConditionDto newQualityGate) { + SqlSession session = myBatis.openSession(false); + try { + insert(newQualityGate, session); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + public void insert(QualityGateConditionDto newQualityGate, SqlSession session) { + getMapper(session).insert(newQualityGate.setCreatedAt(new Date())); + } + + public Collection<QualityGateConditionDto> selectForQualityGate(long qGateId) { + SqlSession session = myBatis.openSession(false); + try { + return selectForQualityGate(qGateId, session); + } finally { + MyBatis.closeQuietly(session); + } + } + + public Collection<QualityGateConditionDto> selectForQualityGate(long qGateId, SqlSession session) { + return getMapper(session).selectForQualityGate(qGateId); + } + + public QualityGateConditionDto selectById(long id) { + SqlSession session = myBatis.openSession(false); + try { + return selectById(id, session); + } finally { + MyBatis.closeQuietly(session); + } + } + + public QualityGateConditionDto selectById(long id, SqlSession session) { + return getMapper(session).selectById(id); + } + + public void delete(QualityGateConditionDto qGate) { + SqlSession session = myBatis.openSession(false); + try { + delete(qGate, session); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + public void delete(QualityGateConditionDto qGate, SqlSession session) { + getMapper(session).delete(qGate.getId()); + } + + public void update(QualityGateConditionDto qGate) { + SqlSession session = myBatis.openSession(false); + try { + update(qGate, session); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + public void update(QualityGateConditionDto qGate, SqlSession session) { + getMapper(session).update(qGate.setUpdatedAt(new Date())); + } + + public void deleteConditionsWithInvalidMetrics() { + SqlSession session = myBatis.openSession(false); + try { + deleteConditionsWithInvalidMetrics(session); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + public void deleteConditionsWithInvalidMetrics(SqlSession session) { + getMapper(session).deleteConditionsWithInvalidMetrics(); + } + + private QualityGateConditionMapper getMapper(SqlSession session) { + return session.getMapper(QualityGateConditionMapper.class); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/qualitygate/QualityGateConditionDto.java b/sonar-db/src/main/java/org/sonar/db/qualitygate/QualityGateConditionDto.java new file mode 100644 index 00000000000..dbfb9654d64 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/qualitygate/QualityGateConditionDto.java @@ -0,0 +1,208 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.qualitygate; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.Map; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.sonar.api.measures.Metric.ValueType; + +/** + * @since 4.3 + */ +public class QualityGateConditionDto { + + public static final String OPERATOR_EQUALS = "EQ"; + + public static final String OPERATOR_NOT_EQUALS = "NE"; + + public static final String OPERATOR_GREATER_THAN = "GT"; + + public static final String OPERATOR_LESS_THAN = "LT"; + + public static final List<String> ALL_OPERATORS = ImmutableList.of( + OPERATOR_LESS_THAN, + OPERATOR_GREATER_THAN, + OPERATOR_EQUALS, + OPERATOR_NOT_EQUALS + ); + + private static final List<String> NUMERIC_OPERATORS = ImmutableList.of( + OPERATOR_LESS_THAN, + OPERATOR_GREATER_THAN, + OPERATOR_EQUALS, + OPERATOR_NOT_EQUALS + ); + private static final List<String> STRING_OPERATORS = ImmutableList.of( + OPERATOR_EQUALS, + OPERATOR_NOT_EQUALS, + OPERATOR_LESS_THAN, + OPERATOR_GREATER_THAN + ); + private static final List<String> LEVEL_OPERATORS = ImmutableList.of( + OPERATOR_EQUALS, + OPERATOR_NOT_EQUALS + ); + private static final List<String> BOOLEAN_OPERATORS = ImmutableList.of( + OPERATOR_EQUALS + ); + + private static final Map<ValueType, List<String>> OPERATORS_BY_TYPE = ImmutableMap.<ValueType, List<String>>builder() + .put(ValueType.BOOL, BOOLEAN_OPERATORS) + .put(ValueType.LEVEL, LEVEL_OPERATORS) + .put(ValueType.STRING, STRING_OPERATORS) + .put(ValueType.INT, NUMERIC_OPERATORS) + .put(ValueType.FLOAT, NUMERIC_OPERATORS) + .put(ValueType.PERCENT, NUMERIC_OPERATORS) + .put(ValueType.MILLISEC, NUMERIC_OPERATORS) + .put(ValueType.RATING, NUMERIC_OPERATORS) + .put(ValueType.WORK_DUR, NUMERIC_OPERATORS) + .build(); + + private long id; + + private long qualityGateId; + + private long metricId; + + private String metricKey; + + private Integer period; + + private String operator; + + private String warningThreshold; + + private String errorThreshold; + + private Date createdAt; + + private Date updatedAt; + + public long getId() { + return id; + } + + public QualityGateConditionDto setId(long id) { + this.id = id; + return this; + } + + public long getQualityGateId() { + return qualityGateId; + } + + public QualityGateConditionDto setQualityGateId(long qualityGateId) { + this.qualityGateId = qualityGateId; + return this; + } + + public long getMetricId() { + return metricId; + } + + public QualityGateConditionDto setMetricId(long metricId) { + this.metricId = metricId; + return this; + } + + @CheckForNull + public String getMetricKey() { + return metricKey; + } + + public QualityGateConditionDto setMetricKey(String metricKey) { + this.metricKey = metricKey; + return this; + } + + @CheckForNull + public Integer getPeriod() { + return period; + } + + public QualityGateConditionDto setPeriod(@Nullable Integer period) { + this.period = period; + return this; + } + + public String getOperator() { + return operator; + } + + public QualityGateConditionDto setOperator(String operator) { + this.operator = operator; + return this; + } + + public String getWarningThreshold() { + return warningThreshold; + } + + public QualityGateConditionDto setWarningThreshold(@Nullable String warningThreshold) { + this.warningThreshold = warningThreshold; + return this; + } + + public String getErrorThreshold() { + return errorThreshold; + } + + public QualityGateConditionDto setErrorThreshold(@Nullable String errorThreshold) { + this.errorThreshold = errorThreshold; + return this; + } + + public Date getCreatedAt() { + return createdAt; + } + + public QualityGateConditionDto setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + return this; + } + + public Date getUpdatedAt() { + return updatedAt; + } + + public QualityGateConditionDto setUpdatedAt(Date updatedAt) { + this.updatedAt = updatedAt; + return this; + } + + public static boolean isOperatorAllowed(String operator, ValueType metricType) { + return getOperatorsForType(metricType).contains(operator); + } + + public static Collection<String> getOperatorsForType(ValueType metricType) { + if (OPERATORS_BY_TYPE.containsKey(metricType)) { + return OPERATORS_BY_TYPE.get(metricType); + } else { + return Collections.emptySet(); + } + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/qualitygate/QualityGateConditionMapper.java b/sonar-db/src/main/java/org/sonar/db/qualitygate/QualityGateConditionMapper.java new file mode 100644 index 00000000000..da9527cbe61 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/qualitygate/QualityGateConditionMapper.java @@ -0,0 +1,37 @@ +package org.sonar.db.qualitygate; + +import java.util.List; + +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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. + */ +public interface QualityGateConditionMapper { + + void insert(QualityGateConditionDto newCondition); + + List<QualityGateConditionDto> selectForQualityGate(long qGateId); + + void update(QualityGateConditionDto newCondition); + + QualityGateConditionDto selectById(long id); + + void delete(long id); + + void deleteConditionsWithInvalidMetrics(); +} diff --git a/sonar-db/src/main/java/org/sonar/db/qualitygate/QualityGateDao.java b/sonar-db/src/main/java/org/sonar/db/qualitygate/QualityGateDao.java new file mode 100644 index 00000000000..5e483bbe30e --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/qualitygate/QualityGateDao.java @@ -0,0 +1,122 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.qualitygate; + +import java.util.Collection; +import java.util.Date; +import org.apache.ibatis.session.SqlSession; +import org.sonar.db.MyBatis; + +/** + * @since 4.3 + */ +public class QualityGateDao { + + private final MyBatis myBatis; + + public QualityGateDao(MyBatis myBatis) { + this.myBatis = myBatis; + } + + public void insert(QualityGateDto newQualityGate) { + SqlSession session = myBatis.openSession(false); + try { + insert(newQualityGate, session); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + public void insert(QualityGateDto newQualityGate, SqlSession session) { + getMapper(session).insert(newQualityGate.setCreatedAt(new Date())); + } + + public Collection<QualityGateDto> selectAll() { + SqlSession session = myBatis.openSession(false); + try { + return selectAll(session); + } finally { + MyBatis.closeQuietly(session); + } + } + + public Collection<QualityGateDto> selectAll(SqlSession session) { + return getMapper(session).selectAll(); + } + + public QualityGateDto selectByName(String name) { + SqlSession session = myBatis.openSession(false); + try { + return selectByName(name, session); + } finally { + MyBatis.closeQuietly(session); + } + } + + public QualityGateDto selectByName(String name, SqlSession session) { + return getMapper(session).selectByName(name); + } + + public QualityGateDto selectById(long id) { + SqlSession session = myBatis.openSession(false); + try { + return selectById(id, session); + } finally { + MyBatis.closeQuietly(session); + } + } + + public QualityGateDto selectById(long id, SqlSession session) { + return getMapper(session).selectById(id); + } + + public void delete(QualityGateDto qGate) { + SqlSession session = myBatis.openSession(false); + try { + delete(qGate, session); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + public void delete(QualityGateDto qGate, SqlSession session) { + getMapper(session).delete(qGate.getId()); + } + + public void update(QualityGateDto qGate) { + SqlSession session = myBatis.openSession(false); + try { + update(qGate, session); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + public void update(QualityGateDto qGate, SqlSession session) { + getMapper(session).update(qGate.setUpdatedAt(new Date())); + } + + private QualityGateMapper getMapper(SqlSession session) { + return session.getMapper(QualityGateMapper.class); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/qualitygate/QualityGateDto.java b/sonar-db/src/main/java/org/sonar/db/qualitygate/QualityGateDto.java new file mode 100644 index 00000000000..e0e0f083ba3 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/qualitygate/QualityGateDto.java @@ -0,0 +1,72 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.qualitygate; + +import java.util.Date; + +/** + * @since 4.3 + */ +public class QualityGateDto { + + private Long id; + + private String name; + + private Date createdAt; + + private Date updatedAt; + + public Long getId() { + return id; + } + + public QualityGateDto setId(Long id) { + this.id = id; + return this; + } + + public String getName() { + return name; + } + + public QualityGateDto setName(String name) { + this.name = name; + return this; + } + + public Date getCreatedAt() { + return createdAt; + } + + public QualityGateDto setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + return this; + } + + public Date getUpdatedAt() { + return updatedAt; + } + + public QualityGateDto setUpdatedAt(Date updatedAt) { + this.updatedAt = updatedAt; + return this; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/qualitygate/QualityGateMapper.java b/sonar-db/src/main/java/org/sonar/db/qualitygate/QualityGateMapper.java new file mode 100644 index 00000000000..c4880835cbe --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/qualitygate/QualityGateMapper.java @@ -0,0 +1,37 @@ +package org.sonar.db.qualitygate; + +import java.util.List; + +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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. + */ +public interface QualityGateMapper { + + void insert(QualityGateDto newQualityGate); + + List<QualityGateDto> selectAll(); + + QualityGateDto selectByName(String name); + + QualityGateDto selectById(long id); + + void delete(long id); + + void update(QualityGateDto qGate); +} diff --git a/sonar-db/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDao.java b/sonar-db/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDao.java new file mode 100644 index 00000000000..24efe187dd7 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDao.java @@ -0,0 +1,67 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.qualityprofile; + +import java.util.List; +import org.apache.ibatis.session.SqlSession; +import org.sonar.api.server.ServerSide; +import org.sonar.db.DbSession; +import org.sonar.db.MyBatis; + +/** + * @deprecated use the ActiveRuleDao class defined in sonar-server + */ +@Deprecated +@ServerSide +public class ActiveRuleDao { + + private final MyBatis mybatis; + + public ActiveRuleDao(MyBatis mybatis) { + this.mybatis = mybatis; + } + + public void insert(ActiveRuleDto dto, SqlSession session) { + session.getMapper(ActiveRuleMapper.class).insert(dto); + } + + public List<ActiveRuleDto> selectByProfileKey(String profileKey) { + DbSession session = mybatis.openSession(false); + try { + return session.getMapper(ActiveRuleMapper.class).selectByProfileKey(profileKey); + } finally { + session.close(); + } + } + + public void insert(ActiveRuleParamDto dto, SqlSession session) { + session.getMapper(ActiveRuleMapper.class).insertParameter(dto); + } + + public List<ActiveRuleParamDto> selectParamsByProfileKey(String profileKey) { + DbSession session = mybatis.openSession(false); + try { + return session.getMapper(ActiveRuleMapper.class).selectParamsByProfileKey(profileKey); + } finally { + session.close(); + } + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDto.java b/sonar-db/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDto.java new file mode 100644 index 00000000000..ab2d37f9e84 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDto.java @@ -0,0 +1,159 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.qualityprofile; + +import com.google.common.base.Preconditions; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.builder.ReflectionToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; +import org.sonar.api.rule.RuleKey; +import org.sonar.api.rules.ActiveRule; +import org.sonar.core.rule.SeverityUtil; +import org.sonar.db.Dto; +import org.sonar.db.rule.RuleDto; + +public class ActiveRuleDto extends Dto<ActiveRuleKey> { + + public static final String INHERITED = ActiveRule.INHERITED; + public static final String OVERRIDES = ActiveRule.OVERRIDES; + + private String repository; + private String ruleField; + private String profileKey; + + private Integer id; + private Integer profileId; + private Integer ruleId; + private Integer severity; + private String inheritance; + + /** + * @deprecated for internal use, should be private + */ + @Deprecated + public ActiveRuleDto setKey(ActiveRuleKey key) { + this.repository = key.ruleKey().repository(); + this.ruleField = key.ruleKey().rule(); + this.profileKey = key.qProfile(); + return this; + } + + @Override + public ActiveRuleKey getKey() { + return ActiveRuleKey.of(profileKey, RuleKey.of(repository, ruleField)); + } + + // This field do not exists in db, it's only retrieve by joins + private Integer parentId; + + public Integer getId() { + return id; + } + + public ActiveRuleDto setId(Integer id) { + this.id = id; + return this; + } + + public Integer getProfileId() { + return profileId; + } + + // TODO mark as private + public ActiveRuleDto setProfileId(Integer profileId) { + this.profileId = profileId; + return this; + } + + public Integer getRuleId() { + return ruleId; + } + + // TODO mark as private + public ActiveRuleDto setRuleId(Integer ruleId) { + this.ruleId = ruleId; + return this; + } + + public Integer getSeverity() { + return severity; + } + + public String getSeverityString() { + return SeverityUtil.getSeverityFromOrdinal(severity); + } + + public ActiveRuleDto setSeverity(Integer severity) { + this.severity = severity; + return this; + } + + public ActiveRuleDto setSeverity(String severity) { + this.severity = SeverityUtil.getOrdinalFromSeverity(severity); + return this; + } + + @CheckForNull + public String getInheritance() { + return inheritance; + } + + public ActiveRuleDto setInheritance(@Nullable String inheritance) { + this.inheritance = inheritance; + return this; + } + + @CheckForNull + public Integer getParentId() { + return parentId; + } + + public ActiveRuleDto setParentId(@Nullable Integer parentId) { + this.parentId = parentId; + return this; + } + + public boolean isInherited() { + return StringUtils.equals(INHERITED, inheritance); + } + + public boolean doesOverride() { + return StringUtils.equals(OVERRIDES, inheritance); + } + + public static ActiveRuleDto createFor(QualityProfileDto profileDto, RuleDto ruleDto) { + Preconditions.checkNotNull(profileDto.getId(), "Profile is not persisted"); + Preconditions.checkNotNull(ruleDto.getId(), "Rule is not persisted"); + ActiveRuleDto dto = new ActiveRuleDto(); + dto.setProfileId(profileDto.getId()); + dto.setRuleId(ruleDto.getId()); + dto.setKey(ActiveRuleKey.of(profileDto.getKee(), ruleDto.getKey())); + return dto; + } + + @Override + public String toString() { + return new ReflectionToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).toString(); + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/qualityprofile/ActiveRuleKey.java b/sonar-db/src/main/java/org/sonar/db/qualityprofile/ActiveRuleKey.java new file mode 100644 index 00000000000..4527fabaf88 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/qualityprofile/ActiveRuleKey.java @@ -0,0 +1,107 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.qualityprofile; + +import com.google.common.base.Preconditions; +import java.io.Serializable; +import org.sonar.api.rule.RuleKey; + +/** + * + * @since 4.4 + */ +public class ActiveRuleKey implements Serializable { + + private final String qualityProfileKey; + private final RuleKey ruleKey; + + protected ActiveRuleKey(String qualityProfileKey, RuleKey ruleKey) { + this.qualityProfileKey = qualityProfileKey; + this.ruleKey = ruleKey; + } + + /** + * Create a key. Parameters are NOT null. + */ + public static ActiveRuleKey of(String qualityProfileKey, RuleKey ruleKey) { + Preconditions.checkNotNull(qualityProfileKey, "QProfile is missing"); + Preconditions.checkNotNull(ruleKey, "RuleKey is missing"); + return new ActiveRuleKey(qualityProfileKey, ruleKey); + } + + /** + * Create a key from a string representation (see {@link #toString()}. An {@link IllegalArgumentException} is raised + * if the format is not valid. + */ + public static ActiveRuleKey parse(String s) { + Preconditions.checkArgument(s.split(":").length >= 3, "Bad format of activeRule key: " + s); + int semiColonPos = s.indexOf(":"); + String key = s.substring(0, semiColonPos); + String ruleKey = s.substring(semiColonPos + 1); + return ActiveRuleKey.of(key, RuleKey.parse(ruleKey)); + } + + /** + * Never null + */ + public RuleKey ruleKey() { + return ruleKey; + } + + /** + * Never null + */ + public String qProfile() { + return qualityProfileKey; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ActiveRuleKey activeRuleKey = (ActiveRuleKey) o; + if (!qualityProfileKey.equals(activeRuleKey.qualityProfileKey)) { + return false; + } + if (!ruleKey.equals(activeRuleKey.ruleKey)) { + return false; + } + return true; + } + + @Override + public int hashCode() { + int result = qualityProfileKey.hashCode(); + result = 31 * result + ruleKey.hashCode(); + return result; + } + + /** + * Format is "qprofile:rule", for example "12345:squid:AvoidCycle" + */ + @Override + public String toString() { + return String.format("%s:%s", qualityProfileKey, ruleKey.toString()); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/qualityprofile/ActiveRuleMapper.java b/sonar-db/src/main/java/org/sonar/db/qualityprofile/ActiveRuleMapper.java new file mode 100644 index 00000000000..ee409f35171 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/qualityprofile/ActiveRuleMapper.java @@ -0,0 +1,68 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.qualityprofile; + +import java.sql.Timestamp; +import java.util.List; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.apache.ibatis.annotations.Param; + +public interface ActiveRuleMapper { + + void insert(ActiveRuleDto dto); + + void update(ActiveRuleDto dto); + + void delete(int activeRuleId); + + @CheckForNull + ActiveRuleDto selectById(Integer id); + + List<ActiveRuleDto> selectByRuleId(int ruleId); + + List<ActiveRuleDto> selectByProfileKey(String key); + + List<ActiveRuleDto> selectAll(); + + void insertParameter(ActiveRuleParamDto dto); + + void updateParameter(ActiveRuleParamDto dto); + + void deleteParameters(int activeRuleId); + + void deleteParameter(int activeRuleParamId); + + @CheckForNull + ActiveRuleParamDto selectParamByActiveRuleAndKey(@Param("activeRuleId") int activeRuleId, @Param("key") String key); + + List<ActiveRuleParamDto> selectParamsByActiveRuleId(int activeRuleId); + + List<ActiveRuleParamDto> selectParamsByProfileKey(String profileKey); + + ActiveRuleDto selectByKey(@Param("profileKey") String profileKey, + @Param("repository") String repository, @Param("rule") String rule); + + List<ActiveRuleParamDto> selectAllParams(); + + List<ActiveRuleDto> selectAfterDate(@Nullable Timestamp date); + +} diff --git a/sonar-db/src/main/java/org/sonar/db/qualityprofile/ActiveRuleParamDto.java b/sonar-db/src/main/java/org/sonar/db/qualityprofile/ActiveRuleParamDto.java new file mode 100644 index 00000000000..6036f548c8c --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/qualityprofile/ActiveRuleParamDto.java @@ -0,0 +1,104 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.qualityprofile; + +import com.google.common.base.Preconditions; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import org.apache.commons.lang.builder.ReflectionToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; +import org.sonar.db.rule.RuleParamDto; + +public class ActiveRuleParamDto { + + private Integer id; + private Integer activeRuleId; + private Integer rulesParameterId; + private String kee; + private String value; + + public Integer getId() { + return id; + } + + public ActiveRuleParamDto setId(Integer id) { + this.id = id; + return this; + } + + public Integer getActiveRuleId() { + return activeRuleId; + } + + public ActiveRuleParamDto setActiveRuleId(Integer activeRuleId) { + this.activeRuleId = activeRuleId; + return this; + } + + public Integer getRulesParameterId() { + return rulesParameterId; + } + + // TODO set private or drop + public ActiveRuleParamDto setRulesParameterId(Integer rulesParameterId) { + this.rulesParameterId = rulesParameterId; + return this; + } + + public String getKey() { + return kee; + } + + public ActiveRuleParamDto setKey(String key) { + this.kee = key; + return this; + } + + public String getValue() { + return value; + } + + public ActiveRuleParamDto setValue(String value) { + this.value = value; + return this; + } + + @Override + public String toString() { + return new ReflectionToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).toString(); + } + + public static ActiveRuleParamDto createFor(RuleParamDto param) { + Preconditions.checkArgument(param.getId() != null, "Parameter is not persisted"); + return new ActiveRuleParamDto() + .setKey(param.getName()) + .setRulesParameterId(param.getId()); + } + + public static Map<String, ActiveRuleParamDto> groupByKey(Collection<ActiveRuleParamDto> params) { + Map<String, ActiveRuleParamDto> result = new HashMap<>(); + for (ActiveRuleParamDto param : params) { + result.put(param.getKey(), param); + } + return result; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/qualityprofile/ProjectQprofileAssociationDto.java b/sonar-db/src/main/java/org/sonar/db/qualityprofile/ProjectQprofileAssociationDto.java new file mode 100644 index 00000000000..cb0c8e205bb --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/qualityprofile/ProjectQprofileAssociationDto.java @@ -0,0 +1,51 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.qualityprofile; + +import javax.annotation.CheckForNull; + +public class ProjectQprofileAssociationDto { + + private Long projectId; + private String projectUuid; + private String projectName; + private String profileKey; + + public Long getProjectId() { + return projectId; + } + + public String getProjectUuid() { + return projectUuid; + } + + public String getProjectName() { + return projectName; + } + + @CheckForNull + public String getProfileKey() { + return profileKey; + } + + public boolean isAssociated() { + return profileKey != null; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/qualityprofile/QualityProfileDao.java b/sonar-db/src/main/java/org/sonar/db/qualityprofile/QualityProfileDao.java new file mode 100644 index 00000000000..b184b493e01 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/qualityprofile/QualityProfileDao.java @@ -0,0 +1,376 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.qualityprofile; + +import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import java.util.Date; +import java.util.List; +import java.util.Map; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.sonar.api.server.ServerSide; +import org.sonar.api.utils.System2; +import org.sonar.db.Dao; +import org.sonar.db.DbSession; +import org.sonar.db.MyBatis; +import org.sonar.db.component.ComponentDto; + +@ServerSide +public class QualityProfileDao implements Dao { + + private final MyBatis mybatis; + private final System2 system; + + public QualityProfileDao(MyBatis mybatis, System2 system) { + this.mybatis = mybatis; + this.system = system; + } + + @CheckForNull + public QualityProfileDto getByKey(DbSession session, String key) { + return getMapper(session).selectByKey(key); + } + + public QualityProfileDto getNonNullByKey(DbSession session, String key) { + QualityProfileDto dto = getByKey(session, key); + if (dto == null) { + throw new IllegalArgumentException("Quality profile not found: " + key); + } + return dto; + } + + public List<QualityProfileDto> findAll(DbSession session) { + return getMapper(session).selectAll(); + } + + public void insert(DbSession session, QualityProfileDto profile, QualityProfileDto... otherProfiles) { + QualityProfileMapper mapper = getMapper(session); + doInsert(mapper, profile); + for (QualityProfileDto other : otherProfiles) { + doInsert(mapper, other); + } + } + + private void doInsert(QualityProfileMapper mapper, QualityProfileDto profile) { + Preconditions.checkArgument(profile.getId() == null, "Quality profile is already persisted (got id %d)", profile.getId()); + Date now = new Date(system.now()); + profile.setCreatedAt(now); + profile.setUpdatedAt(now); + mapper.insert(profile); + } + + /** + * @deprecated use {@link #insert(DbSession, QualityProfileDto, QualityProfileDto...)} + */ + @Deprecated + public void insert(QualityProfileDto dto) { + DbSession session = mybatis.openSession(false); + try { + insert(session, dto); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + public void update(DbSession session, QualityProfileDto profile, QualityProfileDto... otherProfiles) { + QualityProfileMapper mapper = getMapper(session); + doUpdate(mapper, profile); + for (QualityProfileDto otherProfile : otherProfiles) { + doUpdate(mapper, otherProfile); + } + } + + private void doUpdate(QualityProfileMapper mapper, QualityProfileDto profile) { + Preconditions.checkArgument(profile.getId() != null, "Quality profile is not persisted"); + profile.setUpdatedAt(new Date(system.now())); + mapper.update(profile); + } + + /** + * @deprecated use {@link #update(DbSession, QualityProfileDto, QualityProfileDto...)} + */ + @Deprecated + public void update(QualityProfileDto dto) { + DbSession session = mybatis.openSession(false); + try { + update(session, dto); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + public void delete(DbSession session, QualityProfileDto profile, QualityProfileDto... otherProfiles) { + QualityProfileMapper mapper = getMapper(session); + doDelete(mapper, profile); + for (QualityProfileDto otherProfile : otherProfiles) { + doDelete(mapper, otherProfile); + } + } + + private void doDelete(QualityProfileMapper mapper, QualityProfileDto profile) { + Preconditions.checkNotNull(profile.getId(), "Quality profile is not persisted"); + mapper.delete(profile.getId()); + } + + /** + * @deprecated use {@link #delete(DbSession, QualityProfileDto, QualityProfileDto...)} + */ + @Deprecated + public void delete(int id, DbSession session) { + getMapper(session).delete(id); + } + + /** + * @deprecated use {@link #delete(DbSession, QualityProfileDto, QualityProfileDto...)} + */ + @Deprecated + public void delete(int id) { + DbSession session = mybatis.openSession(false); + try { + delete(id, session); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + /** + * @deprecated Replaced by + * {@link #findAll(DbSession)} + */ + @Deprecated + public List<QualityProfileDto> findAll() { + DbSession session = mybatis.openSession(false); + try { + return getMapper(session).selectAll(); + } finally { + MyBatis.closeQuietly(session); + } + } + + @CheckForNull + public QualityProfileDto getDefaultProfile(String language, DbSession session) { + return getMapper(session).selectDefaultProfile(language); + } + + @CheckForNull + public QualityProfileDto getDefaultProfile(String language) { + DbSession session = mybatis.openSession(false); + try { + return getDefaultProfile(language, session); + } finally { + MyBatis.closeQuietly(session); + } + } + + @CheckForNull + public QualityProfileDto getByProjectAndLanguage(long projectId, String language) { + DbSession session = mybatis.openSession(false); + try { + return getMapper(session).selectByProjectIdAndLanguage(projectId, language); + } finally { + MyBatis.closeQuietly(session); + } + } + + @CheckForNull + public QualityProfileDto getByProjectAndLanguage(String projectKey, String language, DbSession session) { + return getMapper(session).selectByProjectAndLanguage(projectKey, language); + } + + public List<QualityProfileDto> findByLanguage(String language) { + DbSession session = mybatis.openSession(false); + try { + return getMapper(session).selectByLanguage(language); + } finally { + MyBatis.closeQuietly(session); + } + } + + /** + * @deprecated Replaced by + * {@link #getByKey(DbSession, String)} + */ + @Deprecated + @CheckForNull + public QualityProfileDto getById(int id, DbSession session) { + return getMapper(session).selectById(id); + } + + /** + * @deprecated Replaced by + * {@link #getByKey(DbSession, String)} + */ + @Deprecated + @CheckForNull + public QualityProfileDto getById(int id) { + DbSession session = mybatis.openSession(false); + try { + return getById(id, session); + } finally { + MyBatis.closeQuietly(session); + } + } + + @CheckForNull + public QualityProfileDto getParent(String childKey, DbSession session) { + return getMapper(session).selectParent(childKey); + } + + @CheckForNull + public QualityProfileDto getParent(String childKey) { + DbSession session = mybatis.openSession(false); + try { + return getParent(childKey, session); + } finally { + MyBatis.closeQuietly(session); + } + } + + @CheckForNull + public QualityProfileDto getParentById(int childId, DbSession session) { + return getMapper(session).selectParentById(childId); + } + + @CheckForNull + public QualityProfileDto getParentById(int childId) { + DbSession session = mybatis.openSession(false); + try { + return getParentById(childId, session); + } finally { + MyBatis.closeQuietly(session); + } + } + + public List<QualityProfileDto> findChildren(DbSession session, String key) { + return getMapper(session).selectChildren(key); + } + + /** + * All descendants, in the top-down order. + */ + public List<QualityProfileDto> findDescendants(DbSession session, String key) { + List<QualityProfileDto> descendants = Lists.newArrayList(); + for (QualityProfileDto child : findChildren(session, key)) { + descendants.add(child); + descendants.addAll(findDescendants(session, child.getKey())); + } + return descendants; + } + + @CheckForNull + public QualityProfileDto getByNameAndLanguage(String name, String language, DbSession session) { + return getMapper(session).selectByNameAndLanguage(name, language); + } + + /** + * @deprecated Replaced by + * {@link #getByNameAndLanguage(String, String, DbSession)} + */ + @Deprecated + public QualityProfileDto getByNameAndLanguage(String name, String language) { + DbSession session = mybatis.openSession(false); + try { + return getByNameAndLanguage(name, language, session); + } finally { + MyBatis.closeQuietly(session); + } + } + + public List<ComponentDto> selectProjects(String profileName, String language) { + DbSession session = mybatis.openSession(false); + try { + return selectProjects(profileName, language, session); + } finally { + MyBatis.closeQuietly(session); + } + } + + public List<ComponentDto> selectProjects(String profileName, String language, DbSession session) { + return getMapper(session).selectProjects(profileName, language); + } + + public int countProjects(String profileName, String language) { + DbSession session = mybatis.openSession(false); + try { + return getMapper(session).countProjects(profileName, language); + } finally { + MyBatis.closeQuietly(session); + } + } + + public Map<String, Long> countProjectsByProfileKey() { + DbSession session = mybatis.openSession(false); + try { + Map<String, Long> countByKey = Maps.newHashMap(); + for (QualityProfileProjectCount count : getMapper(session).countProjectsByProfile()) { + countByKey.put(count.getProfileKey(), count.getProjectCount()); + } + return countByKey; + } finally { + MyBatis.closeQuietly(session); + } + } + + public void insertProjectProfileAssociation(String projectUuid, String profileKey, DbSession session) { + getMapper(session).insertProjectProfileAssociation(projectUuid, profileKey); + } + + public void deleteProjectProfileAssociation(String projectUuid, String profileKey, DbSession session) { + getMapper(session).deleteProjectProfileAssociation(projectUuid, profileKey); + } + + public void updateProjectProfileAssociation(String projectUuid, String profileKey, DbSession session) { + getMapper(session).updateProjectProfileAssociation(projectUuid, profileKey); + } + + public void deleteAllProjectProfileAssociation(String profileKey, DbSession session) { + getMapper(session).deleteAllProjectProfileAssociation(profileKey); + } + + public List<ProjectQprofileAssociationDto> selectSelectedProjects(String profileKey, @Nullable String query, DbSession session) { + String nameQuery = sqlQueryString(query); + return getMapper(session).selectSelectedProjects(profileKey, nameQuery); + } + + public List<ProjectQprofileAssociationDto> selectDeselectedProjects(String profileKey, @Nullable String query, DbSession session) { + String nameQuery = sqlQueryString(query); + return getMapper(session).selectDeselectedProjects(profileKey, nameQuery); + } + + public List<ProjectQprofileAssociationDto> selectProjectAssociations(String profileKey, @Nullable String query, DbSession session) { + String nameQuery = sqlQueryString(query); + return getMapper(session).selectProjectAssociations(profileKey, nameQuery); + } + + private String sqlQueryString(String query) { + return query == null ? "%" : "%" + query.toUpperCase() + "%"; + } + + private QualityProfileMapper getMapper(DbSession session) { + return session.getMapper(QualityProfileMapper.class); + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/qualityprofile/QualityProfileDto.java b/sonar-db/src/main/java/org/sonar/db/qualityprofile/QualityProfileDto.java new file mode 100644 index 00000000000..2c36242e9af --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/qualityprofile/QualityProfileDto.java @@ -0,0 +1,128 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.qualityprofile; + +import java.util.Date; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.sonar.core.util.UtcDateUtils; +import org.sonar.db.Dto; + +public class QualityProfileDto extends Dto<String> { + + private Integer id; + private String kee; + private String name; + private String language; + private String parentKee; + private String rulesUpdatedAt; + private boolean isDefault; + + /** + * @deprecated use {@link #createFor(String)} + */ + @Deprecated + public QualityProfileDto() { + + } + + @Override + public String getKey() { + return kee; + } + + public QualityProfileDto setKey(String s) { + return setKee(s); + } + + public String getKee() { + return kee; + } + + public QualityProfileDto setKee(String s) { + this.kee = s; + return this; + } + + public Integer getId() { + return id; + } + + public QualityProfileDto setId(Integer id) { + this.id = id; + return this; + } + + public String getName() { + return name; + } + + public QualityProfileDto setName(String name) { + this.name = name; + return this; + } + + public String getLanguage() { + return language; + } + + public QualityProfileDto setLanguage(String language) { + this.language = language; + return this; + } + + @CheckForNull + public String getParentKee() { + return parentKee; + } + + public QualityProfileDto setParentKee(@Nullable String s) { + this.parentKee = s; + return this; + } + + public String getRulesUpdatedAt() { + return rulesUpdatedAt; + } + + public QualityProfileDto setRulesUpdatedAt(String s) { + this.rulesUpdatedAt = s; + return this; + } + + public QualityProfileDto setRulesUpdatedAtAsDate(Date d) { + this.rulesUpdatedAt = UtcDateUtils.formatDateTime(d); + return this; + } + + public boolean isDefault() { + return isDefault; + } + + public QualityProfileDto setDefault(boolean isDefault) { + this.isDefault = isDefault; + return this; + } + + public static QualityProfileDto createFor(String key) { + return new QualityProfileDto().setKee(key); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/qualityprofile/QualityProfileMapper.java b/sonar-db/src/main/java/org/sonar/db/qualityprofile/QualityProfileMapper.java new file mode 100644 index 00000000000..ade9c166655 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/qualityprofile/QualityProfileMapper.java @@ -0,0 +1,87 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.qualityprofile; + +import java.util.List; +import javax.annotation.CheckForNull; +import org.apache.ibatis.annotations.Param; +import org.sonar.db.component.ComponentDto; + +public interface QualityProfileMapper { + + void insert(QualityProfileDto dto); + + void update(QualityProfileDto dto); + + void delete(int id); + + List<QualityProfileDto> selectAll(); + + @CheckForNull + QualityProfileDto selectDefaultProfile(@Param("language") String language); + + @CheckForNull + QualityProfileDto selectByNameAndLanguage(@Param("name") String name, @Param("language") String language); + + @CheckForNull + QualityProfileDto selectById(@Param("id") Integer id); + + @CheckForNull + QualityProfileDto selectByKey(String key); + + List<QualityProfileDto> selectByLanguage(String language); + + // INHERITANCE + + @CheckForNull + QualityProfileDto selectParent(String childKey); + + @CheckForNull + QualityProfileDto selectParentById(int childId); + + List<QualityProfileDto> selectChildren(String key); + + // PROJECTS + + List<ComponentDto> selectProjects(@Param("profileName") String profileName, @Param("language") String language); + + int countProjects(@Param("profileName") String profileName, @Param("language") String language); + + List<QualityProfileProjectCount> countProjectsByProfile(); + + QualityProfileDto selectByProjectIdAndLanguage(@Param("projectId") Long projectId, @Param("language") String language); + + QualityProfileDto selectByProjectAndLanguage(@Param("projectKey") String projectKey, @Param("language") String language); + + void insertProjectProfileAssociation(@Param("projectUuid") String projectUuid, @Param("profileKey") String profileKey); + + void updateProjectProfileAssociation(@Param("projectUuid") String projectUuid, @Param("profileKey") String profileKey); + + void deleteProjectProfileAssociation(@Param("projectUuid") String projectUuid, @Param("profileKey") String profileKey); + + void deleteAllProjectProfileAssociation(@Param("profileKey") String profileKey); + + List<ProjectQprofileAssociationDto> selectSelectedProjects(@Param("profileKey") String profileKey, @Param("nameQuery") String nameQuery); + + List<ProjectQprofileAssociationDto> selectDeselectedProjects(@Param("profileKey") String profileKey, @Param("nameQuery") String nameQuery); + + List<ProjectQprofileAssociationDto> selectProjectAssociations(@Param("profileKey") String profileKey, @Param("nameQuery") String nameQuery); +} diff --git a/sonar-db/src/main/java/org/sonar/db/qualityprofile/QualityProfileProjectCount.java b/sonar-db/src/main/java/org/sonar/db/qualityprofile/QualityProfileProjectCount.java new file mode 100644 index 00000000000..287d7e93b36 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/qualityprofile/QualityProfileProjectCount.java @@ -0,0 +1,42 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.qualityprofile; + +public class QualityProfileProjectCount { + + private String profileKey; + private Long projectCount; + + public String getProfileKey() { + return profileKey; + } + + public void setProfileKey(String profileKey) { + this.profileKey = profileKey; + } + + public Long getProjectCount() { + return projectCount; + } + + public void setProjectCount(Long projectCount) { + this.projectCount = projectCount; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/rule/RuleDao.java b/sonar-db/src/main/java/org/sonar/db/rule/RuleDao.java new file mode 100644 index 00000000000..25236bc2bcb --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/rule/RuleDao.java @@ -0,0 +1,67 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.rule; + +import java.util.List; +import org.apache.ibatis.session.SqlSession; +import org.sonar.db.MyBatis; + +/** + * @deprecated in 4.4 moved to org.sonar.server.rule.db.RuleDao. + */ +@Deprecated +public class RuleDao { + + private MyBatis mybatis; + + public RuleDao(MyBatis mybatis) { + this.mybatis = mybatis; + } + + public List<RuleDto> selectEnablesAndNonManual() { + SqlSession session = mybatis.openSession(); + try { + return selectEnablesAndNonManual(session); + } finally { + MyBatis.closeQuietly(session); + } + } + + public List<RuleDto> selectEnablesAndNonManual(SqlSession session) { + return getMapper(session).selectEnablesAndNonManual(); + } + + public List<RuleParamDto> selectParameters() { + SqlSession session = mybatis.openSession(); + try { + return selectParameters(session); + } finally { + MyBatis.closeQuietly(session); + } + } + + public List<RuleParamDto> selectParameters(SqlSession session) { + return getMapper(session).selectAllParams(); + } + + private RuleMapper getMapper(SqlSession session) { + return session.getMapper(RuleMapper.class); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/rule/RuleDto.java b/sonar-db/src/main/java/org/sonar/db/rule/RuleDto.java new file mode 100644 index 00000000000..d3188ec87db --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/rule/RuleDto.java @@ -0,0 +1,403 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.rule; + +import java.util.Arrays; +import java.util.Date; +import java.util.HashSet; +import java.util.Set; +import java.util.TreeSet; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; +import org.apache.commons.lang.builder.ReflectionToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; +import org.sonar.api.rule.RuleKey; +import org.sonar.api.rule.RuleStatus; +import org.sonar.core.rule.SeverityUtil; +import org.sonar.db.Dto; + +public class RuleDto extends Dto<RuleKey> { + + public static final Integer DISABLED_CHARACTERISTIC_ID = -1; + + public enum Format { + HTML, MARKDOWN + } + + private Integer id; + private String repositoryKey; + private String ruleKey; + private String description; + private Format descriptionFormat; + private RuleStatus status; + private String name; + private String configKey; + private Integer severity; + private boolean isTemplate; + private String language; + private Integer templateId; + private String noteData; + private String noteUserLogin; + private Date noteCreatedAt; + private Date noteUpdatedAt; + private Integer subCharacteristicId; + private Integer defaultSubCharacteristicId; + private String remediationFunction; + private String defaultRemediationFunction; + private String remediationCoefficient; + private String defaultRemediationCoefficient; + private String remediationOffset; + private String defaultRemediationOffset; + private String effortToFixDescription; + private String tags; + private String systemTags; + + private RuleKey key; + + @Override + public RuleKey getKey() { + if (key == null) { + key = RuleKey.of(getRepositoryKey(), getRuleKey()); + } + return key; + } + + public Integer getId() { + return id; + } + + public RuleDto setId(Integer id) { + this.id = id; + return this; + } + + public String getRepositoryKey() { + return repositoryKey; + } + + public RuleDto setRepositoryKey(String repositoryKey) { + this.repositoryKey = repositoryKey; + return this; + } + + public String getRuleKey() { + return ruleKey; + } + + public RuleDto setRuleKey(String ruleKey) { + this.ruleKey = ruleKey; + return this; + } + + public String getDescription() { + return description; + } + + public RuleDto setDescription(String description) { + this.description = description; + return this; + } + + public Format getDescriptionFormat() { + return descriptionFormat; + } + + public RuleDto setDescriptionFormat(Format descriptionFormat) { + this.descriptionFormat = descriptionFormat; + return this; + } + + public RuleStatus getStatus() { + return status; + } + + public RuleDto setStatus(@Nullable RuleStatus s) { + this.status = s; + return this; + } + + public String getName() { + return name; + } + + public RuleDto setName(@Nullable String name) { + this.name = name; + return this; + } + + public String getConfigKey() { + return configKey; + } + + public RuleDto setConfigKey(@Nullable String configKey) { + this.configKey = configKey; + return this; + } + + @CheckForNull + public Integer getSeverity() { + return severity; + } + + @CheckForNull + public String getSeverityString() { + return severity != null ? SeverityUtil.getSeverityFromOrdinal(severity) : null; + } + + public RuleDto setSeverity(@Nullable String severity) { + return this.setSeverity(severity != null ? SeverityUtil.getOrdinalFromSeverity(severity) : null); + } + + public RuleDto setSeverity(@Nullable Integer severity) { + this.severity = severity; + return this; + } + + public boolean isTemplate() { + return isTemplate; + } + + public RuleDto setIsTemplate(boolean isTemplate) { + this.isTemplate = isTemplate; + return this; + } + + @CheckForNull + public String getLanguage() { + return language; + } + + public RuleDto setLanguage(String language) { + this.language = language; + return this; + } + + @CheckForNull + public Integer getTemplateId() { + return templateId; + } + + public RuleDto setTemplateId(@Nullable Integer templateId) { + this.templateId = templateId; + return this; + } + + public String getNoteData() { + return noteData; + } + + public RuleDto setNoteData(String noteData) { + this.noteData = noteData; + return this; + } + + public String getNoteUserLogin() { + return noteUserLogin; + } + + public RuleDto setNoteUserLogin(String noteUserLogin) { + this.noteUserLogin = noteUserLogin; + return this; + } + + public Date getNoteCreatedAt() { + return noteCreatedAt; + } + + public RuleDto setNoteCreatedAt(Date noteCreatedAt) { + this.noteCreatedAt = noteCreatedAt; + return this; + } + + public Date getNoteUpdatedAt() { + return noteUpdatedAt; + } + + public RuleDto setNoteUpdatedAt(Date noteUpdatedAt) { + this.noteUpdatedAt = noteUpdatedAt; + return this; + } + + @CheckForNull + public Integer getSubCharacteristicId() { + return subCharacteristicId; + } + + public RuleDto setSubCharacteristicId(@Nullable Integer subCharacteristicId) { + this.subCharacteristicId = subCharacteristicId; + return this; + } + + @CheckForNull + public Integer getDefaultSubCharacteristicId() { + return defaultSubCharacteristicId; + } + + public RuleDto setDefaultSubCharacteristicId(@Nullable Integer defaultSubCharacteristicId) { + this.defaultSubCharacteristicId = defaultSubCharacteristicId; + return this; + } + + @CheckForNull + public String getRemediationFunction() { + return remediationFunction; + } + + public RuleDto setRemediationFunction(@Nullable String remediationFunction) { + this.remediationFunction = remediationFunction; + return this; + } + + @CheckForNull + public String getDefaultRemediationFunction() { + return defaultRemediationFunction; + } + + public RuleDto setDefaultRemediationFunction(@Nullable String defaultRemediationFunction) { + this.defaultRemediationFunction = defaultRemediationFunction; + return this; + } + + @CheckForNull + public String getRemediationCoefficient() { + return remediationCoefficient; + } + + public RuleDto setRemediationCoefficient(@Nullable String remediationCoefficient) { + this.remediationCoefficient = remediationCoefficient; + return this; + } + + @CheckForNull + public String getDefaultRemediationCoefficient() { + return defaultRemediationCoefficient; + } + + public RuleDto setDefaultRemediationCoefficient(@Nullable String defaultRemediationCoefficient) { + this.defaultRemediationCoefficient = defaultRemediationCoefficient; + return this; + } + + @CheckForNull + public String getRemediationOffset() { + return remediationOffset; + } + + public RuleDto setRemediationOffset(@Nullable String remediationOffset) { + this.remediationOffset = remediationOffset; + return this; + } + + @CheckForNull + public String getDefaultRemediationOffset() { + return defaultRemediationOffset; + } + + public RuleDto setDefaultRemediationOffset(@Nullable String defaultRemediationOffset) { + this.defaultRemediationOffset = defaultRemediationOffset; + return this; + } + + @CheckForNull + public String getEffortToFixDescription() { + return effortToFixDescription; + } + + public RuleDto setEffortToFixDescription(@Nullable String s) { + this.effortToFixDescription = s; + return this; + } + + public Set<String> getTags() { + return tags == null ? + new HashSet<String>() : + new TreeSet<>(Arrays.asList(StringUtils.split(tags, ','))); + } + + public Set<String> getSystemTags() { + return systemTags == null ? + new HashSet<String>() : + new TreeSet<>(Arrays.asList(StringUtils.split(systemTags, ','))); + } + + private String getTagsField() { + return tags; + } + + private String getSystemTagsField() { + return systemTags; + } + + private void setTagsField(String s) { + tags = s; + } + + private void setSystemTagsField(String s) { + systemTags = s; + } + + public RuleDto setTags(Set<String> tags) { + this.tags = tags.isEmpty() ? null : StringUtils.join(tags, ','); + return this; + } + + public RuleDto setSystemTags(Set<String> tags) { + this.systemTags = tags.isEmpty() ? null : StringUtils.join(tags, ','); + return this; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof RuleDto)) { + return false; + } + if (this == obj) { + return true; + } + RuleDto other = (RuleDto) obj; + return new EqualsBuilder() + .append(repositoryKey, other.getRepositoryKey()) + .append(ruleKey, other.getRuleKey()) + .isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder(17, 37) + .append(repositoryKey) + .append(ruleKey) + .toHashCode(); + } + + @Override + public String toString() { + return new ReflectionToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).toString(); + } + + public static RuleDto createFor(RuleKey key) { + return new RuleDto() + .setRepositoryKey(key.repository()) + .setRuleKey(key.rule()); + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/rule/RuleMapper.java b/sonar-db/src/main/java/org/sonar/db/rule/RuleMapper.java new file mode 100644 index 00000000000..5074160a11c --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/rule/RuleMapper.java @@ -0,0 +1,65 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.rule; + +import java.sql.Timestamp; +import java.util.List; +import javax.annotation.Nullable; +import org.apache.ibatis.annotations.Param; +import org.sonar.api.rule.RuleKey; + +public interface RuleMapper { + + List<RuleDto> selectAll(); + + List<RuleDto> selectEnablesAndNonManual(); + + List<RuleDto> selectNonManual(); + + List<RuleDto> selectBySubCharacteristicId(int characteristicId); + + RuleDto selectById(Integer id); + + RuleDto selectByKey(RuleKey ruleKey); + + RuleDto selectByName(String name); + + void update(RuleDto rule); + + void batchInsert(RuleDto rule); + + void insert(RuleDto rule); + + List<RuleParamDto> selectAllParams(); + + List<RuleParamDto> selectParamsByRuleIds(@Param("ruleIds") List<Integer> ruleIds); + + List<RuleParamDto> selectParamsByRuleKey(RuleKey ruleKey); + + RuleParamDto selectParamByRuleAndKey(@Param("ruleId") Integer ruleId, @Param("key") String key); + + void insertParameter(RuleParamDto param); + + void updateParameter(RuleParamDto param); + + void deleteParameter(Integer paramId); + + List<RuleDto> selectAfterDate(@Nullable @Param("date") Timestamp timestamp); +} diff --git a/sonar-db/src/main/java/org/sonar/db/rule/RuleParamDto.java b/sonar-db/src/main/java/org/sonar/db/rule/RuleParamDto.java new file mode 100644 index 00000000000..2df5c541a93 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/rule/RuleParamDto.java @@ -0,0 +1,102 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.rule; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.apache.commons.lang.builder.ReflectionToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; + +public class RuleParamDto { + + private Integer id; + private Integer ruleId; + private String name; + private String type; + private String defaultValue; + private String description; + + public Integer getId() { + return id; + } + + public RuleParamDto setId(Integer id) { + this.id = id; + return this; + } + + public Integer getRuleId() { + return ruleId; + } + + public RuleParamDto setRuleId(Integer ruleId) { + this.ruleId = ruleId; + return this; + } + + public String getName() { + return name; + } + + public RuleParamDto setName(String name) { + this.name = name; + return this; + } + + public String getType() { + return type; + } + + public RuleParamDto setType(String type) { + this.type = type; + return this; + } + + @CheckForNull + public String getDefaultValue() { + return defaultValue; + } + + public RuleParamDto setDefaultValue(@Nullable String defaultValue) { + this.defaultValue = defaultValue; + return this; + } + + public String getDescription() { + return description; + } + + public RuleParamDto setDescription(String description) { + this.description = description; + return this; + } + + @Override + public String toString() { + return new ReflectionToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).toString(); + } + + public static RuleParamDto createFor(RuleDto rule) { + // Should eventually switch to RuleKey (RuleKey is available before insert) + return new RuleParamDto().setRuleId(rule.getId()); + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/semaphore/SemaphoreDao.java b/sonar-db/src/main/java/org/sonar/db/semaphore/SemaphoreDao.java new file mode 100644 index 00000000000..c34a9b89542 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/semaphore/SemaphoreDao.java @@ -0,0 +1,150 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.semaphore; + +import com.google.common.base.Strings; +import javax.annotation.CheckForNull; +import org.apache.ibatis.session.SqlSession; +import org.sonar.api.utils.Semaphores; +import org.sonar.api.utils.System2; +import org.sonar.db.MyBatis; + +import static com.google.common.base.Preconditions.checkArgument; +import static org.sonar.api.utils.DateUtils.longToDate; + +/** + * @since 3.4 + */ +public class SemaphoreDao { + + private static final String SEMAPHORE_NAME_MUST_NOT_BE_EMPTY = "Semaphore name must not be empty"; + private final MyBatis mybatis; + private final System2 system; + + public SemaphoreDao(MyBatis mybatis, System2 system) { + this.mybatis = mybatis; + this.system = system; + } + + public Semaphores.Semaphore acquire(String name, int maxAgeInSeconds) { + checkArgument(!Strings.isNullOrEmpty(name), SEMAPHORE_NAME_MUST_NOT_BE_EMPTY); + checkArgument(maxAgeInSeconds >= 0, "Semaphore max age must be positive: " + maxAgeInSeconds); + + try (SqlSession session = mybatis.openSession(false)) { + SemaphoreDto semaphore = tryToInsert(name, system.now(), session); + boolean isAcquired; + if (semaphore == null) { + semaphore = selectSemaphore(name, session); + isAcquired = acquireIfOutdated(name, maxAgeInSeconds, session); + } else { + isAcquired = true; + } + return createLock(semaphore, isAcquired); + } + } + + public Semaphores.Semaphore acquire(String name) { + checkArgument(!Strings.isNullOrEmpty(name), SEMAPHORE_NAME_MUST_NOT_BE_EMPTY); + + try (SqlSession session = mybatis.openSession(false)) { + SemaphoreDto semaphore = tryToInsert(name, system.now(), session); + if (semaphore == null) { + semaphore = selectSemaphore(name, session); + return createLock(semaphore, false); + } else { + return createLock(semaphore, true); + } + } + } + + public void update(Semaphores.Semaphore semaphore) { + checkArgument(semaphore != null, "Semaphore must not be null"); + + try (SqlSession session = mybatis.openSession(false)) { + mapper(session).update(semaphore.getName(), system.now()); + session.commit(); + } + } + + public void release(String name) { + checkArgument(!Strings.isNullOrEmpty(name), SEMAPHORE_NAME_MUST_NOT_BE_EMPTY); + try (SqlSession session = mybatis.openSession(false)) { + mapper(session).release(name); + session.commit(); + } + } + + private boolean acquireIfOutdated(String name, int maxAgeInSeconds, SqlSession session) { + long now = system.now(); + long updatedBefore = now - (long) maxAgeInSeconds * 1000; + + boolean ok = mapper(session).acquire(name, updatedBefore, now) == 1; + session.commit(); + return ok; + } + + /** + * Insert the semaphore and commit. Rollback and return null if the semaphore already exists in db (whatever + * the lock date) + */ + @CheckForNull + private SemaphoreDto tryToInsert(String name, long lockedNow, SqlSession session) { + try { + long now = system.now(); + SemaphoreDto semaphore = new SemaphoreDto() + .setName(name) + .setCreatedAt(now) + .setUpdatedAt(now) + .setLockedAt(lockedNow); + mapper(session).initialize(semaphore); + session.commit(); + return semaphore; + } catch (Exception e) { + // probably because the semaphore already exists in db + session.rollback(); + return null; + } + } + + private Semaphores.Semaphore createLock(SemaphoreDto dto, boolean acquired) { + Semaphores.Semaphore semaphore = new Semaphores.Semaphore() + .setName(dto.getName()) + .setLocked(acquired) + .setLockedAt(longToDate(dto.getLockedAt())) + .setCreatedAt(longToDate(dto.getCreatedAt())) + .setUpdatedAt(longToDate(dto.getUpdatedAt())); + if (!acquired) { + semaphore.setDurationSinceLocked(lockedSince(dto)); + } + return semaphore; + } + + private long lockedSince(SemaphoreDto semaphore) { + return system.now() - semaphore.getLockedAt(); + } + + protected SemaphoreDto selectSemaphore(String name, SqlSession session) { + return mapper(session).selectSemaphore(name); + } + + private SemaphoreMapper mapper(SqlSession session) { + return session.getMapper(SemaphoreMapper.class); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/semaphore/SemaphoreDto.java b/sonar-db/src/main/java/org/sonar/db/semaphore/SemaphoreDto.java new file mode 100644 index 00000000000..a26e6a35037 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/semaphore/SemaphoreDto.java @@ -0,0 +1,86 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.semaphore; + +import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.lang.builder.ReflectionToStringBuilder; + +/** + * @since 3.4 + */ +public class SemaphoreDto { + private Long id; + private String name; + private String checksum; + private Long lockedAt; + private Long createdAt; + private Long updatedAt; + + public String getName() { + return name; + } + + public SemaphoreDto setName(String s) { + this.name = s; + this.checksum = DigestUtils.md5Hex(s); + return this; + } + + public Long getLockedAt() { + return lockedAt; + } + + public SemaphoreDto setLockedAt(Long d) { + this.lockedAt = d; + return this; + } + + public Long getId() { + return id; + } + + public SemaphoreDto setId(Long id) { + this.id = id; + return this; + } + + public Long getCreatedAt() { + return createdAt; + } + + public SemaphoreDto setCreatedAt(Long createdAt) { + this.createdAt = createdAt; + return this; + } + + public Long getUpdatedAt() { + return updatedAt; + } + + public SemaphoreDto setUpdatedAt(Long updatedAt) { + this.updatedAt = updatedAt; + return this; + } + + @Override + public String toString() { + return ReflectionToStringBuilder.toString(this); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/semaphore/SemaphoreMapper.java b/sonar-db/src/main/java/org/sonar/db/semaphore/SemaphoreMapper.java new file mode 100644 index 00000000000..fc517e9f42d --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/semaphore/SemaphoreMapper.java @@ -0,0 +1,35 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.semaphore; + +import org.apache.ibatis.annotations.Param; + +public interface SemaphoreMapper { + + int initialize(SemaphoreDto semaphore); + + int acquire(@Param("name") String name, @Param("updatedBefore") Long updatedBefore, @Param("now") Long now); + + void release(String name); + + SemaphoreDto selectSemaphore(@Param("name") String name); + + void update(@Param("name") String name, @Param("now") Long now); +} diff --git a/sonar-db/src/main/java/org/sonar/db/semaphore/SemaphoreUpdater.java b/sonar-db/src/main/java/org/sonar/db/semaphore/SemaphoreUpdater.java new file mode 100644 index 00000000000..767539d385c --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/semaphore/SemaphoreUpdater.java @@ -0,0 +1,80 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.semaphore; + +import com.google.common.collect.Maps; +import java.util.Map; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.server.ServerSide; +import org.sonar.api.utils.Semaphores; + +/** + * @since 3.5 + */ +@ServerSide +public class SemaphoreUpdater { + + private static final Logger LOG = LoggerFactory.getLogger(SemaphoreUpdater.class); + + private SemaphoreDao dao; + + private Map<String, ScheduledExecutorService> handlers = Maps.newHashMap(); + + public SemaphoreUpdater(SemaphoreDao dao) { + this.dao = dao; + } + + public void scheduleForUpdate(final Semaphores.Semaphore semaphore, int updatePeriodInSeconds) { + ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); + Runnable updater = new Runnable() { + @Override + public void run() { + try { + LOG.debug("Updating semaphore " + semaphore.getName()); + dao.update(semaphore); + } catch (Exception e) { + LOG.error("Unable to update semaphore", e); + } + + } + }; + scheduler.scheduleWithFixedDelay(updater, updatePeriodInSeconds, updatePeriodInSeconds, TimeUnit.SECONDS); + handlers.put(semaphore.getName(), scheduler); + } + + public void stopUpdate(final String name) { + if (handlers.containsKey(name)) { + handlers.get(name).shutdown(); + try { + if (!handlers.get(name).awaitTermination(1, TimeUnit.SECONDS)) { + LOG.error("Unable to cancel semaphore updater in 1 second"); + } + } catch (InterruptedException e) { + LOG.error("Unable to cancel semaphore updater", e); + } finally { + handlers.remove(name); + } + } + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/semaphore/SemaphoresImpl.java b/sonar-db/src/main/java/org/sonar/db/semaphore/SemaphoresImpl.java new file mode 100644 index 00000000000..63958124965 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/semaphore/SemaphoresImpl.java @@ -0,0 +1,54 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.semaphore; + +import org.sonar.api.utils.Semaphores; + +/** + * @since 3.4 + */ +public class SemaphoresImpl implements Semaphores { + + private SemaphoreDao dao; + private SemaphoreUpdater updater; + + public SemaphoresImpl(SemaphoreDao dao, SemaphoreUpdater updater) { + this.dao = dao; + this.updater = updater; + } + + @Override + public Semaphore acquire(String name, int maxAgeInSeconds, int updatePeriodInSeconds) { + Semaphore semaphore = dao.acquire(name, maxAgeInSeconds); + updater.scheduleForUpdate(semaphore, updatePeriodInSeconds); + return semaphore; + } + + @Override + public Semaphore acquire(String name) { + return dao.acquire(name); + } + + @Override + public void release(String name) { + updater.stopUpdate(name); + dao.release(name); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/semaphore/package-info.java b/sonar-db/src/main/java/org/sonar/db/semaphore/package-info.java new file mode 100644 index 00000000000..888655d88da --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/semaphore/package-info.java @@ -0,0 +1,24 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.semaphore; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/sonar-db/src/main/java/org/sonar/db/source/FileSourceDto.java b/sonar-db/src/main/java/org/sonar/db/source/FileSourceDto.java new file mode 100644 index 00000000000..0ac7561084f --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/source/FileSourceDto.java @@ -0,0 +1,277 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.source; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import net.jpountz.lz4.LZ4BlockInputStream; +import net.jpountz.lz4.LZ4BlockOutputStream; +import org.apache.commons.io.IOUtils; +import org.sonar.server.source.db.FileSourceDb; +import org.sonar.server.source.db.FileSourceDb.Test; + +public class FileSourceDto { + + private Long id; + private String projectUuid; + private String fileUuid; + private long createdAt; + private long updatedAt; + private String lineHashes; + private String srcHash; + private byte[] binaryData; + private String dataType; + private String dataHash; + + public Long getId() { + return id; + } + + public FileSourceDto setId(Long id) { + this.id = id; + return this; + } + + public String getProjectUuid() { + return projectUuid; + } + + public FileSourceDto setProjectUuid(String projectUuid) { + this.projectUuid = projectUuid; + return this; + } + + public String getFileUuid() { + return fileUuid; + } + + public FileSourceDto setFileUuid(String fileUuid) { + this.fileUuid = fileUuid; + return this; + } + + @CheckForNull + public String getDataHash() { + return dataHash; + } + + /** + * MD5 of column BINARY_DATA. Used to know to detect data changes and need for update. + */ + public FileSourceDto setDataHash(String s) { + this.dataHash = s; + return this; + } + + public static FileSourceDb.Data decodeSourceData(byte[] binaryData) { + // stream is always closed + return decodeSourceData(new ByteArrayInputStream(binaryData)); + } + + /** + * Decompress and deserialize content of column FILE_SOURCES.BINARY_DATA. + * The parameter "input" is always closed by this method. + */ + public static FileSourceDb.Data decodeSourceData(InputStream binaryInput) { + LZ4BlockInputStream lz4Input = null; + try { + lz4Input = new LZ4BlockInputStream(binaryInput); + return FileSourceDb.Data.parseFrom(lz4Input); + } catch (IOException e) { + throw new IllegalStateException("Fail to decompress and deserialize source data", e); + } finally { + IOUtils.closeQuietly(lz4Input); + } + } + + /** + * Serialize and compress protobuf message {@link org.sonar.server.source.db.FileSourceDb.Data} + * in the column BINARY_DATA. + */ + public static byte[] encodeSourceData(FileSourceDb.Data data) { + ByteArrayOutputStream byteOutput = new ByteArrayOutputStream(); + LZ4BlockOutputStream compressedOutput = new LZ4BlockOutputStream(byteOutput); + try { + data.writeTo(compressedOutput); + compressedOutput.close(); + return byteOutput.toByteArray(); + } catch (IOException e) { + throw new IllegalStateException("Fail to serialize and compress source data", e); + } finally { + IOUtils.closeQuietly(compressedOutput); + } + } + + public static List<Test> decodeTestData(byte[] binaryData) { + // stream is always closed + return decodeTestData(new ByteArrayInputStream(binaryData)); + } + + /** + * Decompress and deserialize content of column FILE_SOURCES.BINARY_DATA. + * The parameter "input" is always closed by this method. + */ + public static List<Test> decodeTestData(InputStream binaryInput) { + LZ4BlockInputStream lz4Input = null; + List<Test> tests = new ArrayList<>(); + try { + lz4Input = new LZ4BlockInputStream(binaryInput); + + Test currentTest; + do { + currentTest = Test.parseDelimitedFrom(lz4Input); + if (currentTest != null) { + tests.add(currentTest); + } + } while (currentTest != null); + return tests; + } catch (IOException e) { + throw new IllegalStateException("Fail to decompress and deserialize source data", e); + } finally { + IOUtils.closeQuietly(lz4Input); + } + } + + /** + * Serialize and compress protobuf message {@link org.sonar.server.source.db.FileSourceDb.Data} + * in the column BINARY_DATA. + */ + public static byte[] encodeTestData(List<Test> tests) { + ByteArrayOutputStream byteOutput = new ByteArrayOutputStream(); + LZ4BlockOutputStream compressedOutput = new LZ4BlockOutputStream(byteOutput); + try { + for (Test test : tests) { + test.writeDelimitedTo(compressedOutput); + } + compressedOutput.close(); + return byteOutput.toByteArray(); + } catch (IOException e) { + throw new IllegalStateException("Fail to serialize and compress source tests", e); + } finally { + IOUtils.closeQuietly(compressedOutput); + } + } + + /** + * Compressed value of serialized protobuf message {@link org.sonar.server.source.db.FileSourceDb.Data} + */ + public byte[] getBinaryData() { + return binaryData; + } + + /** + * Set compressed value of the protobuf message {@link org.sonar.server.source.db.FileSourceDb.Data} + */ + public FileSourceDto setBinaryData(byte[] data) { + this.binaryData = data; + return this; + } + + /** + * Compressed value of serialized protobuf message {@link org.sonar.server.source.db.FileSourceDb.Data} + */ + public FileSourceDb.Data getSourceData() { + return decodeSourceData(binaryData); + } + + public FileSourceDto setSourceData(FileSourceDb.Data data) { + this.dataType = Type.SOURCE; + this.binaryData = encodeSourceData(data); + return this; + } + + /** + * Compressed value of serialized protobuf message {@link org.sonar.server.source.db.FileSourceDb.Data} + */ + public List<Test> getTestData() { + return decodeTestData(binaryData); + } + + public FileSourceDto setTestData(List<Test> data) { + this.dataType = Type.TEST; + this.binaryData = encodeTestData(data); + return this; + } + + @CheckForNull + public String getLineHashes() { + return lineHashes; + } + + public FileSourceDto setLineHashes(@Nullable String lineHashes) { + this.lineHashes = lineHashes; + return this; + } + + @CheckForNull + public String getSrcHash() { + return srcHash; + } + + /** + * Hash of file content. Value is computed by batch. + */ + public FileSourceDto setSrcHash(@Nullable String srcHash) { + this.srcHash = srcHash; + return this; + } + + public long getCreatedAt() { + return createdAt; + } + + public FileSourceDto setCreatedAt(long createdAt) { + this.createdAt = createdAt; + return this; + } + + public long getUpdatedAt() { + return updatedAt; + } + + public FileSourceDto setUpdatedAt(long updatedAt) { + this.updatedAt = updatedAt; + return this; + } + + public String getDataType() { + return dataType; + } + + public FileSourceDto setDataType(String dataType) { + this.dataType = dataType; + return this; + } + + public static class Type { + public static final String SOURCE = "SOURCE"; + public static final String TEST = "TEST"; + + private Type() { + // utility class + } + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/source/FileSourceMapper.java b/sonar-db/src/main/java/org/sonar/db/source/FileSourceMapper.java new file mode 100644 index 00000000000..45b03b15b65 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/source/FileSourceMapper.java @@ -0,0 +1,39 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.source; + +import java.util.List; +import javax.annotation.CheckForNull; +import org.apache.ibatis.annotations.Param; + +public interface FileSourceMapper { + + List<FileSourceDto> selectHashesForProject(@Param("projectUuid") String projectUuid, @Param("dataType") String dataType); + + @CheckForNull + FileSourceDto select(@Param("fileUuid") String fileUuid, @Param("dataType") String dataType); + + void insert(FileSourceDto dto); + + void update(FileSourceDto dto); + + void updateDateWhenUpdatedDateIsZero(@Param("projectUuid") String projectUuid, @Param("date") Long updateDate); +} diff --git a/sonar-db/src/main/java/org/sonar/db/user/AuthorDao.java b/sonar-db/src/main/java/org/sonar/db/user/AuthorDao.java new file mode 100644 index 00000000000..5837964ce82 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/user/AuthorDao.java @@ -0,0 +1,122 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.user; + +import com.google.common.base.Function; +import com.google.common.base.Strings; +import java.util.Collection; +import java.util.Date; +import java.util.List; +import org.apache.ibatis.session.SqlSession; +import org.sonar.db.Dao; +import org.sonar.db.DaoUtils; +import org.sonar.db.MyBatis; +import org.sonar.db.component.ComponentDto; +import org.sonar.db.component.ResourceDao; +import org.sonar.db.component.ResourceDto; + +/** + * Be careful when updating this class because it's used by the Dev Cockpit plugin. + */ +public class AuthorDao implements Dao { + + private final MyBatis mybatis; + private final ResourceDao resourceDao; + + public AuthorDao(MyBatis mybatis, ResourceDao resourceDao) { + this.mybatis = mybatis; + this.resourceDao = resourceDao; + } + + public AuthorDto selectByLogin(String login) { + SqlSession session = mybatis.openSession(false); + try { + AuthorMapper mapper = session.getMapper(AuthorMapper.class); + return mapper.selectByLogin(login); + } finally { + MyBatis.closeQuietly(session); + } + } + + public int countDeveloperLogins(long developerId) { + SqlSession session = mybatis.openSession(false); + try { + AuthorMapper mapper = session.getMapper(AuthorMapper.class); + return mapper.countDeveloperLogins(developerId); + } finally { + MyBatis.closeQuietly(session); + } + } + + public void insertAuthor(String login, long personId) { + SqlSession session = mybatis.openSession(false); + try { + insertAuthor(login, personId, session); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + public void insertAuthorAndDeveloper(String login, ResourceDto resourceDto) { + SqlSession session = mybatis.openSession(false); + try { + // Hack in order to set the right module uuid path on DEVs + if (Strings.isNullOrEmpty(resourceDto.getModuleUuidPath())) { + resourceDto.setModuleUuidPath(ComponentDto.MODULE_UUID_PATH_SEP + resourceDto.getUuid() + ComponentDto.MODULE_UUID_PATH_SEP); + } + resourceDao.insertUsingExistingSession(resourceDto, session); + insertAuthor(login, resourceDto.getId(), session); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + private void insertAuthor(String login, long personId, SqlSession session) { + AuthorMapper authorMapper = session.getMapper(AuthorMapper.class); + Date now = new Date(); + AuthorDto authorDto = new AuthorDto() + .setLogin(login) + .setPersonId(personId) + .setCreatedAt(now) + .setUpdatedAt(now); + + authorMapper.insert(authorDto); + } + + public List<String> selectScmAccountsByDeveloperUuids(Collection<String> developerUuid) { + SqlSession session = mybatis.openSession(false); + try { + return selectScmAccountsByDeveloperUuids(session, developerUuid); + } finally { + MyBatis.closeQuietly(session); + } + } + + public List<String> selectScmAccountsByDeveloperUuids(final SqlSession session, Collection<String> developerUuids) { + return DaoUtils.executeLargeInputs(developerUuids, new Function<List<String>, List<String>>() { + @Override + public List<String> apply(List<String> partition) { + return session.getMapper(AuthorMapper.class).selectScmAccountsByDeveloperUuids(partition); + } + }); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/user/AuthorDto.java b/sonar-db/src/main/java/org/sonar/db/user/AuthorDto.java new file mode 100644 index 00000000000..32275ab680e --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/user/AuthorDto.java @@ -0,0 +1,80 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.user; + +import java.util.Date; + +/** + * @since 3.0 + */ +public final class AuthorDto { + + private Long id; + private Long personId; + private String login; + private Date createdAt; + private Date updatedAt; + + public Long getId() { + return id; + } + + public AuthorDto setId(Long id) { + this.id = id; + return this; + } + + public Long getPersonId() { + return personId; + } + + public AuthorDto setPersonId(Long personId) { + this.personId = personId; + return this; + } + + public String getLogin() { + return login; + } + + public AuthorDto setLogin(String login) { + this.login = login; + return this; + } + + public Date getCreatedAt() { + return createdAt;// NOSONAR May expose internal representation by returning reference to mutable object + } + + public AuthorDto setCreatedAt(Date createdAt) { + this.createdAt = createdAt;// NOSONAR May expose internal representation by incorporating reference to mutable object + return this; + } + + public Date getUpdatedAt() { + return updatedAt;// NOSONAR May expose internal representation by returning reference to mutable object + } + + public AuthorDto setUpdatedAt(Date updatedAt) { + this.updatedAt = updatedAt;// NOSONAR May expose internal representation by incorporating reference to mutable object + return this; + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/user/AuthorMapper.java b/sonar-db/src/main/java/org/sonar/db/user/AuthorMapper.java new file mode 100644 index 00000000000..06f12adf1d5 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/user/AuthorMapper.java @@ -0,0 +1,38 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.user; + +import java.util.Collection; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + * @since 3.0 + */ +public interface AuthorMapper { + + AuthorDto selectByLogin(String login); + + void insert(AuthorDto authorDto); + + int countDeveloperLogins(long developerId); + + List<String> selectScmAccountsByDeveloperUuids(@Param("uuids") Collection<String> uuids); +} diff --git a/sonar-db/src/main/java/org/sonar/db/user/AuthorizationDao.java b/sonar-db/src/main/java/org/sonar/db/user/AuthorizationDao.java new file mode 100644 index 00000000000..2a386c1d2b7 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/user/AuthorizationDao.java @@ -0,0 +1,134 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.user; + +import com.google.common.base.Function; +import com.google.common.collect.Sets; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import javax.annotation.Nullable; +import org.apache.ibatis.session.SqlSession; +import org.sonar.api.server.ServerSide; +import org.sonar.db.Dao; +import org.sonar.db.DaoUtils; +import org.sonar.db.DbSession; +import org.sonar.db.MyBatis; + +import static com.google.common.collect.Maps.newHashMap; + +@ServerSide +public class AuthorizationDao implements Dao { + + private static final String USER_ID_PARAM = "userId"; + private final MyBatis mybatis; + + public AuthorizationDao(MyBatis mybatis) { + this.mybatis = mybatis; + } + + public Collection<Long> keepAuthorizedProjectIds(final DbSession session, final Collection<Long> componentIds, @Nullable final Integer userId, final String role) { + if (componentIds.isEmpty()) { + return Collections.emptySet(); + } + return DaoUtils.executeLargeInputs(componentIds, new Function<List<Long>, List<Long>>() { + @Override + public List<Long> apply(List<Long> partition) { + if (userId == null) { + return session.getMapper(AuthorizationMapper.class).keepAuthorizedProjectIdsForAnonymous(role, componentIds); + } else { + return session.getMapper(AuthorizationMapper.class).keepAuthorizedProjectIdsForUser(userId, role, componentIds); + } + } + }); + } + + /** + * Used by the Views Plugin + */ + public boolean isAuthorizedComponentKey(String componentKey, @Nullable Integer userId, String role) { + DbSession session = mybatis.openSession(false); + try { + return keepAuthorizedComponentKeys(session, componentKey, userId, role).size() == 1; + } finally { + MyBatis.closeQuietly(session); + } + } + + private List<String> keepAuthorizedComponentKeys(final DbSession session, final String componentKey, @Nullable final Integer userId, final String role) { + if (userId == null) { + return session.getMapper(AuthorizationMapper.class).keepAuthorizedComponentKeysForAnonymous(role, Sets.newHashSet(componentKey)); + } else { + return session.getMapper(AuthorizationMapper.class).keepAuthorizedComponentKeysForUser(userId, role, Sets.newHashSet(componentKey)); + } + } + + public Collection<String> selectAuthorizedRootProjectsKeys(@Nullable Integer userId, String role) { + SqlSession session = mybatis.openSession(false); + try { + return selectAuthorizedRootProjectsKeys(userId, role, session); + + } finally { + MyBatis.closeQuietly(session); + } + } + + public Collection<String> selectAuthorizedRootProjectsUuids(@Nullable Integer userId, String role) { + SqlSession session = mybatis.openSession(false); + try { + return selectAuthorizedRootProjectsUuids(userId, role, session); + + } finally { + MyBatis.closeQuietly(session); + } + } + + public Collection<String> selectAuthorizedRootProjectsKeys(@Nullable Integer userId, String role, SqlSession session) { + String sql; + Map<String, Object> params = newHashMap(); + sql = "selectAuthorizedRootProjectsKeys"; + params.put(USER_ID_PARAM, userId); + params.put("role", role); + + return session.selectList(sql, params); + } + + public Collection<String> selectAuthorizedRootProjectsUuids(@Nullable Integer userId, String role, SqlSession session) { + String sql; + Map<String, Object> params = newHashMap(); + sql = "selectAuthorizedRootProjectsUuids"; + params.put(USER_ID_PARAM, userId); + params.put("role", role); + + return session.selectList(sql, params); + } + + public List<String> selectGlobalPermissions(@Nullable String userLogin) { + SqlSession session = mybatis.openSession(false); + try { + Map<String, Object> params = newHashMap(); + params.put("userLogin", userLogin); + return session.selectList("selectGlobalPermissions", params); + } finally { + MyBatis.closeQuietly(session); + } + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/user/AuthorizationMapper.java b/sonar-db/src/main/java/org/sonar/db/user/AuthorizationMapper.java new file mode 100644 index 00000000000..ca2eadd15d2 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/user/AuthorizationMapper.java @@ -0,0 +1,37 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.user; + +import java.util.Collection; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +public interface AuthorizationMapper { + + List<Long> keepAuthorizedProjectIdsForAnonymous(@Param("role") String role, @Param("componentIds") Collection<Long> componentIds); + + List<Long> keepAuthorizedProjectIdsForUser(@Param("userId") Integer userId, @Param("role") String role, @Param("componentIds") Collection<Long> componentIds); + + List<String> keepAuthorizedComponentKeysForAnonymous(@Param("role") String role, @Param("componentKeys") Collection<String> componentKeys); + + List<String> keepAuthorizedComponentKeysForUser(@Param("userId") Integer userId, @Param("role") String role, @Param("componentKeys") Collection<String> componentKeys); + +} diff --git a/sonar-db/src/main/java/org/sonar/db/user/GroupDto.java b/sonar-db/src/main/java/org/sonar/db/user/GroupDto.java new file mode 100644 index 00000000000..dd483344959 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/user/GroupDto.java @@ -0,0 +1,65 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.user; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.sonar.db.Dto; + +public class GroupDto extends Dto<String> { + + private Long id; + private String name; + private String description; + + public Long getId() { + return id; + } + + public GroupDto setId(Long id) { + this.id = id; + return this; + } + + public String getName() { + return name; + } + + public GroupDto setName(String name) { + this.name = name; + return this; + } + + @CheckForNull + public String getDescription() { + return description; + } + + public GroupDto setDescription(@Nullable String description) { + this.description = description; + return this; + } + + @Override + public String getKey() { + return name; + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/user/GroupMapper.java b/sonar-db/src/main/java/org/sonar/db/user/GroupMapper.java new file mode 100644 index 00000000000..d1cafb62fa9 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/user/GroupMapper.java @@ -0,0 +1,46 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.user; + +import java.util.List; +import javax.annotation.CheckForNull; +import org.apache.ibatis.session.RowBounds; + +public interface GroupMapper { + + @CheckForNull + GroupDto selectByKey(String name); + + @CheckForNull + GroupDto selectById(long groupId); + + List<GroupDto> selectByUserLogin(String userLogin); + + void insert(GroupDto groupDto); + + void update(GroupDto item); + + List<GroupDto> selectByQuery(String query, RowBounds rowBounds); + + int countByQuery(String query); + + void deleteById(long groupId); +} diff --git a/sonar-db/src/main/java/org/sonar/db/user/GroupMembershipDao.java b/sonar-db/src/main/java/org/sonar/db/user/GroupMembershipDao.java new file mode 100644 index 00000000000..a62609259b8 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/user/GroupMembershipDao.java @@ -0,0 +1,118 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.user; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Function; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import javax.annotation.Nonnull; +import org.apache.ibatis.session.RowBounds; +import org.apache.ibatis.session.SqlSession; +import org.sonar.db.Dao; +import org.sonar.db.DaoUtils; +import org.sonar.db.DbSession; +import org.sonar.db.MyBatis; + +public class GroupMembershipDao implements Dao { + + private final MyBatis mybatis; + + public GroupMembershipDao(MyBatis mybatis) { + this.mybatis = mybatis; + } + + // TODO Remove this method and associated client code when the UI is migrated to Backbone + public List<GroupMembershipDto> selectGroups(GroupMembershipQuery query, Long userId, int offset, int limit) { + SqlSession session = mybatis.openSession(false); + try { + return selectGroups(session, query, userId, offset, limit); + } finally { + MyBatis.closeQuietly(session); + } + } + + public List<GroupMembershipDto> selectGroups(SqlSession session, GroupMembershipQuery query, Long userId, int offset, int limit) { + Map<String, Object> params = ImmutableMap.of("query", query, "userId", userId); + return mapper(session).selectGroups(params, new RowBounds(offset, limit)); + } + + public int countGroups(SqlSession session, GroupMembershipQuery query, Long userId) { + Map<String, Object> params = ImmutableMap.of("query", query, "userId", userId); + return mapper(session).countGroups(params); + } + + public List<UserMembershipDto> selectMembers(SqlSession session, UserMembershipQuery query, int offset, int limit) { + Map<String, Object> params = ImmutableMap.of("query", query, "groupId", query.groupId()); + return mapper(session).selectMembers(params, new RowBounds(offset, limit)); + } + + public int countMembers(SqlSession session, UserMembershipQuery query) { + Map<String, Object> params = ImmutableMap.of("query", query, "groupId", query.groupId()); + return mapper(session).countMembers(params); + } + + public Map<String, Integer> countUsersByGroups(final DbSession session, Collection<Long> groupIds) { + final Map<String, Integer> result = Maps.newHashMap(); + DaoUtils.executeLargeInputs(groupIds, new Function<List<Long>, List<GroupUserCount>>() { + @Override + public List<GroupUserCount> apply(@Nonnull List<Long> input) { + List<GroupUserCount> userCounts = mapper(session).countUsersByGroup(input); + for (GroupUserCount count : userCounts) { + result.put(count.groupName(), count.userCount()); + } + return userCounts; + } + }); + + return result; + } + + public Multimap<String, String> selectGroupsByLogins(final DbSession session, Collection<String> logins) { + final Multimap<String, String> result = ArrayListMultimap.create(); + DaoUtils.executeLargeInputs(logins, new Function<List<String>, List<LoginGroup>>() { + @Override + public List<LoginGroup> apply(@Nonnull List<String> input) { + List<LoginGroup> groupMemberships = mapper(session).selectGroupsByLogins(input); + for (LoginGroup membership : groupMemberships) { + result.put(membership.login(), membership.groupName()); + } + return groupMemberships; + } + }); + + return result; + } + + @VisibleForTesting + List<GroupMembershipDto> selectGroups(GroupMembershipQuery query, Long userId) { + return selectGroups(query, userId, 0, Integer.MAX_VALUE); + } + + private GroupMembershipMapper mapper(SqlSession session) { + return session.getMapper(GroupMembershipMapper.class); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/user/GroupMembershipDto.java b/sonar-db/src/main/java/org/sonar/db/user/GroupMembershipDto.java new file mode 100644 index 00000000000..65e32e9b7e1 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/user/GroupMembershipDto.java @@ -0,0 +1,81 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.user; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.sonar.core.user.GroupMembership; + +/** + * @since 4.1 + */ +public class GroupMembershipDto { + + private Long id; + private String name; + private String description; + private Long userId; + + public Long getId() { + return id; + } + + public GroupMembershipDto setId(Long id) { + this.id = id; + return this; + } + + public String getName() { + return name; + } + + public GroupMembershipDto setName(String name) { + this.name = name; + return this; + } + + @CheckForNull + public String getDescription() { + return description; + } + + public GroupMembershipDto setDescription(@Nullable String description) { + this.description = description; + return this; + } + + @CheckForNull + public Long getUserId() { + return userId; + } + + public GroupMembershipDto setUserId(@Nullable Long userId) { + this.userId = userId; + return this; + } + + public GroupMembership toGroupMembership() { + return new GroupMembership() + .setId(id) + .setName(name) + .setDescription(description) + .setMember(userId != null); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/user/GroupMembershipMapper.java b/sonar-db/src/main/java/org/sonar/db/user/GroupMembershipMapper.java new file mode 100644 index 00000000000..37dda516a23 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/user/GroupMembershipMapper.java @@ -0,0 +1,42 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.user; + +import java.util.List; +import java.util.Map; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.session.RowBounds; + +public interface GroupMembershipMapper { + + List<GroupMembershipDto> selectGroups(GroupMembershipQuery query); + + List<GroupMembershipDto> selectGroups(Map<String, Object> params, RowBounds rowBounds); + + int countGroups(Map<String, Object> params); + + List<UserMembershipDto> selectMembers(Map<String, Object> params, RowBounds rowBounds); + + int countMembers(Map<String, Object> params); + + List<GroupUserCount> countUsersByGroup(@Param("groupIds") List<Long> groupIds); + + List<LoginGroup> selectGroupsByLogins(@Param("logins") List<String> logins); +} diff --git a/sonar-db/src/main/java/org/sonar/db/user/GroupMembershipQuery.java b/sonar-db/src/main/java/org/sonar/db/user/GroupMembershipQuery.java new file mode 100644 index 00000000000..3dadb5963bf --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/user/GroupMembershipQuery.java @@ -0,0 +1,164 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.user; + +import com.google.common.collect.ImmutableSet; +import java.util.Set; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.apache.commons.lang.StringUtils; + +import static com.google.common.base.Objects.firstNonNull; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +public class GroupMembershipQuery { + + public static final int DEFAULT_PAGE_INDEX = 1; + public static final int DEFAULT_PAGE_SIZE = 100; + + public static final String ANY = "ANY"; + public static final String IN = "IN"; + public static final String OUT = "OUT"; + public static final Set<String> AVAILABLE_MEMBERSHIP = ImmutableSet.of(ANY, IN, OUT); + + private final String login; + private final String membership; + + private final String groupSearch; + + // for internal use in MyBatis + final String groupSearchSql; + + // max results per page + private final int pageSize; + + // index of selected page. Start with 1. + private final int pageIndex; + + private GroupMembershipQuery(Builder builder) { + this.login = builder.login; + this.membership = builder.membership; + this.groupSearch = builder.groupSearch; + this.groupSearchSql = groupSearchToSql(groupSearch); + + this.pageSize = builder.pageSize; + this.pageIndex = builder.pageIndex; + } + + private static String groupSearchToSql(@Nullable String s) { + String sql = null; + if (s != null) { + sql = StringUtils.replace(StringUtils.upperCase(s), "%", "/%"); + sql = StringUtils.replace(sql, "_", "/_"); + sql = "%" + sql + "%"; + } + return sql; + } + + public String login() { + return login; + } + + @CheckForNull + public String membership() { + return membership; + } + + /** + * Search for groups containing a given string + */ + @CheckForNull + public String groupSearch() { + return groupSearch; + } + + public int pageSize() { + return pageSize; + } + + public int pageIndex() { + return pageIndex; + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private String login; + private String membership; + private String groupSearch; + + private Integer pageIndex = DEFAULT_PAGE_INDEX; + private Integer pageSize = DEFAULT_PAGE_SIZE; + + private Builder() { + } + + public Builder login(String login) { + this.login = login; + return this; + } + + public Builder membership(@Nullable String membership) { + this.membership = membership; + return this; + } + + public Builder groupSearch(@Nullable String s) { + this.groupSearch = StringUtils.defaultIfBlank(s, null); + return this; + } + + public Builder pageSize(@Nullable Integer i) { + this.pageSize = i; + return this; + } + + public Builder pageIndex(@Nullable Integer i) { + this.pageIndex = i; + return this; + } + + private void initMembership() { + membership = firstNonNull(membership, ANY); + checkArgument(AVAILABLE_MEMBERSHIP.contains(membership), + "Membership is not valid (got " + membership + "). Availables values are " + AVAILABLE_MEMBERSHIP); + } + + private void initPageSize() { + pageSize = firstNonNull(pageSize, DEFAULT_PAGE_SIZE); + } + + private void initPageIndex() { + pageIndex = firstNonNull(pageIndex, DEFAULT_PAGE_INDEX); + checkArgument(pageIndex > 0, "Page index must be greater than 0 (got " + pageIndex + ")"); + } + + public GroupMembershipQuery build() { + checkNotNull(login, "User login cant be null."); + initMembership(); + initPageIndex(); + initPageSize(); + return new GroupMembershipQuery(this); + } + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/user/GroupRoleDto.java b/sonar-db/src/main/java/org/sonar/db/user/GroupRoleDto.java new file mode 100644 index 00000000000..9c24a10dcdc --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/user/GroupRoleDto.java @@ -0,0 +1,72 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.user; + +import javax.annotation.Nullable; + +/** + * @since 3.2 + */ +public class GroupRoleDto { + private Long id; + private Long groupId; + private Long resourceId; + private String role; + + public Long getId() { + return id; + } + + public GroupRoleDto setId(Long id) { + this.id = id; + return this; + } + + public Long getGroupId() { + return groupId; + } + + /** + * Null when Anyone + */ + public GroupRoleDto setGroupId(@Nullable Long groupId) { + this.groupId = groupId; + return this; + } + + @Nullable + public Long getResourceId() { + return resourceId; + } + + public GroupRoleDto setResourceId(@Nullable Long resourceId) { + this.resourceId = resourceId; + return this; + } + + public String getRole() { + return role; + } + + public GroupRoleDto setRole(String role) { + this.role = role; + return this; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/user/GroupUserCount.java b/sonar-db/src/main/java/org/sonar/db/user/GroupUserCount.java new file mode 100644 index 00000000000..0c82650f0da --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/user/GroupUserCount.java @@ -0,0 +1,34 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.user; + +public class GroupUserCount { + + private String groupName; + private int userCount; + + public String groupName() { + return groupName; + } + + public int userCount() { + return userCount; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/user/LoginGroup.java b/sonar-db/src/main/java/org/sonar/db/user/LoginGroup.java new file mode 100644 index 00000000000..1f2b080147e --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/user/LoginGroup.java @@ -0,0 +1,34 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.user; + +public class LoginGroup { + + private String login; + private String groupName; + + public String login() { + return login; + } + + public String groupName() { + return groupName; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/user/RoleDao.java b/sonar-db/src/main/java/org/sonar/db/user/RoleDao.java new file mode 100644 index 00000000000..d1314b65900 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/user/RoleDao.java @@ -0,0 +1,79 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.user; + +import java.util.List; +import javax.annotation.Nullable; +import org.apache.ibatis.session.SqlSession; +import org.sonar.api.security.DefaultGroups; +import org.sonar.db.Dao; +import org.sonar.db.DbSession; + +public class RoleDao implements Dao { + + public List<String> selectUserPermissions(DbSession session, String userLogin, @Nullable Long resourceId) { + return session.getMapper(RoleMapper.class).selectUserPermissions(userLogin, resourceId); + } + + public List<String> selectGroupPermissions(DbSession session, String groupName, @Nullable Long resourceId) { + return session.getMapper(RoleMapper.class).selectGroupPermissions(groupName, resourceId, DefaultGroups.isAnyone(groupName)); + } + + public void insertGroupRole(GroupRoleDto groupRole, SqlSession session) { + mapper(session).insertGroupRole(groupRole); + } + + public void insertUserRole(UserRoleDto userRole, SqlSession session) { + mapper(session).insertUserRole(userRole); + } + + public void deleteUserRole(UserRoleDto userRole, SqlSession session) { + mapper(session).deleteUserRole(userRole); + } + + public void deleteGroupRole(GroupRoleDto groupRole, SqlSession session) { + mapper(session).deleteGroupRole(groupRole); + } + + public void deleteGroupRolesByResourceId(Long resourceId, SqlSession session) { + mapper(session).deleteGroupRolesByResourceId(resourceId); + } + + public void deleteUserRolesByResourceId(Long resourceId, SqlSession session) { + mapper(session).deleteUserRolesByResourceId(resourceId); + } + + public int countResourceGroupRoles(DbSession session, Long resourceId) { + return mapper(session).countResourceGroupRoles(resourceId); + } + + public int countResourceUserRoles(DbSession session, Long resourceId) { + return mapper(session).countResourceUserRoles(resourceId); + } + + public void deleteGroupRolesByGroupId(DbSession session, long groupId) { + mapper(session).deleteGroupRolesByGroupId(groupId); + } + + private static RoleMapper mapper(SqlSession session) { + return session.getMapper(RoleMapper.class); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/user/RoleMapper.java b/sonar-db/src/main/java/org/sonar/db/user/RoleMapper.java new file mode 100644 index 00000000000..f26b59874bf --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/user/RoleMapper.java @@ -0,0 +1,59 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.user; + +import java.util.List; +import javax.annotation.Nullable; +import org.apache.ibatis.annotations.Param; + +/** + * @since 3.2 + */ +public interface RoleMapper { + + /** + * @return permissions from a user + */ + List<String> selectUserPermissions(@Param("userLogin") String userLogin, @Nullable @Param("resourceId") Long resourceId); + + /** + * @return permissions from to a group + */ + List<String> selectGroupPermissions(@Param("groupName") String groupName, @Nullable @Param("resourceId") Long resourceId, @Param("isAnyOneGroup") Boolean isAnyOneGroup); + + void insertGroupRole(GroupRoleDto groupRole); + + void insertUserRole(UserRoleDto userRole); + + void deleteUserRole(UserRoleDto userRole); + + void deleteGroupRole(GroupRoleDto groupRole); + + void deleteGroupRolesByResourceId(Long resourceId); + + void deleteUserRolesByResourceId(Long resourceId); + + int countResourceGroupRoles(Long resourceId); + + int countResourceUserRoles(Long resourceId); + + void deleteGroupRolesByGroupId(long groupId); + +} diff --git a/sonar-db/src/main/java/org/sonar/db/user/UserDao.java b/sonar-db/src/main/java/org/sonar/db/user/UserDao.java new file mode 100644 index 00000000000..985da344a29 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/user/UserDao.java @@ -0,0 +1,175 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.user; + +import com.google.common.collect.Lists; +import java.util.List; +import javax.annotation.CheckForNull; +import org.apache.ibatis.session.SqlSession; +import org.sonar.api.user.UserQuery; +import org.sonar.api.utils.System2; +import org.sonar.db.Dao; +import org.sonar.db.DbSession; +import org.sonar.db.MyBatis; + +public class UserDao implements Dao { + + private final MyBatis mybatis; + private final System2 system2; + + public UserDao(MyBatis mybatis, System2 system2) { + this.mybatis = mybatis; + this.system2 = system2; + } + + public UserDto getUser(long userId) { + SqlSession session = mybatis.openSession(false); + try { + return getUser(userId, session); + } finally { + MyBatis.closeQuietly(session); + } + } + + public UserDto getUser(long userId, SqlSession session) { + return session.getMapper(UserMapper.class).selectUser(userId); + } + + /** + * Search for user by login. Disabled users are ignored. + * + * @return the user, null if user not found + */ + @CheckForNull + public UserDto selectActiveUserByLogin(String login) { + DbSession session = mybatis.openSession(false); + try { + return selectActiveUserByLogin(session, login); + } finally { + MyBatis.closeQuietly(session); + } + } + + @CheckForNull + public UserDto selectActiveUserByLogin(DbSession session, String login) { + UserMapper mapper = session.getMapper(UserMapper.class); + return mapper.selectUserByLogin(login); + } + + public List<UserDto> selectUsersByLogins(List<String> logins) { + List<UserDto> users = Lists.newArrayList(); + DbSession session = mybatis.openSession(false); + try { + users.addAll(selectUsersByLogins(session, logins)); + } finally { + MyBatis.closeQuietly(session); + } + return users; + } + + public List<UserDto> selectUsersByLogins(DbSession session, List<String> logins) { + List<UserDto> users = Lists.newArrayList(); + if (!logins.isEmpty()) { + UserMapper mapper = session.getMapper(UserMapper.class); + List<List<String>> partitions = Lists.partition(logins, 1000); + for (List<String> partition : partitions) { + users.addAll(mapper.selectUsersByLogins(partition)); + } + } + return users; + } + + public List<UserDto> selectUsers(UserQuery query) { + SqlSession session = mybatis.openSession(false); + try { + UserMapper mapper = session.getMapper(UserMapper.class); + return mapper.selectUsers(query); + } finally { + MyBatis.closeQuietly(session); + } + } + + public UserDto insert(SqlSession session, UserDto dto) { + session.getMapper(UserMapper.class).insert(dto); + return dto; + } + + public UserDto update(SqlSession session, UserDto dto) { + session.getMapper(UserMapper.class).update(dto); + return dto; + } + + /** + * Deactivate a user and drops all his preferences. + * @return false if the user does not exist, true if the existing user has been deactivated + */ + public boolean deactivateUserByLogin(String login) { + SqlSession session = mybatis.openSession(false); + try { + UserMapper mapper = session.getMapper(UserMapper.class); + UserDto dto = mapper.selectUserByLogin(login); + if (dto == null) { + return false; + } + + mapper.removeUserFromGroups(dto.getId()); + mapper.deleteUserActiveDashboards(dto.getId()); + mapper.deleteUnsharedUserDashboards(dto.getId()); + mapper.deleteUnsharedUserIssueFilters(dto.getLogin()); + mapper.deleteUserIssueFilterFavourites(dto.getLogin()); + mapper.deleteUnsharedUserMeasureFilters(dto.getId()); + mapper.deleteUserMeasureFilterFavourites(dto.getId()); + mapper.deleteUserProperties(dto.getId()); + mapper.deleteUserRoles(dto.getId()); + mapper.deactivateUser(dto.getId(), system2.now()); + session.commit(); + return true; + + } finally { + MyBatis.closeQuietly(session); + } + } + + /** + * Search for group by name. + * + * @return the group, null if group not found + * + * TODO should be moved to GroupDao + */ + @CheckForNull + public GroupDto selectGroupByName(String name, DbSession session) { + UserMapper mapper = session.getMapper(UserMapper.class); + return mapper.selectGroupByName(name); + } + + /** + * TODO should be moved to GroupDao + */ + @CheckForNull + public GroupDto selectGroupByName(String name) { + DbSession session = mybatis.openSession(false); + try { + return selectGroupByName(name, session); + } finally { + MyBatis.closeQuietly(session); + } + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/user/UserDto.java b/sonar-db/src/main/java/org/sonar/db/user/UserDto.java new file mode 100644 index 00000000000..b0d9f79d95f --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/user/UserDto.java @@ -0,0 +1,175 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.user; + +import com.google.common.base.Splitter; +import com.google.common.collect.Lists; +import java.util.ArrayList; +import java.util.List; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.apache.commons.lang.StringUtils; +import org.sonar.core.user.DefaultUser; + +/** + * @since 3.2 + */ +public class UserDto { + public static final char SCM_ACCOUNTS_SEPARATOR = '\n'; + + private Long id; + private String login; + private String name; + private String email; + private boolean active = true; + private String scmAccounts; + private String cryptedPassword; + private String salt; + private Long createdAt; + private Long updatedAt; + + public Long getId() { + return id; + } + + public UserDto setId(Long id) { + this.id = id; + return this; + } + + public String getLogin() { + return login; + } + + public UserDto setLogin(String login) { + this.login = login; + return this; + } + + public String getName() { + return name; + } + + public UserDto setName(String name) { + this.name = name; + return this; + } + + @CheckForNull + public String getEmail() { + return email; + } + + public UserDto setEmail(@Nullable String email) { + this.email = email; + return this; + } + + public boolean isActive() { + return active; + } + + public UserDto setActive(boolean b) { + this.active = b; + return this; + } + + @CheckForNull + public String getScmAccounts() { + return scmAccounts; + } + + public List<String> getScmAccountsAsList() { + return decodeScmAccounts(scmAccounts); + } + + /** + * List of SCM accounts separated by '|' + */ + public UserDto setScmAccounts(@Nullable String s) { + this.scmAccounts = s; + return this; + } + + public UserDto setScmAccounts(@Nullable List list) { + this.scmAccounts = encodeScmAccounts(list); + return this; + } + + @CheckForNull + public static String encodeScmAccounts(@Nullable List<String> scmAccounts) { + if (scmAccounts != null && !scmAccounts.isEmpty()) { + return String.format("%s%s%s", SCM_ACCOUNTS_SEPARATOR, StringUtils.join(scmAccounts, SCM_ACCOUNTS_SEPARATOR), SCM_ACCOUNTS_SEPARATOR); + } + return null; + } + + public static List<String> decodeScmAccounts(@Nullable String dbValue) { + if (dbValue == null) { + return new ArrayList<>(); + } else { + return Lists.newArrayList(Splitter.on(SCM_ACCOUNTS_SEPARATOR).omitEmptyStrings().split(dbValue)); + } + } + + public String getCryptedPassword() { + return cryptedPassword; + } + + public UserDto setCryptedPassword(String cryptedPassword) { + this.cryptedPassword = cryptedPassword; + return this; + } + + public String getSalt() { + return salt; + } + + public UserDto setSalt(String salt) { + this.salt = salt; + return this; + } + + public Long getCreatedAt() { + return createdAt; + } + + public UserDto setCreatedAt(Long createdAt) { + this.createdAt = createdAt; + return this; + } + + public Long getUpdatedAt() { + return updatedAt; + } + + public UserDto setUpdatedAt(Long updatedAt) { + this.updatedAt = updatedAt; + return this; + } + + public DefaultUser toUser() { + return new DefaultUser() + .setLogin(login) + .setName(name) + .setEmail(email) + .setActive(active); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/user/UserGroupDto.java b/sonar-db/src/main/java/org/sonar/db/user/UserGroupDto.java new file mode 100644 index 00000000000..d26510f69ad --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/user/UserGroupDto.java @@ -0,0 +1,45 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.user; + +public class UserGroupDto { + + private Long userId; + private Long groupId; + + public Long getUserId() { + return userId; + } + + public UserGroupDto setUserId(Long userId) { + this.userId = userId; + return this; + } + + public Long getGroupId() { + return groupId; + } + + public UserGroupDto setGroupId(Long groupId) { + this.groupId = groupId; + return this; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/user/UserGroupMapper.java b/sonar-db/src/main/java/org/sonar/db/user/UserGroupMapper.java new file mode 100644 index 00000000000..6c723dbf838 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/user/UserGroupMapper.java @@ -0,0 +1,30 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.user; + +public interface UserGroupMapper { + + void insert(UserGroupDto userGroupDto); + + void delete(UserGroupDto dto); + + void deleteMembersByGroup(long groupId); +} diff --git a/sonar-db/src/main/java/org/sonar/db/user/UserMapper.java b/sonar-db/src/main/java/org/sonar/db/user/UserMapper.java new file mode 100644 index 00000000000..e387210942a --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/user/UserMapper.java @@ -0,0 +1,79 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.user; + +import java.util.List; +import javax.annotation.CheckForNull; +import org.apache.ibatis.annotations.Param; +import org.sonar.api.user.UserQuery; + +public interface UserMapper { + + @CheckForNull + UserDto selectByLogin(String login); + + /** + * Search for a user by SCM account, login or email. + * Can return multiple results if an email is used by many users (For instance, technical account can use the same email as a none technical account) + */ + @CheckForNull + List<UserDto> selectNullableByScmAccountOrLoginOrEmail(@Param("scmAccount") String scmAccountOrLoginOrEmail, @Param("likeScmAccount") String likeScmAccount); + + @CheckForNull + UserDto selectUser(long userId); + + /** + * Select user by login. Note that disabled users are ignored. + */ + @CheckForNull + UserDto selectUserByLogin(String login); + + List<UserDto> selectUsersByLogins(@Param("logins") List<String> logins); + + List<UserDto> selectUsers(UserQuery query); + + @CheckForNull + GroupDto selectGroupByName(String name); + + void insert(UserDto userDto); + + void update(UserDto userDto); + + void removeUserFromGroups(long userId); + + void deleteUserActiveDashboards(long userId); + + void deleteUnsharedUserDashboards(long userId); + + void deleteUnsharedUserIssueFilters(String login); + + void deleteUserIssueFilterFavourites(String login); + + void deleteUnsharedUserMeasureFilters(long userId); + + void deleteUserMeasureFilterFavourites(long userId); + + void deleteUserProperties(long userId); + + void deleteUserRoles(long userId); + + void deactivateUser(@Param("id") long userId, @Param("now") long now); + +} diff --git a/sonar-db/src/main/java/org/sonar/db/user/UserMembershipDto.java b/sonar-db/src/main/java/org/sonar/db/user/UserMembershipDto.java new file mode 100644 index 00000000000..14b3dd3c90b --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/user/UserMembershipDto.java @@ -0,0 +1,69 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.user; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; + +public class UserMembershipDto { + + private Long id; + private Long groupId; + private String login; + private String name; + + public Long getId() { + return id; + } + + public UserMembershipDto setId(Long id) { + this.id = id; + return this; + } + + public String getName() { + return name; + } + + public UserMembershipDto setName(String name) { + this.name = name; + return this; + } + + @CheckForNull + public String getLogin() { + return login; + } + + public UserMembershipDto setLogin(@Nullable String login) { + this.login = login; + return this; + } + + @CheckForNull + public Long getGroupId() { + return groupId; + } + + public UserMembershipDto setGroupId(@Nullable Long groupId) { + this.groupId = groupId; + return this; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/user/UserMembershipQuery.java b/sonar-db/src/main/java/org/sonar/db/user/UserMembershipQuery.java new file mode 100644 index 00000000000..f89d99ce0cc --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/user/UserMembershipQuery.java @@ -0,0 +1,164 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.user; + +import com.google.common.collect.ImmutableSet; +import java.util.Set; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.apache.commons.lang.StringUtils; + +import static com.google.common.base.Objects.firstNonNull; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +public class UserMembershipQuery { + + public static final int DEFAULT_PAGE_INDEX = 1; + public static final int DEFAULT_PAGE_SIZE = 100; + + public static final String ANY = "ANY"; + public static final String IN = "IN"; + public static final String OUT = "OUT"; + public static final Set<String> AVAILABLE_MEMBERSHIPS = ImmutableSet.of(ANY, IN, OUT); + + private final Long groupId; + private final String membership; + + private final String memberSearch; + + // for internal use in MyBatis + final String memberSearchSql; + + // max results per page + private final int pageSize; + + // index of selected page. Start with 1. + private final int pageIndex; + + private UserMembershipQuery(Builder builder) { + this.groupId = builder.groupId; + this.membership = builder.membership; + this.memberSearch = builder.memberSearch; + this.memberSearchSql = memberSearchToSql(memberSearch); + + this.pageSize = builder.pageSize; + this.pageIndex = builder.pageIndex; + } + + private String memberSearchToSql(@Nullable String s) { + String sql = null; + if (s != null) { + sql = StringUtils.replace(StringUtils.upperCase(s), "%", "/%"); + sql = StringUtils.replace(sql, "_", "/_"); + sql = "%" + sql + "%"; + } + return sql; + } + + public Long groupId() { + return groupId; + } + + @CheckForNull + public String membership() { + return membership; + } + + /** + * Search for users names/logins containing a given string + */ + @CheckForNull + public String memberSearch() { + return memberSearch; + } + + public int pageSize() { + return pageSize; + } + + public int pageIndex() { + return pageIndex; + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private Long groupId; + private String membership; + private String memberSearch; + + private Integer pageIndex = DEFAULT_PAGE_INDEX; + private Integer pageSize = DEFAULT_PAGE_SIZE; + + private Builder() { + } + + public Builder groupId(Long groupId) { + this.groupId = groupId; + return this; + } + + public Builder membership(@Nullable String membership) { + this.membership = membership; + return this; + } + + public Builder memberSearch(@Nullable String s) { + this.memberSearch = StringUtils.defaultIfBlank(s, null); + return this; + } + + public Builder pageSize(@Nullable Integer i) { + this.pageSize = i; + return this; + } + + public Builder pageIndex(@Nullable Integer i) { + this.pageIndex = i; + return this; + } + + private void initMembership() { + membership = firstNonNull(membership, ANY); + checkArgument(AVAILABLE_MEMBERSHIPS.contains(membership), + "Membership is not valid (got " + membership + "). Availables values are " + AVAILABLE_MEMBERSHIPS); + } + + private void initPageSize() { + pageSize = firstNonNull(pageSize, DEFAULT_PAGE_SIZE); + } + + private void initPageIndex() { + pageIndex = firstNonNull(pageIndex, DEFAULT_PAGE_INDEX); + checkArgument(pageIndex > 0, "Page index must be greater than 0 (got " + pageIndex + ")"); + } + + public UserMembershipQuery build() { + checkNotNull(groupId, "Group ID cant be null."); + initMembership(); + initPageIndex(); + initPageSize(); + return new UserMembershipQuery(this); + } + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/user/UserRoleDto.java b/sonar-db/src/main/java/org/sonar/db/user/UserRoleDto.java new file mode 100644 index 00000000000..9ce973e7519 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/user/UserRoleDto.java @@ -0,0 +1,69 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.user; + +import javax.annotation.Nullable; + +/** + * @since 3.2 + */ +public class UserRoleDto { + private Long id; + private Long userId; + private Long resourceId; + private String role; + + public Long getId() { + return id; + } + + public UserRoleDto setId(Long id) { + this.id = id; + return this; + } + + public Long getUserId() { + return userId; + } + + public UserRoleDto setUserId(Long userId) { + this.userId = userId; + return this; + } + + @Nullable + public Long getResourceId() { + return resourceId; + } + + public UserRoleDto setResourceId(@Nullable Long resourceId) { + this.resourceId = resourceId; + return this; + } + + public String getRole() { + return role; + } + + public UserRoleDto setRole(String role) { + this.role = role; + return this; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/version/DatabaseVersion.java b/sonar-db/src/main/java/org/sonar/db/version/DatabaseVersion.java new file mode 100644 index 00000000000..e8435f2b05b --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/version/DatabaseVersion.java @@ -0,0 +1,133 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.version; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.ImmutableList; +import java.util.Collections; +import java.util.List; +import org.apache.ibatis.session.SqlSession; +import org.sonar.db.MyBatis; + +public class DatabaseVersion { + + public static final int LAST_VERSION = 923; + + /** + * List of all the tables. + * This list is hardcoded because we didn't succeed in using java.sql.DatabaseMetaData#getTables() in the same way + * for all the supported databases, particularly due to Oracle results. + */ + public static final List<String> TABLES = ImmutableList.of( + "action_plans", + "active_dashboards", + "active_rules", + "active_rule_parameters", + "activities", + "analysis_reports", + "authors", + "characteristics", + "dashboards", + "duplications_index", + "events", + "file_sources", + "groups", + "groups_users", + "group_roles", + "issues", + "issue_changes", + "issue_filters", + "issue_filter_favourites", + "loaded_templates", + "manual_measures", + "measure_filters", + "measure_filter_favourites", + "metrics", + "notifications", + "permission_templates", + "perm_templates_users", + "perm_templates_groups", + "quality_gates", + "quality_gate_conditions", + "projects", + "project_links", + "project_measures", + "project_qprofiles", + "properties", + "resource_index", + "rules", + "rules_parameters", + "rules_profiles", + "semaphores", + "schema_migrations", + "snapshots", + "users", + "user_roles", + "widgets", + "widget_properties" + ); + private MyBatis mybatis; + + public DatabaseVersion(MyBatis mybatis) { + this.mybatis = mybatis; + } + + @VisibleForTesting + static Status getStatus(Integer currentVersion, int lastVersion) { + Status status = Status.FRESH_INSTALL; + if (currentVersion != null) { + if (currentVersion == lastVersion) { + status = Status.UP_TO_DATE; + } else if (currentVersion > lastVersion) { + status = Status.REQUIRES_DOWNGRADE; + } else { + status = Status.REQUIRES_UPGRADE; + } + } + return status; + } + + public Status getStatus() { + return getStatus(getVersion(), LAST_VERSION); + } + + public Integer getVersion() { + SqlSession session = mybatis.openSession(false); + try { + List<Integer> versions = session.getMapper(SchemaMigrationMapper.class).selectVersions(); + if (!versions.isEmpty()) { + Collections.sort(versions); + return versions.get(versions.size() - 1); + } + return null; + } catch (RuntimeException e) { + // The table SCHEMA_MIGRATIONS does not exist. + // Ignore this exception -> it will be created by Ruby on Rails migrations. + return null; + + } finally { + MyBatis.closeQuietly(session); + } + } + + public enum Status { + UP_TO_DATE, REQUIRES_UPGRADE, REQUIRES_DOWNGRADE, FRESH_INSTALL + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/version/SchemaMigrationDto.java b/sonar-db/src/main/java/org/sonar/db/version/SchemaMigrationDto.java new file mode 100644 index 00000000000..c78b8457f97 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/version/SchemaMigrationDto.java @@ -0,0 +1,32 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.version; + +/** + * Maps the table SCHEMA_MIGRATIONS that is fed by Ruby on Rails Migrations + * @since 3.0 + */ +public class SchemaMigrationDto { + private String version;// NOSONAR this field is assigned by MyBatis + + public String getVersion() { + return version; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/version/SchemaMigrationMapper.java b/sonar-db/src/main/java/org/sonar/db/version/SchemaMigrationMapper.java new file mode 100644 index 00000000000..5b8a3645be2 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/version/SchemaMigrationMapper.java @@ -0,0 +1,28 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.version; + +import java.util.List; + +public interface SchemaMigrationMapper { + List<Integer> selectVersions(); + + void insert(String version); +} diff --git a/sonar-db/src/main/java/org/sonar/db/version/package-info.java b/sonar-db/src/main/java/org/sonar/db/version/package-info.java new file mode 100644 index 00000000000..f5be5b6d523 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/version/package-info.java @@ -0,0 +1,24 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.version; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/sonar-db/src/main/java/org/sonar/db/version/v44/ChangeLog.java b/sonar-db/src/main/java/org/sonar/db/version/v44/ChangeLog.java new file mode 100644 index 00000000000..6306bb7704c --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/version/v44/ChangeLog.java @@ -0,0 +1,118 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.version.v44; + +import java.util.Date; + +/** + * SONAR-5329 + * Transition ActiveRuleChanges to ActivityLog + * <p/> + * Used in the Active Record Migration 548. + * + * @since 4.4 + */ +public class ChangeLog { + + private int id; + private Date createdAt; + private int severity; + private String paramKey; + private String paramValue; + private String userLogin; + private String ruleKey; + private String repository; + private String profileKey; + + public ChangeLog() { + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public int getSeverity() { + return severity; + } + + public void setSeverity(int severity) { + this.severity = severity; + } + + public Date getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + } + + public String getParamKey() { + return paramKey; + } + + public void setParamKey(String paramKey) { + this.paramKey = paramKey; + } + + public String getParamValue() { + return paramValue; + } + + public void setParamValue(String paramValue) { + this.paramValue = paramValue; + } + + public String getUserLogin() { + return userLogin; + } + + public void setUserLogin(String userLogin) { + this.userLogin = userLogin; + } + + public String getRuleKey() { + return ruleKey; + } + + public void setRuleKey(String ruleKey) { + this.ruleKey = ruleKey; + } + + public String getRepository() { + return repository; + } + + public void setRepository(String repository) { + this.repository = repository; + } + + public String getProfileKey() { + return profileKey; + } + + public void setProfileKey(String profileKey) { + this.profileKey = profileKey; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/version/v44/Migration44Mapper.java b/sonar-db/src/main/java/org/sonar/db/version/v44/Migration44Mapper.java new file mode 100644 index 00000000000..875be56a080 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/version/v44/Migration44Mapper.java @@ -0,0 +1,63 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.version.v44; + +import java.util.Date; +import java.util.List; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.apache.ibatis.annotations.Param; + +public interface Migration44Mapper { + + // migration of measures "profile" and "profile_version" + List<ProfileMeasure> selectProfileMeasures(); + + @CheckForNull + Integer selectProfileVersion(long snapshotId); + + @CheckForNull + Date selectProfileVersionDate(@Param("profileId") int profileId, @Param("profileVersion") int profileVersion); + + void updateProfileMeasure(@Param("measureId") long measureId, @Param("json") String json); + + void deleteProfileMeasure(long profileMeasureId); + + @CheckForNull + QProfileDto44 selectProfileById(int id); + + // creation of columns RULES_PROFILES.CREATED_AT and UPDATED_AT + List<QProfileDto44> selectAllProfiles(); + + @CheckForNull + Date selectProfileCreatedAt(int profileId); + + @CheckForNull + Date selectProfileUpdatedAt(int profileId); + + void updateProfileDates(@Param("profileId") int profileId, + @Param("createdAt") Date createdAt, @Param("updatedAt") Date updatedAt, + @Param("rulesUpdatedAt") String rulesUpdatedAt); + + // migrate changeLog to Activities + List<ChangeLog> selectActiveRuleChange(@Nullable @Param("enabled") Boolean enabled); + + List<Long> selectMeasuresOnDeletedQualityProfiles(); +} diff --git a/sonar-db/src/main/java/org/sonar/db/version/v44/ProfileMeasure.java b/sonar-db/src/main/java/org/sonar/db/version/v44/ProfileMeasure.java new file mode 100644 index 00000000000..c3663442a87 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/version/v44/ProfileMeasure.java @@ -0,0 +1,50 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.version.v44; + +public class ProfileMeasure { + private long id; + private int profileId; + private long snapshotId; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public int getProfileId() { + return profileId; + } + + public void setProfileId(int profileId) { + this.profileId = profileId; + } + + public long getSnapshotId() { + return snapshotId; + } + + public void setSnapshotId(long snapshotId) { + this.snapshotId = snapshotId; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/version/v44/QProfileDto44.java b/sonar-db/src/main/java/org/sonar/db/version/v44/QProfileDto44.java new file mode 100644 index 00000000000..7b659f52f13 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/version/v44/QProfileDto44.java @@ -0,0 +1,60 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.version.v44; + +public class QProfileDto44 { + + private Integer id; + private String kee; + private String name; + private String language; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getKee() { + return kee; + } + + public void setKee(String kee) { + this.kee = kee; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/version/v44/package-info.java b/sonar-db/src/main/java/org/sonar/db/version/v44/package-info.java new file mode 100644 index 00000000000..9d07e1f584a --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/version/v44/package-info.java @@ -0,0 +1,25 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.version.v44; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/sonar-db/src/main/java/org/sonar/db/version/v45/Migration45Mapper.java b/sonar-db/src/main/java/org/sonar/db/version/v45/Migration45Mapper.java new file mode 100644 index 00000000000..7d6cac507c7 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/version/v45/Migration45Mapper.java @@ -0,0 +1,63 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.version.v45; + +import java.util.Date; +import java.util.List; +import org.apache.ibatis.annotations.Insert; +import org.apache.ibatis.annotations.Options; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Result; +import org.apache.ibatis.annotations.Select; + +public interface Migration45Mapper { + + @Select("SELECT rules_parameters.id, rules_parameters.rule_id as \"ruleId\", rules_parameters.name as \"name\", rules_parameters.param_type as \"type\", " + + " rules_parameters.default_value as \"defaultValue\", rules_parameters.description, rules.template_id as \"ruleTemplateId\" " + + "FROM rules_parameters " + + " INNER JOIN rules ON rules.id = rules_parameters.rule_id " + + "WHERE rules.is_template = ${_true}") + @Result(javaType = RuleParameter.class) + List<RuleParameter> selectAllTemplateRuleParameters(); + + @Select("SELECT rules_parameters.id, rules_parameters.rule_id as \"ruleId\", rules_parameters.name as \"name\", rules_parameters.param_type as \"type\", " + + " rules_parameters.default_value as \"defaultValue\", rules_parameters.description, rules.template_id as \"ruleTemplateId\" " + + "FROM rules_parameters " + + " INNER JOIN rules ON rules.id = rules_parameters.rule_id " + + "WHERE rules.template_id IS NOT NULL") + @Result(javaType = RuleParameter.class) + List<RuleParameter> selectAllCustomRuleParameters(); + + @Select("SELECT id, plugin_rule_key as \"ruleKey\", plugin_name as \"repositoryKey\", is_template as \"isTemplate\", template_id as \"templateId\"" + + "FROM rules " + + "WHERE rules.template_id IS NOT NULL") + @Result(javaType = Rule.class) + List<Rule> selectAllCustomRules(); + + @Insert("INSERT INTO rules_parameters (rule_id, name, param_type, default_value, description)" + + " VALUES (#{ruleId}, #{name}, #{type}, #{defaultValue}, #{description})") + @Options(useGeneratedKeys = false) + void insertRuleParameter(RuleParameter ruleParameter); + + @Insert("UPDATE rules SET updated_at=#{date} WHERE id=#{id}") + @Options(useGeneratedKeys = false) + void updateRuleUpdateAt(@Param("id") Integer ruleId, @Param("date") Date updatedAt); + +} diff --git a/sonar-db/src/main/java/org/sonar/db/version/v45/Rule.java b/sonar-db/src/main/java/org/sonar/db/version/v45/Rule.java new file mode 100644 index 00000000000..18fcf353e78 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/version/v45/Rule.java @@ -0,0 +1,111 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.version.v45; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; + +/** + * SONAR-5575 + * <p/> + * Used in the Active Record Migration 601. + * + * @since 4.5 + */ +public final class Rule { + + private Integer id; + private String repositoryKey; + private String ruleKey; + private boolean isTemplate; + private Integer templateId; + + public Integer getId() { + return id; + } + + public Rule setId(Integer id) { + this.id = id; + return this; + } + + public String getRepositoryKey() { + return repositoryKey; + } + + public Rule setRepositoryKey(String repositoryKey) { + this.repositoryKey = repositoryKey; + return this; + } + + public String getRuleKey() { + return ruleKey; + } + + public Rule setRuleKey(String ruleKey) { + this.ruleKey = ruleKey; + return this; + } + + public boolean isTemplate() { + return isTemplate; + } + + public Rule setIsTemplate(boolean isTemplate) { + this.isTemplate = isTemplate; + return this; + } + + @CheckForNull + public Integer getTemplateId() { + return templateId; + } + + public Rule setTemplateId(@Nullable Integer templateId) { + this.templateId = templateId; + return this; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Rule)) { + return false; + } + if (this == obj) { + return true; + } + Rule other = (Rule) obj; + return new EqualsBuilder() + .append(repositoryKey, other.getRepositoryKey()) + .append(ruleKey, other.getRuleKey()) + .isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder(17, 37) + .append(repositoryKey) + .append(ruleKey) + .toHashCode(); + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/version/v45/RuleParameter.java b/sonar-db/src/main/java/org/sonar/db/version/v45/RuleParameter.java new file mode 100644 index 00000000000..e2102b23bab --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/version/v45/RuleParameter.java @@ -0,0 +1,113 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.version.v45; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.apache.commons.lang.builder.ReflectionToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; + +/** + * SONAR-5575 + * <p/> + * Used in the Active Record Migration 601. + * + * @since 4.5 + */ +public class RuleParameter { + + private Integer id; + private Integer ruleId; + private Integer ruleTemplateId; + private String name; + private String type; + private String defaultValue; + private String description; + + public Integer getId() { + return id; + } + + public RuleParameter setId(Integer id) { + this.id = id; + return this; + } + + public Integer getRuleId() { + return ruleId; + } + + public RuleParameter setRuleId(Integer ruleId) { + this.ruleId = ruleId; + return this; + } + + @CheckForNull + public Integer getRuleTemplateId() { + return ruleTemplateId; + } + + public RuleParameter setRuleTemplateId(@Nullable Integer ruleTemplateId) { + this.ruleTemplateId = ruleTemplateId; + return this; + } + + public String getName() { + return name; + } + + public RuleParameter setName(String name) { + this.name = name; + return this; + } + + public String getType() { + return type; + } + + public RuleParameter setType(String type) { + this.type = type; + return this; + } + + @CheckForNull + public String getDefaultValue() { + return defaultValue; + } + + public RuleParameter setDefaultValue(@Nullable String defaultValue) { + this.defaultValue = defaultValue; + return this; + } + + public String getDescription() { + return description; + } + + public RuleParameter setDescription(String description) { + this.description = description; + return this; + } + + @Override + public String toString() { + return new ReflectionToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).toString(); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/version/v45/package-info.java b/sonar-db/src/main/java/org/sonar/db/version/v45/package-info.java new file mode 100644 index 00000000000..98d09760f72 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/version/v45/package-info.java @@ -0,0 +1,24 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.version.v45; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/sonar-db/src/main/java/org/sonar/db/version/v50/Component.java b/sonar-db/src/main/java/org/sonar/db/version/v50/Component.java new file mode 100644 index 00000000000..acfa141ea9a --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/version/v50/Component.java @@ -0,0 +1,121 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.version.v50; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; + +public class Component { + + private Long id; + private Long projectId; + private Long snapshotId; + private String snapshotPath; + private String scope; + + private String uuid; + private String projectUuid; + private String moduleUuid; + private String moduleUuidPath = ""; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + /** + * Can be null on provisioned projects or library + */ + @CheckForNull + public Long getProjectId() { + return projectId; + } + + public void setProjectId(@Nullable Long projectId) { + this.projectId = projectId; + } + + /** + * Can be null on provisioned projects or library + */ + @CheckForNull + public Long getSnapshotId() { + return snapshotId; + } + + public void setSnapshotId(@Nullable Long snapshotId) { + this.snapshotId = snapshotId; + } + + @CheckForNull + public String getSnapshotPath() { + return snapshotPath; + } + + public void setSnapshotPath(@Nullable String snapshotPath) { + this.snapshotPath = snapshotPath; + } + + public String getScope() { + return scope; + } + + public void setScope(String scope) { + this.scope = scope; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public String getProjectUuid() { + return projectUuid; + } + + public void setProjectUuid(String projectUuid) { + this.projectUuid = projectUuid; + } + + @CheckForNull + public String getModuleUuid() { + return moduleUuid; + } + + public void setModuleUuid(@Nullable String moduleUuid) { + this.moduleUuid = moduleUuid; + } + + @CheckForNull + public String getModuleUuidPath() { + return moduleUuidPath; + } + + public void setModuleUuidPath(@Nullable String moduleUuidPath) { + this.moduleUuidPath = moduleUuidPath; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/version/v50/Migration50Mapper.java b/sonar-db/src/main/java/org/sonar/db/version/v50/Migration50Mapper.java new file mode 100644 index 00000000000..f8f60aea16c --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/version/v50/Migration50Mapper.java @@ -0,0 +1,128 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.version.v50; + +import java.util.List; +import org.apache.ibatis.annotations.Options; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Result; +import org.apache.ibatis.annotations.Select; +import org.apache.ibatis.annotations.Update; +import org.apache.ibatis.mapping.ResultSetType; + +public interface Migration50Mapper { + + /** + * Return root projects (Views and Developers are NOT returned) + */ + @Select("SELECT " + + " p.id AS \"id\", " + + " p.uuid AS \"uuid\", " + + " p.project_uuid AS \"projectUuid\", " + + " s.root_project_id AS \"projectId\", " + + " s.id AS \"snapshotId\", " + + " s.path AS \"snapshotPath\", " + + " p.scope AS \"scope\" " + + "FROM projects p " + + " LEFT OUTER JOIN snapshots s ON s.project_id = p.id AND s.islast = ${_true} " + + " WHERE " + + " p.scope = 'PRJ' " + + " AND p.root_id IS NULL ") + @Result(javaType = Component.class) + @Options(resultSetType = ResultSetType.FORWARD_ONLY, fetchSize = 200) + List<Component> selectRootProjects(); + + @Select("SELECT " + + " p.id AS \"id\", " + + " p.uuid AS \"uuid\", " + + " p.project_uuid AS \"projectUuid\", " + + " p.module_uuid AS \"moduleUuid\", " + + " p.module_uuid_path AS \"moduleUuidPath\", " + + " s.root_project_id AS \"projectId\", " + + " s.id AS \"snapshotId\", " + + " s.path AS \"snapshotPath\", " + + " p.scope AS \"scope\" " + + "FROM projects root " + + " INNER JOIN snapshots root_snapshot ON root_snapshot.project_id = root.id AND root_snapshot.islast = ${_true} " + + " INNER JOIN snapshots s ON s.root_snapshot_id = root_snapshot.id AND s.islast = ${_true} " + + " INNER JOIN projects p ON p.id = s.project_id " + + " WHERE root.id = #{id} ") + @Result(javaType = Component.class) + List<Component> selectComponentChildrenForProjects(@Param("id") Long projectId); + + /** + * Return disabled direct children from a project (1st level modules, files on single module project) + * For migration re-entrance, ignore components already having UUID + */ + @Select("SELECT " + + " p.id AS \"id\", " + + " p.uuid AS \"uuid\" " + + "FROM projects p " + + " INNER JOIN projects root ON root.id = p.root_id " + + " WHERE root.id = #{id} " + + " AND p.uuid IS NULL " + + " AND p.enabled=${_false} ") + @Result(javaType = Component.class) + List<Component> selectDisabledDirectComponentChildrenForProjects(@Param("id") Long projectId); + + /** + * Return disabled none direct children (2nd level modules and more, files on modules, etc.) + * For migration re-entrance, ignore components already having UUID + */ + @Select("SELECT " + + " p.id AS \"id\", " + + " p.uuid AS \"uuid\" " + + "FROM projects p " + + " INNER JOIN projects root_one ON root_one.id = p.root_id " + + " INNER JOIN projects root_two ON root_two.id = root_one.root_id " + + " WHERE root_two.id=#{id} " + + " AND p.uuid IS NULL " + + " AND p.enabled=${_false} ") + @Result(javaType = Component.class) + List<Component> selectDisabledNoneDirectComponentChildrenForProjects(@Param("id") Long projectId); + + /** + * Return not migrated components + */ + @Select("SELECT " + + " p.id AS \"id\" " + + "FROM projects p " + + " WHERE p.uuid IS NULL ") + @Result(javaType = Component.class) + List<Component> selectComponentsWithoutUuid(); + + @Select("SELECT " + + " p.id AS \"id\", " + + " p.uuid AS \"uuid\", " + + " p.project_uuid AS \"projectUuid\", " + + " p.module_uuid AS \"moduleUuid\", " + + " p.module_uuid_path AS \"moduleUuidPath\" " + + "FROM projects p " + + " WHERE p.kee = #{key}") + @Result(javaType = Component.class) + Component selectComponentByKey(@Param("key") String key); + + @Update("UPDATE projects " + + " SET uuid=#{uuid}, project_uuid=#{projectUuid}, module_uuid=#{moduleUuid}, module_uuid_path=#{moduleUuidPath} " + + " WHERE id=#{id}") + @Options(useGeneratedKeys = false) + void updateComponentUuids(Component component); +} diff --git a/sonar-db/src/main/java/org/sonar/db/version/v50/package-info.java b/sonar-db/src/main/java/org/sonar/db/version/v50/package-info.java new file mode 100644 index 00000000000..03bb5056ad3 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/version/v50/package-info.java @@ -0,0 +1,25 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.version.v50; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/sonar-db/src/main/resources/org/sonar/db/IsAliveMapper.xml b/sonar-db/src/main/resources/org/sonar/db/IsAliveMapper.xml new file mode 100644 index 00000000000..c26b5961f8a --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/IsAliveMapper.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.IsAliveMapper"> + + <select id="isAlive" resultType="int"> + select 1 + <choose> + <when test="_databaseId == 'oracle'"> + from dual + </when> + </choose> + </select> + +</mapper> + diff --git a/sonar-db/src/main/resources/org/sonar/db/activity/ActivityMapper.xml b/sonar-db/src/main/resources/org/sonar/db/activity/ActivityMapper.xml new file mode 100644 index 00000000000..0014464aa2c --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/activity/ActivityMapper.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.activity.ActivityMapper"> + + <insert id="insert" parameterType="Activity" useGeneratedKeys="false"> + insert into activities + (created_at, log_key, log_type, log_action, user_login, data_field, log_message) + values (#{createdAt,jdbcType=TIMESTAMP}, #{key,jdbcType=VARCHAR}, #{type,jdbcType=VARCHAR}, + #{action,jdbcType=VARCHAR}, + #{author,jdbcType=VARCHAR}, #{data,jdbcType=VARCHAR}, #{message,jdbcType=VARCHAR}) + </insert> + +</mapper> + diff --git a/sonar-db/src/main/resources/org/sonar/db/component/ComponentIndexMapper.xml b/sonar-db/src/main/resources/org/sonar/db/component/ComponentIndexMapper.xml new file mode 100644 index 00000000000..2a308781795 --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/component/ComponentIndexMapper.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> +<mapper namespace="org.sonar.db.component.ComponentIndexMapper"> + + <select id="selectProjectIdsFromQueryAndViewOrSubViewUuid" parameterType="map" resultType="long"> + SELECT r.resource_id FROM resource_index r + INNER JOIN projects copy ON copy.copy_resource_id = r.resource_id + <where> + AND copy.module_uuid_path LIKE #{viewUuidQuery} + AND r.kee LIKE #{query} + </where> + ORDER BY r.name_size + </select> + +</mapper> + diff --git a/sonar-db/src/main/resources/org/sonar/db/component/ComponentLinkMapper.xml b/sonar-db/src/main/resources/org/sonar/db/component/ComponentLinkMapper.xml new file mode 100644 index 00000000000..c6db203313b --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/component/ComponentLinkMapper.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> +<mapper namespace="org.sonar.db.component.ComponentLinkMapper"> + + <sql id="componentLinkColumns"> + p.id, + p.component_uuid as "componentUuid", + p.link_type as "type", + p.name as name, + p.href as href + </sql> + + <select id="selectByComponentUuid" parameterType="String" resultType="ComponentLink"> + SELECT + <include refid="componentLinkColumns"/> + FROM project_links p + <where> + AND p.component_uuid=#{uuid} + </where> + </select> + + <insert id="insert" parameterType="ComponentLink" keyColumn="id" useGeneratedKeys="true" keyProperty="id"> + INSERT INTO project_links (component_uuid, link_type, name, href) + VALUES (#{componentUuid,jdbcType=VARCHAR}, #{type,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, + #{href,jdbcType=VARCHAR}) + </insert> + + <insert id="update" parameterType="ComponentLink" useGeneratedKeys="false"> + UPDATE project_links SET component_uuid=#{componentUuid,jdbcType=VARCHAR}, link_type=#{type,jdbcType=VARCHAR}, + name=#{name,jdbcType=VARCHAR}, href=#{href,jdbcType=VARCHAR} + WHERE id=#{id} + </insert> + + <delete id="delete"> + DELETE FROM project_links WHERE id=#{id} + </delete> + +</mapper> + diff --git a/sonar-db/src/main/resources/org/sonar/db/component/ComponentMapper.xml b/sonar-db/src/main/resources/org/sonar/db/component/ComponentMapper.xml new file mode 100644 index 00000000000..19740c7f76e --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/component/ComponentMapper.xml @@ -0,0 +1,315 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> +<mapper namespace="org.sonar.db.component.ComponentMapper"> + + <sql id="componentColumns"> + p.id, + p.uuid as uuid, + p.project_uuid as projectUuid, + p.module_uuid as moduleUuid, + p.module_uuid_path as moduleUuidPath, + p.kee as kee, + p.deprecated_kee as deprecatedKey, + p.name as name, + p.long_name as longName, + p.description as description, + p.qualifier as qualifier, + p.scope as scope, + p.language as language, + p.root_id as parentProjectId, + p.path as path, + p.enabled as enabled, + p.copy_resource_id as copyResourceId, + p.authorization_updated_at as authorizationUpdatedAt, + p.created_at as createdAt + </sql> + + <sql id="authorizedComponentColumns"> + p.id, + p.uuid as uuid, + p.kee as kee, + p.qualifier as qualifier, + p.scope as scope + </sql> + + <select id="selectByKey" parameterType="String" resultType="Component"> + SELECT + <include refid="componentColumns"/> + FROM projects p + <where> + AND p.kee=#{key} + </where> + </select> + + <select id="selectById" parameterType="long" resultType="Component"> + SELECT + <include refid="componentColumns"/> + FROM projects p + <where> + AND p.id=#{id} + </where> + </select> + + <select id="selectByUuid" parameterType="String" resultType="Component"> + SELECT + <include refid="componentColumns"/> + FROM projects p + <where> + AND p.uuid=#{uuid} + </where> + </select> + + <select id="countById" parameterType="long" resultType="long"> + SELECT count(p.id) + FROM projects p + <where> + AND p.id=#{id} + </where> + </select> + + <select id="selectByKeys" parameterType="String" resultType="Component"> + select + <include refid="componentColumns"/> + from projects p + <where> + p.enabled=${_true} + and p.kee in + <foreach collection="keys" open="(" close=")" item="key" separator=","> + #{key} + </foreach> + </where> + </select> + + <select id="selectByIds" parameterType="long" resultType="Component"> + select + <include refid="componentColumns"/> + from projects p + <where> + p.enabled=${_true} + and p.id in + <foreach collection="ids" open="(" close=")" item="id" separator=","> + #{id} + </foreach> + </where> + </select> + + <select id="selectByUuids" parameterType="String" resultType="Component"> + select + <include refid="componentColumns"/> + from projects p + <where> + and p.uuid in + <foreach collection="uuids" open="(" close=")" item="uuid" separator=","> + #{uuid} + </foreach> + </where> + </select> + + <select id="selectExistingUuids" parameterType="String" resultType="String"> + select p.uuid + from projects p + <where> + and p.uuid in + <foreach collection="uuids" open="(" close=")" item="uuid" separator=","> + #{uuid} + </foreach> + </where> + </select> + + <select id="selectSubProjectsByComponentUuids" parameterType="String" resultType="Component"> + SELECT + <include refid="componentColumns"/> + FROM projects p + INNER JOIN projects child ON child.root_id=p.id AND child.enabled=${_true} + <where> + AND p.enabled=${_true} + AND p.scope='PRJ' + AND child.uuid in + <foreach collection="uuids" open="(" close=")" item="uuid" separator=","> + #{uuid} + </foreach> + </where> + </select> + + <select id="selectDescendantModules" parameterType="map" resultType="Component"> + SELECT + <include refid="componentColumns"/> + FROM projects p + <include refid="modulesTreeQuery"/> + </select> + + <sql id="modulesTreeQuery"> + INNER JOIN projects module ON module.project_uuid = p.project_uuid AND module.uuid = #{moduleUuid} AND + module.scope='PRJ' AND module.enabled = ${_true} + <where> + <if test="excludeDisabled"> + p.enabled = ${_true} + </if> + AND p.scope = #{scope} + AND + <choose> + <when test="_databaseId == 'mssql'"> + p.module_uuid_path LIKE module.module_uuid_path + '%' + </when> + <when test="_databaseId == 'mysql'"> + p.module_uuid_path LIKE concat(module.module_uuid_path, '%') + </when> + <otherwise> + p.module_uuid_path LIKE module.module_uuid_path || '%' + </otherwise> + </choose> + </where> + </sql> + + <select id="selectEnabledFilesFromProject" parameterType="map" resultType="FilePathWithHash"> + SELECT p.uuid, p.path, p.module_uuid as moduleUuid, fs.src_hash as srcHash + FROM projects p + INNER JOIN file_sources fs ON fs.file_uuid=p.uuid + <where> + AND p.project_uuid=#{projectUuid} + AND p.enabled=${_true} + AND p.scope='FIL' + </where> + </select> + + <select id="selectDescendantFiles" parameterType="map" resultType="FilePathWithHash"> + SELECT p.uuid, p.path, p.module_uuid as moduleUuid, fs.src_hash as srcHash + FROM projects p + INNER JOIN file_sources fs ON fs.file_uuid=p.uuid and fs.data_type='SOURCE' + <include refid="modulesTreeQuery"/> + </select> + + <select id="selectProjectUuids" resultType="String"> + SELECT p.uuid + FROM projects p + <where> + AND p.enabled=${_true} + AND p.scope='PRJ' + AND p.qualifier='TRK' + </where> + </select> + + <select id="selectUuidsForQualifiers" resultType="UuidWithProjectUuid"> + SELECT p.uuid as "uuid", p.project_uuid as "projectUuid" FROM projects p + INNER JOIN snapshots s on s.project_id=p.id AND s.islast=${_true} + <where> + p.enabled=${_true} AND + <foreach collection="qualifiers" open="(" close=")" item="qualifier" separator="OR "> + s.qualifier=#{qualifier} + </foreach> + </where> + </select> + + <select id="selectProjectsFromView" resultType="String"> + SELECT p.uuid FROM projects technical_projects + INNER JOIN projects p on p.id=technical_projects.copy_resource_id AND p.enabled=${_true} + <where> + technical_projects.enabled=${_true} AND technical_projects.project_uuid=#{projectViewUuid} + AND technical_projects.module_uuid_path LIKE #{viewUuidLikeQuery} + </where> + </select> + + <select id="selectComponentsFromProjectKeyAndScope" parameterType="map" resultType="Component"> + SELECT + <include refid="componentColumns"/> + FROM projects p + INNER JOIN projects root ON root.uuid=p.project_uuid AND root.kee=#{projectKey} + <where> + AND p.enabled=${_true} + <if test="scope != null"> + AND p.scope=#{scope} + </if> + </where> + </select> + + <select id="selectProvisionedProjects" parameterType="map" resultType="Component"> + select + <include refid="componentColumns"/> + from projects p + <include refid="provisionClauses"/> + </select> + + <select id="countProvisionedProjects" parameterType="map" resultType="int"> + select count(p.id) + from projects p + <include refid="provisionClauses"/> + </select> + + <sql id="provisionClauses"> + left join snapshots s on s.project_id=p.id + where + s.id is null + and p.enabled=${_true} + and p.qualifier=#{qualifier} + and p.copy_resource_id is null + <if test="query!=null"> + and ( + UPPER(p.name) like #{query} + or UPPER(p.kee) like #{query} + ) + </if> + </sql> + + <select id="selectGhostProjects" parameterType="map" resultType="Component"> + select distinct + <include refid="componentColumns"/> + from projects p + <include refid="ghostClauses"/> + </select> + + <select id="countGhostProjects" parameterType="map" resultType="long"> + select count(p.id) + from projects p + <include refid="ghostClauses"/> + </select> + + <sql id="ghostClauses"> + inner join snapshots s1 on s1.project_id = p.id and s1.status='U' + left join snapshots s2 on s2.project_id = p.id and s2.status='P' + where + s2.id is null + and p.qualifier=#{qualifier} + and p.copy_resource_id is null + <if test="query!=null"> + and ( + UPPER(p.name) like #{query} + or UPPER(p.kee) like #{query} + ) + </if> + </sql> + + <insert id="insert" parameterType="Component" keyColumn="id" useGeneratedKeys="true" keyProperty="id"> + INSERT INTO projects (kee, deprecated_kee, uuid, project_uuid, module_uuid, module_uuid_path, name, long_name, + qualifier, scope, language, description, root_id, path, copy_resource_id, enabled, + created_at, authorization_updated_at) + VALUES (#{kee,jdbcType=VARCHAR}, #{deprecatedKey,jdbcType=VARCHAR}, #{uuid,jdbcType=VARCHAR}, + #{projectUuid,jdbcType=VARCHAR}, #{moduleUuid,jdbcType=VARCHAR}, #{moduleUuidPath,jdbcType=VARCHAR}, + #{name,jdbcType=VARCHAR}, #{longName,jdbcType=VARCHAR}, #{qualifier,jdbcType=VARCHAR}, #{scope,jdbcType=VARCHAR}, + #{language,jdbcType=VARCHAR}, #{description,jdbcType=VARCHAR}, + #{parentProjectId,jdbcType=BIGINT}, #{path,jdbcType=VARCHAR}, #{copyResourceId,jdbcType=BIGINT}, + #{enabled,jdbcType=BOOLEAN}, + #{createdAt,jdbcType=TIMESTAMP}, #{authorizationUpdatedAt,jdbcType=BIGINT}) + </insert> + + <insert id="update" parameterType="Component" useGeneratedKeys="false"> + UPDATE projects SET + kee=#{kee,jdbcType=VARCHAR}, + deprecated_kee=#{deprecatedKey,jdbcType=VARCHAR}, + project_uuid=#{projectUuid,jdbcType=VARCHAR}, + module_uuid=#{moduleUuid,jdbcType=VARCHAR}, + module_uuid_path=#{moduleUuidPath,jdbcType=VARCHAR}, + name=#{name,jdbcType=VARCHAR}, + long_name=#{longName,jdbcType=VARCHAR}, + qualifier=#{qualifier,jdbcType=VARCHAR}, + scope=#{scope,jdbcType=VARCHAR}, + language=#{language,jdbcType=VARCHAR}, + description=#{description,jdbcType=VARCHAR}, + root_id=#{parentProjectId,jdbcType=BIGINT}, + path=#{path,jdbcType=VARCHAR}, + copy_resource_id=#{copyResourceId,jdbcType=BIGINT}, + enabled=#{enabled,jdbcType=BOOLEAN}, + authorization_updated_at=#{authorizationUpdatedAt,jdbcType=BIGINT} + WHERE uuid=#{uuid} + </insert> + +</mapper> diff --git a/sonar-db/src/main/resources/org/sonar/db/component/ResourceIndexerMapper.xml b/sonar-db/src/main/resources/org/sonar/db/component/ResourceIndexerMapper.xml new file mode 100644 index 00000000000..82afc7fa85d --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/component/ResourceIndexerMapper.xml @@ -0,0 +1,69 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.component.ResourceIndexerMapper"> + + <!-- + The column PROJECTS.ROOT_ID is not exact on multi-modules projects. The root id must + be loaded from the table SNAPSHOTS + --> + <select id="selectResources" parameterType="map" resultType="Resource"> + select p.name as "name", p.id as "id", p.scope as "scope", p.qualifier as "qualifier", s.root_project_id as "rootId" + from projects p, snapshots s + <where> + p.enabled=${_true} + and p.copy_resource_id is null + and p.id=s.project_id + and s.islast=${_true} + <if test="scopes != null"> + and p.scope in + <foreach item="scope" index="index" collection="scopes" open="(" separator="," close=")">#{scope}</foreach> + </if> + <if test="qualifiers != null"> + and p.qualifier in + <foreach item="qualifier" index="index" collection="qualifiers" open="(" separator="," close=")">#{qualifier} + </foreach> + </if> + <if test="rootProjectId != null"> + and s.root_project_id=#{rootProjectId} + </if> + <if test="nonIndexedOnly"> + and not exists(select * from resource_index ri where ri.resource_id=p.id) + </if> + </where> + order by p.id + </select> + + <select id="selectRootProjectIds" parameterType="map" resultType="int"> + select distinct root_project_id + from snapshots + where islast=${_true} + and scope='PRJ' + and qualifier in ('TRK', 'VW', 'SVW') + </select> + + <select id="selectMasterIndexByResourceId" parameterType="long" resultType="ResourceIndex"> + select kee as "key", resource_id as "resourceId" + from resource_index + where resource_id=#{id} and position=0 + </select> + + <select id="selectResourceToIndex" parameterType="long" resultType="Resource"> + select id, name, root_id as "rootId", qualifier + from projects + where id=#{id} and enabled=${_true} + </select> + + <delete id="deleteByResourceId" parameterType="long"> + delete from resource_index + where resource_id=#{id} + </delete> + + <insert id="insert" parameterType="ResourceIndex" useGeneratedKeys="false"> + insert into resource_index (kee, position, name_size, resource_id, root_project_id, qualifier) + values (#{key}, #{position}, #{nameSize}, + #{resourceId}, #{rootProjectId}, #{qualifier}) + </insert> + +</mapper> + diff --git a/sonar-db/src/main/resources/org/sonar/db/component/ResourceKeyUpdaterMapper.xml b/sonar-db/src/main/resources/org/sonar/db/component/ResourceKeyUpdaterMapper.xml new file mode 100644 index 00000000000..40add31c8cd --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/component/ResourceKeyUpdaterMapper.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.component.ResourceKeyUpdaterMapper"> + + <resultMap id="resourceResultMap" type="Resource"> + <id property="id" column="id"/> + <result property="key" column="kee"/> + <result property="deprecatedKey" column="deprecated_kee"/> + <result property="rootId" column="root_id"/> + <result property="scope" column="scope"/> + </resultMap> + + <select id="countResourceByKey" parameterType="String" resultType="int"> + SELECT count(*) + FROM projects + WHERE kee = #{key} + </select> + + <select id="selectProject" parameterType="long" resultMap="resourceResultMap"> + select * from projects where id=#{id} + </select> + + <select id="selectProjectResources" parameterType="long" resultMap="resourceResultMap"> + select * from projects where root_id=#{id} AND scope!='PRJ' + </select> + + <select id="selectDescendantProjects" parameterType="long" resultMap="resourceResultMap"> + select * from projects where scope='PRJ' and root_id=#{id} + </select> + + <update id="update" parameterType="Resource"> + update projects + set kee = #{key}, deprecated_kee = #{deprecatedKey} + where id = #{id} + </update> + +</mapper> + diff --git a/sonar-db/src/main/resources/org/sonar/db/component/ResourceMapper.xml b/sonar-db/src/main/resources/org/sonar/db/component/ResourceMapper.xml new file mode 100644 index 00000000000..39339fe5ec2 --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/component/ResourceMapper.xml @@ -0,0 +1,255 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.component.ResourceMapper"> + + <resultMap id="snapshotResultMap" type="Snapshot"> + <id property="id" column="id"/> + <result property="parentId" column="parent_snapshot_id"/> + <result property="rootId" column="root_snapshot_id"/> + <result property="createdAt" column="created_at"/> + <result property="buildDate" column="build_date"/> + <result property="componentId" column="project_id"/> + <result property="status" column="status"/> + <result property="purgeStatus" column="purge_status"/> + <result property="last" column="islast"/> + <result property="scope" column="scope"/> + <result property="qualifier" column="qualifier"/> + <result property="version" column="version"/> + <result property="path" column="path"/> + <result property="depth" column="depth"/> + <result property="rootProjectId" column="root_project_id"/> + <result property="period1Mode" column="period1_mode"/> + <result property="period2Mode" column="period2_mode"/> + <result property="period3Mode" column="period3_mode"/> + <result property="period4Mode" column="period4_mode"/> + <result property="period5Mode" column="period5_mode"/> + <result property="period1Param" column="period1_param"/> + <result property="period2Param" column="period2_param"/> + <result property="period3Param" column="period3_param"/> + <result property="period4Param" column="period4_param"/> + <result property="period5Param" column="period5_param"/> + <result property="period1Date" column="period1_date"/> + <result property="period2Date" column="period2_date"/> + <result property="period3Date" column="period3_date"/> + <result property="period4Date" column="period4_date"/> + <result property="period5Date" column="period5_date"/> + </resultMap> + + <resultMap id="resourceResultMap" type="Resource"> + <id property="id" column="id"/> + <result property="key" column="kee"/> + <result property="uuid" column="uuid"/> + <result property="projectUuid" column="project_uuid"/> + <result property="moduleUuid" column="module_uuid"/> + <result property="moduleUuidPath" column="module_uuid_path"/> + <result property="deprecatedKey" column="deprecated_kee"/> + <result property="path" column="path"/> + <result property="name" column="name"/> + <result property="longName" column="long_name"/> + <result property="rootId" column="root_id"/> + <result property="scope" column="scope"/> + <result property="qualifier" column="qualifier"/> + <result property="enabled" column="enabled"/> + <result property="description" column="description"/> + <result property="language" column="language"/> + <result property="copyResourceId" column="copy_resource_id"/> + <result property="personId" column="person_id"/> + <result property="createdAt" column="created_at"/> + <result property="authorizationUpdatedAt" column="authorization_updated_at"/> + </resultMap> + + <select id="selectResources" parameterType="map" resultMap="resourceResultMap"> + select * from projects p + <where> + <if test="qualifiers != null and qualifiers.length!=0"> + and p.qualifier in + <foreach item="qualifier" index="index" collection="qualifiers" open="(" separator="," close=")">#{qualifier} + </foreach> + </if> + <if test="key != null"> + and p.kee=#{key} + </if> + <if test="excludeDisabled"> + and p.enabled=${_true} + </if> + </where> + </select> + + <select id="selectResourceIds" parameterType="map" resultType="long"> + select p.id + from projects p + <where> + <if test="qualifiers != null and qualifiers.length!=0"> + and p.qualifier in + <foreach item="qualifier" index="index" collection="qualifiers" open="(" separator="," close=")">#{qualifier} + </foreach> + </if> + <if test="key != null"> + and p.kee=#{key} + </if> + <if test="excludeDisabled"> + and p.enabled=${_true} + </if> + </where> + </select> + + <select id="selectResource" parameterType="long" resultMap="resourceResultMap"> + select * from projects p + where p.id=#{id} + </select> + + <select id="selectResourceByUuid" parameterType="String" resultMap="resourceResultMap"> + select * from projects p + where p.uuid=#{uuid} + </select> + + <select id="selectSnapshot" parameterType="long" resultMap="snapshotResultMap"> + select * from snapshots where id=#{id} + </select> + + <select id="selectLastSnapshotByResourceKey" parameterType="string" resultMap="snapshotResultMap"> + SELECT s.* FROM snapshots s + INNER JOIN projects p on p.id=s.project_id AND p.enabled=${_true} AND p.copy_resource_id IS NULL + <where> + AND p.kee=#{id} + AND s.islast=${_true} + </where> + </select> + + <select id="selectLastSnapshotByResourceUuid" parameterType="string" resultMap="snapshotResultMap"> + SELECT s.* from snapshots s + INNER JOIN projects p on p.id=s.project_id AND p.enabled=${_true} AND p.copy_resource_id IS NULL + <where> + AND p.uuid=#{uuid} + AND s.islast=${_true} + </where> + </select> + + <select id="selectDescendantProjects" parameterType="long" resultMap="resourceResultMap"> + select * from projects where scope='PRJ' and root_id=#{id} + </select> + + <select id="selectRootProjectByComponentKey" parameterType="string" resultMap="resourceResultMap"> + select rootProject.* + from projects p + inner join snapshots s on s.project_id=p.id and s.islast=${_true} + inner join projects rootProject on rootProject.id=s.root_project_id + <where> + and p.kee=#{componentKey} + </where> + </select> + + <select id="selectRootProjectByComponentId" parameterType="long" resultMap="resourceResultMap"> + select rootProject.* + from snapshots s + inner join projects rootProject on rootProject.id=s.root_project_id + where + s.project_id=#{componentId} + and s.islast=${_true} + </select> + + <select id="selectProjectsIncludingNotCompletedOnesByQualifiers" parameterType="map" resultMap="resourceResultMap"> + select * from projects p + <where> + <if test="qualifiers != null and qualifiers.size() > 0"> + and + <foreach item="qualifier" index="index" collection="qualifiers" open="(" separator=" or " close=")"> + p.qualifier=#{qualifier} + </foreach> + </if> + and p.enabled=${_true} + and p.copy_resource_id is null + </where> + </select> + + <select id="selectProjectsByQualifiers" parameterType="map" resultMap="resourceResultMap"> + <include refid="selectProjectsByQualifiersQuery"/> + </select> + + <sql id="selectProjectsByQualifiersQuery"> + select p.* from projects p + inner join snapshots s on s.project_id=p.id + <where> + <if test="qualifiers != null and qualifiers.size() > 0"> + and + <foreach item="qualifier" index="index" collection="qualifiers" open="(" separator=" or " close=")"> + p.qualifier=#{qualifier} + </foreach> + </if> + and p.enabled=${_true} + and p.copy_resource_id is null + and s.islast=${_true} + </where> + </sql> + + <select id="selectGhostsProjects" parameterType="map" resultMap="resourceResultMap"> + select distinct p.* from projects p + inner join snapshots s1 on s1.project_id = p.id and s1.status='U' + left join snapshots s2 on s2.project_id = p.id and s2.status='P' + <where> + and s2.id is null + <if test="qualifiers != null and qualifiers.size() > 0"> + and + <foreach item="qualifier" index="index" collection="qualifiers" open="(" separator=" or " close=")"> + p.qualifier=#{qualifier} + </foreach> + </if> + and p.copy_resource_id is null + </where> + </select> + + <select id="selectProvisionedProjects" parameterType="map" resultMap="resourceResultMap"> + select p.* from projects p + left join snapshots s on s.project_id=p.id + <where> + and s.id is null + <if test="qualifiers != null and qualifiers.size() > 0"> + and + <foreach item="qualifier" index="index" collection="qualifiers" open="(" separator=" or " close=")"> + p.qualifier=#{qualifier} + </foreach> + </if> + and p.copy_resource_id is null + </where> + </select> + + <select id="selectProvisionedProject" parameterType="string" resultMap="resourceResultMap"> + select p.* from projects p + left join snapshots s on s.project_id=p.id + where s.id is null + and p.kee = #{key} + and p.copy_resource_id is null + </select> + + <insert id="insert" parameterType="Resource" keyColumn="id" useGeneratedKeys="true" keyProperty="id"> + insert into projects + (uuid, project_uuid, module_uuid, module_uuid_path, name, long_name, description, scope, qualifier, kee, + deprecated_kee, path, language, root_id, copy_resource_id, person_id, + enabled, authorization_updated_at, created_at) + values ( + #{uuid,jdbcType=VARCHAR}, #{projectUuid,jdbcType=VARCHAR}, #{moduleUuid,jdbcType=VARCHAR}, + #{moduleUuidPath,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, + #{longName,jdbcType=VARCHAR}, #{description,jdbcType=VARCHAR}, #{scope,jdbcType=VARCHAR}, + #{qualifier,jdbcType=VARCHAR}, + #{key,jdbcType=VARCHAR}, #{deprecatedKey,jdbcType=VARCHAR}, #{path,jdbcType=VARCHAR}, #{language,jdbcType=VARCHAR}, + #{rootId,jdbcType=INTEGER}, #{copyResourceId,jdbcType=INTEGER}, + #{personId,jdbcType=INTEGER}, #{enabled,jdbcType=BOOLEAN}, #{authorizationUpdatedAt,jdbcType=BIGINT}, + #{createdAt,jdbcType=TIMESTAMP} + ) + </insert> + + <update id="update" parameterType="Resource"> + update projects set name=#{name}, long_name=#{longName}, description=#{description}, + scope=#{scope}, qualifier=#{qualifier}, kee=#{key}, deprecated_kee=#{deprecatedKey}, path=#{path}, + language=#{language}, root_id=#{rootId}, copy_resource_id=#{copyResourceId}, + person_id=#{personId}, enabled=#{enabled} where id=#{id} + </update> + + <update id="updateAuthorizationDate" parameterType="map"> + update projects set authorization_updated_at=#{authorizationDate} + where id=#{projectId} + </update> + +</mapper> + diff --git a/sonar-db/src/main/resources/org/sonar/db/component/SnapshotMapper.xml b/sonar-db/src/main/resources/org/sonar/db/component/SnapshotMapper.xml new file mode 100644 index 00000000000..95af7ba53a8 --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/component/SnapshotMapper.xml @@ -0,0 +1,140 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> +<mapper namespace="org.sonar.db.component.SnapshotMapper"> + + <sql id="snapshotColumns"> + s.id, + s.parent_snapshot_id as parentId, + s.root_snapshot_id as rootId, + s.root_project_id as rootProjectId, + s.project_id as componentId, + s.created_at as createdAt, + s.build_date as buildDate, + s.status as status, + s.purge_status as purgeStatus, + s.islast as last, + s.scope as scope, + s.qualifier as qualifier, + s.version as version, + s.path as path, + s.depth as depth, + s.period1_mode as period1Mode, + s.period2_mode as period2Mode, + s.period3_mode as period3Mode, + s.period4_mode as period4Mode, + s.period5_mode as period5Mode, + s.period1_param as period1Param, + s.period2_param as period2Param, + s.period3_param as period3Param, + s.period4_param as period4Param, + s.period5_param as period5Param, + s.period1_date as period1Date, + s.period2_date as period2Date, + s.period3_date as period3Date, + s.period4_date as period4Date, + s.period5_date as period5Date + </sql> + + <select id="selectByKey" parameterType="Long" resultType="Snapshot"> + SELECT + <include refid="snapshotColumns"/> + FROM snapshots s + <where> + AND s.id=#{key} + </where> + </select> + + <select id="selectLastSnapshot" resultType="Snapshot"> + select + <include refid="snapshotColumns"/> + from snapshots s + where s.islast=${_true} and s.project_id = #{resource} + </select> + + <select id="selectSnapshotsByQuery" parameterType="map" resultType="Snapshot"> + SELECT + <include refid="snapshotColumns"/> + FROM snapshots s + <where> + <if test="query.componentId != null"> + AND s.project_id=#{query.componentId} + </if> + <if test="query.status != null"> + AND status=#{query.status} + </if> + <if test="query.version != null"> + AND version=#{query.version} + </if> + <if test="query.isLast != null"> + AND islast=#{query.isLast} + </if> + <if test="query.createdAfter != null"> + AND created_at>=#{query.createdAfter} + </if> + <if test="query.createdBefore != null"> + AND created_at<#{query.createdBefore} + </if> + </where> + <if test="query.sortField != null"> + ORDER BY + <if test="query.sortField == 'created_at'"> + created_at + </if> + <if test="query.sortOrder == 'asc'"> + asc + </if> + <if test="query.sortOrder == 'desc'"> + desc + </if> + </if> + </select> + + <select id="selectPreviousVersionSnapshots" parameterType="map" resultType="Snapshot"> + SELECT + <include refid="snapshotColumns"/> + FROM snapshots s + INNER JOIN events e ON s.id = e.snapshot_id AND e.name <> #{lastVersion} AND e.category='Version' + INNER JOIN projects p ON p.uuid=e.component_uuid AND p.id=#{componentId} + ORDER BY e.event_date DESC + </select> + + <select id="selectSnapshotAndChildrenOfScope" parameterType="map" resultType="Snapshot"> + select + <include refid="snapshotColumns"/> + from snapshots s + where s.scope = #{scope} + AND (s.id = #{snapshot} or s.root_snapshot_id = #{snapshot}) + </select> + + <sql id="insertColumns"> + (parent_snapshot_id, root_snapshot_id, root_project_id, project_id, created_at, build_date, status, purge_status, + islast, scope, qualifier, version, path, depth, + period1_mode, period2_mode, period3_mode, period4_mode, period5_mode, + period1_param, period2_param, period3_param, period4_param, period5_param, + period1_date, period2_date, period3_date, period4_date, period5_date) + </sql> + + <update id="updateSnapshotAndChildrenLastFlagAndStatus" parameterType="map"> + update snapshots + set islast = #{isLast}, status = #{status} + where root_snapshot_id=#{root} or id=#{root} or (path like #{path} and root_snapshot_id=#{pathRootId}) + </update> + + <update id="updateSnapshotAndChildrenLastFlag" parameterType="map"> + update snapshots + set islast = #{isLast} + where root_snapshot_id=#{root} or id=#{root} or (path like #{path} and root_snapshot_id=#{pathRootId}) + </update> + + <insert id="insert" parameterType="Snapshot" keyColumn="id" useGeneratedKeys="true" keyProperty="id"> + insert into snapshots + <include refid="insertColumns"/> + values (#{parentId}, #{rootId}, #{rootProjectId}, #{componentId}, #{createdAt}, #{buildDate}, #{status}, + #{purgeStatus}, #{last}, #{scope}, #{qualifier}, #{version}, #{path}, #{depth}, + #{period1Mode}, #{period2Mode}, #{period3Mode}, #{period4Mode}, #{period5Mode}, + #{period1Param}, #{period2Param}, #{period3Param}, #{period4Param}, #{period5Param}, + #{period1Date}, #{period2Date}, #{period3Date}, #{period4Date}, #{period5Date}) + </insert> + +</mapper> + diff --git a/sonar-db/src/main/resources/org/sonar/db/compute/AnalysisReportMapper.xml b/sonar-db/src/main/resources/org/sonar/db/compute/AnalysisReportMapper.xml new file mode 100644 index 00000000000..2a3700186d4 --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/compute/AnalysisReportMapper.xml @@ -0,0 +1,82 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.compute.AnalysisReportMapper"> + <sql id="reportColumns"> + <!-- the data report is not brought back by default as it could be too big in memory --> + ar.id, + ar.project_key as projectKey, + ar.project_name as projectName, + ar.report_status as status, + ar.uuid as uuid, + ar.created_at as createdAt, + ar.updated_at as updatedAt, + ar.started_at as startedAt, + ar.finished_at as finishedAt + </sql> + + <insert id="insert" parameterType="AnalysisReport" useGeneratedKeys="true" keyColumn="id" keyProperty="id"> + insert into analysis_reports + (project_key, project_name, uuid, report_status, created_at, updated_at, started_at, finished_at) + values ( + #{projectKey,jdbcType=VARCHAR}, #{projectName,jdbcType=VARCHAR}, #{uuid,jdbcType=VARCHAR}, + #{status,jdbcType=VARCHAR}, + #{createdAt,jdbcType=BIGINT}, #{updatedAt,jdbcType=BIGINT}, #{startedAt,jdbcType=BIGINT}, + #{finishedAt,jdbcType=BIGINT} + ) + </insert> + + <update id="resetAllToPendingStatus" parameterType="map"> + update analysis_reports + set report_status='PENDING', updated_at=#{updatedAt,jdbcType=BIGINT}, started_at=NULL + </update> + + <update id="updateWithBookingReport" parameterType="map"> + update analysis_reports + set report_status=#{busyStatus,jdbcType=VARCHAR}, + started_at=#{startedAt,jdbcType=BIGINT} + where id=#{id} and report_status=#{availableStatus} + </update> + + <delete id="truncate"> + truncate table analysis_reports + </delete> + + <delete id="delete"> + delete from analysis_reports where id=#{id} + </delete> + + <select id="selectById" resultType="AnalysisReport"> + select + <include refid="reportColumns"/> + from analysis_reports ar + where id = #{id} + </select> + + <select id="selectByProjectKey" parameterType="String" resultType="AnalysisReport"> + select + <include refid="reportColumns"/> + from analysis_reports ar + where project_key = #{projectKey} + </select> + + <!-- TODO optimize by restricting results to first row (LIMIT 1 on most dbs) --> + <select id="selectAvailables" parameterType="map" resultType="Long"> + select ar.id + from analysis_reports ar + where ar.report_status=#{availableStatus} + and not exists( + select 1 + from analysis_reports ar2 + where ar.project_key = ar2.project_key + and ar2.report_status=#{busyStatus} + ) + order by ar.created_at asc, ar.id asc + </select> + + <select id="selectAll" resultType="AnalysisReport"> + select + <include refid="reportColumns"/> + from analysis_reports ar + </select> +</mapper> diff --git a/sonar-db/src/main/resources/org/sonar/db/dashboard/ActiveDashboardMapper.xml b/sonar-db/src/main/resources/org/sonar/db/dashboard/ActiveDashboardMapper.xml new file mode 100644 index 00000000000..6c88317e890 --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/dashboard/ActiveDashboardMapper.xml @@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.dashboard.ActiveDashboardMapper"> + + <insert id="insert" parameterType="ActiveDashboard" keyColumn="id" useGeneratedKeys="true" keyProperty="id"> + INSERT INTO active_dashboards (dashboard_id, user_id, order_index) + VALUES (#{dashboardId}, #{userId}, #{orderIndex}) + </insert> + + <select id="selectMaxOrderIndexForNullUser" resultType="Integer"> + SELECT MAX(order_index) + FROM active_dashboards + WHERE user_id IS NULL + </select> + + <sql id="dashboardColumns"> + d.id, d.user_id as "userId", d.name, d.description, d.column_layout as "columnLayout", + d.shared, d.is_global as "global", d.created_at as "createdAt", d.updated_at as "updatedAt" + </sql> + + <select id="selectGlobalDashboardsForUserLogin" parameterType="String" resultType="Dashboard"> + SELECT + <include refid="dashboardColumns"/> + FROM dashboards d + INNER JOIN active_dashboards ad on d.id=ad.dashboard_id + LEFT OUTER JOIN users u on u.id=ad.user_id + WHERE d.is_global=${_true} + <choose> + <when test="login == null"> + AND u.login IS NULL + </when> + <otherwise> + AND u.login=#{login} + </otherwise> + </choose> + ORDER BY order_index ASC + </select> + + <select id="selectProjectDashboardsForUserLogin" parameterType="String" resultType="Dashboard"> + SELECT + <include refid="dashboardColumns"/> + FROM dashboards d + INNER JOIN active_dashboards ad on d.id=ad.dashboard_id + LEFT OUTER JOIN users u on u.id=ad.user_id + WHERE d.is_global=${_false} + <choose> + <when test="login == null"> + AND u.login IS NULL + </when> + <otherwise> + AND u.login=#{login} + </otherwise> + </choose> + ORDER BY order_index ASC + </select> + +</mapper> diff --git a/sonar-db/src/main/resources/org/sonar/db/dashboard/DashboardMapper.xml b/sonar-db/src/main/resources/org/sonar/db/dashboard/DashboardMapper.xml new file mode 100644 index 00000000000..ce27a44c73b --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/dashboard/DashboardMapper.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.dashboard.DashboardMapper"> + +</mapper> diff --git a/sonar-db/src/main/resources/org/sonar/db/dashboard/WidgetMapper.xml b/sonar-db/src/main/resources/org/sonar/db/dashboard/WidgetMapper.xml new file mode 100644 index 00000000000..d77042a1d07 --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/dashboard/WidgetMapper.xml @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.dashboard.WidgetMapper"> + + <sql id="selectColumns"> + w.id as "id", + w.dashboard_id as "dashboardId", + w.widget_key as "widgetKey", + w.name as "name", + w.description as "description", + w.column_index as "columnIndex", + w.row_index as "rowIndex", + w.configured as "configured", + w.created_at as "createdAt", + w.updated_at as "updatedAt", + w.resource_id as "resourceId" + </sql> + + <select id="selectById" parameterType="Integer" resultType="Widget"> + select + <include refid="selectColumns"/> + from widgets w where w.id=#{id} + </select> + + <select id="selectByDashboard" parameterType="Integer" resultType="Widget"> + select + <include refid="selectColumns"/> + from widgets w where w.dashboard_id=#{id} + </select> + + <select id="selectAll" resultType="Widget"> + select + <include refid="selectColumns"/> + from widgets w + </select> + +</mapper> diff --git a/sonar-db/src/main/resources/org/sonar/db/dashboard/WidgetPropertyMapper.xml b/sonar-db/src/main/resources/org/sonar/db/dashboard/WidgetPropertyMapper.xml new file mode 100644 index 00000000000..a2bf8024a7f --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/dashboard/WidgetPropertyMapper.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.dashboard.WidgetPropertyMapper"> + + <delete id="deleteByWidgetIds" parameterType="map"> + DELETE FROM widget_properties + WHERE widget_id IN + <foreach collection="list" open="(" close=")" item="wid" separator=",">#{wid}</foreach> + </delete> + +</mapper> diff --git a/sonar-db/src/main/resources/org/sonar/db/debt/CharacteristicMapper.xml b/sonar-db/src/main/resources/org/sonar/db/debt/CharacteristicMapper.xml new file mode 100644 index 00000000000..a5f7aa7848a --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/debt/CharacteristicMapper.xml @@ -0,0 +1,137 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mappei.dtd"> + +<mapper namespace="org.sonar.db.debt.CharacteristicMapper"> + + <sql id="characteristicColumns"> + c.id, + c.kee as kee, + c.name as name, + c.parent_id as parentId, + c.characteristic_order as characteristicOrder, + c.enabled as enabled, + c.created_at as createdAt, + c.updated_at as updatedAt + </sql> + + <select id="selectEnabledCharacteristics" parameterType="map" resultType="Characteristic"> + select + <include refid="characteristicColumns"/> + from characteristics c + where c.enabled=${_true} + </select> + + <select id="selectCharacteristics" parameterType="map" resultType="Characteristic"> + select + <include refid="characteristicColumns"/> + from characteristics c + </select> + + <select id="selectEnabledRootCharacteristics" parameterType="map" resultType="Characteristic"> + select + <include refid="characteristicColumns"/> + from characteristics c + <where> + and c.parent_id is null + and c.enabled=${_true} + </where> + order by characteristic_order asc + </select> + + <select id="selectCharacteristicsByParentId" parameterType="map" resultType="Characteristic"> + select + <include refid="characteristicColumns"/> + from characteristics c + <where> + and c.parent_id=#{parent_id} + and c.enabled=${_true} + </where> + </select> + + <select id="selectCharacteristicsByIds" parameterType="map" resultType="Characteristic"> + select + <include refid="characteristicColumns"/> + from characteristics c + <where> + and c.enabled=${_true} + AND (<foreach item="id" index="index" collection="ids" open="(" separator=" or " close=")">c.id=#{id}</foreach>) + </where> + </select> + + <select id="selectByKey" parameterType="String" resultType="Characteristic"> + select + <include refid="characteristicColumns"/> + from characteristics c + <where> + and c.kee=#{key} + and c.enabled=${_true} + </where> + </select> + + <select id="selectById" parameterType="Integer" resultType="Characteristic"> + select + <include refid="characteristicColumns"/> + from characteristics c + <where> + and c.id=#{id} + and c.enabled=${_true} + </where> + </select> + + <select id="selectByName" parameterType="String" resultType="Characteristic"> + select + <include refid="characteristicColumns"/> + from characteristics c + <where> + and c.name=#{name} + and c.enabled=${_true} + </where> + </select> + + <select id="selectMaxCharacteristicOrder" resultType="Integer"> + select max(c.characteristic_order) + from characteristics c + <where> + and c.parent_id is null + and c.enabled=${_true} + </where> + </select> + + <insert id="insert" parameterType="Characteristic" keyColumn="id" useGeneratedKeys="true" keyProperty="id"> + INSERT INTO characteristics (kee, name, parent_id, characteristic_order, enabled, created_at, updated_at) + VALUES (#{kee,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{parentId,jdbcType=INTEGER}, + #{characteristicOrder,jdbcType=INTEGER}, #{enabled,jdbcType=BOOLEAN}, #{createdAt,jdbcType=TIMESTAMP}, + #{updatedAt,jdbcType=TIMESTAMP}) + </insert> + + <update id="update" parameterType="Characteristic"> + update characteristics set + name=#{name}, + parent_id=#{parentId}, + characteristic_order=#{characteristicOrder}, + enabled=#{enabled}, + updated_at=#{updatedAt} + where id=#{id} + </update> + + <select id="selectDeprecatedRequirements" resultType="RequirementMigration"> + select id as "id", + parent_id as "parentId", + root_id as "rootId", + rule_id as "ruleId", + function_key as "functionKey", + factor_value as "coefficientValue", + factor_unit as "coefficientUnit", + offset_value as "offsetValue", + offset_unit as "offsetUnit", + enabled as "enabled" + from characteristics + where rule_id IS NOT NULL + </select> + + <delete id="deleteRequirementsFromCharacteristicsTable"> + DELETE FROM characteristics WHERE rule_id IS NOT NULL + </delete> +</mapper> + diff --git a/sonar-db/src/main/resources/org/sonar/db/duplication/DuplicationMapper.xml b/sonar-db/src/main/resources/org/sonar/db/duplication/DuplicationMapper.xml new file mode 100644 index 00000000000..66212b3b205 --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/duplication/DuplicationMapper.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.duplication.DuplicationMapper"> + + <select id="selectCandidates" parameterType="map" resultType="DuplicationUnit"> + SELECT DISTINCT to_blocks.hash as hash, res.kee as resourceKey, to_blocks.index_in_file as indexInFile, + to_blocks.start_line as startLine, to_blocks.end_line as endLine + FROM duplications_index to_blocks, duplications_index from_blocks, snapshots snapshot, projects res + WHERE from_blocks.snapshot_id = #{resource_snapshot_id} + AND to_blocks.hash = from_blocks.hash + AND to_blocks.snapshot_id = snapshot.id + AND snapshot.islast = ${_true} + AND snapshot.project_id = res.id + AND res.language = #{language} + <if test="last_project_snapshot_id != null"> + AND to_blocks.project_snapshot_id != #{last_project_snapshot_id} + </if> + </select> + + <insert id="batchInsert" parameterType="DuplicationUnit" useGeneratedKeys="false"> + INSERT INTO duplications_index (snapshot_id, project_snapshot_id, hash, index_in_file, start_line, end_line) + VALUES (#{snapshotId}, #{projectSnapshotId}, #{hash}, #{indexInFile}, #{startLine}, #{endLine}) + </insert> +</mapper> diff --git a/sonar-db/src/main/resources/org/sonar/db/event/EventMapper.xml b/sonar-db/src/main/resources/org/sonar/db/event/EventMapper.xml new file mode 100644 index 00000000000..fa30a1f766f --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/event/EventMapper.xml @@ -0,0 +1,80 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> +<mapper namespace="org.sonar.db.event.EventMapper"> + + <sql id="eventColumns"> + e.id, + e.name, + e.category, + e.description, + e.event_data as "data", + e.event_date as "date", + e.component_uuid as "componentUuid", + e.snapshot_id as "snapshotId", + e.created_at as "createdAt" + </sql> + + <select id="selectByComponentUuid" parameterType="String" resultType="Event"> + SELECT + <include refid="eventColumns"/> + FROM events e + <where> + AND e.component_uuid=#{uuid} + </where> + </select> + + <insert id="insert" parameterType="Event" keyColumn="id" useGeneratedKeys="true" keyProperty="id"> + INSERT INTO events (name, category, description, event_data, event_date, component_uuid, snapshot_id, created_at) + VALUES (#{name}, #{category}, #{description}, #{data}, #{date}, #{componentUuid}, #{snapshotId}, #{createdAt}) + </insert> + + <delete id="delete"> + DELETE FROM events WHERE id=#{id} + </delete> + + <select id="findSnapshotIdOfPreviousVersion" parameterType="map" resultType="long"> + SELECT s.id + FROM snapshots s, events e, projects p + <where> + AND p.id=#{componentId} + AND p.uuid=e.component_uuid + AND e.name <> #{currentVersion} + AND e.category='Version' + AND s.id = e.snapshot_id + </where> + ORDER BY e.event_date DESC + LIMIT 1 + </select> + + <!-- SQL Server --> + <select id="findSnapshotIdOfPreviousVersion" parameterType="map" resultType="long" databaseId="mssql"> + SELECT TOP 1 s.id + FROM snapshots s, events e, projects p + <where> + AND p.id=#{componentId} + AND p.uuid=e.component_uuid + AND e.name <> #{currentVersion} + AND e.category='Version' + AND s.id = e.snapshot_id + </where> + ORDER BY e.event_date DESC + </select> + + <!-- Oracle --> + <select id="findSnapshotIdOfPreviousVersion" parameterType="map" resultType="long" databaseId="oracle"> + SELECT * FROM (SELECT s.id + FROM snapshots s, events e, projects p + <where> + AND p.id=#{componentId} + AND p.uuid=e.component_uuid + AND e.name <> #{currentVersion} + AND e.category='Version' + AND s.id = e.snapshot_id + </where> + ORDER BY e.event_date DESC + ) + WHERE ROWNUM <= 1 + </select> + +</mapper> + diff --git a/sonar-db/src/main/resources/org/sonar/db/issue/ActionPlanMapper.xml b/sonar-db/src/main/resources/org/sonar/db/issue/ActionPlanMapper.xml new file mode 100644 index 00000000000..49174ddad74 --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/issue/ActionPlanMapper.xml @@ -0,0 +1,88 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mappei.dtd"> + +<mapper namespace="org.sonar.db.issue.ActionPlanMapper"> + + <sql id="actionPlanColumns"> + ap.id, + ap.kee as kee, + ap.name as name, + ap.description as description, + ap.user_login as userLogin, + ap.project_id as projectId, + ap.status as status, + ap.deadline as deadLine, + ap.created_at as createdAt, + ap.updated_at as updatedAt, + p.kee as projectKey + </sql> + + <insert id="insert" parameterType="ActionPlanIssue" keyColumn="id" useGeneratedKeys="true" keyProperty="id"> + INSERT INTO action_plans (kee, name, description, user_login, project_id, status, deadline, created_at, updated_at) + VALUES (#{kee}, #{name}, #{description}, #{userLogin}, #{projectId}, #{status}, #{deadLine}, #{createdAt}, + #{updatedAt}) + </insert> + + <update id="update" parameterType="ActionPlanIssue"> + update action_plans set + name=#{name}, + description=#{description}, + user_login=#{userLogin}, + project_id=#{projectId}, + status=#{status}, + deadline=#{deadLine}, + updated_at=current_timestamp + where kee = #{kee} + </update> + + <delete id="delete" parameterType="String"> + delete from action_plans where kee=#{key} + </delete> + + <select id="findByKey" parameterType="long" resultType="ActionPlanIssue"> + select + <include refid="actionPlanColumns"/> + from action_plans ap, projects p + <where> + and ap.kee=#{key} + and ap.project_id=p.id + </where> + </select> + + <select id="findByKeys" parameterType="long" resultType="ActionPlanIssue"> + select + <include refid="actionPlanColumns"/> + from action_plans ap, projects p + <where> + and ap.kee in + <foreach collection="keys" open="(" close=")" item="key" separator=","> + #{key} + </foreach> + and ap.project_id=p.id + </where> + </select> + + <select id="findOpenByProjectId" parameterType="long" resultType="ActionPlanIssue"> + select + <include refid="actionPlanColumns"/> + from action_plans ap, projects p + <where> + and ap.project_id=#{projectId} + and ap.status='OPEN' + and ap.project_id=p.id + </where> + </select> + + <select id="findByNameAndProjectId" parameterType="long" resultType="ActionPlanIssue"> + select + <include refid="actionPlanColumns"/> + from action_plans ap, projects p + <where> + and ap.project_id=#{projectId} + and ap.name=#{name} + and ap.project_id=p.id + </where> + </select> + +</mapper> diff --git a/sonar-db/src/main/resources/org/sonar/db/issue/ActionPlanStatsMapper.xml b/sonar-db/src/main/resources/org/sonar/db/issue/ActionPlanStatsMapper.xml new file mode 100644 index 00000000000..ec6ddb40ea3 --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/issue/ActionPlanStatsMapper.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mappei.dtd"> + +<mapper namespace="org.sonar.db.issue.ActionPlanStatsMapper"> + + <sql id="actionPlanColumns"> + ap.id as id, + ap.kee as kee, + ap.name as name, + ap.description as description, + ap.user_login as userLogin, + ap.project_id as projectId, + ap.status as status, + ap.deadline as deadLine, + ap.created_at as createdAt, + ap.updated_at as updatedAt, + p.kee as projectKey + </sql> + + <select id="findByProjectId" parameterType="map" resultType="ActionPlanStats"> + select<include refid="actionPlanColumns"/>, count(total_issues.id) as totalIssues, count(open_issues.id) as + unresolvedIssues + from action_plans ap + left join projects p on p.id = ap.project_id + left join issues total_issues on total_issues.action_plan_key = ap.kee + left join issues open_issues on open_issues.id = total_issues.id and open_issues.resolution is null + <where> + and ap.project_id = #{projectId} + </where> + group by ap.id, ap.kee, ap.name, ap.description, ap.user_login, ap.project_id, ap.status, ap.deadline, + ap.created_at, ap.updated_at, p.kee + </select> + +</mapper> diff --git a/sonar-db/src/main/resources/org/sonar/db/issue/IssueChangeMapper.xml b/sonar-db/src/main/resources/org/sonar/db/issue/IssueChangeMapper.xml new file mode 100644 index 00000000000..96caa141092 --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/issue/IssueChangeMapper.xml @@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.issue.IssueChangeMapper"> + + <sql id="issueChangeColumns"> + c.id, + c.kee as kee, + c.issue_key as issueKey, + c.user_login as userLogin, + c.change_type as changeType, + c.change_data as changeData, + c.created_at as createdAt, + c.updated_at as updatedAt, + c.issue_change_creation_date as issueChangeCreationDate + </sql> + + <insert id="insert" parameterType="IssueChange" useGeneratedKeys="false" keyProperty="id"> + INSERT INTO issue_changes (kee, issue_key, user_login, change_type, change_data, created_at, updated_at, + issue_change_creation_date) + VALUES (#{kee,jdbcType=VARCHAR}, #{issueKey,jdbcType=VARCHAR}, #{userLogin,jdbcType=VARCHAR}, + #{changeType,jdbcType=VARCHAR}, #{changeData,jdbcType=VARCHAR}, #{createdAt,jdbcType=BIGINT}, + #{updatedAt,jdbcType=BIGINT}, #{issueChangeCreationDate,jdbcType=BIGINT}) + </insert> + + <delete id="delete" parameterType="string"> + delete from issue_changes where kee=#{id} + </delete> + + <update id="update" parameterType="map"> + update issue_changes set change_data=#{changeData}, updated_at=#{updatedAt} where kee=#{kee} + </update> + + <select id="selectByIssuesAndType" parameterType="map" resultType="IssueChange"> + select + <include refid="issueChangeColumns"/> + from issue_changes c + where c.change_type=#{changeType} and c.issue_key in + <foreach collection="issueKeys" open="(" close=")" item="key" separator=","> + #{key} + </foreach> + order by c.created_at + </select> + + <select id="selectByKeyAndType" parameterType="map" resultType="IssueChange"> + select + <include refid="issueChangeColumns"/> + from issue_changes c + where c.change_type=#{changeType} and c.kee=#{key} + </select> + + <select id="selectByIssue" parameterType="string" resultType="IssueChange"> + select + <include refid="issueChangeColumns"/> + from issue_changes c + where c.issue_key=#{id} + order by created_at asc + </select> + + <select id="selectChangelogOfNonClosedIssuesByComponent" parameterType="map" resultType="IssueChange"> + select + <include refid="issueChangeColumns"/> + from issue_changes c + inner join issues i on i.kee = c.issue_key + where i.component_uuid=#{componentUuid} + and c.change_type=#{changeType} + and i.status <> 'CLOSED' + </select> +</mapper> + diff --git a/sonar-db/src/main/resources/org/sonar/db/issue/IssueFilterFavouriteMapper.xml b/sonar-db/src/main/resources/org/sonar/db/issue/IssueFilterFavouriteMapper.xml new file mode 100644 index 00000000000..77db11f635c --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/issue/IssueFilterFavouriteMapper.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.issue.IssueFilterFavouriteMapper"> + + <sql id="issueFilterFavouriteColumns"> + filter_favourites.id as id, + filter_favourites.user_login as userLogin, + filter_favourites.issue_filter_id as issueFilterId, + filter_favourites.created_at as createdAt + </sql> + + <select id="selectById" parameterType="long" resultType="issueFilterFavourite"> + select + <include refid="issueFilterFavouriteColumns"/> + from issue_filter_favourites filter_favourites + where filter_favourites.id=#{id} + </select> + + <select id="selectByFilterId" parameterType="long" resultType="issueFilterFavourite"> + select + <include refid="issueFilterFavouriteColumns"/> + from issue_filter_favourites filter_favourites + where filter_favourites.issue_filter_id=#{filterId} + </select> + + <insert id="insert" parameterType="issueFilterFavourite" keyColumn="id" useGeneratedKeys="true" keyProperty="id"> + INSERT INTO issue_filter_favourites (user_login, issue_filter_id, created_at) + VALUES (#{userLogin}, #{issueFilterId}, current_timestamp) + </insert> + + <delete id="delete" parameterType="long"> + delete from issue_filter_favourites where id=#{id} + </delete> + + <delete id="deleteByFilterId" parameterType="long"> + delete from issue_filter_favourites where issue_filter_id=#{issueFilterId} + </delete> + +</mapper> diff --git a/sonar-db/src/main/resources/org/sonar/db/issue/IssueFilterMapper.xml b/sonar-db/src/main/resources/org/sonar/db/issue/IssueFilterMapper.xml new file mode 100644 index 00000000000..aca8dffc6c2 --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/issue/IssueFilterMapper.xml @@ -0,0 +1,76 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.issue.IssueFilterMapper"> + + <sql id="issueFilterColumns"> + filters.id as id, + filters.name as name, + filters.user_login as userLogin, + filters.shared as shared, + filters.description as description, + filters.data as data, + filters.created_at as createdAt, + filters.updated_at as updatedAt + </sql> + + <select id="selectById" parameterType="long" resultType="IssueFilter"> + select + <include refid="issueFilterColumns"/> + from issue_filters filters + where filters.id=#{id} + </select> + + <select id="selectByUser" parameterType="String" resultType="IssueFilter"> + select + <include refid="issueFilterColumns"/> + from issue_filters filters + where filters.user_login=#{user} + </select> + + <select id="selectFavoriteFiltersByUser" parameterType="String" resultType="IssueFilter"> + select + <include refid="issueFilterColumns"/> + from issue_filters filters + inner join issue_filter_favourites fav on fav.issue_filter_id = filters.id + where fav.user_login=#{user} + </select> + + <select id="selectSharedFilters" parameterType="String" resultType="IssueFilter"> + select + <include refid="issueFilterColumns"/> + from issue_filters filters + where filters.shared=${_true} + </select> + + <select id="selectProvidedFilterByName" parameterType="String" resultType="IssueFilter"> + select + <include refid="issueFilterColumns"/> + from issue_filters filters + where filters.user_login is null + and filters.shared=${_true} + and filters.name=#{name} + </select> + + <insert id="insert" parameterType="IssueFilter" keyColumn="id" useGeneratedKeys="true" keyProperty="id"> + INSERT INTO issue_filters (name, user_login, shared, description, data, created_at, updated_at) + VALUES (#{name}, #{userLogin}, #{shared}, #{description}, #{data}, #{createdAt}, #{updatedAt}) + </insert> + + <update id="update" parameterType="IssueFilter"> + update issue_filters set + name=#{name}, + shared=#{shared}, + description=#{description}, + data=#{data}, + user_login=#{userLogin}, + updated_at=current_timestamp + where id=#{id} + </update> + + <delete id="delete" parameterType="long"> + delete from issue_filters where id=#{id} + </delete> + +</mapper> diff --git a/sonar-db/src/main/resources/org/sonar/db/issue/IssueMapper.xml b/sonar-db/src/main/resources/org/sonar/db/issue/IssueMapper.xml new file mode 100644 index 00000000000..790040bc6e3 --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/issue/IssueMapper.xml @@ -0,0 +1,234 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mappei.dtd"> + +<mapper namespace="org.sonar.db.issue.IssueMapper"> + + <sql id="issueColumns"> + i.id, + i.kee as kee, + i.rule_id as ruleId, + i.action_plan_key as actionPlanKey, + i.severity as severity, + i.manual_severity as manualSeverity, + i.message as message, + i.line as line, + i.effort_to_fix as effortToFix, + i.technical_debt as debt, + i.status as status, + i.resolution as resolution, + i.checksum as checksum, + i.reporter as reporter, + i.assignee as assignee, + i.author_login as authorLogin, + i.tags as tagsString, + i.issue_attributes as issueAttributes, + i.issue_creation_date as issueCreationTime, + i.issue_update_date as issueUpdateTime, + i.issue_close_date as issueCloseTime, + i.created_at as createdAt, + i.updated_at as updatedAt, + r.plugin_rule_key as ruleKey, + r.plugin_name as ruleRepo, + r.language as language, + p.kee as componentKey, + i.component_uuid as componentUuid, + p.module_uuid as moduleUuid, + p.module_uuid_path as moduleUuidPath, + p.path as filePath, + root.kee as projectKey, + i.project_uuid as projectUuid + </sql> + + <sql id="sortColumn"> + <if test="query.sort() != null">, + <choose> + <when test="'SEVERITY'.equals(query.sort())"> + i.severity as severity + </when> + <when test="'STATUS'.equals(query.sort())"> + i.status as status + </when> + <when test="'ASSIGNEE'.equals(query.sort())"> + i.assignee as assignee + </when> + <when test="'CREATION_DATE'.equals(query.sort())"> + i.issue_creation_date as issueCreationTime + </when> + <when test="'UPDATE_DATE'.equals(query.sort())"> + i.issue_update_date as issueUpdateTime + </when> + <when test="'CLOSE_DATE'.equals(query.sort())"> + i.issue_close_date as issueCloseTime + </when> + </choose> + </if> + </sql> + + <insert id="insert" parameterType="Issue" useGeneratedKeys="false" keyProperty="id"> + INSERT INTO issues (kee, rule_id, action_plan_key, severity, manual_severity, + message, line, effort_to_fix, technical_debt, status, tags, + resolution, checksum, reporter, assignee, author_login, issue_attributes, issue_creation_date, issue_update_date, + issue_close_date, created_at, updated_at, component_uuid, project_uuid) + VALUES (#{kee,jdbcType=VARCHAR}, #{ruleId,jdbcType=INTEGER}, #{actionPlanKey,jdbcType=VARCHAR}, + #{severity,jdbcType=VARCHAR}, + #{manualSeverity,jdbcType=BOOLEAN}, #{message,jdbcType=VARCHAR}, #{line,jdbcType=INTEGER}, + #{effortToFix,jdbcType=DOUBLE}, #{debt,jdbcType=INTEGER}, #{status,jdbcType=VARCHAR}, + #{tagsString,jdbcType=VARCHAR}, #{resolution,jdbcType=VARCHAR}, #{checksum,jdbcType=VARCHAR}, + #{reporter,jdbcType=VARCHAR}, #{assignee,jdbcType=VARCHAR}, #{authorLogin,jdbcType=VARCHAR}, + #{issueAttributes,jdbcType=VARCHAR}, + #{issueCreationTime,jdbcType=BIGINT},#{issueUpdateTime,jdbcType=BIGINT}, #{issueCloseTime,jdbcType=BIGINT}, + #{createdAt,jdbcType=BIGINT}, #{updatedAt,jdbcType=BIGINT}, + #{componentUuid,jdbcType=VARCHAR}, #{projectUuid,jdbcType=VARCHAR}) + </insert> + + <!-- + IMPORTANT - invariant columns can't be updated. See IssueDto#toDtoForUpdate() + --> + <update id="update" parameterType="Issue"> + update issues set + action_plan_key=#{actionPlanKey,jdbcType=VARCHAR}, + severity=#{severity,jdbcType=VARCHAR}, + manual_severity=#{manualSeverity,jdbcType=BOOLEAN}, + message=#{message,jdbcType=VARCHAR}, + line=#{line,jdbcType=INTEGER}, + effort_to_fix=#{effortToFix,jdbcType=DOUBLE}, + technical_debt=#{debt,jdbcType=INTEGER}, + status=#{status,jdbcType=VARCHAR}, + resolution=#{resolution,jdbcType=VARCHAR}, + checksum=#{checksum,jdbcType=VARCHAR}, + reporter=#{reporter,jdbcType=VARCHAR}, + assignee=#{assignee,jdbcType=VARCHAR}, + author_login=#{authorLogin,jdbcType=VARCHAR}, + tags=#{tagsString,jdbcType=VARCHAR}, + project_uuid=#{projectUuid,jdbcType=VARCHAR}, + issue_attributes=#{issueAttributes,jdbcType=VARCHAR}, + issue_creation_date=#{issueCreationTime,jdbcType=BIGINT}, + issue_update_date=#{issueUpdateTime,jdbcType=BIGINT}, + issue_close_date=#{issueCloseTime,jdbcType=BIGINT}, + updated_at=#{updatedAt,jdbcType=BIGINT} + where kee = #{kee} + </update> + + <!-- + IMPORTANT - invariant columns can't be updated. See IssueDto#toDtoForUpdate() + --> + <update id="updateIfBeforeSelectedDate" parameterType="Issue"> + update issues set + action_plan_key=#{actionPlanKey,jdbcType=VARCHAR}, + severity=#{severity,jdbcType=VARCHAR}, + manual_severity=#{manualSeverity,jdbcType=BOOLEAN}, + message=#{message,jdbcType=VARCHAR}, + line=#{line,jdbcType=INTEGER}, + effort_to_fix=#{effortToFix,jdbcType=DOUBLE}, + technical_debt=#{debt,jdbcType=INTEGER}, + status=#{status,jdbcType=VARCHAR}, + resolution=#{resolution,jdbcType=VARCHAR}, + checksum=#{checksum,jdbcType=VARCHAR}, + reporter=#{reporter,jdbcType=VARCHAR}, + assignee=#{assignee,jdbcType=VARCHAR}, + author_login=#{authorLogin,jdbcType=VARCHAR}, + tags=#{tagsString,jdbcType=VARCHAR}, + project_uuid=#{projectUuid,jdbcType=VARCHAR}, + issue_attributes=#{issueAttributes,jdbcType=VARCHAR}, + issue_creation_date=#{issueCreationTime,jdbcType=BIGINT}, + issue_update_date=#{issueUpdateTime,jdbcType=BIGINT}, + issue_close_date=#{issueCloseTime,jdbcType=BIGINT}, + updated_at=#{updatedAt,jdbcType=BIGINT} + where kee = #{kee} and updated_at <= #{selectedAt} + </update> + + <select id="selectByKey" parameterType="String" resultType="Issue"> + select + <include refid="issueColumns"/> + from issues i + inner join rules r on r.id=i.rule_id + inner join projects p on p.uuid=i.component_uuid + inner join projects root on root.uuid=i.project_uuid + where i.kee=#{kee} + </select> + + <select id="selectNonClosedByComponentUuid" parameterType="String" resultType="Issue"> + select + <include refid="issueColumns"/> + from issues i + inner join rules r on r.id=i.rule_id + inner join projects p on p.uuid=i.component_uuid + inner join projects root on root.uuid=i.project_uuid + where + i.component_uuid=#{componentUuid} and + i.status <> 'CLOSED' + </select> + + <select id="selectNonClosedIssuesByModule" parameterType="long" resultType="Issue"> + select + i.id, + i.kee as kee, + i.rule_id as ruleId, + i.component_uuid as componentUuid, + i.project_uuid as projectUuid, + i.action_plan_key as actionPlanKey, + i.severity as severity, + i.manual_severity as manualSeverity, + i.message as message, + i.line as line, + i.effort_to_fix as effortToFix, + i.technical_debt as debt, + i.status as status, + i.resolution as resolution, + i.checksum as checksum, + i.reporter as reporter, + i.assignee as assignee, + i.author_login as authorLogin, + i.tags as tagsString, + i.issue_attributes as issueAttributes, + i.issue_creation_date as issueCreationTime, + i.issue_update_date as issueUpdateTime, + i.issue_close_date as issueCloseTime, + i.created_at as createdAt, + i.updated_at as updatedAt, + r.plugin_rule_key as ruleKey, + r.plugin_name as ruleRepo, + p.kee as componentKey, + root.kee as projectKey + from issues i + inner join (select p.id, p.uuid,p.kee from projects p where (p.root_id=#{id} and p.qualifier <> 'BRC') or + (p.id=#{id})) p on p.uuid=i.component_uuid + inner join rules r on r.id=i.rule_id + left outer join projects root on root.uuid=i.project_uuid + where i.status <> 'CLOSED' + </select> + + <select id="selectComponentUuidsOfOpenIssuesForProjectUuid" parameterType="string" resultType="string"> + select distinct(i.component_uuid) + from issues i + where i.project_uuid=#{projectUuid} and i.status <> 'CLOSED' + </select> + + <select id="selectByKeys" parameterType="map" resultType="Issue"> + select + <include refid="issueColumns"/> + from issues i + inner join rules r on r.id=i.rule_id + inner join projects p on p.uuid=i.component_uuid + inner join projects root on root.uuid=i.project_uuid + where i.kee in + <foreach collection="list" open="(" close=")" item="key" separator=","> + #{key} + </foreach> + </select> + + <select id="selectByActionPlan" parameterType="map" resultType="Issue"> + select + <include refid="issueColumns"/> + from issues i + inner join rules r on r.id=i.rule_id + inner join projects p on p.uuid=i.component_uuid + inner join projects root on root.uuid=i.project_uuid + <where> + and i.action_plan_key=#{action_plan} + </where> + </select> + +</mapper> + diff --git a/sonar-db/src/main/resources/org/sonar/db/loadedtemplate/LoadedTemplateMapper.xml b/sonar-db/src/main/resources/org/sonar/db/loadedtemplate/LoadedTemplateMapper.xml new file mode 100644 index 00000000000..0395aad517a --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/loadedtemplate/LoadedTemplateMapper.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.loadedtemplate.LoadedTemplateMapper"> + + <resultMap id="loadedTemplateResultMap" type="LoadedTemplate"> + <result property="id" column="id"/> + <result property="key" column="kee"/> + <result property="type" column="template_type"/> + </resultMap> + + <select id="countByTypeAndKey" parameterType="map" resultType="int"> + SELECT count(*) + FROM loaded_templates + WHERE kee = #{key} AND template_type = #{type} + </select> + + <insert id="insert" parameterType="LoadedTemplate" keyColumn="id" useGeneratedKeys="true" keyProperty="id"> + INSERT INTO loaded_templates (kee, template_type) + VALUES (#{key}, #{type}) + </insert> + + <delete id="delete" parameterType="map"> + delete from loaded_templates where kee = #{key} AND template_type = #{type} + </delete> +</mapper> diff --git a/sonar-db/src/main/resources/org/sonar/db/measure/CustomMeasureMapper.xml b/sonar-db/src/main/resources/org/sonar/db/measure/CustomMeasureMapper.xml new file mode 100644 index 00000000000..119cec178b4 --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/measure/CustomMeasureMapper.xml @@ -0,0 +1,83 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.measure.CustomMeasureMapper"> + <sql id="selectColumns"> + m.id, + m.metric_id as metricId, + m.component_uuid as componentUuid, + m.value, + m.text_value as textValue, + m.user_login as userLogin, + m.description, + m.created_at as createdAt, + m.updated_at as updatedAt + </sql> + + <select id="selectById" resultType="CustomMeasure"> + select + <include refid="selectColumns"/> + from manual_measures m + where m.id=#{id} + </select> + + <select id="selectByMetricId" resultType="CustomMeasure"> + select + <include refid="selectColumns"/> + from manual_measures m + where m.metric_id=#{metricId} + </select> + + <select id="selectByComponentUuid" resultType="CustomMeasure"> + select + <include refid="selectColumns"/> + from manual_measures m + where m.component_uuid=#{componentUuid} + </select> + + <insert id="insert" parameterType="CustomMeasure" useGeneratedKeys="true" keyColumn="id" keyProperty="id"> + INSERT INTO manual_measures ( + metric_id, component_uuid, value, text_value, user_login, description, created_at, updated_at + ) + VALUES ( + #{metricId, jdbcType=INTEGER}, #{componentUuid, jdbcType=VARCHAR}, + #{value, jdbcType=DOUBLE}, #{textValue, jdbcType=VARCHAR}, #{userLogin, jdbcType=VARCHAR}, + #{description, jdbcType=VARCHAR}, #{createdAt, jdbcType=BIGINT}, #{updatedAt, jdbcType=BIGINT} + ) + </insert> + + <update id="update" parameterType="CustomMeasure"> + update manual_measures + set value = #{value, jdbcType=DOUBLE}, + text_value = #{textValue, jdbcType=VARCHAR}, + description = #{description, jdbcType=VARCHAR}, + user_login = #{userLogin, jdbcType=VARCHAR}, + updated_at = #{updatedAt, jdbcType=BIGINT} + where id = #{id} + </update> + + <delete id="deleteByMetricIds"> + delete from manual_measures + where metric_id in + <foreach collection="metricIds" item="metricId" open="(" close=")" separator=","> + #{metricId} + </foreach> + </delete> + + <delete id="delete"> + delete from manual_measures + where id=#{id} + </delete> + + <select id="countByComponentUuid" resultType="Integer"> + select count(*) + from manual_measures m + where m.component_uuid=#{componentUuid} + </select> + + <select id="countByComponentIdAndMetricId" resultType="Integer"> + select count(*) + from manual_measures m + where m.metric_id=#{metricId} and m.component_uuid=#{componentUuid} + </select> +</mapper> diff --git a/sonar-db/src/main/resources/org/sonar/db/measure/MeasureFilterMapper.xml b/sonar-db/src/main/resources/org/sonar/db/measure/MeasureFilterMapper.xml new file mode 100644 index 00000000000..85e85b3fa4e --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/measure/MeasureFilterMapper.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.measure.MeasureFilterMapper"> + + <select id="findSystemFilterByName" parameterType="string" resultType="MeasureFilter"> + select id, name, user_id as "userId", shared, description, data, created_at as "createdAt", updated_at as + "updatedAt" + from measure_filters WHERE user_id is null and name=#{id} + </select> + + <insert id="insert" parameterType="MeasureFilter" keyColumn="id" useGeneratedKeys="true" keyProperty="id"> + INSERT INTO measure_filters (name, user_id, shared, description, data, created_at, updated_at) + VALUES (#{name}, #{userId}, #{shared}, #{description}, #{data}, #{createdAt}, #{updatedAt}) + </insert> + +</mapper> diff --git a/sonar-db/src/main/resources/org/sonar/db/measure/MeasureMapper.xml b/sonar-db/src/main/resources/org/sonar/db/measure/MeasureMapper.xml new file mode 100644 index 00000000000..7d83e993e05 --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/measure/MeasureMapper.xml @@ -0,0 +1,113 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.measure.MeasureMapper"> + + <sql id="measureColumns"> + pm.id, + pm.snapshot_id as snapshotId, + pm.value as value, + pm.text_value as textValue, + pm.alert_status as alertStatus, + pm.alert_text as alertText, + pm.measure_data as dataValue, + pm.variation_value_1 as variation1, + pm.variation_value_2 as variation2, + pm.variation_value_3 as variation3, + pm.variation_value_4 as variation4, + pm.variation_value_5 as variation5, + p.kee as componentKey, + metric.name as metricKey + </sql> + + <select id="selectByComponentAndMetric" parameterType="map" resultType="Measure"> + SELECT metric.name as metric_name, + <include refid="measureColumns"/> + FROM project_measures pm + INNER JOIN snapshots s ON s.id=pm.snapshot_id AND s.islast=${_true} + INNER JOIN projects p ON p.id=s.project_id AND p.enabled=${_true} + INNER JOIN metrics metric ON metric.id=pm.metric_id + <where> + AND p.kee = #{componentKey} + AND metric.name=#{metricKey} + AND pm.rule_id IS NULL + AND pm.characteristic_id IS NULL + AND pm.person_id IS NULL + </where> + </select> + + <select id="selectByComponentAndMetrics" parameterType="map" resultType="Measure"> + SELECT metric.name as metric_name, + <include refid="measureColumns"/> + FROM project_measures pm + INNER JOIN snapshots s ON s.id=pm.snapshot_id AND s.islast=${_true} + INNER JOIN projects p ON p.id=s.project_id AND p.enabled=${_true} + INNER JOIN metrics metric ON metric.id=pm.metric_id + <where> + AND p.kee = #{componentKey} + AND + <foreach item="metricKey" index="index" collection="metricKeys" open="(" separator=" or " close=")"> + metric.name=#{metricKey} + </foreach> + AND pm.rule_id IS NULL + AND pm.characteristic_id IS NULL + AND pm.person_id IS NULL + </where> + </select> + + <select id="countByComponentAndMetric" parameterType="map" resultType="long"> + SELECT count(pm.id) + FROM project_measures pm + INNER JOIN snapshots s ON s.id=pm.snapshot_id AND s.islast=${_true} + INNER JOIN metrics metric ON metric.id=pm.metric_id + INNER JOIN projects p ON p.id=s.project_id AND p.enabled=${_true} + <where> + AND p.kee = #{componentKey} + AND metric.name = #{metricKey} + AND pm.rule_id IS NULL + AND pm.characteristic_id IS NULL + AND pm.person_id IS NULL + </where> + </select> + + <select id="selectByComponentUuidAndProjectSnapshotIdAndStatusAndMetricIds" parameterType="map" + resultType="org.sonar.db.measure.PastMeasureDto"> + SELECT pm.id as id, pm.metric_id as metricId, pm.rule_id as ruleId, pm.characteristic_id as characteristicId, + pm.person_id as personId, pm.value as value + FROM project_measures pm + INNER JOIN snapshots s ON s.id=pm.snapshot_id AND s.status=#{status} + INNER JOIN projects p ON p.id=s.project_id AND p.enabled=${_true} + <where> + AND p.uuid = #{componentUuid} + AND (s.root_snapshot_id=#{rootSnapshotId} OR s.id=#{rootSnapshotId}) + AND + <foreach item="metricId" index="index" collection="metricIds" open="(" separator=" or " close=")"> + pm.metric_id=#{metricId} + </foreach> + </where> + </select> + + <insert id="insert" parameterType="Measure" useGeneratedKeys="false"> + INSERT INTO project_measures ( + value, metric_id, snapshot_id, rule_id, text_value, project_id, alert_status, alert_text, description, + characteristic_id, person_id, variation_value_1, variation_value_2, variation_value_3, variation_value_4, + variation_value_5, measure_data) + VALUES ( + #{value, jdbcType=DOUBLE}, #{metricId, jdbcType=INTEGER}, #{snapshotId, jdbcType=INTEGER}, + #{ruleId, jdbcType=INTEGER}, #{textValue, jdbcType=VARCHAR}, + #{componentId, jdbcType=INTEGER}, #{alertStatus, jdbcType=VARCHAR}, #{alertText, jdbcType=VARCHAR}, + #{description, jdbcType=VARCHAR}, #{characteristicId, jdbcType=INTEGER}, + #{personId, jdbcType=INTEGER}, #{variation1, jdbcType=DOUBLE}, #{variation2, jdbcType=DOUBLE}, + #{variation3, jdbcType=DOUBLE}, + #{variation4, jdbcType=DOUBLE}, #{variation5, jdbcType=DOUBLE}, #{dataValue, jdbcType=BINARY} + ) + </insert> + + <select id="selectMetricKeysForSnapshot" parameterType="long" resultType="string"> + SELECT DISTINCT m.name + FROM project_measures pm + INNER JOIN metrics m ON m.id=pm.metric_id + WHERE pm.snapshot_id=#{snapshotId} + </select> + +</mapper> diff --git a/sonar-db/src/main/resources/org/sonar/db/metric/MetricMapper.xml b/sonar-db/src/main/resources/org/sonar/db/metric/MetricMapper.xml new file mode 100644 index 00000000000..ca4a79a3a82 --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/metric/MetricMapper.xml @@ -0,0 +1,164 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.metric.MetricMapper"> + + <sql id="metricColumns"> + m.id, + m.name as kee, + m.description, + m.direction, + m.domain, + m.short_name as shortName, + m.qualitative, + m.val_type as valueType, + m.user_managed as userManaged, + m.enabled, + m.worst_value as worstValue, + m.best_value as bestValue, + m.optimized_best_value as optimizedBestValue, + m.hidden, + m.delete_historical_data as deleteHistoricalData + </sql> + + <select id="selectByKey" parameterType="map" resultType="org.sonar.db.metric.MetricDto"> + SELECT + <include refid="metricColumns"/> + FROM metrics m + <where> + AND m.name=#{key} + </where> + </select> + + <select id="selectAllEnabled" parameterType="map" resultType="org.sonar.db.metric.MetricDto"> + SELECT + <include refid="metricColumns"/> + FROM metrics m + <where> + AND m.enabled=${_true} + <if test="isCustom!=null"> + <if test="isCustom.equals(true)"> + AND m.user_managed=${_true} + </if> + <if test="isCustom.equals(false)"> + AND m.user_managed=${_false} + </if> + </if> + </where> + ORDER BY UPPER(m.short_name), m.short_name + </select> + + <select id="selectAvailableCustomMetricsByComponentUuid" resultType="org.sonar.db.metric.MetricDto"> + select + <include refid="metricColumns"/> + from metrics m + left join manual_measures mm on mm.metric_id = m.id and mm.component_uuid=#{componentUuid} + where m.enabled=${_true} + and m.user_managed=${_true} + and mm.id is null + ORDER BY UPPER(m.short_name), m.short_name + </select> + + <select id="countEnabled" resultType="Integer"> + SELECT COUNT(*) + FROM metrics m + <where> + AND m.enabled=${_true} + <if test="isCustom!=null"> + <if test="isCustom.equals(true)"> + AND m.user_managed=${_true} + </if> + <if test="isCustom.equals(false)"> + AND m.user_managed=${_false} + </if> + </if> + </where> + </select> + + <insert id="insert" parameterType="org.sonar.db.metric.MetricDto" useGeneratedKeys="true" keyColumn="id" + keyProperty="id"> + INSERT INTO metrics ( + name, description, direction, domain, short_name, qualitative, val_type, user_managed, enabled, worst_value, + best_value, optimized_best_value, hidden, delete_historical_data) + VALUES ( + #{kee, jdbcType=VARCHAR}, #{description, jdbcType=VARCHAR}, #{direction, jdbcType=INTEGER}, + #{domain, jdbcType=VARCHAR}, #{shortName, jdbcType=VARCHAR}, #{qualitative, jdbcType=BOOLEAN}, + #{valueType, jdbcType=VARCHAR}, #{userManaged, jdbcType=BOOLEAN}, #{enabled, jdbcType=BOOLEAN}, + #{worstValue, jdbcType=DOUBLE}, #{bestValue, jdbcType=DOUBLE}, + #{optimizedBestValue, jdbcType=BOOLEAN}, #{hidden, jdbcType=BOOLEAN}, #{deleteHistoricalData, jdbcType=BOOLEAN} + ) + </insert> + + <update id="update" parameterType="org.sonar.db.metric.MetricDto"> + update metrics + set + name=#{key, jdbcType=VARCHAR}, + short_name=#{shortName, jdbcType=VARCHAR}, + val_type=#{valueType, jdbcType=VARCHAR}, + enabled=#{enabled, jdbcType=BOOLEAN}, + domain=#{domain, jdbcType=VARCHAR}, + description=#{description, jdbcType=VARCHAR}, + direction=#{direction, jdbcType=INTEGER}, + hidden=#{hidden, jdbcType=BOOLEAN}, + qualitative=#{qualitative, jdbcType=BOOLEAN} + where id=#{id} + </update> + + <select id="selectDomains" resultType="String"> + select distinct domain + from metrics m + where m.domain is not null and m.enabled=${_true} + </select> + + <update id="disableByIds"> + update metrics + set enabled=${_false} + <where> + AND user_managed=${_true} + AND id in + <foreach item="id" collection="ids" open="(" separator="," close=")"> + #{id} + </foreach> + </where> + </update> + + <update id="disableByKey" parameterType="string"> + update metrics + set enabled=${_false} + where name=#{key} + </update> + + <select id="selectByKeys" resultType="org.sonar.db.metric.MetricDto"> + SELECT + <include refid="metricColumns"/> + FROM metrics m + <where> + AND m.name in + <foreach item="key" collection="keys" open="(" separator="," close=")"> + #{key} + </foreach> + </where> + </select> + + <select id="selectByIds" resultType="org.sonar.db.metric.MetricDto"> + SELECT + <include refid="metricColumns"/> + FROM metrics m + <where> + AND m.id in + <foreach item="id" collection="ids" open="(" separator="," close=")"> + #{id} + </foreach> + </where> + </select> + + <select id="selectById" resultType="org.sonar.db.metric.MetricDto"> + SELECT + <include refid="metricColumns"/> + FROM metrics m + <where> + AND m.id=#{id} + </where> + </select> + +</mapper> diff --git a/sonar-db/src/main/resources/org/sonar/db/notification/NotificationQueueMapper.xml b/sonar-db/src/main/resources/org/sonar/db/notification/NotificationQueueMapper.xml new file mode 100644 index 00000000000..c09eafc31d0 --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/notification/NotificationQueueMapper.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mappei.dtd"> + +<mapper namespace="org.sonar.db.notification.NotificationQueueMapper"> + + <insert id="insert" parameterType="NotificationQueue" useGeneratedKeys="false"> + INSERT INTO notifications (data) + VALUES (#{data}) + </insert> + + <delete id="delete" parameterType="long"> + delete from notifications where id=#{id} + </delete> + + <select id="count" resultType="long"> + select count(*) from notifications + </select> + + <select id="findOldest" parameterType="int" resultType="NotificationQueue"> + select id, data + from notifications + order by id asc + limit #{count} + </select> + + <!-- SQL Server --> + <select id="findOldest" parameterType="int" resultType="NotificationQueue" databaseId="mssql"> + select top (#{count}) id, data + from notifications + order by id asc + </select> + + <!-- Oracle --> + <select id="findOldest" parameterType="int" resultType="NotificationQueue" databaseId="oracle"> + select * from (select + id, data + from notifications + order by id asc + ) + where rownum <= #{count} + </select> + +</mapper> diff --git a/sonar-db/src/main/resources/org/sonar/db/permission/PermissionMapper.xml b/sonar-db/src/main/resources/org/sonar/db/permission/PermissionMapper.xml new file mode 100644 index 00000000000..79a705a44dc --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/permission/PermissionMapper.xml @@ -0,0 +1,69 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.permission.PermissionMapper"> + + <select id="selectUsers" parameterType="map" resultType="UserWithPermission"> + SELECT u.login as login, u.name as name, user_role.role as permission + FROM users u + LEFT JOIN user_roles user_role ON user_role.user_id=u.id + AND user_role.role=#{query.permission} + <if test="componentId != null"> + AND user_role.resource_id=#{componentId} + </if> + <if test="componentId == null"> + AND user_role.resource_id IS NULL + </if> + <where> + u.active = ${_true} + <choose> + <when test="query.membership() == 'IN'"> + AND user_role.role IS NOT NULL + </when> + <when test="query.membership() == 'OUT'"> + AND user_role.role IS NULL + </when> + </choose> + <if test="query.search() != null"> + AND (UPPER(u.name) LIKE #{query.searchSql} ESCAPE '/') + </if> + </where> + ORDER BY u.name + </select> + + <select id="selectGroups" parameterType="map" resultType="GroupWithPermission"> + SELECT name, description, permission FROM + (SELECT g.name as name, g.description as description, group_role.role as permission + FROM groups g + LEFT JOIN group_roles group_role ON group_role.group_id=g.id + AND group_role.role=#{query.permission} + <if test="componentId != null"> + AND group_role.resource_id=#{componentId} + </if> + <if test="componentId == null"> + AND group_role.resource_id IS NULL + </if> + UNION + -- Add Anyone group permission + SELECT #{anyoneGroup} as name, NULL as description, group_role.role as permission + FROM group_roles group_role + <where> + AND group_role.role=#{query.permission} + AND group_role.group_id IS NULL + <if test="componentId != null"> + AND group_role.resource_id=#{componentId} + </if> + <if test="componentId == null"> + AND group_role.resource_id IS NULL + </if> + </where> + ) groups + <where> + <if test="query.search() != null"> + AND (UPPER(groups.name) LIKE #{query.searchSql} ESCAPE '/') + </if> + </where> + ORDER BY groups.name + </select> + +</mapper> diff --git a/sonar-db/src/main/resources/org/sonar/db/permission/PermissionTemplateMapper.xml b/sonar-db/src/main/resources/org/sonar/db/permission/PermissionTemplateMapper.xml new file mode 100644 index 00000000000..95567f2e5c2 --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/permission/PermissionTemplateMapper.xml @@ -0,0 +1,186 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.permission.PermissionTemplateMapper"> + + <insert id="insert" parameterType="PermissionTemplate" keyColumn="id" useGeneratedKeys="true" keyProperty="id"> + INSERT INTO permission_templates (name, kee, description, key_pattern, created_at, updated_at) + VALUES (#{name}, #{kee}, #{description}, #{keyPattern}, #{createdAt}, #{updatedAt}) + </insert> + + <update id="update" parameterType="PermissionTemplate"> + UPDATE permission_templates + SET name = #{name}, description = #{description}, key_pattern = #{keyPattern}, updated_at = #{updatedAt} + WHERE id = #{id} + </update> + + <delete id="delete" parameterType="long"> + DELETE FROM permission_templates + WHERE id = #{templateId} + </delete> + + <delete id="deleteUsersPermissions" parameterType="long"> + DELETE FROM perm_templates_users + WHERE template_id = #{templateId} + </delete> + + <delete id="deleteGroupsPermissions" parameterType="long"> + DELETE FROM perm_templates_groups + WHERE template_id = #{templateId} + </delete> + + <insert id="insertUserPermission" parameterType="PermissionTemplateUser"> + INSERT INTO perm_templates_users (template_id, user_id, permission_reference, created_at, updated_at) + VALUES (#{templateId}, #{userId}, #{permission}, #{createdAt}, #{updatedAt}) + </insert> + + <delete id="deleteUserPermission" parameterType="PermissionTemplateUser"> + DELETE FROM perm_templates_users + WHERE template_id = #{templateId} + AND user_id = #{userId} + AND permission_reference = #{permission} + </delete> + + <insert id="insertGroupPermission" parameterType="PermissionTemplateGroup"> + INSERT INTO perm_templates_groups (template_id, group_id, permission_reference, created_at, updated_at) + VALUES (#{templateId}, #{groupId}, #{permission}, #{createdAt}, #{updatedAt}) + </insert> + + <delete id="deleteGroupPermission" parameterType="PermissionTemplateGroup"> + DELETE FROM perm_templates_groups + WHERE template_id = #{templateId} + AND permission_reference = #{permission} + AND + <choose> + <when test="groupId != null"> + group_id = #{groupId} + </when> + <otherwise> + group_id IS NULL + </otherwise> + </choose> + </delete> + + <delete id="deleteByGroupId" parameterType="long"> + DELETE FROM perm_templates_groups + WHERE group_id = #{groupId} + </delete> + + <select id="selectUsers" parameterType="map" resultType="UserWithPermission"> + SELECT u.login as login, u.name as name, ptu.permission_reference as permission + FROM users u + LEFT JOIN perm_templates_users ptu ON ptu.user_id=u.id + AND ptu.permission_reference=#{query.permission} + AND ptu.template_id=#{templateId} + <where> + u.active = ${_true} + <choose> + <when test="query.membership() == 'IN'"> + AND ptu.permission_reference IS NOT NULL + </when> + <when test="query.membership() == 'OUT'"> + AND ptu.permission_reference IS NULL + </when> + </choose> + <if test="query.search() != null"> + AND (UPPER(u.name) LIKE #{query.searchSql} ESCAPE '/') + </if> + </where> + ORDER BY u.name + </select> + + <select id="selectGroups" parameterType="map" resultType="GroupWithPermission"> + SELECT name, description, permission FROM + (SELECT g.name as name, g.description as description, ptg.permission_reference as permission + FROM groups g + LEFT JOIN perm_templates_groups ptg ON ptg.group_id=g.id + AND ptg.permission_reference=#{query.permission} + AND ptg.template_id=#{templateId} + UNION + -- Add Anyone group permission + SELECT #{anyoneGroup} as name, NULL as description, ptg.permission_reference as permission + FROM perm_templates_groups ptg + <where> + AND ptg.permission_reference=#{query.permission} + AND ptg.template_id=#{templateId} + AND ptg.group_id IS NULL + </where> + ) groups + <where> + <if test="query.search() != null"> + AND (UPPER(groups.name) LIKE #{query.searchSql} ESCAPE '/') + </if> + </where> + ORDER BY groups.name + </select> + + <select id="selectByKey" parameterType="String" resultType="PermissionTemplate"> + SELECT id, name, kee, description, key_pattern AS keyPattern, created_at AS createdAt, updated_at AS updatedAt + FROM permission_templates + WHERE kee = #{kee} + </select> + + <select id="selectAllPermissionTemplates" resultType="PermissionTemplate"> + SELECT id, name, kee, description, key_pattern AS keyPattern, created_at AS createdAt, updated_at AS updatedAt + FROM permission_templates + </select> + + <select id="selectTemplateUsersPermissions" parameterType="String" resultMap="fullPermissionsTemplateResult"> + SELECT pt.id AS template_id, + pt.name AS template_name, + pt.description AS template_description, + pt.key_pattern AS template_key_pattern, + pt.created_at AS template_created_at, + pt.updated_at AS template_updated_at, + ptu.id AS permission_template_user_id, + ptu.permission_reference AS user_permission, + ptu.user_id AS user_id, + u.name AS user_name, + u.login AS user_login + FROM permission_templates pt + INNER JOIN perm_templates_users ptu ON ptu.template_id = pt.id + INNER JOIN users u ON u.id = ptu.user_id AND u.active = ${_true} + WHERE pt.kee = #{templateKey} + </select> + + <select id="selectTemplateGroupsPermissions" parameterType="String" resultMap="fullPermissionsTemplateResult"> + SELECT pt.id AS template_id, + pt.name AS template_name, + pt.description AS template_description, + pt.key_pattern AS template_key_pattern, + pt.created_at AS template_created_at, + pt.updated_at AS template_updated_at, + ptg.id AS permission_template_group_id, + ptg.permission_reference AS group_permission, + ptg.group_id AS group_id, + g.name AS group_name + FROM permission_templates pt + INNER JOIN perm_templates_groups ptg ON ptg.template_id = pt.id + LEFT OUTER JOIN groups g ON g.id = ptg.group_id + WHERE pt.kee = #{templateKey} + AND (g.name IS NOT NULL OR ptg.group_id IS NULL) + </select> + + <resultMap id="fullPermissionsTemplateResult" type="PermissionTemplate"> + <id property="id" column="template_id"/> + <result property="name" column="template_name"/> + <result property="description" column="template_description"/> + <result property="keyPattern" column="template_key_pattern"/> + <result property="createdAt" column="template_created_at"/> + <result property="updatedAt" column="template_updated_at"/> + <collection property="usersPermissions" ofType="PermissionTemplateUser"> + <id property="id" column="permission_template_user_id"/> + <result property="userId" column="user_id"/> + <result property="permission" column="user_permission"/> + <result property="userName" column="user_name"/> + <result property="userLogin" column="user_login"/> + </collection> + <collection property="groupsPermissions" ofType="PermissionTemplateGroup"> + <id property="id" column="permission_template_group_id"/> + <result property="groupId" column="group_id"/> + <result property="permission" column="group_permission"/> + <result property="groupName" column="group_name"/> + </collection> + </resultMap> + +</mapper> diff --git a/sonar-db/src/main/resources/org/sonar/db/property/PropertiesMapper.xml b/sonar-db/src/main/resources/org/sonar/db/property/PropertiesMapper.xml new file mode 100644 index 00000000000..d36c205772c --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/property/PropertiesMapper.xml @@ -0,0 +1,142 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.property.PropertiesMapper"> + + <select id="findUsersForNotification" parameterType="map" resultType="String"> + select u.login + from users u + inner join properties p on p.user_id=u.id + <if test="projectUuid == null"> + where p.prop_key = #{notifKey} and p.text_value LIKE 'true' and p.resource_id is null + </if> + <if test="projectUuid != null"> + inner join projects c on c.id=p.resource_id + where p.prop_key = #{notifKey} AND p.text_value LIKE 'true' + and c.uuid = #{projectUuid} and p.resource_id is not null + </if> + </select> + + <select id="findNotificationSubscribers" parameterType="map" resultType="String"> + SELECT U.login + FROM properties P, users U + WHERE P.user_id = U.id AND P.prop_key = #{propKey} AND P.text_value LIKE 'true' + AND ( + P.resource_id is null + <if test="componentKey != null"> + OR P.resource_id in (select id from projects where kee=#{componentKey}) + </if> + ) + </select> + + <select id="selectGlobalProperties" resultType="Property"> + select p.id as id, p.prop_key as "key", p.text_value as value, p.resource_id as resourceId, p.user_id as userId + from properties p + where p.resource_id is null and p.user_id is null + </select> + + <select id="selectProjectProperties" parameterType="String" resultType="Property"> + select p.id as id, p.prop_key as "key", p.text_value as value, p.resource_id as resourceId, p.user_id as userId + from properties p, projects r + where p.resource_id=r.id and p.user_id is null and r.kee=#{resourceKey} + </select> + + <select id="selectProjectPropertiesByResourceId" parameterType="Long" resultType="Property"> + select p.id as id, p.prop_key as "key", p.text_value as value, p.resource_id as resourceId, p.user_id as userId + from properties p + where p.resource_id=#{resourceId} and p.user_id is null + </select> + + <select id="selectDescendantModuleProperties" parameterType="String" resultType="Property"> + SELECT prop.id as id, prop.prop_key as "key", prop.text_value as value, prop.resource_id as resourceId, prop.user_id + as userId + FROM properties prop + INNER JOIN (SELECT p.id FROM projects p<include refid="org.sonar.db.component.ComponentMapper.modulesTreeQuery"/>) + modules on modules.id=prop.resource_id + WHERE prop.user_id IS NULL + </select> + + <select id="selectSetOfResourceProperties" parameterType="map" resultType="Property"> + select p.id as id, p.prop_key as "key", p.text_value as value, p.resource_id as resourceId, p.user_id as userId + from properties p + where p.resource_id=#{rId} and p.prop_key in + <foreach item="propKey" index="index" collection="propKeys" open="(" separator="," close=")">#{propKey}</foreach> + </select> + + <select id="selectByKey" parameterType="map" resultType="Property"> + select p.id as id, p.prop_key as "key", p.text_value as value, p.resource_id as resourceId, p.user_id as userId + from properties p + where p.prop_key=#{key} + <if test="resourceId == null"> + AND p.resource_id is null + </if> + <if test="resourceId != null"> + AND p.resource_id=#{resourceId} + </if> + <if test="userId == null"> + AND p.user_id is null + </if> + <if test="userId != null"> + AND p.user_id=#{userId} + </if> + </select> + + <select id="selectByQuery" parameterType="map" resultType="Property"> + select p.id as id, p.prop_key as "key", p.text_value as value, p.resource_id as resourceId, p.user_id as userId + from properties p + <where> + <if test="query.key() != null"> + AND p.prop_key=#{query.key} + </if> + <if test="query.componentId() != null"> + AND p.resource_id=#{query.componentId} + </if> + <if test="query.userId() != null"> + AND p.user_id=#{query.userId} + </if> + </where> + </select> + + <update id="update" parameterType="Property"> + update properties set text_value = #{value} where id = #{id} + </update> + + <insert id="insert" parameterType="Property" useGeneratedKeys="false"> + INSERT INTO properties (prop_key, resource_id, user_id, text_value) + VALUES (#{key}, #{resourceId}, #{userId}, #{value}) + </insert> + + <delete id="deleteProjectProperty" parameterType="map"> + delete from properties where prop_key=#{key} and resource_id=#{rId} and user_id is null + </delete> + + <delete id="deleteProjectProperties" parameterType="map"> + DELETE FROM properties + WHERE + prop_key=#{key} + AND text_value LIKE #{value} + AND resource_id IS NOT NULL + AND user_id IS NULL + </delete> + + <delete id="deleteGlobalProperty" parameterType="string"> + delete from properties where prop_key=#{id} and resource_id is null and user_id is null + </delete> + + <delete id="deleteGlobalProperties"> + delete from properties where resource_id is null and user_id is null + </delete> + + <delete id="deleteAllProperties" parameterType="string"> + delete from properties where prop_key=#{id} + </delete> + + <update id="renamePropertyKey" parameterType="map"> + update properties set prop_key=#{newKey} where prop_key=#{oldKey} + </update> + + <update id="updateProperties" parameterType="map"> + update properties set text_value=#{newValue} where text_value LIKE #{oldValue} and prop_key=#{key} + </update> + +</mapper> diff --git a/sonar-db/src/main/resources/org/sonar/db/purge/PurgeMapper.xml b/sonar-db/src/main/resources/org/sonar/db/purge/PurgeMapper.xml new file mode 100644 index 00000000000..1d6bed47806 --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/purge/PurgeMapper.xml @@ -0,0 +1,341 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.purge.PurgeMapper"> + + <select id="selectSnapshotIds" parameterType="map" resultType="long"> + select s.id from snapshots s + <where> + <if test="islast != null"> + and s.islast=#{islast} + </if> + <if test="notPurged != null and notPurged"> + and (s.purge_status is null or s.purge_status=0) + </if> + <if test="rootSnapshotId != null"> + and s.root_snapshot_id=#{rootSnapshotId} + </if> + <if test="id != null"> + and s.id=#{id} + </if> + <if test="rootProjectId != null"> + and s.root_project_id=#{rootProjectId} + </if> + <if test="resourceId != null"> + and s.project_id=#{resourceId} + </if> + <if test="status != null"> + and s.status in + <foreach item="s" index="index" collection="status" open="(" separator="," close=")">#{s}</foreach> + </if> + <if test="scopes != null"> + and s.scope in + <foreach item="scope" index="index" collection="scopes" open="(" separator="," close=")">#{scope}</foreach> + </if> + <if test="qualifiers != null"> + and s.qualifier in + <foreach item="qualifier" index="index" collection="qualifiers" open="(" separator="," close=")">#{qualifier} + </foreach> + </if> + <if test="withVersionEvent != null"> + <if test="withVersionEvent"> + and exists(select e.id from events e where e.snapshot_id=s.id and e.category='Version') + </if> + <if test="!withVersionEvent"> + and not exists(select e.id from events e where e.snapshot_id=s.id and e.category='Version') + </if> + </if> + </where> + </select> + + <select id="selectSnapshotIdsByResource" parameterType="map" resultType="long"> + select s.id from snapshots s + <where> + s.project_id in + <foreach collection="resourceIds" open="(" close=")" item="resourceId" separator=","> + #{resourceId} + </foreach> + </where> + </select> + + <select id="selectPurgeableSnapshotsWithEvents" parameterType="long" resultType="PurgeableSnapshot"> + select s.id as "snapshotId", s.created_at as "date", ${_true} as "hasEvents", islast as "isLast" from + snapshots s where + s.project_id=#{id} and s.status='P' and s.qualifier <> 'LIB' and + exists(select e.id from events e where e.snapshot_id=s.id) + </select> + + <select id="selectPurgeableSnapshotsWithoutEvents" parameterType="long" resultType="PurgeableSnapshot"> + select s.id as "snapshotId", s.created_at as "date", ${_false} as "hasEvents", islast as "isLast" from + snapshots s where + s.project_id=#{id} and s.status='P' and s.qualifier <> 'LIB' and + not exists(select e.id from events e where e.snapshot_id=s.id) + </select> + + <select id="selectComponentIdUuidsToDisable" resultType="IdUuidPair" parameterType="long"> + select p.id, p.uuid from projects p + where (p.id=#{id} or p.root_id=#{id}) and p.enabled=${_true} + and not exists(select s.project_id from snapshots s where s.islast=${_true} and s.project_id=p.id) + </select> + + <select id="selectPurgeableFileUuids" resultType="string" parameterType="long"> + select p.uuid from projects p + where (p.id=#{id} or p.root_id=#{id}) and p.enabled=${_true} and p.scope='FIL' + and not exists(select s.project_id from snapshots s where s.islast=${_true} and s.project_id=p.id) + </select> + + <select id="selectMetricIdsWithoutHistoricalData" resultType="long"> + select id from metrics where delete_historical_data=${_true} + </select> + + <select id="selectProjectIdUuidsByRootId" resultType="IdUuidPair" parameterType="long"> + select id, uuid from projects where root_id=#{id} and scope='PRJ' + </select> + + <select id="selectComponentIdUuidsByRootId" resultType="IdUuidPair" parameterType="long"> + select id, uuid from projects where root_id=#{id} or id=#{id} + </select> + + <delete id="deleteSnapshotMeasures" parameterType="map"> + delete from project_measures where snapshot_id in + <foreach collection="snapshotIds" open="(" close=")" item="snapshotId" separator=","> + #{snapshotId} + </foreach> + </delete> + + <delete id="deleteSnapshotDuplications" parameterType="map"> + delete from duplications_index where snapshot_id in + <foreach collection="snapshotIds" open="(" close=")" item="snapshotId" separator=","> + #{snapshotId} + </foreach> + </delete> + + <delete id="deleteSnapshotEvents" parameterType="map"> + delete from events where snapshot_id in + <foreach collection="snapshotIds" open="(" close=")" item="snapshotId" separator=","> + #{snapshotId} + </foreach> + </delete> + + <delete id="deleteSnapshot" parameterType="map"> + delete from snapshots where id in + <foreach collection="snapshotIds" open="(" close=")" item="snapshotId" separator=","> + #{snapshotId} + </foreach> + </delete> + + <delete id="deleteSnapshotWastedMeasures" parameterType="map"> + delete from project_measures + <where> + snapshot_id in + <foreach collection="snapshotIds" open="(" close=")" item="snapshotId" separator=","> + #{snapshotId} + </foreach> + and (rule_id is not null or person_id is not null + <if test="mids.size()>0"> + or metric_id in + <foreach item="mid" index="index" collection="mids" open="(" separator="," close=")">#{mid}</foreach> + </if> + ) + </where> + </delete> + + <update id="updatePurgeStatusToOne" parameterType="long"> + update snapshots set purge_status = 1 where id = #{id} + </update> + + <update id="disableResource" parameterType="long"> + update projects set enabled=${_false} where id=#{id} + </update> + + <update id="resolveResourceIssuesNotAlreadyResolved" parameterType="map"> + UPDATE issues SET status='CLOSED',resolution='REMOVED',updated_at=#{dateAsLong},issue_close_date=#{dateAsLong}, + issue_update_date=#{dateAsLong} + WHERE component_uuid=#{componentUuid} AND resolution IS NULL + </update> + + <delete id="deleteResourceIndex" parameterType="map"> + delete from resource_index where resource_id in + <foreach collection="resourceIds" open="(" close=")" item="resourceId" separator=","> + #{resourceId} + </foreach> + </delete> + + <delete id="deleteEvent" parameterType="map"> + delete from events where id in + <foreach collection="resourceIds" open="(" close=")" item="resourceId" separator=","> + #{resourceId} + </foreach> + </delete> + + <delete id="deleteResourceLinks" parameterType="map"> + delete from project_links where component_uuid in + <foreach collection="componentUuids" open="(" close=")" item="componentUuid" separator=","> + #{componentUuid} + </foreach> + </delete> + + <delete id="deleteResourceProperties" parameterType="map"> + delete from properties where resource_id in + <foreach collection="resourceIds" open="(" close=")" item="resourceId" separator=","> + #{resourceId} + </foreach> + </delete> + + <delete id="deleteResource" parameterType="map"> + delete from projects where id in + <foreach collection="resourceIds" open="(" close=")" item="resourceId" separator=","> + #{resourceId} + </foreach> + </delete> + + <delete id="deleteResourceGroupRoles" parameterType="map"> + delete from group_roles where resource_id in + <foreach collection="resourceIds" open="(" close=")" item="resourceId" separator=","> + #{resourceId} + </foreach> + </delete> + + <delete id="deleteResourceUserRoles" parameterType="map"> + delete from user_roles where resource_id in + <foreach collection="resourceIds" open="(" close=")" item="resourceId" separator=","> + #{resourceId} + </foreach> + </delete> + + <delete id="deleteResourceManualMeasures" parameterType="map"> + delete from manual_measures where component_uuid in + <foreach collection="componentUuids" open="(" close=")" item="componentUuid" separator=","> + #{componentUuid} + </foreach> + </delete> + + <delete id="deleteComponentEvents" parameterType="map"> + delete from events where component_uuid in + <foreach collection="componentUuids" open="(" close=")" item="componentUuid" separator=","> + #{componentUuid} + </foreach> + </delete> + + <delete id="deleteResourceActionPlans" parameterType="map"> + delete from action_plans where project_id in + <foreach collection="resourceIds" open="(" close=")" item="resourceId" separator=","> + #{resourceId} + </foreach> + </delete> + + <delete id="deleteAuthors" parameterType="map"> + delete from authors where person_id in + <foreach collection="resourceIds" open="(" close=")" item="resourceId" separator=","> + #{resourceId} + </foreach> + </delete> + + <update id="setSnapshotIsLastToFalse" parameterType="long"> + update snapshots set islast=${_false} where project_id=#{id} + </update> + + <delete id="deleteComponentIssueChanges" parameterType="map"> + delete from issue_changes ic + where exists (select * from issues i where i.kee=ic.issue_key and i.component_uuid in + <foreach collection="componentUuids" open="(" close=")" item="componentUuid" separator=","> + #{componentUuid} + </foreach> + ) + </delete> + + <!-- Mssql --> + <delete id="deleteComponentIssueChanges" databaseId="mssql" parameterType="map"> + delete issue_changes from issue_changes + inner join issues on issue_changes.issue_key=issues.kee + where issues.component_uuid in + <foreach collection="componentUuids" open="(" close=")" item="componentUuid" separator=","> + #{componentUuid} + </foreach> + </delete> + + <!-- Mysql --> + <delete id="deleteComponentIssueChanges" databaseId="mysql" parameterType="map"> + delete ic from issue_changes as ic, issues as i where ic.issue_key=i.kee and i.component_uuid in + <foreach collection="componentUuids" open="(" close=")" item="componentUuid" separator=","> + #{componentUuid} + </foreach> + </delete> + + <delete id="deleteComponentIssues" parameterType="map"> + delete from issues where component_uuid in + <foreach collection="componentUuids" open="(" close=")" item="componentUuid" separator=","> + #{componentUuid} + </foreach> + </delete> + + <delete id="deleteFileSourcesByProjectUuid"> + delete from file_sources where project_uuid=#{rootProjectUuid} + </delete> + + <delete id="deleteFileSourcesByUuid"> + delete from file_sources where file_uuid=#{fileUuid} + </delete> + + <delete id="deleteOldClosedIssueChanges" parameterType="map"> + delete from issue_changes ic + where exists ( + select * from issues i + where i.project_uuid=#{projectUuid} and i.kee=ic.issue_key + <choose> + <when test="toDate == null"> + and i.issue_close_date is not null + </when> + <otherwise> + and i.issue_close_date < #{toDate} + </otherwise> + </choose> + ) + </delete> + + <!-- Mssql --> + <delete id="deleteOldClosedIssueChanges" databaseId="mssql" parameterType="map"> + delete issue_changes from issue_changes + inner join issues on issue_changes.issue_key=issues.kee + where issues.project_uuid=#{projectUuid} + <choose> + <when test="toDate == null"> + and issues.issue_close_date is not null + </when> + <otherwise> + and issues.issue_close_date < #{toDate} + </otherwise> + </choose> + </delete> + + <!-- Mysql --> + <delete id="deleteOldClosedIssueChanges" databaseId="mysql" parameterType="map"> + delete ic + from issue_changes as ic, issues as i + where i.project_uuid=#{projectUuid} + and ic.issue_key=i.kee + <choose> + <when test="toDate == null"> + and i.issue_close_date is not null + </when> + <otherwise> + and i.issue_close_date < #{toDate} + </otherwise> + </choose> + </delete> + + <delete id="deleteOldClosedIssues" parameterType="map"> + delete from issues + where project_uuid=#{projectUuid} + <choose> + <when test="toDate == null"> + and issue_close_date is not null + </when> + <otherwise> + and issue_close_date < #{toDate} + </otherwise> + </choose> + </delete> + +</mapper> + diff --git a/sonar-db/src/main/resources/org/sonar/db/qualitygate/ProjectQgateAssociationMapper.xml b/sonar-db/src/main/resources/org/sonar/db/qualitygate/ProjectQgateAssociationMapper.xml new file mode 100644 index 00000000000..bbcf7b52121 --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/qualitygate/ProjectQgateAssociationMapper.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.qualitygate.ProjectQgateAssociationMapper"> + + <select id="selectProjects" parameterType="map" resultType="ProjectQgateAssociation"> + SELECT proj.id as id, proj.name as name, prop.text_value as gateId + FROM projects proj + <if test="query.projectSearch() != null"> + JOIN resource_index ind ON ind.root_project_id=proj.id + </if> + LEFT JOIN properties prop ON prop.resource_id=proj.id AND prop.prop_key='sonar.qualitygate' AND prop.text_value LIKE + #{gateId} + <where> + <choose> + <when test="query.membership() == 'selected'"> + AND prop.text_value IS NOT NULL + </when> + <when test="query.membership() == 'deselected'"> + AND prop.text_value IS NULL + </when> + </choose> + <if test="query.projectSearch() != null"> + AND ind.kee LIKE #{query.projectSearchSql} + </if> + AND proj.qualifier='TRK' + AND proj.scope='PRJ' + <if test="query.projectSearch() != null"> + AND ind.qualifier='TRK' + </if> + </where> + ORDER BY proj.name + </select> + +</mapper> diff --git a/sonar-db/src/main/resources/org/sonar/db/qualitygate/QualityGateConditionMapper.xml b/sonar-db/src/main/resources/org/sonar/db/qualitygate/QualityGateConditionMapper.xml new file mode 100644 index 00000000000..0923db5ae60 --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/qualitygate/QualityGateConditionMapper.xml @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.qualitygate.QualityGateConditionMapper"> + + <insert id="insert" parameterType="QualityGateCondition" keyColumn="id" useGeneratedKeys="true" keyProperty="id"> + insert into quality_gate_conditions (qgate_id, metric_id, operator, value_error, value_warning, period, created_at, + updated_at) + values (#{qualityGateId}, #{metricId}, #{operator}, #{errorThreshold}, #{warningThreshold}, #{period}, #{createdAt}, + #{updatedAt}) + </insert> + + <sql id="conditionColumns"> + id, qgate_id as qualityGateId, metric_id as metricId, operator, value_warning as warningThreshold, value_error as + errorThreshold, period, + created_at as createdAt, updated_at as updatedAt + </sql> + + <select id="selectForQualityGate" resultType="QualityGateCondition" parameterType="long"> + select + <include refid="conditionColumns"/> + from quality_gate_conditions where qgate_id=#{qGateId} + order by id asc + </select> + + <select id="selectById" parameterType="long" resultType="QualityGateCondition"> + select + <include refid="conditionColumns"/> + from quality_gate_conditions where id=#{id} + </select> + + <update id="delete" parameterType="long"> + delete from quality_gate_conditions where id=#{id} + </update> + + <update id="update" parameterType="QualityGateCondition"> + update quality_gate_conditions set + metric_id=#{metricId}, + operator=#{operator}, + value_warning=#{warningThreshold}, + value_error=#{errorThreshold}, + period=#{period}, + updated_at=#{updatedAt} + where id=#{id} + </update> + + <delete id="deleteConditionsWithInvalidMetrics"> + delete from quality_gate_conditions + where metric_id not in (select id from metrics where enabled=${_true}) + </delete> + +</mapper> + diff --git a/sonar-db/src/main/resources/org/sonar/db/qualitygate/QualityGateMapper.xml b/sonar-db/src/main/resources/org/sonar/db/qualitygate/QualityGateMapper.xml new file mode 100644 index 00000000000..64d2e58efb4 --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/qualitygate/QualityGateMapper.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.qualitygate.QualityGateMapper"> + + <insert id="insert" parameterType="QualityGate" keyColumn="id" useGeneratedKeys="true" keyProperty="id"> + insert into quality_gates (name, created_at, updated_at) + values (#{name}, #{createdAt}, #{updatedAt}) + </insert> + + <sql id="gateColumns"> + id, name, created_at as createdAt, updated_at as updatedAt + </sql> + + <select id="selectAll" resultType="QualityGate"> + select + <include refid="gateColumns"/> + from quality_gates + order by name asc + </select> + + <select id="selectByName" parameterType="String" resultType="QualityGate"> + select + <include refid="gateColumns"/> + from quality_gates + where name=#{name} + </select> + + <select id="selectById" parameterType="long" resultType="QualityGate"> + select + <include refid="gateColumns"/> + from quality_gates + where id=#{id} + </select> + + <update id="delete" parameterType="long"> + delete from quality_gates where id=#{id} + </update> + + <update id="update" parameterType="QualityGate"> + update quality_gates set + name=#{name}, + updated_at=#{updatedAt} + where id=#{id} + </update> + +</mapper> + diff --git a/sonar-db/src/main/resources/org/sonar/db/qualityprofile/ActiveRuleMapper.xml b/sonar-db/src/main/resources/org/sonar/db/qualityprofile/ActiveRuleMapper.xml new file mode 100644 index 00000000000..23ac091ce8a --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/qualityprofile/ActiveRuleMapper.xml @@ -0,0 +1,208 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.qualityprofile.ActiveRuleMapper"> + + <sql id="activeRuleKeyColumns"> + a.id, + a.profile_id as "profileId", + a.rule_id as "ruleId", + a.failure_level as "severity", + a.inheritance as "inheritance", + r.plugin_rule_key as "rulefield", + r.plugin_name as "repository", + qp.kee as "profileKey", + a.created_at as "createdAt", + a.updated_at as "updatedAt" + </sql> + + <sql id="activeRuleKeyJoin"> + LEFT JOIN rules_profiles qp ON qp.id=a.profile_id + LEFT JOIN rules r ON r.id = a.rule_id + </sql> + + + <sql id="activeRuleColumns"> + a.id, + a.profile_id as profileId, + a.rule_id as ruleId, + a.failure_level as severity, + a.inheritance as inheritance, + active_rule_parent.id as parentId, + a.created_at as "createdAt", + a.updated_at as "updatedAt" + </sql> + + <sql id="activeRuleJoin"> + LEFT JOIN rules_profiles qp ON qp.id=a.profile_id + LEFT JOIN rules_profiles profile_parent ON profile_parent.kee=qp.parent_kee + LEFT JOIN active_rules active_rule_parent ON active_rule_parent.profile_id=profile_parent.id AND + a.rule_id=active_rule_parent.rule_id + </sql> + + <select id="selectAfterDate" parameterType="Date" resultType="ActiveRule" + fetchSize="${_scrollFetchSize}" resultSetType="FORWARD_ONLY"> + select + <include refid="activeRuleKeyColumns"/> + from active_rules a + <include refid="activeRuleKeyJoin"/> + <where> + <if test="date != null"> + a.updated_at IS NULL or a.updated_at >= #{date} + </if> + </where> + </select> + + <insert id="insert" parameterType="ActiveRule" keyColumn="id" useGeneratedKeys="true" keyProperty="id"> + INSERT INTO active_rules (profile_id, rule_id, failure_level, inheritance, created_at, updated_at) + VALUES (#{profileId}, #{ruleId}, #{severity}, #{inheritance}, #{createdAt}, #{updatedAt}) + </insert> + + <update id="update" parameterType="ActiveRule"> + UPDATE active_rules SET + profile_id=#{profileId}, + rule_id=#{ruleId}, + failure_level=#{severity}, + inheritance=#{inheritance}, + updated_at=#{updatedAt} + WHERE id=#{id} + </update> + + <update id="delete" parameterType="int"> + DELETE FROM active_rules WHERE id=#{id} + </update> + + <select id="selectByIds" parameterType="map" resultType="ActiveRule"> + select + <include refid="activeRuleColumns"/> + from active_rules a + <include refid="activeRuleJoin"/> + <where> + (<foreach collection="list" item="id" open="(" separator=" or " close=")"> + a.id=#{id} + </foreach>) + </where> + </select> + + <select id="selectById" parameterType="int" resultType="ActiveRule"> + SELECT + <include refid="activeRuleColumns"/> + FROM active_rules a + <include refid="activeRuleJoin"/> + WHERE a.id=#{id} + </select> + + + <select id="selectByKey" parameterType="map" resultType="ActiveRule"> + SELECT + <include refid="activeRuleKeyColumns"/> + FROM active_rules a + <include refid="activeRuleKeyJoin"/> + WHERE + qp.kee = #{profileKey} + AND r.plugin_rule_key = #{rule} + AND r.plugin_name = #{repository} + </select> + + <select id="selectByProfileKey" parameterType="string" resultType="ActiveRule"> + SELECT + <include refid="activeRuleKeyColumns"/> + FROM active_rules a + <include refid="activeRuleKeyJoin"/> + where qp.kee=#{id} + </select> + + <select id="selectByRuleId" parameterType="Integer" resultType="ActiveRule"> + SELECT + <include refid="activeRuleKeyColumns"/> + FROM active_rules a + <include refid="activeRuleKeyJoin"/> + WHERE a.rule_id=#{ruleId} + </select> + + <select id="selectAll" parameterType="map" resultType="ActiveRule"> + select + <include refid="activeRuleColumns"/> + from active_rules a + <include refid="activeRuleJoin"/> + </select> + + <!-- Parameters --> + + <sql id="activeRuleParamColumns"> + p.id, + p.active_rule_id as activeRuleId, + p.rules_parameter_id as rulesParameterId, + p.rules_parameter_key as kee, + p.value as value + </sql> + + <insert id="insertParameter" parameterType="ActiveRuleParam" keyColumn="id" useGeneratedKeys="true" keyProperty="id"> + INSERT INTO active_rule_parameters (active_rule_id, rules_parameter_id, rules_parameter_key, value) + VALUES (#{activeRuleId}, #{rulesParameterId}, #{key}, #{value}) + </insert> + + <update id="updateParameter" parameterType="ActiveRuleParam"> + UPDATE active_rule_parameters SET + active_rule_id=#{activeRuleId}, + rules_parameter_id=#{rulesParameterId}, + rules_parameter_key=#{key}, + value=#{value} + WHERE id=#{id} + </update> + + <update id="deleteParameters" parameterType="int"> + DELETE FROM active_rule_parameters WHERE active_rule_id=#{id} + </update> + + <update id="deleteParameter" parameterType="int"> + DELETE FROM active_rule_parameters WHERE id=#{id} + </update> + + <select id="selectParamsByActiveRuleId" parameterType="Integer" resultType="ActiveRuleParam"> + select + <include refid="activeRuleParamColumns"/> + from active_rule_parameters p + <where> + p.active_rule_id=#{id} + </where> + </select> + + <select id="selectParamsByActiveRuleIds" parameterType="map" resultType="ActiveRuleParam"> + select + <include refid="activeRuleParamColumns"/> + from active_rule_parameters p + <where> + (<foreach collection="list" item="id" open="(" separator=" or " close=")"> + p.active_rule_id=#{id} + </foreach>) + </where> + </select> + + <select id="selectParamByActiveRuleAndKey" parameterType="map" resultType="ActiveRuleParam"> + SELECT + <include refid="activeRuleParamColumns"/> + FROM active_rule_parameters p + <where> + AND p.active_rule_id=#{activeRuleId} + AND p.rules_parameter_key=#{key} + </where> + </select> + + <select id="selectParamsByProfileKey" parameterType="string" resultType="ActiveRuleParam"> + select + <include refid="activeRuleParamColumns"/> + from active_rule_parameters p + inner join active_rules ar on ar.id=p.active_rule_id + inner join rules_profiles rp on rp.id=ar.profile_id + where rp.kee=#{id} + </select> + + <select id="selectAllParams" resultType="ActiveRuleParam"> + select + <include refid="activeRuleParamColumns"/> + from active_rule_parameters p + </select> + +</mapper> + diff --git a/sonar-db/src/main/resources/org/sonar/db/qualityprofile/QualityProfileMapper.xml b/sonar-db/src/main/resources/org/sonar/db/qualityprofile/QualityProfileMapper.xml new file mode 100644 index 00000000000..873a983c4cb --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/qualityprofile/QualityProfileMapper.xml @@ -0,0 +1,209 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.qualityprofile.QualityProfileMapper"> + + <sql id="profilesColumns"> + p.id as id, + p.kee as kee, + p.name as name, + p.language as language, + p.parent_kee as parentKee, + p.is_default as isDefault, + p.created_at as createdAt, + p.updated_at as updatedAt, + p.rules_updated_at as rulesUpdatedAt + </sql> + + <insert id="insert" parameterType="QualityProfile" keyColumn="id" useGeneratedKeys="true" keyProperty="id"> + INSERT INTO rules_profiles (kee, parent_kee, name, language, is_default, created_at, updated_at, rules_updated_at) + VALUES (#{kee}, #{parentKee}, #{name}, #{language}, #{isDefault}, #{createdAt}, #{updatedAt}, #{rulesUpdatedAt,}) + </insert> + + <update id="update" parameterType="QualityProfile"> + UPDATE rules_profiles SET + name=#{name}, + language=#{language}, + is_default=#{isDefault}, + parent_kee=#{parentKee}, + updated_at=#{updatedAt}, + rules_updated_at=#{rulesUpdatedAt} + WHERE id=#{id} + </update> + + <update id="delete" parameterType="int"> + DELETE FROM rules_profiles WHERE id=#{id} + </update> + + <select id="selectAll" parameterType="map" resultType="QualityProfile"> + SELECT + <include refid="profilesColumns"/> + FROM rules_profiles p + ORDER BY p.name, p.language + </select> + + <select id="selectByNameAndLanguage" parameterType="map" resultType="QualityProfile"> + SELECT + <include refid="profilesColumns"/> + FROM rules_profiles p + WHERE p.name=#{name} AND p.language=#{language} + </select> + + <select id="selectByKey" parameterType="string" resultType="QualityProfile"> + SELECT + <include refid="profilesColumns"/> + FROM rules_profiles p + WHERE p.kee=#{id} + </select> + + <select id="selectByLanguage" parameterType="String" resultType="QualityProfile"> + SELECT + <include refid="profilesColumns"/> + FROM rules_profiles p + WHERE p.language=#{language} + ORDER BY p.name + </select> + + <select id="selectById" parameterType="Integer" resultType="QualityProfile"> + SELECT + <include refid="profilesColumns"/> + FROM rules_profiles p + WHERE p.id=#{id} + </select> + + <select id="selectParent" parameterType="string" resultType="QualityProfile"> + SELECT + <include refid="profilesColumns"/> + FROM rules_profiles p + INNER JOIN rules_profiles child ON child.parent_kee=p.kee AND child.kee=#{id} + </select> + + <select id="selectParentById" parameterType="int" resultType="QualityProfile"> + SELECT + <include refid="profilesColumns"/> + FROM rules_profiles p + INNER JOIN rules_profiles child ON child.parent_kee=p.kee and child.id=#{id} + </select> + + <select id="selectChildren" parameterType="string" resultType="QualityProfile"> + SELECT + <include refid="profilesColumns"/> + FROM rules_profiles p + WHERE p.parent_kee=#{id} + ORDER BY p.name + </select> + + <select id="selectDefaultProfile" parameterType="map" resultType="QualityProfile"> + SELECT + <include refid="profilesColumns"/> + FROM rules_profiles p + WHERE p.is_default=${_true} + AND p.language=#{language} + </select> + + <select id="selectProjects" resultType="Component"> + SELECT projects.id as id, projects.name as name, projects.kee as kee, projects.uuid as uuid + FROM projects projects + JOIN project_qprofiles pp ON pp.project_uuid = projects.uuid + JOIN rules_profiles prof ON pp.profile_key = prof.kee + <where> + AND prof.name = #{profileName} + AND prof.language = #{language} + </where> + </select> + + <select id="selectSelectedProjects" resultType="org.sonar.db.qualityprofile.ProjectQprofileAssociationDto"> + SELECT pp.id as id, pj.id as projectId, pj.uuid as projectUuid, pj.name as projectName, pp.profile_key as profileKey + FROM projects pj + JOIN project_qprofiles pp ON pp.project_uuid = pj.uuid + AND pp.profile_key = #{profileKey} + <where> + AND pj.scope='PRJ' AND pj.qualifier='TRK' + AND UPPER(pj.name) LIKE #{nameQuery} + </where> + ORDER BY pj.name ASC + </select> + + <select id="selectDeselectedProjects" resultType="org.sonar.db.qualityprofile.ProjectQprofileAssociationDto"> + SELECT pp.id as id, pj.id as projectId, pj.uuid as projectUuid, pj.name as projectName, pp.profile_key as profileKey + FROM projects pj + LEFT JOIN project_qprofiles pp ON pp.project_uuid = pj.uuid + AND pp.profile_key = #{profileKey} + <where> + AND pj.scope='PRJ' AND pj.qualifier='TRK' + AND UPPER(pj.name) LIKE #{nameQuery} + AND pp.profile_key IS NULL + </where> + ORDER BY pj.name ASC + </select> + + <select id="selectProjectAssociations" resultType="org.sonar.db.qualityprofile.ProjectQprofileAssociationDto"> + SELECT pp.id as id, pj.id as projectId, pj.uuid as projectUuid, pj.name as projectName, pp.profile_key as profileKey + FROM projects pj + LEFT JOIN project_qprofiles pp ON pp.project_uuid = pj.uuid + AND pp.profile_key = #{profileKey} + <where> + AND pj.scope='PRJ' AND pj.qualifier='TRK' + AND UPPER(pj.name) LIKE #{nameQuery} + </where> + ORDER BY pj.name ASC + </select> + + <select id="countProjects" parameterType="Integer" resultType="Integer"> + SELECT count(projects.id) + FROM projects projects + JOIN project_qprofiles pp ON pp.project_uuid=projects.uuid + JOIN rules_profiles prof ON pp.profile_key=prof.kee + <where> + AND prof.language=#{language} + AND prof.name=#{profileName} + </where> + </select> + + <select id="countProjectsByProfile" resultType="org.sonar.db.qualityprofile.QualityProfileProjectCount"> + SELECT pp.profile_key as profileKey, count(projects.id) as projectCount + FROM projects projects + INNER JOIN project_qprofiles pp ON pp.project_uuid=projects.uuid + INNER JOIN rules_profiles prof ON pp.profile_key=prof.kee + WHERE projects.enabled=${_true} + GROUP BY pp.profile_key + </select> + + <select id="selectByProjectIdAndLanguage" parameterType="map" resultType="QualityProfile"> + SELECT + <include refid="profilesColumns"/> + FROM rules_profiles p + JOIN project_qprofiles pp ON pp.profile_key=p.kee + JOIN projects project ON pp.project_uuid=project.uuid + AND project.id=#{projectId} + WHERE p.language=#{language} + </select> + + <select id="selectByProjectAndLanguage" parameterType="map" resultType="QualityProfile"> + SELECT + <include refid="profilesColumns"/> + FROM rules_profiles p + JOIN project_qprofiles pp ON pp.profile_key=p.kee + JOIN projects project ON pp.project_uuid=project.uuid + AND project.kee=#{projectKey} + WHERE p.language=#{language} + </select> + + <insert id="insertProjectProfileAssociation" keyColumn="id" useGeneratedKeys="true"> + INSERT INTO project_qprofiles (project_uuid, profile_key) VALUES (#{projectUuid}, #{profileKey}) + </insert> + + <update id="updateProjectProfileAssociation"> + UPDATE project_qprofiles SET profile_key=#{profileKey} WHERE project_uuid=#{projectUuid} + </update> + + <update id="deleteProjectProfileAssociation"> + DELETE FROM project_qprofiles WHERE project_uuid=#{projectUuid} AND profile_key=#{profileKey} + </update> + + <update id="deleteAllProjectProfileAssociation"> + DELETE FROM project_qprofiles WHERE profile_key=#{profileKey} + </update> + +</mapper> + diff --git a/sonar-db/src/main/resources/org/sonar/db/rule/RuleMapper.xml b/sonar-db/src/main/resources/org/sonar/db/rule/RuleMapper.xml new file mode 100644 index 00000000000..fd93ba7b0a5 --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/rule/RuleMapper.xml @@ -0,0 +1,219 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.rule.RuleMapper"> + + <sql id="selectColumns"> + r.id, + r.plugin_rule_key as "ruleKey", + r.plugin_name as "repositoryKey", + r.description, + r.description_format as "descriptionFormat", + r.status, + r.name, + r.plugin_config_key as "configKey", + r.priority as "severity", + r.is_template as "isTemplate", + r.language as "language", + r.template_id as "templateId", + r.note_data as "noteData", + r.note_user_login as "noteUserLogin", + r.note_created_at as "noteCreatedAt", + r.note_updated_at as "noteUpdatedAt", + r.characteristic_id as "subCharacteristicId", + r.default_characteristic_id as "defaultSubCharacteristicId", + r.remediation_function as "remediationFunction", + r.default_remediation_function as "defaultRemediationFunction", + r.remediation_coeff as "remediationCoefficient", + r.default_remediation_coeff as "defaultRemediationCoefficient", + r.remediation_offset as "remediationOffset", + r.default_remediation_offset as "defaultRemediationOffset", + r.effort_to_fix_description as "effortToFixDescription", + r.tags as "tagsField", + r.system_tags as "systemTagsField", + r.created_at as "createdAt", + r.updated_at as "updatedAt" + </sql> + + <select id="selectAll" resultType="Rule"> + select + <include refid="selectColumns"/> + from rules r + </select> + + <select id="selectAfterDate" resultType="Rule" fetchSize="${_scrollFetchSize}" resultSetType="FORWARD_ONLY"> + select + <include refid="selectColumns"/> + from rules r + <where> + <if test="date != null"> + r.updated_at IS NULL or r.updated_at >= #{date} + </if> + </where> + </select> + + <select id="selectEnablesAndNonManual" resultType="Rule"> + select + <include refid="selectColumns"/> + from rules r + where r.status != 'REMOVED' and r.plugin_name != 'manual' + </select> + + <select id="selectById" parameterType="Integer" resultType="Rule"> + select + <include refid="selectColumns"/> + from rules r WHERE r.id=#{id} + </select> + + <select id="selectByKey" parameterType="map" resultType="Rule"> + SELECT + <include refid="selectColumns"/> + FROM rules r WHERE r.plugin_name=#{repository} AND r.plugin_rule_key=#{rule} + </select> + + <select id="selectByName" parameterType="String" resultType="Rule"> + select + <include refid="selectColumns"/> + from rules r WHERE r.name=#{name} + </select> + + <select id="selectNonManual" resultType="Rule"> + select + <include refid="selectColumns"/> + from rules r + where r.plugin_name != 'manual' + </select> + + <select id="selectBySubCharacteristicId" resultType="Rule"> + select + <include refid="selectColumns"/> + from rules r + where (r.characteristic_id=#{subCharacteristicId} or r.default_characteristic_id=#{subCharacteristicId}) + </select> + + <update id="update" parameterType="Rule"> + UPDATE rules SET + plugin_rule_key=#{ruleKey}, + plugin_name=#{repositoryKey}, + description=#{description}, + description_format=#{descriptionFormat}, + status=#{status}, + name=#{name}, + plugin_config_key=#{configKey}, + priority=#{severity}, + is_template=#{isTemplate}, + language=#{language}, + template_id=#{templateId}, + note_data=#{noteData}, + note_user_login=#{noteUserLogin}, + note_created_at=#{noteCreatedAt}, + note_updated_at=#{noteUpdatedAt}, + characteristic_id=#{subCharacteristicId}, + default_characteristic_id=#{defaultSubCharacteristicId}, + remediation_function=#{remediationFunction}, + default_remediation_function=#{defaultRemediationFunction}, + remediation_coeff=#{remediationCoefficient}, + default_remediation_coeff=#{defaultRemediationCoefficient}, + remediation_offset=#{remediationOffset}, + default_remediation_offset=#{defaultRemediationOffset}, + effort_to_fix_description=#{effortToFixDescription}, + updated_at=#{updatedAt}, + tags=#{tagsField}, + system_tags=#{systemTagsField} + WHERE id=#{id} + </update> + + <sql id="insertColumns"> + (plugin_rule_key, plugin_name, description, description_format, status, name, plugin_config_key, priority, + is_template, language, template_id, + characteristic_id, default_characteristic_id, remediation_function, default_remediation_function, + remediation_coeff, default_remediation_coeff, remediation_offset, default_remediation_offset, + effort_to_fix_description, tags, system_tags, note_data, note_user_login, note_created_at, note_updated_at, + created_at, updated_at) + </sql> + + <insert id="insert" parameterType="Rule" keyColumn="id" useGeneratedKeys="true" keyProperty="id"> + insert into rules + <include refid="insertColumns"/> + values (#{ruleKey}, #{repositoryKey}, #{description}, #{descriptionFormat}, #{status}, #{name}, #{configKey}, + #{severity}, #{isTemplate}, #{language}, #{templateId}, + #{subCharacteristicId}, #{defaultSubCharacteristicId}, #{remediationFunction}, #{defaultRemediationFunction}, + #{remediationCoefficient}, #{defaultRemediationCoefficient}, #{remediationOffset}, #{defaultRemediationOffset}, + #{effortToFixDescription}, #{tagsField}, #{systemTagsField}, #{noteData}, #{noteUserLogin}, #{noteCreatedAt}, + #{noteUpdatedAt}, #{createdAt}, #{updatedAt}) + </insert> + + <insert id="batchInsert" parameterType="Rule" useGeneratedKeys="false"> + insert into rules + <include refid="insertColumns"/> + values (#{ruleKey,jdbcType=VARCHAR}, #{repositoryKey,jdbcType=VARCHAR}, #{description,jdbcType=CLOB}, + #{descriptionFormat,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, + #{configKey,jdbcType=VARCHAR}, + #{severity,jdbcType=INTEGER}, #{isTemplate,jdbcType=BOOLEAN}, #{language,jdbcType=VARCHAR}, + #{templateId,jdbcType=INTEGER}, + #{subCharacteristicId,jdbcType=INTEGER}, #{defaultSubCharacteristicId,jdbcType=INTEGER}, + #{remediationFunction,jdbcType=VARCHAR}, #{defaultRemediationFunction,jdbcType=VARCHAR}, + #{remediationCoefficient,jdbcType=VARCHAR}, #{defaultRemediationCoefficient,jdbcType=VARCHAR}, + #{remediationOffset,jdbcType=VARCHAR}, #{defaultRemediationOffset,jdbcType=VARCHAR}, + #{effortToFixDescription}, #{tagsField}, #{systemTagsField}, #{noteData}, #{noteUserLogin}, #{noteCreatedAt}, + #{noteUpdatedAt,jdbcType=TIMESTAMP}, #{createdAt,jdbcType=TIMESTAMP}, #{updatedAt,jdbcType=TIMESTAMP}) + </insert> + + <delete id="deleteParams" parameterType="Integer"> + delete from active_rule_parameters where rules_parameter_id=#{id} + </delete> + + <sql id="paramColumns"> + p.id as "id", p.rule_id as "ruleId", p.name as "name", p.param_type as "type", p.default_value as "defaultValue", + p.description as "description" + </sql> + + <select id="selectAllParams" resultType="RuleParam"> + select + <include refid="paramColumns"/> + from rules_parameters p + </select> + + <select id="selectParamsByRuleIds" resultType="RuleParam"> + SELECT + <include refid="paramColumns"/> + FROM rules_parameters p + <where> + AND (<foreach item="id" index="index" collection="ruleIds" open="(" separator=" or " close=")"> + p.rule_id=#{id}</foreach>) + </where> + </select> + + <select id="selectParamsByRuleKey" resultType="RuleParam" parameterType="org.sonar.api.rule.RuleKey"> + SELECT + <include refid="paramColumns"/> + FROM rules_parameters p, rules r + WHERE p.rule_id=r.id + AND r.plugin_name=#{repository} AND r.plugin_rule_key=#{rule} + </select> + + <select id="selectParamByRuleAndKey" resultType="RuleParam"> + SELECT + <include refid="paramColumns"/> + FROM rules_parameters p + WHERE p.rule_id=#{ruleId} AND p.name=#{key} + </select> + + <delete id="deleteParameter" parameterType="Integer"> + delete from rules_parameters where id=#{id} + </delete> + + <insert id="insertParameter" parameterType="RuleParam" keyColumn="id" useGeneratedKeys="true" keyProperty="id"> + INSERT INTO rules_parameters (rule_id, name, param_type, default_value, description) + VALUES (#{ruleId}, #{name}, #{type}, #{defaultValue}, #{description}) + </insert> + + <update id="updateParameter" parameterType="RuleParam"> + UPDATE rules_parameters SET + param_type=#{type}, + default_value=#{defaultValue}, + description=#{description} + WHERE id=#{id} + </update> +</mapper> + diff --git a/sonar-db/src/main/resources/org/sonar/db/semaphore/SemaphoreMapper.xml b/sonar-db/src/main/resources/org/sonar/db/semaphore/SemaphoreMapper.xml new file mode 100644 index 00000000000..5d1c1028478 --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/semaphore/SemaphoreMapper.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.semaphore.SemaphoreMapper"> + + <insert id="initialize" parameterType="map" useGeneratedKeys="false"> + INSERT INTO semaphores (name, checksum, created_at, updated_at, locked_at) + VALUES (#{name}, #{checksum}, #{createdAt}, #{updatedAt}, #{lockedAt}) + </insert> + + <update id="acquire" parameterType="map"> + update semaphores + set updated_at = #{now}, locked_at = #{now} + where name=#{name} + <if test="updatedBefore != null"> + AND updated_at < #{updatedBefore} + </if> + </update> + + <delete id="release" parameterType="String"> + delete from semaphores where name=#{id} + </delete> + + <select id="selectSemaphore" parameterType="String" resultType="Semaphore"> + select s.id, s.name as name, s.locked_at as lockedAt, s.created_at as createdAt, s.updated_at as updatedAt + from semaphores s where s.name=#{name} + </select> + + <update id="update" parameterType="map"> + update semaphores + set updated_at = #{now} + where name=#{name} + </update> + +</mapper> + diff --git a/sonar-db/src/main/resources/org/sonar/db/source/FileSourceMapper.xml b/sonar-db/src/main/resources/org/sonar/db/source/FileSourceMapper.xml new file mode 100644 index 00000000000..dd6a83ed5ff --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/source/FileSourceMapper.xml @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.source.FileSourceMapper"> + + <select id="select" parameterType="map" resultType="org.sonar.db.source.FileSourceDto"> + SELECT id, project_uuid as projectUuid, file_uuid as fileUuid, created_at as createdAt, updated_at as updatedAt, + binary_data as binaryData, line_hashes as lineHashes, data_hash as dataHash, src_hash as srcHash, data_type as + dataType + FROM file_sources + WHERE file_uuid = #{fileUuid} and data_type = #{dataType} + </select> + + <select id="selectHashesForProject" parameterType="map" resultType="org.sonar.db.source.FileSourceDto"> + SELECT id, file_uuid as fileUuid, data_hash as dataHash, src_hash as srcHash, updated_at as updatedAt + FROM file_sources + WHERE project_uuid = #{projectUuid} and data_type=#{dataType} + </select> + + <insert id="insert" parameterType="org.sonar.db.source.FileSourceDto" useGeneratedKeys="false"> + INSERT INTO file_sources (project_uuid, file_uuid, created_at, updated_at, binary_data, line_hashes, data_hash, + src_hash, data_type) + VALUES (#{projectUuid,jdbcType=VARCHAR}, #{fileUuid,jdbcType=VARCHAR}, #{createdAt,jdbcType=BIGINT}, + #{updatedAt,jdbcType=BIGINT}, #{binaryData,jdbcType=BLOB}, #{lineHashes,jdbcType=CLOB}, + #{dataHash,jdbcType=VARCHAR}, #{srcHash,jdbcType=VARCHAR},#{dataType,jdbcType=VARCHAR}) + </insert> + + <update id="update" parameterType="org.sonar.db.source.FileSourceDto" useGeneratedKeys="false"> + UPDATE file_sources SET + updated_at = #{updatedAt,jdbcType=BIGINT}, + binary_data = #{binaryData,jdbcType=BLOB}, + line_hashes = #{lineHashes,jdbcType=CLOB}, + data_hash = #{dataHash,jdbcType=VARCHAR}, + src_hash = #{srcHash,jdbcType=VARCHAR} + WHERE id = #{id} + </update> + + <update id="updateDateWhenUpdatedDateIsZero" parameterType="org.sonar.db.source.FileSourceDto" + useGeneratedKeys="false"> + UPDATE file_sources SET + updated_at = #{date,jdbcType=BIGINT} + WHERE project_uuid = #{projectUuid} + AND updated_at = 0 + </update> +</mapper> + diff --git a/sonar-db/src/main/resources/org/sonar/db/source/SnapshotDataMapper.xml b/sonar-db/src/main/resources/org/sonar/db/source/SnapshotDataMapper.xml new file mode 100644 index 00000000000..022381e4df8 --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/source/SnapshotDataMapper.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.source.SnapshotDataMapper"> + + <sql id="snapshotDataColumns"> + snapshot_id AS "snapshotId", + snapshot_data AS "data", + data_type AS "dataType" + </sql> + + <select id="selectSnapshotData" parameterType="map" resultType="SnapshotData"> + SELECT + <include refid="snapshotDataColumns"/> + FROM snapshot_data + WHERE snapshot_id = #{sid} + AND data_type IN + <foreach item="dataType" index="index" collection="dataTypes" open="(" separator="," close=")">#{dataType}</foreach> + </select> + + <select id="selectSnapshotDataByComponentKey" parameterType="map" resultType="SnapshotData"> + SELECT + <include refid="snapshotDataColumns"/> + FROM snapshot_data sd + INNER JOIN projects p ON p.id=sd.resource_id and p.enabled=${_true} + WHERE p.kee = #{componentKey} + AND data_type IN + <foreach item="dataType" index="index" collection="dataTypes" open="(" separator="," close=")">#{dataType}</foreach> + </select> + + <insert id="insert" parameterType="SnapshotData" useGeneratedKeys="false"> + insert into snapshot_data + (resource_id, snapshot_id, snapshot_data, data_type, created_at, updated_at) + values ( + #{resourceId,jdbcType=INTEGER}, #{snapshotId,jdbcType=INTEGER}, #{data,jdbcType=CLOB}, #{dataType,jdbcType=VARCHAR}, + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP) + </insert> +</mapper> + diff --git a/sonar-db/src/main/resources/org/sonar/db/user/AuthorMapper.xml b/sonar-db/src/main/resources/org/sonar/db/user/AuthorMapper.xml new file mode 100644 index 00000000000..440d2d74701 --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/user/AuthorMapper.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.user.AuthorMapper"> + + <select id="selectByLogin" parameterType="string" resultType="Author"> + SELECT id, person_id AS personId, login, created_at AS createdAt, updated_at AS updatedAt + FROM authors WHERE login=#{id} + </select> + + <select id="countDeveloperLogins" parameterType="long" resultType="int"> + SELECT count(id) + FROM authors WHERE person_id=#{id} + </select> + + <insert id="insert" parameterType="Author" keyColumn="id" useGeneratedKeys="true" keyProperty="id"> + INSERT INTO authors (person_id, login, created_at, updated_at) + VALUES (#{personId}, #{login}, + #{createdAt}, #{updatedAt}) + </insert> + + <select id="selectScmAccountsByDeveloperUuids" parameterType="String" resultType="String"> + SELECT a.login + FROM authors a + INNER JOIN projects p ON p.id=a.person_id + <where> + and p.uuid in + <foreach collection="uuids" open="(" close=")" item="uuid" separator=","> + #{uuid} + </foreach> + </where> + </select> +</mapper> diff --git a/sonar-db/src/main/resources/org/sonar/db/user/AuthorizationMapper.xml b/sonar-db/src/main/resources/org/sonar/db/user/AuthorizationMapper.xml new file mode 100644 index 00000000000..f33a7ae0640 --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/user/AuthorizationMapper.xml @@ -0,0 +1,210 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.user.AuthorizationMapper"> + + <select id="keepAuthorizedComponentKeysForUser" parameterType="map" resultType="string"> + SELECT p.kee + FROM group_roles gr, projects p + WHERE + gr.role=#{role} + and (gr.group_id is null or gr.group_id in (select gu.group_id from groups_users gu where gu.user_id=#{userId})) + and (gr.resource_id = p.root_id or gr.resource_id = p.id) and + <foreach collection="componentKeys" open="(" close=")" item="element" index="index" separator=" or "> + p.kee=#{element} + </foreach> + UNION + SELECT p.kee + FROM user_roles ur + INNER JOIN projects p on p.id = ur.resource_id + WHERE + ur.role=#{role} + and ur.user_id=#{userId} and + <foreach collection="componentKeys" open="(" close=")" item="element" index="index" separator=" or "> + p.kee=#{element} + </foreach> + </select> + + <select id="keepAuthorizedComponentKeysForAnonymous" parameterType="map" resultType="string"> + SELECT p.kee + FROM group_roles gr, projects p + WHERE + gr.role=#{role} + and gr.group_id is null + and (gr.resource_id = p.root_id or gr.resource_id = p.id) and + <foreach collection="componentKeys" open="(" close=")" item="element" index="index" separator=" or "> + p.kee=#{element} + </foreach> + </select> + + <select id="keepAuthorizedProjectIdsForUser" parameterType="map" resultType="long"> + SELECT gr.resource_id + FROM group_roles gr + WHERE + gr.role=#{role} + and (gr.group_id is null or gr.group_id in (select gu.group_id from groups_users gu where gu.user_id=#{userId})) + and + <foreach collection="componentIds" open="(" close=")" item="element" index="index" separator=" or "> + gr.resource_id=#{element} + </foreach> + UNION + SELECT p.id + FROM user_roles ur + INNER JOIN projects p on p.id = ur.resource_id + WHERE + ur.role=#{role} + and ur.user_id=#{userId} and + <foreach collection="componentIds" open="(" close=")" item="element" index="index" separator=" or "> + p.id=#{element} + </foreach> + </select> + + <select id="keepAuthorizedProjectIdsForAnonymous" parameterType="map" resultType="long"> + SELECT gr.resource_id + FROM group_roles gr + WHERE + gr.role=#{role} + and gr.group_id is null + and + <foreach collection="componentIds" open="(" close=")" item="element" index="index" separator=" or "> + gr.resource_id=#{element} + </foreach> + </select> + + <select id="selectAuthorizedRootProjectsKeys" parameterType="map" resultType="string"> + <include refid="selectAuthorizedRootProjectsKeysQuery"/> + </select> + + <sql id="selectAuthorizedRootProjectsKeysQuery"> + <choose> + <when test="userId != null"> + SELECT p.kee as root_project_kee + FROM group_roles gr + INNER JOIN projects p on p.id = gr.resource_id AND p.module_uuid IS NULL + <where> + and gr.role=#{role} + and (gr.group_id is null or gr.group_id in (select gu.group_id from groups_users gu where + gu.user_id=#{userId})) + </where> + UNION + SELECT p.kee as root_project_kee + FROM user_roles ur + INNER JOIN projects p on p.id = ur.resource_id AND p.module_uuid IS NULL + <where> + and ur.role=#{role} + and ur.user_id = #{userId} + </where> + </when> + <otherwise> + SELECT p.kee as root_project_kee + FROM group_roles gr + INNER JOIN projects p on p.id = gr.resource_id AND p.module_uuid IS NULL + <where> + and gr.role=#{role} + and gr.group_id is null + </where> + </otherwise> + </choose> + </sql> + + <select id="selectAuthorizedRootProjectsUuids" parameterType="map" resultType="string"> + <choose> + <when test="userId != null"> + SELECT p.uuid as root_project_uuid + FROM group_roles gr + INNER JOIN projects p on p.id = gr.resource_id AND p.module_uuid IS NULL + <where> + and gr.role=#{role} + and (gr.group_id is null or gr.group_id in (select gu.group_id from groups_users gu where + gu.user_id=#{userId})) + </where> + UNION + SELECT p.uuid as root_project_uuid + FROM user_roles ur + INNER JOIN projects p on p.id = ur.resource_id AND p.module_uuid IS NULL + <where> + and ur.role=#{role} + and ur.user_id = #{userId} + </where> + </when> + <otherwise> + SELECT p.uuid as root_project_uuid + FROM group_roles gr + INNER JOIN projects p on p.id = gr.resource_id AND p.module_uuid IS NULL + <where> + and gr.role=#{role} + and gr.group_id is null + </where> + </otherwise> + </choose> + </select> + + <!-- same as selectAuthorizedRootProjectsKeysQuery but returns ids instead of keys --> + <sql id="selectAuthorizedRootProjectIdsQuery"> + <choose> + <when test="userId != null"> + SELECT p.id as root_project_id + FROM group_roles gr + INNER JOIN projects p on p.id = gr.resource_id AND p.module_uuid IS NULL + <where> + and gr.role=#{role} + and (gr.group_id is null or gr.group_id in (select gu.group_id from groups_users gu where + gu.user_id=#{userId})) + </where> + UNION + SELECT p.id as root_project_id + FROM user_roles ur + INNER JOIN projects p on p.id = ur.resource_id AND p.module_uuid IS NULL + <where> + and ur.role=#{role} + and ur.user_id = #{userId} + </where> + </when> + <otherwise> + SELECT p.id as root_project_id + FROM group_roles gr + INNER JOIN projects p on p.id = gr.resource_id AND p.module_uuid IS NULL + <where> + and gr.role=#{role} + and gr.group_id is null + </where> + </otherwise> + </choose> + </sql> + + <select id="selectGlobalPermissions" parameterType="map" resultType="String"> + <choose> + <when test="userLogin != null"> + SELECT gr.role + FROM group_roles gr + INNER JOIN groups_users gu on gu.group_id=gr.group_id + INNER JOIN users u on u.id=gu.user_id + <where> + and u.login=#{userLogin} + and gr.resource_id is null + </where> + UNION + SELECT gr.role + FROM group_roles gr + WHERE gr.group_id IS NULL AND gr.resource_id IS NULL + UNION + SELECT ur.role + FROM user_roles ur + INNER JOIN users u on u.id=ur.user_id + <where> + and u.login=#{userLogin} + and ur.resource_id is null + </where> + </when> + <otherwise> + SELECT gr.role + FROM group_roles gr + <where> + and gr.resource_id is null + and gr.group_id is null + </where> + </otherwise> + </choose> + </select> + +</mapper> diff --git a/sonar-db/src/main/resources/org/sonar/db/user/GroupMapper.xml b/sonar-db/src/main/resources/org/sonar/db/user/GroupMapper.xml new file mode 100644 index 00000000000..0991bcffc0b --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/user/GroupMapper.xml @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.user.GroupMapper"> + + <sql id="groupColumns"> + g.id as id, + g.name as name, + g.description as description, + g.created_at as "createdAt", + g.updated_at as "updatedAt" + </sql> + + <select id="selectByKey" parameterType="string" resultType="Group"> + SELECT + <include refid="groupColumns"/> + FROM groups g + <where> + g.name=#{id} + </where> + </select> + + <select id="selectById" parameterType="long" resultType="Group"> + SELECT + <include refid="groupColumns"/> + FROM groups g + <where> + g.id=#{id} + </where> + </select> + + <delete id="deleteById" parameterType="long"> + DELETE FROM groups + <where> + id=#{id} + </where> + </delete> + + <select id="selectByUserLogin" parameterType="string" resultType="Group"> + SELECT + <include refid="groupColumns"/> + FROM groups g + INNER JOIN groups_users gu on gu.group_id=g.id + INNER JOIN users u on u.id=gu.user_id + <where> + u.login=#{login} + </where> + </select> + + <insert id="insert" parameterType="Group" keyColumn="id" useGeneratedKeys="true" keyProperty="id"> + INSERT INTO groups (name, description, created_at, updated_at) + VALUES (#{name}, #{description}, #{createdAt}, #{updatedAt}) + </insert> + + <update id="update" parameterType="Group"> + UPDATE groups SET + name=#{name}, + description=#{description}, + updated_at=#{updatedAt} + WHERE id=#{id} + </update> + + <select id="selectByQuery" parameterType="map" resultType="Group"> + SELECT + <include refid="groupColumns"/> + FROM groups g + WHERE UPPER(g.name) LIKE #{query} + ORDER BY UPPER(g.name) + </select> + + <select id="countByQuery" parameterType="map" resultType="int"> + SELECT count(g.id) + FROM groups g + WHERE UPPER(g.name) LIKE #{query} + </select> +</mapper> diff --git a/sonar-db/src/main/resources/org/sonar/db/user/GroupMembershipMapper.xml b/sonar-db/src/main/resources/org/sonar/db/user/GroupMembershipMapper.xml new file mode 100644 index 00000000000..36591ceea05 --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/user/GroupMembershipMapper.xml @@ -0,0 +1,92 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.user.GroupMembershipMapper"> + + <sql id="commonClauses"> + FROM groups g + LEFT JOIN groups_users gu ON gu.group_id=g.id AND gu.user_id=#{userId} + <where> + <choose> + <when test="query.membership() == 'IN'"> + AND gu.user_id IS NOT NULL + </when> + <when test="query.membership() == 'OUT'"> + AND gu.user_id IS NULL + </when> + </choose> + <if test="query.groupSearch() != null"> + AND (UPPER(g.name) LIKE #{query.groupSearchSql} ESCAPE '/') + </if> + </where> + </sql> + + <select id="selectGroups" parameterType="map" resultType="GroupMembership"> + SELECT g.id as id, g.name as name, g.description as description, gu.user_id as userId + <include refid="commonClauses"/> + ORDER BY g.name + </select> + + <select id="countGroups" parameterType="map" resultType="int"> + SELECT COUNT(g.id) + <include refid="commonClauses"/> + </select> + + <select id="countUsersByGroup" parameterType="long" resultType="org.sonar.db.user.GroupUserCount"> + SELECT g.name as groupName, count(gu.user_id) as userCount + FROM groups g + LEFT JOIN groups_users gu ON gu.group_id=g.id + <where> + g.id in + <foreach collection="groupIds" open="(" close=")" item="id" separator=","> + #{id} + </foreach> + </where> + GROUP BY g.name + </select> + + <select id="selectGroupsByLogins" parameterType="string" resultType="org.sonar.db.user.LoginGroup"> + SELECT u.login as login, g.name as groupName + FROM users u + LEFT JOIN groups_users gu ON gu.user_id=u.id + INNER JOIN groups g ON gu.group_id=g.id + <where> + u.login in + <foreach collection="logins" open="(" close=")" item="login" separator=","> + #{login} + </foreach> + </where> + </select> + + <sql id="userCommonClauses"> + FROM users u + LEFT JOIN groups_users gu ON gu.user_id=u.id AND gu.group_id=#{groupId} + <where> + <choose> + <when test="query.membership() == 'IN'"> + AND gu.group_id IS NOT NULL + </when> + <when test="query.membership() == 'OUT'"> + AND gu.group_id IS NULL + </when> + </choose> + <if test="query.memberSearch() != null"> + AND ((UPPER(u.login) LIKE #{query.memberSearchSql} ESCAPE '/') OR (UPPER(u.name) LIKE #{query.memberSearchSql} + ESCAPE '/')) + </if> + AND u.active=${_true} + </where> + </sql> + + <select id="selectMembers" parameterType="map" resultType="org.sonar.db.user.UserMembershipDto"> + SELECT u.id as id, u.login as login, u.name as name, gu.group_id as groupId + <include refid="userCommonClauses"/> + ORDER BY u.name ASC + </select> + + <select id="countMembers" parameterType="map" resultType="int"> + SELECT COUNT(u.id) + <include refid="userCommonClauses"/> + </select> + +</mapper> diff --git a/sonar-db/src/main/resources/org/sonar/db/user/RoleMapper.xml b/sonar-db/src/main/resources/org/sonar/db/user/RoleMapper.xml new file mode 100644 index 00000000000..41303206013 --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/user/RoleMapper.xml @@ -0,0 +1,118 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.user.RoleMapper"> + + <select id="selectUserPermissions" parameterType="map" resultType="String"> + SELECT ur.role + FROM user_roles ur + INNER JOIN users u ON u.id=ur.user_id AND u.active=${_true} + <where> + AND u.login = #{userLogin} + <choose> + <when test="resourceId != null"> + AND resource_id=#{resourceId} + </when> + <otherwise> + AND resource_id IS NULL + </otherwise> + </choose> + </where> + </select> + + <select id="selectGroupPermissions" parameterType="map" resultType="String"> + SELECT gr.role + FROM group_roles gr + <if test="isAnyOneGroup != true"> + INNER JOIN groups g ON g.id = gr.group_id + </if> + <where> + <choose> + <when test="isAnyOneGroup != true"> + AND g.name = #{groupName} + </when> + <otherwise> + AND gr.group_id IS NULL + </otherwise> + </choose> + <choose> + <when test="resourceId != null"> + AND resource_id=#{resourceId} + </when> + <otherwise> + AND resource_id IS NULL + </otherwise> + </choose> + </where> + </select> + + <insert id="insertGroupRole" parameterType="GroupRole" keyColumn="id" useGeneratedKeys="true" keyProperty="id"> + INSERT INTO group_roles (group_id, resource_id, role) + VALUES (#{groupId}, #{resourceId}, #{role}) + </insert> + + <insert id="insertUserRole" parameterType="UserRole" keyColumn="id" useGeneratedKeys="true" keyProperty="id"> + INSERT INTO user_roles (user_id, resource_id, role) + VALUES (#{userId}, #{resourceId}, #{role}) + </insert> + + <delete id="deleteGroupRole" parameterType="map"> + DELETE FROM group_roles + WHERE role=#{role} + AND + <choose> + <when test="resourceId != null"> + resource_id=#{resourceId} + </when> + <otherwise> + resource_id IS NULL + </otherwise> + </choose> + AND + <choose> + <when test="groupId != null"> + group_id=#{groupId} + </when> + <otherwise> + group_id IS NULL + </otherwise> + </choose> + </delete> + + <delete id="deleteUserRole" parameterType="map"> + DELETE FROM user_roles + WHERE user_id=#{userId} + AND role=#{role} + AND + <choose> + <when test="resourceId != null"> + resource_id=#{resourceId} + </when> + <otherwise> + resource_id IS NULL + </otherwise> + </choose> + </delete> + + <delete id="deleteGroupRolesByResourceId" parameterType="long"> + delete from group_roles where resource_id=#{id} + </delete> + + <delete id="deleteUserRolesByResourceId" parameterType="long"> + delete from user_roles where resource_id=#{id} + </delete> + + <select id="countResourceUserRoles" parameterType="long" resultType="int"> + SELECT count(id) + FROM user_roles WHERE resource_id=#{id} + </select> + + <select id="countResourceGroupRoles" parameterType="long" resultType="int"> + SELECT count(id) + FROM group_roles WHERE resource_id=#{id} + </select> + + <delete id="deleteGroupRolesByGroupId" parameterType="long"> + delete from group_roles where group_id=#{id} + </delete> +</mapper> diff --git a/sonar-db/src/main/resources/org/sonar/db/user/UserGroupMapper.xml b/sonar-db/src/main/resources/org/sonar/db/user/UserGroupMapper.xml new file mode 100644 index 00000000000..d2177b452c0 --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/user/UserGroupMapper.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.user.UserGroupMapper"> + + <insert id="insert" parameterType="UserGroup" useGeneratedKeys="false"> + INSERT INTO groups_users (user_id, group_id) + VALUES (#{userId}, #{groupId}) + </insert> + + <delete id="delete" parameterType="UserGroup"> + DELETE FROM groups_users + <where> + AND user_id = #{userId} + AND group_id = #{groupId} + </where> + </delete> + + <delete id="deleteMembersByGroup" parameterType="long"> + DELETE FROM groups_users + <where> + AND group_id = #{groupId} + </where> + </delete> + +</mapper> diff --git a/sonar-db/src/main/resources/org/sonar/db/user/UserMapper.xml b/sonar-db/src/main/resources/org/sonar/db/user/UserMapper.xml new file mode 100644 index 00000000000..d46d44f2eaa --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/user/UserMapper.xml @@ -0,0 +1,141 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.user.UserMapper"> + + <sql id="userColumns"> + u.id as id, + u.login as login, + u.name as name, + u.email as email, + u.active as "active", + u.scm_accounts as "scmAccounts", + u.salt as "salt", + u.crypted_password as "cryptedPassword", + u.created_at as "createdAt", + u.updated_at as "updatedAt" + </sql> + + <select id="selectByLogin" parameterType="String" resultType="User"> + SELECT + <include refid="userColumns"/> + FROM users u + WHERE u.login=#{login} + </select> + + <select id="selectNullableByScmAccountOrLoginOrEmail" parameterType="map" resultType="User"> + SELECT + <include refid="userColumns"/> + FROM users u + WHERE + u.login=#{scmAccount} + OR u.email=#{scmAccount} + OR u.scm_accounts like #{likeScmAccount} + </select> + + <select id="selectUser" parameterType="long" resultType="User"> + SELECT + <include refid="userColumns"/> + FROM users u + WHERE u.id=#{id} + </select> + + <select id="selectUserByLogin" parameterType="string" resultType="User"> + SELECT + <include refid="userColumns"/> + FROM users u + WHERE u.login=#{id} AND u.active=${_true} + </select> + + <select id="selectUsersByLogins" parameterType="map" resultType="User"> + SELECT + <include refid="userColumns"/> + FROM users u WHERE + (<foreach item="login" index="index" collection="logins" open="(" separator=" or " close=")"> + u.login=#{login} + </foreach>) + </select> + + <select id="selectUsers" parameterType="map" resultType="User"> + SELECT + <include refid="userColumns"/> + FROM users u + <where> + <if test="logins != null and logins.size() > 0"> + u.login IN + <foreach item="login" index="index" collection="logins" open="(" separator="," close=")"> + #{login} + </foreach> + </if> + <if test="includeDeactivated==false"> + AND u.active=${_true} + </if> + <if test="searchText != null"> + AND (u.login LIKE #{searchTextSql} ESCAPE '/' OR u.name LIKE #{searchTextSql} ESCAPE '/') + </if> + </where> + ORDER BY u.name + </select> + + <select id="selectGroupByName" parameterType="string" resultType="Group"> + SELECT id, name, description, created_at AS "createdAt", updated_at AS "updatedAt" + FROM groups WHERE name=#{id} + </select> + + <delete id="removeUserFromGroups" parameterType="long"> + DELETE FROM groups_users WHERE user_id=#{id} + </delete> + + <delete id="deleteUserRoles" parameterType="long"> + DELETE FROM user_roles WHERE user_id=#{id} + </delete> + + <delete id="deleteUserProperties" parameterType="long"> + DELETE FROM properties WHERE user_id=#{id} + </delete> + + <delete id="deleteUnsharedUserDashboards" parameterType="long"> + DELETE FROM dashboards WHERE user_id=#{id} and shared <> ${_true} + </delete> + + <delete id="deleteUserActiveDashboards" parameterType="long"> + DELETE FROM active_dashboards WHERE user_id=#{id} + </delete> + + <delete id="deleteUnsharedUserMeasureFilters" parameterType="long"> + DELETE FROM measure_filters WHERE user_id=#{id} and shared <> ${_true} + </delete> + + <delete id="deleteUserMeasureFilterFavourites" parameterType="long"> + DELETE FROM measure_filter_favourites WHERE user_id=#{id} + </delete> + + <delete id="deleteUnsharedUserIssueFilters" parameterType="String"> + DELETE FROM issue_filters WHERE user_login=#{id} and shared <> ${_true} + </delete> + + <delete id="deleteUserIssueFilterFavourites" parameterType="String"> + DELETE FROM issue_filter_favourites WHERE user_login=#{id} + </delete> + + <update id="deactivateUser" parameterType="long"> + UPDATE users SET active=${_false}, updated_at=#{now,jdbcType=BIGINT} WHERE id=#{id} + </update> + + <insert id="insert" parameterType="User" keyColumn="id" useGeneratedKeys="true" keyProperty="id"> + INSERT INTO users (login, name, email, active, scm_accounts, salt, crypted_password, created_at, updated_at) + VALUES (#{login,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{email,jdbcType=VARCHAR}, #{active,jdbcType=BOOLEAN}, + #{scmAccounts,jdbcType=VARCHAR}, + #{salt,jdbcType=VARCHAR}, #{cryptedPassword,jdbcType=VARCHAR}, #{createdAt,jdbcType=BIGINT}, + #{updatedAt,jdbcType=BIGINT}) + </insert> + + <insert id="update" parameterType="User" useGeneratedKeys="false"> + UPDATE users set name=#{name,jdbcType=VARCHAR}, email=#{email,jdbcType=VARCHAR}, active=#{active,jdbcType=BOOLEAN}, + scm_accounts=#{scmAccounts,jdbcType=VARCHAR}, + salt=#{salt,jdbcType=VARCHAR}, crypted_password=#{cryptedPassword,jdbcType=BIGINT}, + updated_at=#{updatedAt,jdbcType=BIGINT} + WHERE login = #{login} + </insert> + +</mapper> diff --git a/sonar-db/src/main/resources/org/sonar/db/version/SchemaMigrationMapper.xml b/sonar-db/src/main/resources/org/sonar/db/version/SchemaMigrationMapper.xml new file mode 100644 index 00000000000..cde37378a00 --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/version/SchemaMigrationMapper.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.version.SchemaMigrationMapper"> + + <select id="selectVersions" resultType="int"> + select version from schema_migrations + </select> + + <insert id="insert" parameterType="string" useGeneratedKeys="false"> + insert into schema_migrations(version) values (#{version,jdbcType=VARCHAR}) + </insert> +</mapper> + diff --git a/sonar-db/src/main/resources/org/sonar/db/version/rows-h2.sql b/sonar-db/src/main/resources/org/sonar/db/version/rows-h2.sql new file mode 100644 index 00000000000..706947ab524 --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/version/rows-h2.sql @@ -0,0 +1,348 @@ +-- All the rows inserted during Rails migrations. Rows inserted during server startup tasks (Java) are excluded : rules, profiles, metrics, ... + +INSERT INTO GROUPS(ID, NAME, DESCRIPTION, CREATED_AT, UPDATED_AT) VALUES (1, 'sonar-administrators', 'System administrators', '2011-09-26 22:27:51.0', '2011-09-26 22:27:51.0'); +INSERT INTO GROUPS(ID, NAME, DESCRIPTION, CREATED_AT, UPDATED_AT) VALUES (2, 'sonar-users', 'Any new users created will automatically join this group', '2011-09-26 22:27:51.0', '2011-09-26 22:27:51.0'); +ALTER TABLE GROUPS ALTER COLUMN ID RESTART WITH 3; + +INSERT INTO GROUP_ROLES(ID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (1, 1, null, 'admin'); +INSERT INTO GROUP_ROLES(ID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (2, 1, null, 'profileadmin'); +INSERT INTO GROUP_ROLES(ID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (3, 1, null, 'shareDashboard'); +INSERT INTO GROUP_ROLES(ID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (4, null, null, 'scan'); +INSERT INTO GROUP_ROLES(ID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (5, null, null, 'dryRunScan'); +INSERT INTO GROUP_ROLES(ID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (6, 1, null, 'provisioning'); +ALTER TABLE GROUP_ROLES ALTER COLUMN ID RESTART WITH 7; + +INSERT INTO GROUPS_USERS(USER_ID, GROUP_ID) VALUES (1, 1); +INSERT INTO GROUPS_USERS(USER_ID, GROUP_ID) VALUES (1, 2); + + +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('2'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('10'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('11'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('14'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('35'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('48'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('49'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('53'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('54'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('59'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('61'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('62'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('79'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('80'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('86'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('87'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('88'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('93'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('95'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('111'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('115'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('118'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('119'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('120'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('131'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('132'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('133'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('134'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('135'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('136'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('137'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('138'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('139'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('140'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('141'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('142'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('151'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('160'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('162'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('163'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('165'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('166'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('167'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('168'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('169'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('170'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('180'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('190'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('191'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('200'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('201'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('202'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('203'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('210'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('211'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('212'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('213'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('214'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('215'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('216'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('217'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('220'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('221'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('222'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('230'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('231'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('232'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('233'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('234'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('235'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('236'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('237'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('238'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('239'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('240'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('241'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('250'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('251'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('252'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('254'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('255'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('256'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('257'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('258'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('259'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('260'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('261'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('262'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('263'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('280'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('281'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('282'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('283'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('284'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('285'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('286'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('287'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('300'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('301'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('302'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('303'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('304'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('305'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('306'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('320'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('321'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('330'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('331'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('332'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('333'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('334'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('335'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('350'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('351'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('352'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('353'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('354'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('355'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('356'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('358'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('359'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('360'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('361'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('362'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('363'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('370'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('379'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('380'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('381'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('382'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('383'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('387'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('388'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('391'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('392'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('394'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('397'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('398'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('399'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('400'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('401'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('402'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('403'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('404'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('405'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('406'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('410'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('411'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('412'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('413'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('414'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('415'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('416'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('417'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('418'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('419'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('430'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('431'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('432'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('433'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('434'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('440'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('441'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('442'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('443'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('444'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('460'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('461'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('462'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('463'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('464'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('465'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('466'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('467'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('480'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('481'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('482'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('483'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('484'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('485'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('486'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('488'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('489'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('490'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('492'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('493'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('494'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('495'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('496'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('497'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('498'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('510'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('511'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('512'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('513'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('514'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('515'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('516'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('517'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('518'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('519'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('520'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('521'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('522'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('523'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('524'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('525'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('526'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('530'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('531'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('532'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('533'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('534'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('535'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('536'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('537'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('539'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('540'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('541'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('542'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('544'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('545'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('546'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('547'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('548'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('549'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('551'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('552'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('553'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('554'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('555'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('556'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('580'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('581'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('582'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('583'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('584'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('600'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('601'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('603'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('604'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('605'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('702'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('703'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('704'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('705'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('706'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('707'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('708'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('709'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('710'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('711'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('712'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('713'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('714'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('715'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('716'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('717'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('718'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('719'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('720'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('721'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('750'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('752'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('753'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('754'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('755'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('756'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('757'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('758'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('759'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('760'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('761'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('762'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('763'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('764'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('765'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('766'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('768'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('769'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('770'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('771'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('772'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('773'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('775'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('776'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('777'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('778'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('779'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('780'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('781'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('782'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('783'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('784'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('785'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('786'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('787'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('788'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('789'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('790'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('791'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('792'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('793'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('794'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('795'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('796'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('900'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('901'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('902'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('903'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('904'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('905'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('906'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('907'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('908'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('912'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('913'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('915'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('916'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('917'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('918'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('919'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('920'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('921'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('922'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('923'); + +INSERT INTO USERS(ID, LOGIN, NAME, EMAIL, CRYPTED_PASSWORD, SALT, CREATED_AT, UPDATED_AT, REMEMBER_TOKEN, REMEMBER_TOKEN_EXPIRES_AT) VALUES (1, 'admin', 'Administrator', '', 'a373a0e667abb2604c1fd571eb4ad47fe8cc0878', '48bc4b0d93179b5103fd3885ea9119498e9d161b', '1418215735482', '1418215735482', null, null); +ALTER TABLE USERS ALTER COLUMN ID RESTART WITH 2; diff --git a/sonar-db/src/main/resources/org/sonar/db/version/schema-h2.ddl b/sonar-db/src/main/resources/org/sonar/db/version/schema-h2.ddl new file mode 100644 index 00000000000..d0ad5236787 --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/version/schema-h2.ddl @@ -0,0 +1,686 @@ +CREATE TABLE "GROUPS_USERS" ( + "USER_ID" INTEGER, + "GROUP_ID" INTEGER +); + +CREATE TABLE "CHARACTERISTICS" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "KEE" VARCHAR(100), + "NAME" VARCHAR(100), + "PARENT_ID" INTEGER, + "ROOT_ID" INTEGER, + "RULE_ID" INTEGER, + "FUNCTION_KEY" VARCHAR(100), + "FACTOR_VALUE" DOUBLE, + "FACTOR_UNIT" VARCHAR(100), + "OFFSET_VALUE" DOUBLE, + "OFFSET_UNIT" VARCHAR(100), + "CHARACTERISTIC_ORDER" INTEGER, + "ENABLED" BOOLEAN, + "CREATED_AT" TIMESTAMP, + "UPDATED_AT" TIMESTAMP +); + +CREATE TABLE "RULES_PARAMETERS" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "RULE_ID" INTEGER NOT NULL, + "NAME" VARCHAR(128) NOT NULL, + "PARAM_TYPE" VARCHAR(512) NOT NULL, + "DEFAULT_VALUE" VARCHAR(4000), + "DESCRIPTION" VARCHAR(4000) +); + +CREATE TABLE "RULES_PROFILES" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "NAME" VARCHAR(100) NOT NULL, + "LANGUAGE" VARCHAR(20), + "KEE" VARCHAR(255) NOT NULL, + "PARENT_KEE" VARCHAR(255), + "RULES_UPDATED_AT" VARCHAR(100), + "IS_DEFAULT" BOOLEAN NOT NULL DEFAULT FALSE, + "CREATED_AT" TIMESTAMP, + "UPDATED_AT" TIMESTAMP +); + +CREATE TABLE "PROJECT_QPROFILES" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "PROJECT_UUID" VARCHAR(50) NOT NULL, + "PROFILE_KEY" VARCHAR(255) NOT NULL +); + +CREATE TABLE "WIDGETS" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "DASHBOARD_ID" INTEGER NOT NULL, + "WIDGET_KEY" VARCHAR(256) NOT NULL, + "NAME" VARCHAR(256), + "DESCRIPTION" VARCHAR(1000), + "COLUMN_INDEX" INTEGER, + "ROW_INDEX" INTEGER, + "CONFIGURED" BOOLEAN, + "CREATED_AT" TIMESTAMP, + "UPDATED_AT" TIMESTAMP, + "RESOURCE_ID" INTEGER +); + +CREATE TABLE "GROUPS" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "NAME" VARCHAR(500), + "DESCRIPTION" VARCHAR(200), + "CREATED_AT" TIMESTAMP, + "UPDATED_AT" TIMESTAMP +); + +CREATE TABLE "SNAPSHOTS" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "CREATED_AT" BIGINT, + "BUILD_DATE" BIGINT, + "PROJECT_ID" INTEGER NOT NULL, + "PARENT_SNAPSHOT_ID" INTEGER, + "STATUS" VARCHAR(4) NOT NULL DEFAULT 'U', + "PURGE_STATUS" INTEGER, + "ISLAST" BOOLEAN NOT NULL DEFAULT FALSE, + "SCOPE" VARCHAR(3), + "QUALIFIER" VARCHAR(10), + "ROOT_SNAPSHOT_ID" INTEGER, + "VERSION" VARCHAR(500), + "PATH" VARCHAR(500), + "DEPTH" INTEGER, + "ROOT_PROJECT_ID" INTEGER, + "PERIOD1_MODE" VARCHAR(100), + "PERIOD1_PARAM" VARCHAR(100), + "PERIOD1_DATE" BIGINT, + "PERIOD2_MODE" VARCHAR(100), + "PERIOD2_PARAM" VARCHAR(100), + "PERIOD2_DATE" BIGINT, + "PERIOD3_MODE" VARCHAR(100), + "PERIOD3_PARAM" VARCHAR(100), + "PERIOD3_DATE" BIGINT, + "PERIOD4_MODE" VARCHAR(100), + "PERIOD4_PARAM" VARCHAR(100), + "PERIOD4_DATE" BIGINT, + "PERIOD5_MODE" VARCHAR(100), + "PERIOD5_PARAM" VARCHAR(100), + "PERIOD5_DATE" BIGINT +); + +CREATE TABLE "SCHEMA_MIGRATIONS" ( +"VERSION" VARCHAR(256) NOT NULL +); + +CREATE TABLE "GROUP_ROLES" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "GROUP_ID" INTEGER, + "RESOURCE_ID" INTEGER, + "ROLE" VARCHAR(64) NOT NULL +); + +CREATE TABLE "RULES" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "PLUGIN_RULE_KEY" VARCHAR(200) NOT NULL, + "PLUGIN_NAME" VARCHAR(255) NOT NULL, + "DESCRIPTION" VARCHAR(16777215), + "DESCRIPTION_FORMAT" VARCHAR(20), + "PRIORITY" INTEGER, + "IS_TEMPLATE" BOOLEAN DEFAULT FALSE, + "TEMPLATE_ID" INTEGER, + "PLUGIN_CONFIG_KEY" VARCHAR(500), + "NAME" VARCHAR(200), + "STATUS" VARCHAR(40), + "LANGUAGE" VARCHAR(20), + "NOTE_DATA" CLOB(2147483647), + "NOTE_USER_LOGIN" VARCHAR(255), + "NOTE_CREATED_AT" TIMESTAMP, + "NOTE_UPDATED_AT" TIMESTAMP, + "CHARACTERISTIC_ID" INTEGER, + "DEFAULT_CHARACTERISTIC_ID" INTEGER, + "REMEDIATION_FUNCTION" VARCHAR(20), + "DEFAULT_REMEDIATION_FUNCTION" VARCHAR(20), + "REMEDIATION_COEFF" VARCHAR(20), + "DEFAULT_REMEDIATION_COEFF" VARCHAR(20), + "REMEDIATION_OFFSET" VARCHAR(20), + "DEFAULT_REMEDIATION_OFFSET" VARCHAR(20), + "EFFORT_TO_FIX_DESCRIPTION" VARCHAR(4000), + "TAGS" VARCHAR(4000), + "SYSTEM_TAGS" VARCHAR(4000), + "CREATED_AT" TIMESTAMP, + "UPDATED_AT" TIMESTAMP +); + + +CREATE TABLE "WIDGET_PROPERTIES" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "WIDGET_ID" INTEGER NOT NULL, + "KEE" VARCHAR(100), + "TEXT_VALUE" VARCHAR(4000) +); + +CREATE TABLE "EVENTS" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "NAME" VARCHAR(400), + "COMPONENT_UUID" VARCHAR(50), + "SNAPSHOT_ID" INTEGER, + "CATEGORY" VARCHAR(50), + "EVENT_DATE" BIGINT NOT NULL, + "CREATED_AT" BIGINT NOT NULL, + "DESCRIPTION" VARCHAR(4000), + "EVENT_DATA" VARCHAR(4000) +); + +CREATE TABLE "QUALITY_GATES" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "NAME" VARCHAR(100) NOT NULL, + "CREATED_AT" TIMESTAMP, + "UPDATED_AT" TIMESTAMP, +); + +CREATE TABLE "QUALITY_GATE_CONDITIONS" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "QGATE_ID" INTEGER, + "METRIC_ID" INTEGER, + "OPERATOR" VARCHAR(3), + "VALUE_ERROR" VARCHAR(64), + "VALUE_WARNING" VARCHAR(64), + "PERIOD" INTEGER, + "CREATED_AT" TIMESTAMP, + "UPDATED_AT" TIMESTAMP, +); + +CREATE TABLE "PROPERTIES" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "PROP_KEY" VARCHAR(512), + "RESOURCE_ID" INTEGER, + "TEXT_VALUE" CLOB(2147483647), + "USER_ID" INTEGER +); + +CREATE TABLE "PROJECT_LINKS" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "COMPONENT_UUID" VARCHAR(50), + "LINK_TYPE" VARCHAR(20), + "NAME" VARCHAR(128), + "HREF" VARCHAR(2048) NOT NULL +); + +CREATE TABLE "DUPLICATIONS_INDEX" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "PROJECT_SNAPSHOT_ID" INTEGER NOT NULL, + "SNAPSHOT_ID" INTEGER NOT NULL, + "HASH" VARCHAR(50) NOT NULL, + "INDEX_IN_FILE" INTEGER NOT NULL, + "START_LINE" INTEGER NOT NULL, + "END_LINE" INTEGER NOT NULL +); + +CREATE TABLE "PROJECT_MEASURES" ( + "ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "VALUE" DOUBLE, + "METRIC_ID" INTEGER NOT NULL, + "SNAPSHOT_ID" INTEGER, + "RULE_ID" INTEGER, + "RULES_CATEGORY_ID" INTEGER, + "TEXT_VALUE" VARCHAR(4000), + "TENDENCY" INTEGER, + "MEASURE_DATE" TIMESTAMP, + "PROJECT_ID" INTEGER, + "ALERT_STATUS" VARCHAR(5), + "ALERT_TEXT" VARCHAR(4000), + "URL" VARCHAR(2000), + "DESCRIPTION" VARCHAR(4000), + "RULE_PRIORITY" INTEGER, + "CHARACTERISTIC_ID" INTEGER, + "PERSON_ID" INTEGER, + "VARIATION_VALUE_1" DOUBLE, + "VARIATION_VALUE_2" DOUBLE, + "VARIATION_VALUE_3" DOUBLE, + "VARIATION_VALUE_4" DOUBLE, + "VARIATION_VALUE_5" DOUBLE, + "MEASURE_DATA" BINARY(167772150) +); + +CREATE TABLE "PROJECTS" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "KEE" VARCHAR(400), + "ROOT_ID" INTEGER, + "UUID" VARCHAR(50), + "PROJECT_UUID" VARCHAR(50), + "MODULE_UUID" VARCHAR(50), + "MODULE_UUID_PATH" VARCHAR(4000), + "NAME" VARCHAR(256), + "DESCRIPTION" VARCHAR(2000), + "ENABLED" BOOLEAN NOT NULL DEFAULT TRUE, + "SCOPE" VARCHAR(3), + "QUALIFIER" VARCHAR(10), + "DEPRECATED_KEE" VARCHAR(400), + "PATH" VARCHAR(2000), + "LANGUAGE" VARCHAR(20), + "COPY_RESOURCE_ID" INTEGER, + "LONG_NAME" VARCHAR(256), + "PERSON_ID" INTEGER, + "CREATED_AT" TIMESTAMP, + "AUTHORIZATION_UPDATED_AT" BIGINT +); + +CREATE TABLE "MANUAL_MEASURES" ( + "ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "METRIC_ID" INTEGER NOT NULL, + "COMPONENT_UUID" VARCHAR(50), + "VALUE" DOUBLE, + "TEXT_VALUE" VARCHAR(4000), + "USER_LOGIN" VARCHAR(255), + "DESCRIPTION" VARCHAR(4000), + "CREATED_AT" BIGINT, + "UPDATED_AT" BIGINT +); + +CREATE TABLE "ACTIVE_RULES" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "PROFILE_ID" INTEGER NOT NULL, + "RULE_ID" INTEGER NOT NULL, + "FAILURE_LEVEL" INTEGER NOT NULL, + "INHERITANCE" VARCHAR(10), + "CREATED_AT" TIMESTAMP, + "UPDATED_AT" TIMESTAMP +); + +CREATE TABLE "NOTIFICATIONS" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "DATA" BLOB(167772150) +); + +CREATE TABLE "USER_ROLES" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "USER_ID" INTEGER, + "RESOURCE_ID" INTEGER, + "ROLE" VARCHAR(64) NOT NULL +); + +CREATE TABLE "ACTIVE_DASHBOARDS" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "DASHBOARD_ID" INTEGER NOT NULL, + "USER_ID" INTEGER, + "ORDER_INDEX" INTEGER +); + +CREATE TABLE "ACTIVE_RULE_PARAMETERS" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "ACTIVE_RULE_ID" INTEGER NOT NULL, + "RULES_PARAMETER_ID" INTEGER NOT NULL, + "RULES_PARAMETER_KEY" VARCHAR(128), + "VALUE" VARCHAR(4000) +); + +CREATE TABLE "USERS" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "LOGIN" VARCHAR(255), + "NAME" VARCHAR(200), + "EMAIL" VARCHAR(100), + "CRYPTED_PASSWORD" VARCHAR(40), + "SALT" VARCHAR(40), + "REMEMBER_TOKEN" VARCHAR(500), + "REMEMBER_TOKEN_EXPIRES_AT" TIMESTAMP, + "ACTIVE" BOOLEAN DEFAULT TRUE, + "SCM_ACCOUNTS" VARCHAR(4000), + "CREATED_AT" BIGINT, + "UPDATED_AT" BIGINT +); + +CREATE TABLE "DASHBOARDS" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "USER_ID" INTEGER, + "NAME" VARCHAR(256), + "DESCRIPTION" VARCHAR(1000), + "COLUMN_LAYOUT" VARCHAR(20), + "SHARED" BOOLEAN, + "IS_GLOBAL" BOOLEAN, + "CREATED_AT" TIMESTAMP, + "UPDATED_AT" TIMESTAMP +); + +CREATE TABLE "METRICS" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "NAME" VARCHAR(64) NOT NULL, + "DESCRIPTION" VARCHAR(255), + "DIRECTION" INTEGER NOT NULL DEFAULT 0, + "DOMAIN" VARCHAR(64), + "SHORT_NAME" VARCHAR(64), + "QUALITATIVE" BOOLEAN NOT NULL DEFAULT FALSE, + "VAL_TYPE" VARCHAR(8), + "USER_MANAGED" BOOLEAN DEFAULT FALSE, + "ENABLED" BOOLEAN DEFAULT TRUE, + "WORST_VALUE" DOUBLE, + "BEST_VALUE" DOUBLE, + "OPTIMIZED_BEST_VALUE" BOOLEAN, + "HIDDEN" BOOLEAN, + "DELETE_HISTORICAL_DATA" BOOLEAN +); + +CREATE TABLE "LOADED_TEMPLATES" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "KEE" VARCHAR(200), + "TEMPLATE_TYPE" VARCHAR(15) +); + +CREATE TABLE "RESOURCE_INDEX" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "KEE" VARCHAR(400) NOT NULL, + "POSITION" INTEGER NOT NULL, + "NAME_SIZE" INTEGER NOT NULL, + "RESOURCE_ID" INTEGER NOT NULL, + "ROOT_PROJECT_ID" INTEGER NOT NULL, + "QUALIFIER" VARCHAR(10) NOT NULL +); + +CREATE TABLE "ACTION_PLANS" ( + "ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "KEE" VARCHAR(100), + "NAME" VARCHAR(200), + "DESCRIPTION" VARCHAR(1000), + "DEADLINE" TIMESTAMP, + "USER_LOGIN" VARCHAR(255), + "PROJECT_ID" INTEGER, + "STATUS" VARCHAR(10), + "CREATED_AT" TIMESTAMP, + "UPDATED_AT" TIMESTAMP +); + +CREATE TABLE "AUTHORS" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "PERSON_ID" INTEGER, + "LOGIN" VARCHAR(100), + "CREATED_AT" TIMESTAMP, + "UPDATED_AT" TIMESTAMP +); + +CREATE TABLE "SEMAPHORES" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "NAME" VARCHAR(4000), + "CHECKSUM" VARCHAR(200), + "CREATED_AT" BIGINT, + "UPDATED_AT" BIGINT, + "LOCKED_AT" BIGINT +); + +CREATE TABLE "MEASURE_FILTERS" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "NAME" VARCHAR(100) NOT NULL, + "SHARED" BOOLEAN NOT NULL DEFAULT FALSE, + "USER_ID" INTEGER, + "DESCRIPTION" VARCHAR(4000), + "DATA" CLOB(2147483647), + "CREATED_AT" TIMESTAMP, + "UPDATED_AT" TIMESTAMP +); + +CREATE TABLE "MEASURE_FILTER_FAVOURITES" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "USER_ID" INTEGER NOT NULL, + "MEASURE_FILTER_ID" INTEGER NOT NULL, + "CREATED_AT" TIMESTAMP +); + +CREATE TABLE "ISSUES" ( + "ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "KEE" VARCHAR(50) UNIQUE NOT NULL, + "COMPONENT_UUID" VARCHAR(50), + "PROJECT_UUID" VARCHAR(50), + "RULE_ID" INTEGER, + "SEVERITY" VARCHAR(10), + "MANUAL_SEVERITY" BOOLEAN NOT NULL, + "MESSAGE" VARCHAR(4000), + "LINE" INTEGER, + "EFFORT_TO_FIX" DOUBLE, + "TECHNICAL_DEBT" INTEGER, + "STATUS" VARCHAR(20), + "RESOLUTION" VARCHAR(20), + "CHECKSUM" VARCHAR(1000), + "REPORTER" VARCHAR(255), + "ASSIGNEE" VARCHAR(255), + "AUTHOR_LOGIN" VARCHAR(255), + "ACTION_PLAN_KEY" VARCHAR(50) NULL, + "ISSUE_ATTRIBUTES" VARCHAR(4000), + "TAGS" VARCHAR(4000), + "ISSUE_CREATION_DATE" BIGINT, + "ISSUE_CLOSE_DATE" BIGINT, + "ISSUE_UPDATE_DATE" BIGINT, + "CREATED_AT" BIGINT, + "UPDATED_AT" BIGINT +); + +CREATE TABLE "ISSUE_CHANGES" ( + "ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "KEE" VARCHAR(50), + "ISSUE_KEY" VARCHAR(50) NOT NULL, + "USER_LOGIN" VARCHAR(255), + "CHANGE_TYPE" VARCHAR(40), + "CHANGE_DATA" VARCHAR(16777215), + "CREATED_AT" BIGINT, + "UPDATED_AT" BIGINT, + "ISSUE_CHANGE_CREATION_DATE" BIGINT +); + +CREATE TABLE "ISSUE_FILTERS" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "NAME" VARCHAR(100) NOT NULL, + "SHARED" BOOLEAN NOT NULL DEFAULT FALSE, + "USER_LOGIN" VARCHAR(255), + "DESCRIPTION" VARCHAR(4000), + "DATA" CLOB(2147483647), + "CREATED_AT" TIMESTAMP, + "UPDATED_AT" TIMESTAMP +); + +CREATE TABLE "ISSUE_FILTER_FAVOURITES" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "USER_LOGIN" VARCHAR(255) NOT NULL, + "ISSUE_FILTER_ID" INTEGER NOT NULL, + "CREATED_AT" TIMESTAMP +); + +CREATE TABLE "PERMISSION_TEMPLATES" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "NAME" VARCHAR(100) NOT NULL, + "KEE" VARCHAR(100) NOT NULL, + "DESCRIPTION" VARCHAR(4000), + "KEY_PATTERN" VARCHAR(500), + "CREATED_AT" TIMESTAMP, + "UPDATED_AT" TIMESTAMP +); + +CREATE TABLE "PERM_TEMPLATES_USERS" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "USER_ID" INTEGER NOT NULL, + "TEMPLATE_ID" INTEGER NOT NULL, + "PERMISSION_REFERENCE" VARCHAR(64) NOT NULL, + "CREATED_AT" TIMESTAMP, + "UPDATED_AT" TIMESTAMP +); + +CREATE TABLE "PERM_TEMPLATES_GROUPS" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "GROUP_ID" INTEGER, + "TEMPLATE_ID" INTEGER NOT NULL, + "PERMISSION_REFERENCE" VARCHAR(64) NOT NULL, + "CREATED_AT" TIMESTAMP, + "UPDATED_AT" TIMESTAMP +); + + +CREATE TABLE "ACTIVITIES" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "LOG_KEY" VARCHAR(250), + "CREATED_AT" TIMESTAMP, + "USER_LOGIN" VARCHAR(30), + "LOG_TYPE" VARCHAR(250), + "LOG_ACTION" VARCHAR(250), + "LOG_MESSAGE" VARCHAR(250), + "DATA_FIELD" CLOB(2147483647) +); + +CREATE TABLE "ANALYSIS_REPORTS" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "PROJECT_KEY" VARCHAR(400) NOT NULL, + "PROJECT_NAME" VARCHAR(256) NULL, + "REPORT_STATUS" VARCHAR(20) NOT NULL, + "UUID" VARCHAR(50) NOT NULL, + "CREATED_AT" BIGINT NOT NULL, + "UPDATED_AT" BIGINT NOT NULL, + "STARTED_AT" BIGINT, + "FINISHED_AT" BIGINT +); + +CREATE TABLE "FILE_SOURCES" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "PROJECT_UUID" VARCHAR(50) NOT NULL, + "FILE_UUID" VARCHAR(50) NOT NULL, + "LINE_HASHES" CLOB(2147483647), + "BINARY_DATA" BLOB(167772150), + "DATA_TYPE" VARCHAR(20), + "DATA_HASH" VARCHAR(50), + "SRC_HASH" VARCHAR(50), + "CREATED_AT" BIGINT NOT NULL, + "UPDATED_AT" BIGINT NOT NULL +); + +-- ---------------------------------------------- +-- DDL Statements for indexes +-- ---------------------------------------------- + +CREATE UNIQUE INDEX "LOG_KEY_INDEX" ON "ACTIVITIES" ("LOG_KEY"); + +CREATE INDEX "GROUP_ROLES_RESOURCE" ON "GROUP_ROLES" ("RESOURCE_ID"); + +CREATE INDEX "GROUP_ROLES_GROUP" ON "GROUP_ROLES" ("GROUP_ID"); + +CREATE INDEX "USER_ROLES_RESOURCE" ON "USER_ROLES" ("RESOURCE_ID"); + +CREATE INDEX "USER_ROLES_USER" ON "USER_ROLES" ("USER_ID"); + +CREATE INDEX "DUPLICATIONS_INDEX_HASH" ON "DUPLICATIONS_INDEX" ("HASH"); + +CREATE INDEX "DUPLICATIONS_INDEX_SID" ON "DUPLICATIONS_INDEX" ("SNAPSHOT_ID"); + +CREATE INDEX "DUPLICATIONS_INDEX_PSID" ON "DUPLICATIONS_INDEX" ("PROJECT_SNAPSHOT_ID"); + +CREATE INDEX "INDEX_GROUPS_USERS_ON_GROUP_ID" ON "GROUPS_USERS" ("GROUP_ID"); + +CREATE INDEX "INDEX_GROUPS_USERS_ON_USER_ID" ON "GROUPS_USERS" ("USER_ID"); + +CREATE UNIQUE INDEX "GROUPS_USERS_UNIQUE" ON "GROUPS_USERS" ("GROUP_ID", "USER_ID"); + +CREATE INDEX "MEASURES_SID_METRIC" ON "PROJECT_MEASURES" ("SNAPSHOT_ID", "METRIC_ID"); + +CREATE UNIQUE INDEX "METRICS_UNIQUE_NAME" ON "METRICS" ("NAME"); + +CREATE INDEX "EVENTS_SNAPSHOT_ID" ON "EVENTS" ("SNAPSHOT_ID"); + +CREATE INDEX "EVENTS_COMPONENT_UUID" ON "EVENTS" ("COMPONENT_UUID"); + +CREATE INDEX "WIDGETS_WIDGETKEY" ON "WIDGETS" ("WIDGET_KEY"); + +CREATE INDEX "WIDGETS_DASHBOARDS" ON "WIDGETS" ("DASHBOARD_ID"); + +CREATE INDEX "SNAPSHOTS_QUALIFIER" ON "SNAPSHOTS" ("QUALIFIER"); + +CREATE INDEX "SNAPSHOTS_ROOT" ON "SNAPSHOTS" ("ROOT_SNAPSHOT_ID"); + +CREATE INDEX "SNAPSHOTS_PARENT" ON "SNAPSHOTS" ("PARENT_SNAPSHOT_ID"); + +CREATE INDEX "SNAPSHOT_PROJECT_ID" ON "SNAPSHOTS" ("PROJECT_ID"); + +CREATE INDEX "RULES_PARAMETERS_RULE_ID" ON "RULES_PARAMETERS" ("RULE_ID"); + +CREATE INDEX "ACTIVE_DASHBOARDS_DASHBOARDID" ON "ACTIVE_DASHBOARDS" ("DASHBOARD_ID"); + +CREATE INDEX "ACTIVE_DASHBOARDS_USERID" ON "ACTIVE_DASHBOARDS" ("USER_ID"); + +CREATE INDEX "UNIQUE_SCHEMA_MIGRATIONS" ON "SCHEMA_MIGRATIONS" ("VERSION"); + +CREATE INDEX "WIDGET_PROPERTIES_WIDGETS" ON "WIDGET_PROPERTIES" ("WIDGET_ID"); + +CREATE INDEX "PROPERTIES_KEY" ON "PROPERTIES" ("PROP_KEY"); + +CREATE INDEX "MANUAL_MEASURES_COMPONENT_UUID" ON "MANUAL_MEASURES" ("COMPONENT_UUID"); + +CREATE INDEX "PROJECTS_KEE" ON "PROJECTS" ("KEE", "ENABLED"); + +CREATE INDEX "PROJECTS_ROOT_ID" ON "PROJECTS" ("ROOT_ID"); + +CREATE UNIQUE INDEX "PROJECTS_UUID" ON "PROJECTS" ("UUID"); + +CREATE INDEX "PROJECTS_PROJECT_UUID" ON "PROJECTS" ("PROJECT_UUID"); + +CREATE INDEX "PROJECTS_MODULE_UUID" ON "PROJECTS" ("MODULE_UUID"); + +CREATE INDEX "RESOURCE_INDEX_KEE" ON "RESOURCE_INDEX" ("KEE"); + +CREATE INDEX "RESOURCE_INDEX_RID" ON "RESOURCE_INDEX" ("RESOURCE_ID"); + +CREATE INDEX "INDEX_ACTION_PLANS_ON_PROJET_ID" ON "ACTION_PLANS" ("PROJECT_ID"); + +CREATE UNIQUE INDEX "UNIQ_SEMAPHORE_CHECKSUMS" ON "SEMAPHORES" ("CHECKSUM"); + +CREATE INDEX "SEMAPHORE_NAMES" ON "SEMAPHORES" ("NAME"); + +CREATE UNIQUE INDEX "UNIQ_AUTHOR_LOGINS" ON "AUTHORS" ("LOGIN"); + +CREATE INDEX "MEASURE_FILTERS_NAME" ON "MEASURE_FILTERS" ("NAME"); + +CREATE INDEX "MEASURE_FILTER_FAVS_USERID" ON "MEASURE_FILTER_FAVOURITES" ("USER_ID"); + +CREATE UNIQUE INDEX "ISSUES_KEE" ON "ISSUES" ("KEE"); + +CREATE INDEX "ISSUES_COMPONENT_UUID" ON "ISSUES" ("COMPONENT_UUID"); + +CREATE INDEX "ISSUES_PROJECT_UUID" ON "ISSUES" ("PROJECT_UUID"); + +CREATE INDEX "ISSUES_RULE_ID" ON "ISSUES" ("RULE_ID"); + +CREATE INDEX "ISSUES_SEVERITY" ON "ISSUES" ("SEVERITY"); + +CREATE INDEX "ISSUES_STATUS" ON "ISSUES" ("STATUS"); + +CREATE INDEX "ISSUES_RESOLUTION" ON "ISSUES" ("RESOLUTION"); + +CREATE INDEX "ISSUES_ASSIGNEE" ON "ISSUES" ("ASSIGNEE"); + +CREATE INDEX "ISSUES_ACTION_PLAN_KEY" ON "ISSUES" ("ACTION_PLAN_KEY"); + +CREATE INDEX "ISSUES_CREATION_DATE" ON "ISSUES" ("ISSUE_CREATION_DATE"); + +CREATE INDEX "ISSUES_UPDATED_AT" ON "ISSUES" ("UPDATED_AT"); + +CREATE INDEX "ISSUE_CHANGES_KEE" ON "ISSUE_CHANGES" ("KEE"); + +CREATE INDEX "ISSUE_CHANGES_ISSUE_KEY" ON "ISSUE_CHANGES" ("ISSUE_KEY"); + +CREATE INDEX "ISSUE_FILTERS_NAME" ON "ISSUE_FILTERS" ("NAME"); + +CREATE INDEX "ISSUE_FILTER_FAVS_USER" ON "ISSUE_FILTER_FAVOURITES" ("USER_LOGIN"); + +CREATE UNIQUE INDEX "USERS_LOGIN" ON "USERS" ("LOGIN"); + +CREATE INDEX "USERS_UPDATED_AT" ON "USERS" ("UPDATED_AT"); + +CREATE INDEX "SNAPSHOTS_ROOT_PROJECT_ID" ON "SNAPSHOTS" ("ROOT_PROJECT_ID"); + +CREATE INDEX "GROUP_ROLES_ROLE" ON "GROUP_ROLES" ("ROLE"); + +CREATE UNIQUE INDEX "UNIQ_GROUP_ROLES" ON "GROUP_ROLES" ("GROUP_ID", "RESOURCE_ID", "ROLE"); + +CREATE UNIQUE INDEX "RULES_REPO_KEY" ON "RULES" ("PLUGIN_NAME", "PLUGIN_RULE_KEY"); + +CREATE INDEX "CHARACTERISTICS_ENABLED" ON "CHARACTERISTICS" ("ENABLED"); + +CREATE UNIQUE INDEX "QUALITY_GATES_UNIQUE" ON "QUALITY_GATES" ("NAME"); + +CREATE UNIQUE INDEX "ACTIVE_RULES_UNIQUE" ON "ACTIVE_RULES" ("PROFILE_ID","RULE_ID"); + +CREATE UNIQUE INDEX "PROFILE_UNIQUE_KEY" ON "RULES_PROFILES" ("KEE"); + +CREATE INDEX "FILE_SOURCES_PROJECT_UUID" ON "FILE_SOURCES" ("PROJECT_UUID"); + +CREATE UNIQUE INDEX "FILE_SOURCES_UUID_TYPE_UNIQUE" ON "FILE_SOURCES" ("FILE_UUID", "DATA_TYPE"); + +CREATE INDEX "FILE_SOURCES_UPDATED_AT" ON "FILE_SOURCES" ("UPDATED_AT"); + +CREATE UNIQUE INDEX "PROJECT_QPROFILES_UNIQUE" ON "PROJECT_QPROFILES" ("PROJECT_UUID", "PROFILE_KEY"); diff --git a/sonar-db/src/main/resources/org/sonar/db/version/v44/Migration44Mapper.xml b/sonar-db/src/main/resources/org/sonar/db/version/v44/Migration44Mapper.xml new file mode 100644 index 00000000000..30bcffddccb --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/version/v44/Migration44Mapper.xml @@ -0,0 +1,105 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.version.v44.Migration44Mapper"> + + <select id="selectProfileMeasures" resultType="org.sonar.db.version.v44.ProfileMeasure"> + select pm.id as id, pm.value as profileId, pm.snapshot_id as snapshotId + from project_measures pm + inner join metrics m on m.id=pm.metric_id and m.name='profile' + inner join snapshots s on s.islast=${_true} and pm.snapshot_id=s.id and s.scope='PRJ' + where pm.value is not null + </select> + + <select id="selectProfileVersion" resultType="int" parameterType="long"> + select pm.value from project_measures pm + inner join metrics m on m.id=pm.metric_id and m.name='profile_version' + inner join snapshots s on pm.snapshot_id=s.id + where pm.value is not null and s.id=#{id} + </select> + + <select id="selectProfileById" resultType="org.sonar.db.version.v44.QProfileDto44" parameterType="int"> + select id, kee, name, language + from rules_profiles + where id=#{id} + </select> + + <select id="selectProfileVersionDate" resultType="date" parameterType="map"> + select max(change_date) from active_rule_changes + where profile_id=#{profileId} and profile_version=#{profileVersion} + </select> + + <update id="updateProfileMeasure" parameterType="map"> + update project_measures + set text_value=#{json}, value=null + where id=#{measureId} + </update> + + <delete id="deleteProfileMeasure" parameterType="long"> + delete from project_measures where id=#{id} + </delete> + + <select id="selectMeasuresOnDeletedQualityProfiles" resultType="long"> + select pm.id from project_measures pm + inner join snapshots s on s.id=pm.snapshot_id and s.islast=${_true} + where + pm.metric_id=(select id from metrics where name='quality_profiles') + and pm.value is not null + </select> + + <select id="selectAllProfiles" resultType="org.sonar.db.version.v44.QProfileDto44"> + select id, kee, name, language from rules_profiles + </select> + + <select id="selectProfileUpdatedAt" resultType="date" parameterType="int"> + select max(change_date) from active_rule_changes + where profile_id=#{id} + </select> + + <select id="selectProfileCreatedAt" resultType="date" parameterType="int"> + select min(change_date) from active_rule_changes + where profile_id=#{id} + </select> + + <update id="updateProfileDates" parameterType="map"> + update rules_profiles + set created_at=#{createdAt}, updated_at=#{updatedAt}, rules_updated_at=#{rulesUpdatedAt} + where id=#{profileId} + </update> + + <select id="selectActiveRuleChange" parameterType="Boolean" + resultType="org.sonar.db.version.v44.ChangeLog"> + select + rule_change.id as id, + rule_change.change_date as createdAt, + users.login as userLogin, + rule_def.plugin_name as repository, + rule_def.plugin_rule_key as ruleKey, + profile.kee as profileKey, + rule_change.new_severity as severity , + rule_def.name as ruleName, + rule_def_param.name as paramKey, + rule_param_change.new_value as paramValue + from active_rule_changes rule_change + left join users on users.name = rule_change.username + left join rules rule_def on rule_def.id = rule_change.rule_id + left join rules_profiles profile on profile.id = rule_change.profile_id + left join active_rule_param_changes rule_param_change on rule_param_change.active_rule_change_id = rule_change.id + left join rules_parameters rule_def_param on rule_param_change.rules_parameter_id = rule_def_param.id + WHERE + <choose> + <when test="enabled != null"> + rule_change.enabled = #{enabled} + </when> + <otherwise> + rule_change.enabled is null + </otherwise> + </choose> + AND profile.name is not null + AND profile.language is not null + AND rule_def.plugin_name is not null + AND rule_def.plugin_name is not null + order by rule_change.id ASC + </select> +</mapper> + diff --git a/sonar-db/src/main/resources/org/sonar/db/version/v45/Migration45Mapper.xml b/sonar-db/src/main/resources/org/sonar/db/version/v45/Migration45Mapper.xml new file mode 100644 index 00000000000..0b741e6d396 --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/version/v45/Migration45Mapper.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.version.v45.Migration45Mapper"> + +</mapper> + diff --git a/sonar-db/src/main/resources/org/sonar/db/version/v50/Migration50Mapper.xml b/sonar-db/src/main/resources/org/sonar/db/version/v50/Migration50Mapper.xml new file mode 100644 index 00000000000..46fd146b117 --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/version/v50/Migration50Mapper.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="org.sonar.db.version.v50.Migration50Mapper"> + +</mapper> + diff --git a/sonar-db/src/test/java/org/sonar/core/issue/ActionPlanStatsTest.java b/sonar-db/src/test/java/org/sonar/core/issue/ActionPlanStatsTest.java new file mode 100644 index 00000000000..233f99787b2 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/core/issue/ActionPlanStatsTest.java @@ -0,0 +1,43 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.core.issue; + +import java.util.Date; +import org.apache.commons.lang.time.DateUtils; +import org.junit.Test; +import org.sonar.api.issue.ActionPlan; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ActionPlanStatsTest { + + @Test + public void test_over_due() throws Exception { + Date yesterday = DateUtils.addDays(new Date(), -1); + Date tomorrow = DateUtils.addDays(new Date(), 1); + + assertThat(((ActionPlanStats) ActionPlanStats.create("Short term").setStatus(ActionPlan.STATUS_OPEN).setDeadLine(tomorrow)).overDue()).isFalse(); + assertThat(((ActionPlanStats) ActionPlanStats.create("Short term").setStatus(ActionPlan.STATUS_OPEN).setDeadLine(yesterday)).overDue()).isTrue(); + assertThat(((ActionPlanStats) ActionPlanStats.create("Short term").setStatus(ActionPlan.STATUS_CLOSED).setDeadLine(tomorrow)).overDue()).isFalse(); + assertThat(((ActionPlanStats) ActionPlanStats.create("Short term").setStatus(ActionPlan.STATUS_CLOSED).setDeadLine(yesterday)).overDue()).isFalse(); + assertThat(((ActionPlanStats) ActionPlanStats.create("Short term").setStatus(ActionPlan.STATUS_CLOSED)).overDue()).isFalse(); + } +} diff --git a/sonar-db/src/test/java/org/sonar/core/timemachine/PeriodsTest.java b/sonar-db/src/test/java/org/sonar/core/timemachine/PeriodsTest.java new file mode 100644 index 00000000000..ee5fbb87bb7 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/core/timemachine/PeriodsTest.java @@ -0,0 +1,262 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.core.timemachine; + +import java.util.Locale; +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.CoreProperties; +import org.sonar.api.config.Settings; +import org.sonar.api.database.model.Snapshot; +import org.sonar.api.i18n.I18n; +import org.sonar.api.utils.System2; + +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyString; +import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.isNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class PeriodsTest { + + private Periods periods; + + private Snapshot snapshot; + + private Settings settings; + private I18n i18n; + + private int periodIndex; + private String param; + + @Before + public void before() { + periodIndex = 1; + param = "10"; + + snapshot = mock(Snapshot.class); + when(snapshot.getPeriodModeParameter(periodIndex)).thenReturn(param); + + settings = new Settings(); + i18n = mock(I18n.class); + periods = new Periods(settings, i18n); + } + + @Test + public void label_of_duration_in_days() { + when(snapshot.getPeriodMode(periodIndex)).thenReturn(CoreProperties.TIMEMACHINE_MODE_DAYS); + when(snapshot.getPeriodDateMs(periodIndex)).thenReturn(System2.INSTANCE.now()); + when(snapshot.getPeriodModeParameter(periodIndex)).thenReturn(param); + + periods.label(snapshot, periodIndex); + verify(i18n).message(any(Locale.class), eq("over_x_days_detailed"), isNull(String.class), eq(param), anyString()); + } + + @Test + public void abbreviation_of_duration_in_days() { + when(snapshot.getPeriodMode(periodIndex)).thenReturn(CoreProperties.TIMEMACHINE_MODE_DAYS); + when(snapshot.getPeriodDateMs(periodIndex)).thenReturn(System.currentTimeMillis()); + when(snapshot.getPeriodModeParameter(periodIndex)).thenReturn(param); + + periods.abbreviation(snapshot, periodIndex); + verify(i18n).message(any(Locale.class), eq("over_x_days_detailed.short"), isNull(String.class), eq(param), anyString()); + } + + @Test + public void label_of_snapshot_version() { + when(snapshot.getPeriodMode(periodIndex)).thenReturn(CoreProperties.TIMEMACHINE_MODE_VERSION); + when(snapshot.getPeriodDateMs(periodIndex)).thenReturn(System.currentTimeMillis()); + when(snapshot.getPeriodModeParameter(periodIndex)).thenReturn(param); + + periods.label(snapshot, periodIndex); + verify(i18n).message(any(Locale.class), eq("since_version_detailed"), isNull(String.class), eq(param), anyString()); + } + + @Test + public void abbreviation_of_snapshot_version() { + when(snapshot.getPeriodMode(periodIndex)).thenReturn(CoreProperties.TIMEMACHINE_MODE_VERSION); + when(snapshot.getPeriodDateMs(periodIndex)).thenReturn(System.currentTimeMillis()); + when(snapshot.getPeriodModeParameter(periodIndex)).thenReturn(param); + + periods.abbreviation(snapshot, periodIndex); + verify(i18n).message(any(Locale.class), eq("since_version_detailed.short"), isNull(String.class), eq(param), anyString()); + } + + @Test + public void label_of_previous_analysis_with_date() { + when(snapshot.getPeriodMode(periodIndex)).thenReturn(CoreProperties.TIMEMACHINE_MODE_PREVIOUS_ANALYSIS); + when(snapshot.getPeriodDateMs(periodIndex)).thenReturn(System.currentTimeMillis()); + + periods.label(snapshot, periodIndex); + verify(i18n).message(any(Locale.class), eq("since_previous_analysis_detailed"), isNull(String.class), anyString()); + } + + @Test + public void label_of_previous_analysis_without_date() { + when(snapshot.getPeriodMode(periodIndex)).thenReturn(CoreProperties.TIMEMACHINE_MODE_PREVIOUS_ANALYSIS); + when(snapshot.getPeriodDateMs(periodIndex)).thenReturn(null); + when(snapshot.getPeriodModeParameter(periodIndex)).thenReturn(param); + + periods.label(snapshot, periodIndex); + verify(i18n).message(any(Locale.class), eq("since_previous_analysis"), isNull(String.class)); + } + + @Test + public void abbreviation_of_previous_analysis_with_date() { + when(snapshot.getPeriodMode(periodIndex)).thenReturn(CoreProperties.TIMEMACHINE_MODE_PREVIOUS_ANALYSIS); + when(snapshot.getPeriodDateMs(periodIndex)).thenReturn(System.currentTimeMillis()); + + periods.abbreviation(snapshot, periodIndex); + verify(i18n).message(any(Locale.class), eq("since_previous_analysis_detailed.short"), isNull(String.class), anyString()); + } + + @Test + public void abbreviation_of_previous_analysis_without_date() { + when(snapshot.getPeriodMode(periodIndex)).thenReturn(CoreProperties.TIMEMACHINE_MODE_PREVIOUS_ANALYSIS); + when(snapshot.getPeriodDateMs(periodIndex)).thenReturn(null); + when(snapshot.getPeriodModeParameter(periodIndex)).thenReturn(param); + + periods.abbreviation(snapshot, periodIndex); + verify(i18n).message(any(Locale.class), eq("since_previous_analysis.short"), isNull(String.class)); + } + + @Test + public void shouldReturnSnapshotLabelInModePreviousVersionWithParamNotNull() { + when(snapshot.getPeriodMode(periodIndex)).thenReturn(CoreProperties.TIMEMACHINE_MODE_PREVIOUS_VERSION); + when(snapshot.getPeriodModeParameter(periodIndex)).thenReturn(param); + + periods.label(snapshot, periodIndex); + verify(i18n).message(any(Locale.class), eq("since_previous_version_detailed"), isNull(String.class), eq(param)); + } + + @Test + public void label_of_previous_version_with_param_and_date() { + when(snapshot.getPeriodMode(periodIndex)).thenReturn(CoreProperties.TIMEMACHINE_MODE_PREVIOUS_VERSION); + when(snapshot.getPeriodModeParameter(periodIndex)).thenReturn(param); + when(snapshot.getPeriodDateMs(periodIndex)).thenReturn(System.currentTimeMillis()); + + periods.label(snapshot, periodIndex); + verify(i18n).message(any(Locale.class), eq("since_previous_version_detailed"), isNull(String.class), eq(param), anyString()); + } + + @Test + public void shouldReturnSnapshotLabelInModePreviousVersionWithParamNull() { + when(snapshot.getPeriodMode(periodIndex)).thenReturn(CoreProperties.TIMEMACHINE_MODE_PREVIOUS_VERSION); + when(snapshot.getPeriodModeParameter(periodIndex)).thenReturn(null); + + periods.label(snapshot, periodIndex); + verify(i18n).message(any(Locale.class), eq("since_previous_version"), isNull(String.class)); + } + + @Test + public void shouldReturnSnapshotLabelInModeDate() { + when(snapshot.getPeriodMode(periodIndex)).thenReturn(CoreProperties.TIMEMACHINE_MODE_DATE); + when(snapshot.getPeriodDateMs(periodIndex)).thenReturn(System.currentTimeMillis()); + + periods.label(snapshot, periodIndex); + + verify(i18n).message(any(Locale.class), eq("since_x"), isNull(String.class), anyString()); + } + + @Test(expected = IllegalArgumentException.class) + public void shouldNotSupportUnknownModeForSnapshotLabel() { + when(snapshot.getPeriodMode(periodIndex)).thenReturn("Unknown mode"); + + periods.label(snapshot, periodIndex); + } + + @Test + public void shouldReturnLabelInModeDays() { + int periodIndex = 1; + String days = "5"; + settings.setProperty(CoreProperties.TIMEMACHINE_PERIOD_PREFIX + periodIndex, days); + + periods.label(periodIndex); + verify(i18n).message(any(Locale.class), eq("over_x_days"), isNull(String.class), eq(days)); + } + + @Test + public void shouldReturnLabelInModeVersion() { + int periodIndex = 1; + String version = "3.5"; + settings.setProperty(CoreProperties.TIMEMACHINE_PERIOD_PREFIX + periodIndex, version); + + periods.label(periodIndex); + verify(i18n).message(any(Locale.class), eq("since_version"), isNull(String.class), eq(version)); + } + + @Test + public void shouldReturnLabelInModePreviousAnalysis() { + int periodIndex = 1; + settings.setProperty(CoreProperties.TIMEMACHINE_PERIOD_PREFIX + periodIndex, CoreProperties.TIMEMACHINE_MODE_PREVIOUS_ANALYSIS); + + periods.label(periodIndex); + verify(i18n).message(any(Locale.class), eq("since_previous_analysis"), isNull(String.class)); + } + + @Test + public void label_of_previous_version() { + int periodIndex = 1; + settings.setProperty(CoreProperties.TIMEMACHINE_PERIOD_PREFIX + periodIndex, CoreProperties.TIMEMACHINE_MODE_PREVIOUS_VERSION); + + periods.label(periodIndex); + verify(i18n).message(any(Locale.class), eq("since_previous_version"), isNull(String.class)); + } + + @Test + public void abbreviation_of_previous_version() { + int periodIndex = 1; + settings.setProperty(CoreProperties.TIMEMACHINE_PERIOD_PREFIX + periodIndex, CoreProperties.TIMEMACHINE_MODE_PREVIOUS_VERSION); + + periods.abbreviation(periodIndex); + verify(i18n).message(any(Locale.class), eq("since_previous_version.short"), isNull(String.class)); + } + + @Test + public void label_of_date() { + int periodIndex = 1; + settings.setProperty(CoreProperties.TIMEMACHINE_PERIOD_PREFIX + periodIndex, "2012-12-12"); + + periods.label(periodIndex); + + verify(i18n).message(any(Locale.class), eq("since_x"), isNull(String.class), anyString()); + } + + @Test + public void abbreviation_of_date() { + int periodIndex = 1; + settings.setProperty(CoreProperties.TIMEMACHINE_PERIOD_PREFIX + periodIndex, "2012-12-12"); + + periods.abbreviation(periodIndex); + + verify(i18n).message(any(Locale.class), eq("since_x.short"), isNull(String.class), anyString()); + } + + @Test(expected = IllegalArgumentException.class) + public void shouldNotSupportUnknownModeForLabel() { + int periodIndex = 1; + settings.setProperty(CoreProperties.TIMEMACHINE_PERIOD_PREFIX + periodIndex, ""); + + periods.label(periodIndex); + } + +} diff --git a/sonar-db/src/test/java/org/sonar/core/user/DefaultUserFinderTest.java b/sonar-db/src/test/java/org/sonar/core/user/DefaultUserFinderTest.java new file mode 100644 index 00000000000..2a97bef0a21 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/core/user/DefaultUserFinderTest.java @@ -0,0 +1,66 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.core.user; + +import java.util.Arrays; +import java.util.Collection; +import org.junit.Test; +import org.sonar.api.user.User; +import org.sonar.api.user.UserQuery; +import org.sonar.db.user.UserDao; +import org.sonar.db.user.UserDto; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class DefaultUserFinderTest { + UserDao dao = mock(UserDao.class); + DefaultUserFinder finder = new DefaultUserFinder(dao); + + @Test + public void findByLogin() { + UserDto dto = new UserDto().setLogin("david").setName("David").setEmail("dav@id.com"); + when(dao.selectActiveUserByLogin("david")).thenReturn(dto); + + assertThat(finder.findByLogin("david").name()).isEqualTo("David"); + } + + @Test + public void findByLogins() { + UserDto david = new UserDto().setLogin("david").setName("David").setEmail("dav@id.com"); + UserDto john = new UserDto().setLogin("john").setName("John").setEmail("jo@hn.com"); + when(dao.selectUsersByLogins(Arrays.asList("david", "john"))).thenReturn(Arrays.asList(david, john)); + + Collection<User> users = finder.findByLogins(Arrays.asList("david", "john")); + assertThat(users).hasSize(2); + for (User user : users) { + assertThat(user.login()).isIn("david", "john"); + } + } + + @Test + public void findByQuery() { + UserQuery query = UserQuery.builder().logins("simon").build(); + finder.find(query); + verify(dao).selectUsers(query); + } +} diff --git a/sonar-db/src/test/java/org/sonar/core/user/DefaultUserTest.java b/sonar-db/src/test/java/org/sonar/core/user/DefaultUserTest.java new file mode 100644 index 00000000000..6028a82dd3d --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/core/user/DefaultUserTest.java @@ -0,0 +1,52 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.core.user; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class DefaultUserTest { + @Test + public void test_object_methods() throws Exception { + DefaultUser john = new DefaultUser().setLogin("john").setName("John"); + DefaultUser eric = new DefaultUser().setLogin("eric").setName("Eric"); + + assertThat(john).isEqualTo(john); + assertThat(john).isNotEqualTo(eric); + assertThat(john.hashCode()).isEqualTo(john.hashCode()); + assertThat(john.toString()).contains("login=john").contains("name=John"); + } + + @Test + public void test_email() { + DefaultUser user = new DefaultUser(); + assertThat(user.email()).isNull(); + + user.setEmail(""); + assertThat(user.email()).isNull(); + + user.setEmail(" "); + assertThat(user.email()).isNull(); + + user.setEmail("s@b.com"); + assertThat(user.email()).isEqualTo("s@b.com"); + } +} diff --git a/sonar-db/src/test/java/org/sonar/core/user/DeprecatedUserFinderTest.java b/sonar-db/src/test/java/org/sonar/core/user/DeprecatedUserFinderTest.java new file mode 100644 index 00000000000..0d978a6124a --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/core/user/DeprecatedUserFinderTest.java @@ -0,0 +1,86 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.core.user; + +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.sonar.api.database.model.User; +import org.sonar.api.utils.System2; +import org.sonar.db.DbTester; +import org.sonar.db.user.UserDao; +import org.sonar.test.DbTests; + +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; + +@Category(DbTests.class) +public class DeprecatedUserFinderTest { + + @ClassRule + public static final DbTester dbTester = new DbTester(); + + @BeforeClass + public static void init() { + dbTester.prepareDbUnit(DeprecatedUserFinderTest.class, "fixture.xml"); + } + + @Test + public void shouldFindUserByLogin() { + DeprecatedUserFinder finder = new DeprecatedUserFinder(new UserDao(dbTester.myBatis(), mock(System2.class))); + User user = finder.findByLogin("simon"); + assertThat(user.getId(), is(1)); + assertThat(user.getLogin(), is("simon")); + assertThat(user.getName(), is("Simon Brandhof")); + assertThat(user.getEmail(), is("simon.brandhof@sonarsource.com")); + + user = finder.findByLogin("godin"); + assertThat(user.getId(), is(2)); + assertThat(user.getLogin(), is("godin")); + assertThat(user.getName(), is("Evgeny Mandrikov")); + assertThat(user.getEmail(), is("evgeny.mandrikov@sonarsource.com")); + + user = finder.findByLogin("user"); + assertThat(user, nullValue()); + } + + @Test + public void shouldFindUserById() { + DeprecatedUserFinder finder = new DeprecatedUserFinder(new UserDao(dbTester.myBatis(), mock(System2.class))); + User user = finder.findById(1); + assertThat(user.getId(), is(1)); + assertThat(user.getLogin(), is("simon")); + assertThat(user.getName(), is("Simon Brandhof")); + assertThat(user.getEmail(), is("simon.brandhof@sonarsource.com")); + + user = finder.findById(2); + assertThat(user.getId(), is(2)); + assertThat(user.getLogin(), is("godin")); + assertThat(user.getName(), is("Evgeny Mandrikov")); + assertThat(user.getEmail(), is("evgeny.mandrikov@sonarsource.com")); + + user = finder.findById(3); + assertThat(user, nullValue()); + } + +} diff --git a/sonar-db/src/test/java/org/sonar/db/AbstractDaoTestCase.java b/sonar-db/src/test/java/org/sonar/db/AbstractDaoTestCase.java new file mode 100644 index 00000000000..756a3437595 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/AbstractDaoTestCase.java @@ -0,0 +1,308 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db; + +import com.google.common.collect.Maps; +import com.google.common.io.Closeables; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.URISyntaxException; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.Map; +import java.util.Properties; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.text.StrSubstitutor; +import org.dbunit.Assertion; +import org.dbunit.DataSourceDatabaseTester; +import org.dbunit.DatabaseUnitException; +import org.dbunit.IDatabaseTester; +import org.dbunit.database.DatabaseConfig; +import org.dbunit.database.IDatabaseConnection; +import org.dbunit.dataset.CompositeDataSet; +import org.dbunit.dataset.DataSetException; +import org.dbunit.dataset.IDataSet; +import org.dbunit.dataset.ITable; +import org.dbunit.dataset.ReplacementDataSet; +import org.dbunit.dataset.filter.DefaultColumnFilter; +import org.dbunit.dataset.xml.FlatXmlDataSet; +import org.dbunit.ext.mssql.InsertIdentityOperation; +import org.dbunit.ext.mysql.MySqlMetadataHandler; +import org.dbunit.operation.DatabaseOperation; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.experimental.categories.Category; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.config.Settings; +import org.sonar.db.deprecated.NullQueue; +import org.sonar.db.dialect.MySql; +import org.sonar.test.DbTests; + +import static org.junit.Assert.fail; + +/** + * @deprecated use an instance of {@link DbTester instead} instead, + * and do no forget to annotated the test class with {@link org.sonar.test.DbTests}. + */ +@Category(DbTests.class) +@Deprecated +public abstract class AbstractDaoTestCase { + + private static final Logger LOG = LoggerFactory.getLogger(AbstractDaoTestCase.class); + private static Database database; + private static DatabaseCommands databaseCommands; + private static MyBatis myBatis; + private static String login; + + private IDatabaseTester databaseTester; + + @BeforeClass + public static void startDatabase() throws Exception { + if (database == null) { + Settings settings = new Settings().setProperties(Maps.fromProperties(System.getProperties())); + if (settings.hasKey("orchestrator.configUrl")) { + loadOrchestratorSettings(settings); + } + login = settings.getString("sonar.jdbc.username"); + for (String key : settings.getKeysStartingWith("sonar.jdbc")) { + LOG.info(key + ": " + settings.getString(key)); + } + boolean hasDialect = settings.hasKey("sonar.jdbc.dialect"); + if (hasDialect) { + database = new DefaultDatabase(settings); + } else { + database = new H2Database("test", true); + } + database.start(); + LOG.info("Test Database: " + database); + databaseCommands = DatabaseCommands.forDialect(database.getDialect()); + + myBatis = new MyBatis(database, new NullQueue()); + myBatis.start(); + } + } + + /** + * Orchestrator is the name of a SonarSource close-source library for database and integration testing. + */ + private static void loadOrchestratorSettings(Settings settings) throws URISyntaxException, IOException { + String url = settings.getString("orchestrator.configUrl"); + URI uri = new URI(url); + InputStream input = null; + try { + if (url.startsWith("file:")) { + File file = new File(uri); + input = FileUtils.openInputStream(file); + } else { + HttpURLConnection connection = (HttpURLConnection) uri.toURL().openConnection(); + int responseCode = connection.getResponseCode(); + if (responseCode >= 400) { + throw new IllegalStateException("Fail to request: " + uri + ". Status code=" + responseCode); + } + + input = connection.getInputStream(); + + } + Properties props = new Properties(); + props.load(input); + settings.addProperties(props); + for (Map.Entry<String, String> entry : settings.getProperties().entrySet()) { + String interpolatedValue = StrSubstitutor.replace(entry.getValue(), System.getenv(), "${", "}"); + settings.setProperty(entry.getKey(), interpolatedValue); + } + } finally { + IOUtils.closeQuietly(input); + } + } + + private static RuntimeException translateException(String msg, Exception cause) { + RuntimeException runtimeException = new RuntimeException(String.format("%s: [%s] %s", msg, cause.getClass().getName(), cause.getMessage())); + runtimeException.setStackTrace(cause.getStackTrace()); + return runtimeException; + } + + @Before + public void startDbUnit() throws Exception { + databaseCommands.truncateDatabase(database.getDataSource()); + databaseTester = new DataSourceDatabaseTester(database.getDataSource(), databaseCommands.useLoginAsSchema() ? login : null); + } + + protected MyBatis getMyBatis() { + return myBatis; + } + + protected Database getDatabase() { + return database; + } + + protected void setupData(String... testNames) { + InputStream[] streams = new InputStream[testNames.length]; + try { + for (int i = 0; i < testNames.length; i++) { + String className = getClass().getName(); + className = String.format("/%s/%s.xml", className.replace(".", "/"), testNames[i]); + streams[i] = getClass().getResourceAsStream(className); + if (streams[i] == null) { + throw new RuntimeException("Test not found :" + className); + } + } + + setupData(streams); + databaseCommands.resetPrimaryKeys(database.getDataSource()); + } catch (SQLException e) { + throw translateException("Could not setup DBUnit data", e); + } finally { + for (InputStream stream : streams) { + IOUtils.closeQuietly(stream); + } + } + } + + private void setupData(InputStream... dataSetStream) { + IDatabaseConnection connection = openDbUnitConnection(); + try { + IDataSet[] dataSets = new IDataSet[dataSetStream.length]; + for (int i = 0; i < dataSetStream.length; i++) { + dataSets[i] = getData(dataSetStream[i]); + } + databaseTester.setDataSet(new CompositeDataSet(dataSets)); + new InsertIdentityOperation(DatabaseOperation.INSERT).execute(connection, databaseTester.getDataSet()); + } catch (Exception e) { + throw translateException("Could not setup DBUnit data", e); + } finally { + closeDbUnitConnection(connection); + } + } + + protected void checkTables(String testName, String... tables) { + checkTables(testName, new String[0], tables); + } + + protected void checkTables(String testName, String[] excludedColumnNames, String... tables) { + IDatabaseConnection connection = openDbUnitConnection(); + try { + IDataSet dataSet = connection.createDataSet(); + IDataSet expectedDataSet = getExpectedData(testName); + for (String table : tables) { + ITable filteredTable = DefaultColumnFilter.excludedColumnsTable(dataSet.getTable(table), excludedColumnNames); + ITable filteredExpectedTable = DefaultColumnFilter.excludedColumnsTable(expectedDataSet.getTable(table), excludedColumnNames); + Assertion.assertEquals(filteredExpectedTable, filteredTable); + } + } catch (DatabaseUnitException e) { + fail(e.getMessage()); + } catch (SQLException e) { + throw translateException("Error while checking results", e); + } finally { + closeDbUnitConnection(connection); + } + } + + protected void checkTable(String testName, String table, String... columns) { + IDatabaseConnection connection = openDbUnitConnection(); + try { + IDataSet dataSet = connection.createDataSet(); + IDataSet expectedDataSet = getExpectedData(testName); + ITable filteredTable = DefaultColumnFilter.includedColumnsTable(dataSet.getTable(table), columns); + ITable filteredExpectedTable = DefaultColumnFilter.includedColumnsTable(expectedDataSet.getTable(table), columns); + Assertion.assertEquals(filteredExpectedTable, filteredTable); + } catch (DatabaseUnitException e) { + fail(e.getMessage()); + } catch (SQLException e) { + throw translateException("Error while checking results", e); + } finally { + closeDbUnitConnection(connection); + } + } + + protected void assertEmptyTables(String... emptyTables) { + IDatabaseConnection connection = openDbUnitConnection(); + try { + IDataSet dataSet = connection.createDataSet(); + for (String table : emptyTables) { + try { + Assert.assertEquals("Table " + table + " not empty.", 0, dataSet.getTable(table).getRowCount()); + } catch (DataSetException e) { + throw translateException("Error while checking results", e); + } + } + } catch (SQLException e) { + throw translateException("Error while checking results", e); + } finally { + closeDbUnitConnection(connection); + } + } + + private IDatabaseConnection openDbUnitConnection() { + try { + IDatabaseConnection connection = databaseTester.getConnection(); + connection.getConfig().setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, databaseCommands.getDbUnitFactory()); + connection.getConfig().setFeature(DatabaseConfig.FEATURE_QUALIFIED_TABLE_NAMES, false); + connection.getConfig().setFeature(DatabaseConfig.FEATURE_SKIP_ORACLE_RECYCLEBIN_TABLES, true); + if (MySql.ID.equals(database.getDialect().getId())) { + connection.getConfig().setProperty(DatabaseConfig.FEATURE_CASE_SENSITIVE_TABLE_NAMES, false); + connection.getConfig().setProperty(DatabaseConfig.PROPERTY_METADATA_HANDLER, new MySqlMetadataHandler()); + } + return connection; + } catch (Exception e) { + throw new IllegalStateException("Fail to open dbunit connection", e); + } + } + + private void closeDbUnitConnection(IDatabaseConnection c) { + try { + c.close(); + } catch (SQLException e) { + throw new IllegalStateException("Fail to close dbunit connection", e); + } + } + + private IDataSet getExpectedData(String testName) { + String className = getClass().getName(); + String fileName = String.format("/%s/%s-result.xml", className.replace('.', '/'), testName); + InputStream in = getClass().getResourceAsStream(fileName); + try { + return getData(in); + } finally { + Closeables.closeQuietly(in); + } + } + + private IDataSet getData(InputStream stream) { + try { + ReplacementDataSet dataSet = new ReplacementDataSet(new FlatXmlDataSet(stream)); + dataSet.addReplacementObject("[null]", null); + dataSet.addReplacementObject("[false]", Boolean.FALSE); + dataSet.addReplacementObject("[true]", Boolean.TRUE); + return dataSet; + } catch (Exception e) { + throw translateException("Could not read the dataset stream", e); + } + } + + protected Connection getConnection() throws SQLException { + return database.getDataSource().getConnection(); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/BatchSessionTest.java b/sonar-db/src/test/java/org/sonar/db/BatchSessionTest.java new file mode 100644 index 00000000000..dc6999e61a1 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/BatchSessionTest.java @@ -0,0 +1,86 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db; + +import org.apache.ibatis.session.SqlSession; +import org.junit.Test; +import org.sonar.db.deprecated.ClusterAction; +import org.sonar.db.deprecated.WorkQueue; + +import static org.mockito.Mockito.anyBoolean; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +public class BatchSessionTest { + @Test + public void shouldCommitWhenReachingBatchSize() { + SqlSession mybatisSession = mock(SqlSession.class); + WorkQueue<?> queue = mock(WorkQueue.class); + BatchSession session = new BatchSession(queue, mybatisSession, 10); + + for (int i = 0; i < 9; i++) { + session.insert("id" + i); + verify(mybatisSession).insert("id" + i); + verify(mybatisSession, never()).commit(); + verify(mybatisSession, never()).commit(anyBoolean()); + } + session.insert("id9"); + verify(mybatisSession).commit(); + session.close(); + } + + @Test + public void shouldCommitWhenReachingBatchSizeWithoutCommits() { + SqlSession mybatisSession = mock(SqlSession.class); + WorkQueue<?> queue = mock(WorkQueue.class); + BatchSession session = new BatchSession(queue, mybatisSession, 10); + + ClusterAction action = new ClusterAction() { + @Override + public Object call() throws Exception { + return null; + } + }; + + for (int i = 0; i < 9; i++) { + session.enqueue(action); + verify(mybatisSession, never()).commit(); + verify(mybatisSession, never()).commit(anyBoolean()); + } + session.enqueue(action); + verify(mybatisSession).commit(); + session.close(); + } + + @Test + public void shouldResetCounterAfterCommit() { + SqlSession mybatisSession = mock(SqlSession.class); + WorkQueue<?> queue = mock(WorkQueue.class); + BatchSession session = new BatchSession(queue, mybatisSession, 10); + + for (int i = 0; i < 35; i++) { + session.insert("id" + i); + } + verify(mybatisSession, times(3)).commit(); + session.close(); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/DaoUtilsTest.java b/sonar-db/src/test/java/org/sonar/db/DaoUtilsTest.java new file mode 100644 index 00000000000..24987271dfb --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/DaoUtilsTest.java @@ -0,0 +1,85 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db; + +import com.google.common.base.Function; +import com.google.common.collect.Iterables; +import java.util.Collections; +import java.util.List; +import org.junit.Test; + +import static com.google.common.collect.Lists.newArrayList; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.fail; + +public class DaoUtilsTest { + + @Test + public void list_all_dao_classes() { + List<Class> daoClasses = DaoUtils.getDaoClasses(); + + assertThat(daoClasses).isNotEmpty(); + } + + @Test + public void repeatCondition() { + assertThat(DaoUtils.repeatCondition("uuid=?", 1, "or")).isEqualTo("uuid=?"); + assertThat(DaoUtils.repeatCondition("uuid=?", 3, "or")).isEqualTo("uuid=? or uuid=? or uuid=?"); + } + + @Test + public void execute_large_inputs() { + List<Integer> inputs = newArrayList(); + List<String> expectedOutputs = newArrayList(); + for (int i = 0; i < 2010; i++) { + inputs.add(i); + expectedOutputs.add(Integer.toString(i)); + } + + List<String> outputs = DaoUtils.executeLargeInputs(inputs, new Function<List<Integer>, List<String>>() { + @Override + public List<String> apply(List<Integer> input) { + // Check that each partition is only done on 1000 elements max + assertThat(input.size()).isLessThanOrEqualTo(1000); + return newArrayList(Iterables.transform(input, new Function<Integer, String>() { + @Override + public String apply(Integer input) { + return Integer.toString(input); + } + })); + } + }); + + assertThat(outputs).isEqualTo(expectedOutputs); + } + + @Test + public void execute_large_inputs_on_empty_list() { + List<String> outputs = DaoUtils.executeLargeInputs(Collections.<Integer>emptyList(), new Function<List<Integer>, List<String>>() { + @Override + public List<String> apply(List<Integer> input) { + fail("No partition should be made on empty list"); + return Collections.emptyList(); + } + }); + + assertThat(outputs).isEmpty(); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/DatabaseCommands.java b/sonar-db/src/test/java/org/sonar/db/DatabaseCommands.java new file mode 100644 index 00000000000..626933d4aef --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/DatabaseCommands.java @@ -0,0 +1,211 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Arrays; +import java.util.List; +import javax.sql.DataSource; +import org.apache.commons.dbutils.DbUtils; +import org.apache.commons.lang.StringUtils; +import org.dbunit.dataset.datatype.DefaultDataTypeFactory; +import org.dbunit.dataset.datatype.IDataTypeFactory; +import org.dbunit.dataset.datatype.ToleratedDeltaMap; +import org.dbunit.ext.h2.H2DataTypeFactory; +import org.dbunit.ext.mssql.MsSqlDataTypeFactory; +import org.dbunit.ext.mysql.MySqlDataTypeFactory; +import org.dbunit.ext.oracle.Oracle10DataTypeFactory; +import org.dbunit.ext.postgresql.PostgresqlDataTypeFactory; +import org.sonar.db.dialect.Dialect; +import org.sonar.db.dialect.MsSql; +import org.sonar.db.dialect.MySql; +import org.sonar.db.dialect.Oracle; +import org.sonar.db.dialect.PostgreSql; +import org.sonar.db.version.DatabaseVersion; + +public abstract class DatabaseCommands { + private final IDataTypeFactory dbUnitFactory; + + private DatabaseCommands(DefaultDataTypeFactory dbUnitFactory) { + this.dbUnitFactory = dbUnitFactory; + + // Hack for MsSQL failure in IssueMapperTest. + // All the Double fields should be listed here. + dbUnitFactory.addToleratedDelta(new ToleratedDeltaMap.ToleratedDelta("issues", "effort_to_fix", 0.0001)); + } + + public final IDataTypeFactory getDbUnitFactory() { + return dbUnitFactory; + } + + abstract List<String> resetSequenceSql(String table, int minSequenceValue); + + String truncateSql(String table) { + return "TRUNCATE TABLE " + table; + } + + boolean useLoginAsSchema() { + return false; + } + + public static DatabaseCommands forDialect(Dialect dialect) { + DatabaseCommands command = ImmutableMap.of( + org.sonar.db.dialect.H2.ID, H2, + MsSql.ID, MSSQL, + MySql.ID, MYSQL, + Oracle.ID, ORACLE, + PostgreSql.ID, POSTGRESQL).get(dialect.getId()); + + return Preconditions.checkNotNull(command, "Unknown database: " + dialect); + } + + private static final DatabaseCommands H2 = new DatabaseCommands(new H2DataTypeFactory()) { + @Override + List<String> resetSequenceSql(String table, int minSequenceValue) { + return Arrays.asList("ALTER TABLE " + table + " ALTER COLUMN ID RESTART WITH " + minSequenceValue); + } + }; + + private static final DatabaseCommands POSTGRESQL = new DatabaseCommands(new PostgresqlDataTypeFactory()) { + @Override + List<String> resetSequenceSql(String table, int minSequenceValue) { + return Arrays.asList("ALTER SEQUENCE " + table + "_id_seq RESTART WITH " + minSequenceValue); + } + }; + + private static final DatabaseCommands ORACLE = new DatabaseCommands(new Oracle10DataTypeFactory()) { + @Override + List<String> resetSequenceSql(String table, int minSequenceValue) { + String sequence = StringUtils.upperCase(table) + "_SEQ"; + return Arrays.asList( + "DROP SEQUENCE " + sequence, + "CREATE SEQUENCE " + sequence + " INCREMENT BY 1 MINVALUE 1 START WITH " + minSequenceValue); + } + + @Override + String truncateSql(String table) { + return "TRUNCATE TABLE " + table + " REUSE STORAGE"; + } + + @Override + boolean useLoginAsSchema() { + return true; + } + }; + + private static final DatabaseCommands MSSQL = new DatabaseCommands(new MsSqlDataTypeFactory()) { + @Override + public void resetPrimaryKeys(DataSource dataSource) { + } + + @Override + List<String> resetSequenceSql(String table, int minSequenceValue) { + return null; + } + + @Override + protected boolean shouldTruncate(Connection connection, String table) throws SQLException { + // truncate all tables on mssql, else unexpected errors in some tests + return true; + } + }; + + private static final DatabaseCommands MYSQL = new DatabaseCommands(new MySqlDataTypeFactory()) { + @Override + public void resetPrimaryKeys(DataSource dataSource) { + } + + @Override + List<String> resetSequenceSql(String table, int minSequenceValue) { + return null; + } + }; + + public void truncateDatabase(DataSource dataSource) throws SQLException { + Connection connection = dataSource.getConnection(); + Statement statement = null; + try { + connection.setAutoCommit(false); + statement = connection.createStatement(); + for (String table : DatabaseVersion.TABLES) { + try { + if (shouldTruncate(connection, table)) { + statement.executeUpdate(truncateSql(table)); + connection.commit(); + } + } catch (Exception e) { + connection.rollback(); + throw new IllegalStateException("Fail to truncate table " + table, e); + } + } + } finally { + DbUtils.closeQuietly(connection); + DbUtils.closeQuietly(statement); + } + } + + protected boolean shouldTruncate(Connection connection, String table) throws SQLException { + Statement stmt = connection.createStatement(); + ResultSet rs = null; + try { + rs = stmt.executeQuery("select count(*) from " + table); + if (rs.next()) { + return rs.getInt(1) > 0; + } + + } catch (SQLException ignored) { + // probably because table does not exist. That's the case with H2 tests. + } finally { + DbUtils.closeQuietly(rs); + DbUtils.closeQuietly(stmt); + } + return false; + } + + public void resetPrimaryKeys(DataSource dataSource) throws SQLException { + Connection connection = dataSource.getConnection(); + connection.setAutoCommit(false); + + Statement statement = connection.createStatement(); + for (String table : DatabaseVersion.TABLES) { + try { + ResultSet result = statement.executeQuery("SELECT CASE WHEN MAX(ID) IS NULL THEN 1 ELSE MAX(ID)+1 END FROM " + table); + result.next(); + int maxId = result.getInt(1); + result.close(); + + for (String resetCommand : resetSequenceSql(table, maxId)) { + statement.executeUpdate(resetCommand); + } + connection.commit(); + } catch (Exception e) { + connection.rollback(); // this table has no primary key + } + } + + statement.close(); + connection.close(); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/DatabaseUtilsTest.java b/sonar-db/src/test/java/org/sonar/db/DatabaseUtilsTest.java new file mode 100644 index 00000000000..933e931ac03 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/DatabaseUtilsTest.java @@ -0,0 +1,145 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import org.junit.Test; +import org.sonar.db.dialect.Oracle; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +public class DatabaseUtilsTest extends AbstractDaoTestCase { + + @Test + public void should_close_connection() throws SQLException { + Connection connection = getConnection(); + assertThat(isClosed(connection)).isFalse(); + + DatabaseUtils.closeQuietly(connection); + assertThat(isClosed(connection)).isTrue(); + } + + @Test + public void should_support_null_connection() { + DatabaseUtils.closeQuietly((Connection) null); + // no failure + } + + @Test + public void should_close_statement_and_resultset() throws SQLException { + Connection connection = getConnection(); + try { + PreparedStatement statement = connection.prepareStatement(selectDual()); + ResultSet rs = statement.executeQuery(); + + DatabaseUtils.closeQuietly(rs); + DatabaseUtils.closeQuietly(statement); + + assertThat(isClosed(statement)).isTrue(); + assertThat(isClosed(rs)).isTrue(); + } finally { + DatabaseUtils.closeQuietly(connection); + } + } + + @Test + public void should_not_fail_on_connection_errors() throws SQLException { + Connection connection = mock(Connection.class); + doThrow(new SQLException()).when(connection).close(); + + DatabaseUtils.closeQuietly(connection); + + // no failure + verify(connection).close(); // just to be sure + } + + @Test + public void should_not_fail_on_statement_errors() throws SQLException { + Statement statement = mock(Statement.class); + doThrow(new SQLException()).when(statement).close(); + + DatabaseUtils.closeQuietly(statement); + + // no failure + verify(statement).close(); // just to be sure + } + + @Test + public void should_not_fail_on_resulset_errors() throws SQLException { + ResultSet rs = mock(ResultSet.class); + doThrow(new SQLException()).when(rs).close(); + + DatabaseUtils.closeQuietly(rs); + + // no failure + verify(rs).close(); // just to be sure + } + + /** + * Connection.isClosed() has been introduced in java 1.6 + */ + private boolean isClosed(Connection c) { + try { + c.createStatement().execute(selectDual()); + return false; + } catch (Exception e) { + return true; + } + } + + /** + * Statement.isClosed() has been introduced in java 1.6 + */ + private boolean isClosed(Statement s) { + try { + s.execute("SELECT 1"); + return false; + } catch (Exception e) { + return true; + } + } + + /** + * ResultSet.isClosed() has been introduced in java 1.6 + */ + private boolean isClosed(ResultSet rs) { + try { + rs.next(); + return false; + } catch (Exception e) { + return true; + } + } + + private String selectDual() { + String sql = "SELECT 1"; + if (Oracle.ID.equals(getDatabase().getDialect().getId())) { + sql = "SELECT 1 FROM DUAL"; + } + return sql; + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/DbTester.java b/sonar-db/src/test/java/org/sonar/db/DbTester.java new file mode 100644 index 00000000000..ba428c5cbe8 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/DbTester.java @@ -0,0 +1,453 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db; + +import com.google.common.base.Preconditions; +import com.google.common.collect.Maps; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.math.BigDecimal; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.URISyntaxException; +import java.sql.Clob; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.dbutils.QueryRunner; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.text.StrSubstitutor; +import org.dbunit.Assertion; +import org.dbunit.DataSourceDatabaseTester; +import org.dbunit.DatabaseUnitException; +import org.dbunit.IDatabaseTester; +import org.dbunit.assertion.DiffCollectingFailureHandler; +import org.dbunit.assertion.Difference; +import org.dbunit.database.DatabaseConfig; +import org.dbunit.database.IDatabaseConnection; +import org.dbunit.dataset.CompositeDataSet; +import org.dbunit.dataset.IDataSet; +import org.dbunit.dataset.ITable; +import org.dbunit.dataset.ReplacementDataSet; +import org.dbunit.dataset.filter.DefaultColumnFilter; +import org.dbunit.dataset.xml.FlatXmlDataSet; +import org.dbunit.ext.mssql.InsertIdentityOperation; +import org.dbunit.operation.DatabaseOperation; +import org.junit.AssumptionViolatedException; +import org.junit.rules.ExternalResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.config.Settings; +import org.sonar.db.deprecated.NullQueue; +import org.sonar.db.dialect.Dialect; + +import static com.google.common.collect.Lists.newArrayList; +import static com.google.common.collect.Maps.newHashMap; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.fail; + +/** + * This class should be call using @ClassRule in order to create the schema once (ft @Rule is used + * the schema will be recreated before each test). + * Data will be truncated each time you call prepareDbUnit(). + * <p/> + * File using {@link DbTester} must be annotated with {@link org.sonar.test.DbTests} so + * that they can be executed on all supported DBs (Oracle, MySQL, ...). + */ +public class DbTester extends ExternalResource { + + private static final Logger LOG = LoggerFactory.getLogger(DbTester.class); + + private Database db; + private DatabaseCommands commands; + private IDatabaseTester tester; + private MyBatis myBatis; + private String schemaPath = null; + + public DbTester schema(Class baseClass, String filename) { + String path = StringUtils.replaceChars(baseClass.getCanonicalName(), '.', '/'); + schemaPath = path + "/" + filename; + return this; + } + + @Override + protected void before() throws Throwable { + Settings settings = new Settings().setProperties(Maps.fromProperties(System.getProperties())); + if (settings.hasKey("orchestrator.configUrl")) { + loadOrchestratorSettings(settings); + } + String login = settings.getString("sonar.jdbc.username"); + for (String key : settings.getKeysStartingWith("sonar.jdbc")) { + LOG.info(key + ": " + settings.getString(key)); + } + String dialect = settings.getString("sonar.jdbc.dialect"); + if (dialect != null && !"h2".equals(dialect)) { + db = new DefaultDatabase(settings); + } else { + db = new H2Database("h2Tests" + DigestUtils.md5Hex(StringUtils.defaultString(schemaPath)), schemaPath == null); + } + db.start(); + if (schemaPath != null) { + // will fail if not H2 + if (db.getDialect().getId().equals("h2")) { + ((H2Database) db).executeScript(schemaPath); + } else { + db.stop(); + throw new AssumptionViolatedException("Test disabled because it supports only H2"); + } + } + LOG.info("Test Database: " + db); + + commands = DatabaseCommands.forDialect(db.getDialect()); + tester = new DataSourceDatabaseTester(db.getDataSource(), commands.useLoginAsSchema() ? login : null); + + myBatis = new MyBatis(db, new NullQueue()); + myBatis.start(); + + truncateTables(); + } + + public void truncateTables() { + try { + commands.truncateDatabase(db.getDataSource()); + } catch (SQLException e) { + throw new IllegalStateException("Fail to truncate db tables", e); + } + } + + @Override + protected void after() { + db.stop(); + db = null; + myBatis = null; + } + + public Database database() { + return db; + } + + public Dialect dialect() { + return db.getDialect(); + } + + public MyBatis myBatis() { + return myBatis; + } + + public Connection openConnection() throws SQLException { + return db.getDataSource().getConnection(); + } + + public void executeUpdateSql(String sql) { + try (Connection connection = openConnection()) { + new QueryRunner().update(connection, sql); + } catch (Exception e) { + throw new IllegalStateException("Fail to execute sql: " + sql); + } + } + + /** + * Returns the number of rows in the table. Example: + * <pre>int issues = countTable("issues")</pre> + */ + public int countRowsOfTable(String tableName) { + Preconditions.checkArgument(StringUtils.containsNone(tableName, " "), "Parameter must be the name of a table. Got " + tableName); + return countSql("select count(*) from " + tableName); + } + + /** + * Executes a SQL request starting with "SELECT COUNT(something) FROM", for example: + * <pre>int OpenIssues = countSql("select count('id') from issues where status is not null")</pre> + */ + public int countSql(String sql) { + Preconditions.checkArgument(StringUtils.contains(sql, "count("), + "Parameter must be a SQL request containing 'count(x)' function. Got " + sql); + try ( + Connection connection = openConnection(); + PreparedStatement stmt = connection.prepareStatement(sql); + ResultSet rs = stmt.executeQuery()) { + if (rs.next()) { + return rs.getInt(1); + } + throw new IllegalStateException("No results for " + sql); + + } catch (Exception e) { + throw new IllegalStateException("Fail to execute sql: " + sql, e); + } + } + + public List<Map<String, Object>> select(String selectSql) { + try ( + Connection connection = openConnection(); + PreparedStatement stmt = connection.prepareStatement(selectSql); + ResultSet rs = stmt.executeQuery()) { + return getHashMap(rs); + } catch (Exception e) { + throw new IllegalStateException("Fail to execute sql: " + selectSql, e); + } + } + + public Map<String, Object> selectFirst(String selectSql) { + List<Map<String, Object>> rows = select(selectSql); + if (rows.isEmpty()) { + throw new IllegalStateException("No results for " + selectSql); + } else if (rows.size() > 1) { + throw new IllegalStateException("Too many results for " + selectSql); + } + return rows.get(0); + } + + private static List<Map<String, Object>> getHashMap(ResultSet resultSet) throws Exception { + ResultSetMetaData metaData = resultSet.getMetaData(); + int colCount = metaData.getColumnCount(); + List<Map<String, Object>> rows = newArrayList(); + while (resultSet.next()) { + Map<String, Object> columns = newHashMap(); + for (int i = 1; i <= colCount; i++) { + Object value = resultSet.getObject(i); + if (value instanceof Clob) { + Clob clob = (Clob) value; + value = IOUtils.toString((clob.getAsciiStream())); + doClobFree(clob); + } else if (value instanceof BigDecimal) { + // In Oracle, INTEGER types are mapped as BigDecimal + BigDecimal bgValue = ((BigDecimal) value); + if (bgValue.scale() == 0) { + value = bgValue.longValue(); + } else { + value = bgValue.doubleValue(); + } + } else if (value instanceof Integer) { + // To be consistent, all INTEGER types are mapped as Long + value = ((Integer) value).longValue(); + } + columns.put(metaData.getColumnLabel(i), value); + } + rows.add(columns); + } + return rows; + } + + public void prepareDbUnit(Class testClass, String... testNames) { + InputStream[] streams = new InputStream[testNames.length]; + try { + // Purge previous data + commands.truncateDatabase(db.getDataSource()); + + for (int i = 0; i < testNames.length; i++) { + String path = "/" + testClass.getName().replace('.', '/') + "/" + testNames[i]; + streams[i] = testClass.getResourceAsStream(path); + if (streams[i] == null) { + throw new IllegalStateException("DbUnit file not found: " + path); + } + } + + prepareDbUnit(streams); + commands.resetPrimaryKeys(db.getDataSource()); + } catch (SQLException e) { + throw translateException("Could not setup DBUnit data", e); + } finally { + for (InputStream stream : streams) { + IOUtils.closeQuietly(stream); + } + } + } + + private void prepareDbUnit(InputStream... dataSetStream) { + IDatabaseConnection connection = null; + try { + IDataSet[] dataSets = new IDataSet[dataSetStream.length]; + for (int i = 0; i < dataSetStream.length; i++) { + dataSets[i] = dbUnitDataSet(dataSetStream[i]); + } + tester.setDataSet(new CompositeDataSet(dataSets)); + connection = dbUnitConnection(); + new InsertIdentityOperation(DatabaseOperation.INSERT).execute(connection, tester.getDataSet()); + } catch (Exception e) { + throw translateException("Could not setup DBUnit data", e); + } finally { + closeQuietly(connection); + } + } + + public void assertDbUnit(Class testClass, String filename, String... tables) { + assertDbUnit(testClass, filename, new String[0], tables); + } + + public void assertDbUnit(Class testClass, String filename, String[] excludedColumnNames, String... tables) { + IDatabaseConnection connection = null; + try { + connection = dbUnitConnection(); + + IDataSet dataSet = connection.createDataSet(); + String path = "/" + testClass.getName().replace('.', '/') + "/" + filename; + InputStream inputStream = testClass.getResourceAsStream(path); + if (inputStream == null) { + throw new IllegalStateException(String.format("File '%s' does not exist", path)); + } + IDataSet expectedDataSet = dbUnitDataSet(inputStream); + for (String table : tables) { + DiffCollectingFailureHandler diffHandler = new DiffCollectingFailureHandler(); + + ITable filteredTable = DefaultColumnFilter.excludedColumnsTable(dataSet.getTable(table), excludedColumnNames); + ITable filteredExpectedTable = DefaultColumnFilter.excludedColumnsTable(expectedDataSet.getTable(table), excludedColumnNames); + Assertion.assertEquals(filteredExpectedTable, filteredTable, diffHandler); + // Evaluate the differences and ignore some column values + List diffList = diffHandler.getDiffList(); + for (Object o : diffList) { + Difference diff = (Difference) o; + if (!"[ignore]".equals(diff.getExpectedValue())) { + throw new DatabaseUnitException(diff.toString()); + } + } + } + } catch (DatabaseUnitException e) { + fail(e.getMessage()); + } catch (Exception e) { + throw translateException("Error while checking results", e); + } finally { + closeQuietly(connection); + } + } + + public void assertColumnDefinition(String table, String column, int expectedType, @Nullable Integer expectedSize) { + try (Connection connection = openConnection(); + PreparedStatement stmt = connection.prepareStatement("select * from " + table); + ResultSet res = stmt.executeQuery()) { + Integer columnIndex = getColumnIndex(res, column); + if (columnIndex == null) { + fail("The column '" + column + "' does not exist"); + } + + assertThat(res.getMetaData().getColumnType(columnIndex)).isEqualTo(expectedType); + if (expectedSize != null) { + assertThat(res.getMetaData().getColumnDisplaySize(columnIndex)).isEqualTo(expectedSize); + } + + } catch (Exception e) { + throw new IllegalStateException("Fail to check column"); + } + } + + @CheckForNull + private Integer getColumnIndex(ResultSet res, String column) { + try { + ResultSetMetaData meta = res.getMetaData(); + int numCol = meta.getColumnCount(); + for (int i = 1; i < numCol + 1; i++) { + if (meta.getColumnLabel(i).toLowerCase().equals(column.toLowerCase())) { + return i; + } + } + return null; + + } catch (Exception e) { + throw new IllegalStateException("Fail to get column idnex"); + } + } + + private IDataSet dbUnitDataSet(InputStream stream) { + try { + ReplacementDataSet dataSet = new ReplacementDataSet(new FlatXmlDataSet(stream)); + dataSet.addReplacementObject("[null]", null); + dataSet.addReplacementObject("[false]", Boolean.FALSE); + dataSet.addReplacementObject("[true]", Boolean.TRUE); + + return dataSet; + } catch (Exception e) { + throw translateException("Could not read the dataset stream", e); + } + } + + private IDatabaseConnection dbUnitConnection() { + try { + IDatabaseConnection connection = tester.getConnection(); + connection.getConfig().setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, commands.getDbUnitFactory()); + return connection; + } catch (Exception e) { + throw translateException("Error while getting connection", e); + } + } + + private void closeQuietly(IDatabaseConnection connection) { + try { + if (connection != null) { + connection.close(); + } + } catch (SQLException e) { + // ignore + } + } + + private static RuntimeException translateException(String msg, Exception cause) { + RuntimeException runtimeException = new RuntimeException(String.format("%s: [%s] %s", msg, cause.getClass().getName(), cause.getMessage())); + runtimeException.setStackTrace(cause.getStackTrace()); + return runtimeException; + } + + private void loadOrchestratorSettings(Settings settings) throws URISyntaxException, IOException { + String url = settings.getString("orchestrator.configUrl"); + URI uri = new URI(url); + InputStream input = null; + try { + if (url.startsWith("file:")) { + File file = new File(uri); + input = FileUtils.openInputStream(file); + } else { + HttpURLConnection connection = (HttpURLConnection) uri.toURL().openConnection(); + int responseCode = connection.getResponseCode(); + if (responseCode >= 400) { + throw new IllegalStateException("Fail to request: " + uri + ". Status code=" + responseCode); + } + + input = connection.getInputStream(); + + } + Properties props = new Properties(); + props.load(input); + settings.addProperties(props); + for (Map.Entry<String, String> entry : settings.getProperties().entrySet()) { + String interpolatedValue = StrSubstitutor.replace(entry.getValue(), System.getenv(), "${", "}"); + settings.setProperty(entry.getKey(), interpolatedValue); + } + } finally { + IOUtils.closeQuietly(input); + } + } + + private static void doClobFree(Clob clob) throws SQLException { + try { + clob.free(); + } catch (AbstractMethodError e) { + // JTS driver do not implement free() as it's using JDBC 3.0 + } + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/DdlUtilsTest.java b/sonar-db/src/test/java/org/sonar/db/DdlUtilsTest.java new file mode 100644 index 00000000000..ddc7764b350 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/DdlUtilsTest.java @@ -0,0 +1,63 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import org.assertj.core.api.Assertions; +import org.h2.Driver; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class DdlUtilsTest { + + @Test + public void shouldSupportOnlyH2() { + Assertions.assertThat(DdlUtils.supportsDialect("h2")).isTrue(); + assertThat(DdlUtils.supportsDialect("mysql")).isFalse(); + assertThat(DdlUtils.supportsDialect("oracle")).isFalse(); + assertThat(DdlUtils.supportsDialect("mssql")).isFalse(); + } + + @Test + public void shouldCreateSchema() throws SQLException { + DriverManager.registerDriver(new Driver()); + Connection connection = DriverManager.getConnection("jdbc:h2:mem:sonar_test"); + DdlUtils.createSchema(connection, "h2"); + + int tableCount = countTables(connection); + + connection.close(); + assertThat(tableCount).isGreaterThan(30); + } + + static int countTables(Connection connection) throws SQLException { + int count = 0; + ResultSet resultSet = connection.getMetaData().getTables("", null, null, new String[] {"TABLE"}); + while (resultSet.next()) { + count++; + } + resultSet.close(); + return count; + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/DefaultDatabaseTest.java b/sonar-db/src/test/java/org/sonar/db/DefaultDatabaseTest.java new file mode 100644 index 00000000000..8fda6636030 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/DefaultDatabaseTest.java @@ -0,0 +1,126 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db; + +import java.util.Properties; +import org.apache.commons.dbcp.BasicDataSource; +import org.junit.Test; +import org.sonar.api.config.Settings; +import org.sonar.db.dialect.PostgreSql; + +import static org.assertj.core.api.Assertions.assertThat; + +public class DefaultDatabaseTest { + + @Test + public void shouldLoadDefaultValues() { + DefaultDatabase db = new DefaultDatabase(new Settings()); + db.initSettings(); + + Properties props = db.getProperties(); + assertThat(props.getProperty("sonar.jdbc.username")).isEqualTo("sonar"); + assertThat(props.getProperty("sonar.jdbc.password")).isEqualTo("sonar"); + assertThat(props.getProperty("sonar.jdbc.url")).isEqualTo("jdbc:h2:tcp://localhost/sonar"); + assertThat(props.getProperty("sonar.jdbc.driverClassName")).isEqualTo("org.h2.Driver"); + assertThat(db.toString()).isEqualTo("Database[jdbc:h2:tcp://localhost/sonar]"); + } + + @Test + public void shouldSupportDeprecatedUserProperty() { + Settings settings = new Settings(); + settings.setProperty("sonar.jdbc.user", "me"); + + DefaultDatabase db = new DefaultDatabase(settings); + db.initSettings(); + Properties props = db.getProperties(); + + assertThat(props.getProperty("sonar.jdbc.username")).isEqualTo("me"); + } + + @Test + public void shouldExtractCommonsDbcpProperties() { + Properties props = new Properties(); + props.setProperty("sonar.jdbc.driverClassName", "my.Driver"); + props.setProperty("sonar.jdbc.username", "me"); + props.setProperty("sonar.jdbc.maxActive", "5"); + + Properties commonsDbcpProps = DefaultDatabase.extractCommonsDbcpProperties(props); + + assertThat(commonsDbcpProps.getProperty("username")).isEqualTo("me"); + assertThat(commonsDbcpProps.getProperty("driverClassName")).isEqualTo("my.Driver"); + assertThat(commonsDbcpProps.getProperty("maxActive")).isEqualTo("5"); + } + + @Test + public void shouldCompleteProperties() { + Settings settings = new Settings(); + + DefaultDatabase db = new DefaultDatabase(settings) { + @Override + protected void doCompleteProperties(Properties properties) { + properties.setProperty("sonar.jdbc.maxActive", "2"); + } + }; + db.initSettings(); + + Properties props = db.getProperties(); + + assertThat(props.getProperty("sonar.jdbc.maxActive")).isEqualTo("2"); + } + + @Test + public void shouldStart() { + Settings settings = new Settings(); + settings.setProperty("sonar.jdbc.url", "jdbc:h2:mem:sonar"); + settings.setProperty("sonar.jdbc.driverClassName", "org.h2.Driver"); + settings.setProperty("sonar.jdbc.username", "sonar"); + settings.setProperty("sonar.jdbc.password", "sonar"); + settings.setProperty("sonar.jdbc.maxActive", "1"); + + DefaultDatabase db = new DefaultDatabase(settings); + db.start(); + db.stop(); + + assertThat(db.getDialect().getId()).isEqualTo("h2"); + assertThat(((BasicDataSource) db.getDataSource()).getMaxActive()).isEqualTo(1); + } + + @Test + public void shouldGuessDialectFromUrl() { + Settings settings = new Settings(); + settings.setProperty("sonar.jdbc.url", "jdbc:postgresql://localhost/sonar"); + + DefaultDatabase database = new DefaultDatabase(settings); + database.initSettings(); + + assertThat(database.getDialect().getId()).isEqualTo(PostgreSql.ID); + } + + @Test + public void shouldGuessDefaultDriver() { + Settings settings = new Settings(); + settings.setProperty("sonar.jdbc.url", "jdbc:postgresql://localhost/sonar"); + + DefaultDatabase database = new DefaultDatabase(settings); + database.initSettings(); + + assertThat(database.getProperties().getProperty("sonar.jdbc.driverClassName")).isEqualTo("org.postgresql.Driver"); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/H2Database.java b/sonar-db/src/test/java/org/sonar/db/H2Database.java new file mode 100644 index 00000000000..688211e31b2 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/H2Database.java @@ -0,0 +1,115 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db; + +import java.sql.Connection; +import java.sql.SQLException; +import javax.sql.DataSource; +import org.apache.commons.dbcp.BasicDataSource; +import org.apache.commons.dbutils.DbUtils; +import org.sonar.db.dialect.Dialect; +import org.sonar.db.dialect.H2; + +/** + * H2 in-memory database, used for unit tests only. + * + * @since 3.2 + */ +public class H2Database implements Database { + private final String name; + private final boolean createSchema; + private BasicDataSource datasource; + + /** + * IMPORTANT: change DB name in order to not conflict with {@link DefaultDatabaseTest} + */ + public H2Database(String name, boolean createSchema) { + this.name = name; + this.createSchema = createSchema; + } + + @Override + public void start() { + startDatabase(); + if (createSchema) { + createSchema(); + } + } + + private void startDatabase() { + try { + datasource = new BasicDataSource(); + datasource.setDriverClassName("org.h2.Driver"); + datasource.setUsername("sonar"); + datasource.setPassword("sonar"); + datasource.setUrl("jdbc:h2:mem:" + name); + } catch (Exception e) { + throw new IllegalStateException("Fail to start H2", e); + } + } + + private void createSchema() { + Connection connection = null; + try { + connection = datasource.getConnection(); + DdlUtils.createSchema(connection, "h2"); + + } catch (SQLException e) { + throw new IllegalStateException("Fail to create schema", e); + } finally { + DbUtils.closeQuietly(connection); + } + } + + public void executeScript(String classloaderPath) { + Connection connection = null; + try { + connection = datasource.getConnection(); + DdlUtils.executeScript(connection, classloaderPath); + + } catch (SQLException e) { + throw new IllegalStateException("Fail to execute script: " + classloaderPath, e); + } finally { + DbUtils.closeQuietly(connection); + } + } + + @Override + public void stop() { + try { + datasource.close(); + } catch (SQLException e) { + // Ignore error + } + } + + public DataSource getDataSource() { + return datasource; + } + + public Dialect getDialect() { + return new H2(); + } + + @Override + public String toString() { + return "H2 Database[" + name + "]"; + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/H2DatabaseTest.java b/sonar-db/src/test/java/org/sonar/db/H2DatabaseTest.java new file mode 100644 index 00000000000..363fcc6619b --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/H2DatabaseTest.java @@ -0,0 +1,51 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db; + +import java.sql.Connection; +import java.sql.SQLException; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class H2DatabaseTest { + H2Database db = new H2Database("sonar2", true); + + @Before + public void startDb() { + db.start(); + } + + @After + public void stopDb() { + db.stop(); + } + + @Test + public void shouldExecuteDdlAtStartup() throws SQLException { + Connection connection = db.getDataSource().getConnection(); + int tableCount = DdlUtilsTest.countTables(connection); + connection.close(); + + assertThat(tableCount).isGreaterThan(30); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/IsAliveMapperTest.java b/sonar-db/src/test/java/org/sonar/db/IsAliveMapperTest.java new file mode 100644 index 00000000000..02b9c6b4427 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/IsAliveMapperTest.java @@ -0,0 +1,55 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db; + +import org.junit.After; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.sonar.test.DbTests; + +import static org.assertj.core.api.Assertions.assertThat; + +@Category(DbTests.class) +public class IsAliveMapperTest { + + @ClassRule + public static DbTester dbTester = new DbTester(); + + DbSession session; + IsAliveMapper underTest; + + @Before + public void setUp() { + session = dbTester.myBatis().openSession(false); + underTest = session.getMapper(IsAliveMapper.class); + } + + @After + public void tearDown() { + session.close(); + } + + @Test + public void isAlive_works_for_current_vendors() { + assertThat(underTest.isAlive()).isEqualTo(IsAliveMapper.IS_ALIVE_RETURNED_VALUE); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/MyBatisTest.java b/sonar-db/src/test/java/org/sonar/db/MyBatisTest.java new file mode 100644 index 00000000000..194346fe0a0 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/MyBatisTest.java @@ -0,0 +1,74 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db; + +import org.apache.ibatis.session.Configuration; +import org.apache.ibatis.session.SqlSession; +import org.hamcrest.core.Is; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.sonar.db.deprecated.WorkQueue; +import org.sonar.db.rule.RuleMapper; + +import static org.hamcrest.Matchers.notNullValue; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; + +public class MyBatisTest { + private static H2Database database; + private WorkQueue<?> queue = mock(WorkQueue.class); + + @BeforeClass + public static void start() { + database = new H2Database("sonar2", true); + database.start(); + } + + @AfterClass + public static void stop() { + database.stop(); + } + + @Test + public void shouldConfigureMyBatis() { + MyBatis myBatis = new MyBatis(database, queue); + myBatis.start(); + + Configuration conf = myBatis.getSessionFactory().getConfiguration(); + assertThat(conf.isUseGeneratedKeys(), Is.is(true)); + assertThat(conf.hasMapper(RuleMapper.class), Is.is(true)); + assertThat(conf.isLazyLoadingEnabled(), Is.is(false)); + } + + @Test + public void shouldOpenBatchSession() { + MyBatis myBatis = new MyBatis(database, queue); + myBatis.start(); + + SqlSession session = myBatis.openBatchSession(); + try { + assertThat(session.getConnection(), notNullValue()); + assertThat(session.getMapper(RuleMapper.class), notNullValue()); + } finally { + session.close(); + } + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/component/ComponentDtoTest.java b/sonar-db/src/test/java/org/sonar/db/component/ComponentDtoTest.java new file mode 100644 index 00000000000..c1dc490f695 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/component/ComponentDtoTest.java @@ -0,0 +1,90 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.component; + +import org.junit.Test; +import org.sonar.api.resources.Qualifiers; +import org.sonar.api.resources.Scopes; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ComponentDtoTest { + + @Test + public void setters_and_getters() { + ComponentDto componentDto = new ComponentDto() + .setId(1L) + .setKey("org.struts:struts-core:src/org/struts/RequestContext.java") + .setDeprecatedKey("org.struts:struts-core:src/org/struts/RequestContext.java") + .setName("RequestContext.java") + .setLongName("org.struts.RequestContext") + .setQualifier("FIL") + .setScope("FIL") + .setLanguage("java") + .setDescription("desc") + .setPath("src/org/struts/RequestContext.java") + .setCopyResourceId(5L) + .setParentProjectId(3L) + .setAuthorizationUpdatedAt(123456789L); + + assertThat(componentDto.getId()).isEqualTo(1L); + assertThat(componentDto.key()).isEqualTo("org.struts:struts-core:src/org/struts/RequestContext.java"); + assertThat(componentDto.deprecatedKey()).isEqualTo("org.struts:struts-core:src/org/struts/RequestContext.java"); + assertThat(componentDto.name()).isEqualTo("RequestContext.java"); + assertThat(componentDto.longName()).isEqualTo("org.struts.RequestContext"); + assertThat(componentDto.qualifier()).isEqualTo("FIL"); + assertThat(componentDto.scope()).isEqualTo("FIL"); + assertThat(componentDto.path()).isEqualTo("src/org/struts/RequestContext.java"); + assertThat(componentDto.language()).isEqualTo("java"); + assertThat(componentDto.description()).isEqualTo("desc"); + assertThat(componentDto.parentProjectId()).isEqualTo(3L); + assertThat(componentDto.getCopyResourceId()).isEqualTo(5L); + assertThat(componentDto.getAuthorizationUpdatedAt()).isEqualTo(123456789L); + } + + @Test + public void equals_and_hashcode() { + ComponentDto dto = new ComponentDto().setId(1L); + ComponentDto dtoWithSameId = new ComponentDto().setId(1L); + ComponentDto dtoWithDifferentId = new ComponentDto().setId(2L); + + assertThat(dto).isEqualTo(dto); + assertThat(dto).isEqualTo(dtoWithSameId); + assertThat(dto).isNotEqualTo(dtoWithDifferentId); + + assertThat(dto.hashCode()).isEqualTo(dto.hashCode()); + assertThat(dto.hashCode()).isEqualTo(dtoWithSameId.hashCode()); + assertThat(dto.hashCode()).isNotEqualTo(dtoWithDifferentId.hashCode()); + } + + @Test + public void toString_does_not_fail_if_empty() { + ComponentDto dto = new ComponentDto(); + assertThat(dto.toString()).isNotEmpty(); + } + + @Test + public void is_root_project() { + assertThat(new ComponentDto().setModuleUuid("ABCD").isRootProject()).isFalse(); + assertThat(new ComponentDto().setModuleUuid("ABCD").setScope(Scopes.DIRECTORY).isRootProject()).isFalse(); + assertThat(new ComponentDto().setModuleUuid(null).setScope(Scopes.PROJECT).setQualifier(Qualifiers.PROJECT).isRootProject()).isTrue(); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/component/ComponentLinkDtoTest.java b/sonar-db/src/test/java/org/sonar/db/component/ComponentLinkDtoTest.java new file mode 100644 index 00000000000..165a3ea08f2 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/component/ComponentLinkDtoTest.java @@ -0,0 +1,49 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.component; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ComponentLinkDtoTest { + + @Test + public void test_getters_and_setters() throws Exception { + ComponentLinkDto dto = new ComponentLinkDto() + .setId(1L) + .setComponentUuid("ABCD") + .setType("homepage") + .setName("Home") + .setHref("http://www.sonarqube.org"); + + assertThat(dto.getId()).isEqualTo(1L); + assertThat(dto.getComponentUuid()).isEqualTo("ABCD"); + assertThat(dto.getType()).isEqualTo("homepage"); + assertThat(dto.getName()).isEqualTo("Home"); + assertThat(dto.getHref()).isEqualTo("http://www.sonarqube.org"); + } + + @Test + public void test_provided_types() throws Exception { + assertThat(ComponentLinkDto.PROVIDED_TYPES).hasSize(5); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/component/ResourceDaoTest.java b/sonar-db/src/test/java/org/sonar/db/component/ResourceDaoTest.java new file mode 100644 index 00000000000..a6c809330f1 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/component/ResourceDaoTest.java @@ -0,0 +1,470 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.component; + +import com.google.common.base.Function; +import com.google.common.collect.Iterables; +import java.util.Collections; +import java.util.List; +import javax.annotation.Nullable; +import org.apache.ibatis.session.SqlSession; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.component.Component; +import org.sonar.api.resources.Qualifiers; +import org.sonar.api.resources.Scopes; +import org.sonar.api.utils.System2; +import org.sonar.db.AbstractDaoTestCase; +import org.sonar.db.DbSession; + +import static com.google.common.collect.Lists.newArrayList; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class ResourceDaoTest extends AbstractDaoTestCase { + + private DbSession session; + + private ResourceDao dao; + private System2 system2; + + @Before + public void createDao() { + session = getMyBatis().openSession(false); + system2 = mock(System2.class); + when(system2.now()).thenReturn(1_500_000_000_000L); + dao = new ResourceDao(getMyBatis(), system2); + } + + @After + public void tearDown() { + session.close(); + } + + @Test + public void testDescendantProjects_do_not_include_self() { + setupData("fixture"); + + List<ResourceDto> resources = dao.getDescendantProjects(1L); + + assertThat(resources).extracting("id").containsOnly(2L); + } + + @Test + public void testDescendantProjects_id_not_found() { + setupData("fixture"); + + List<ResourceDto> resources = dao.getDescendantProjects(33333L); + + assertThat(resources).isEmpty(); + } + + @Test + public void get_resource_by_id() { + setupData("fixture"); + + ResourceDto resource = dao.getResource(1L); + + assertThat(resource.getUuid()).isEqualTo("ABCD"); + assertThat(resource.getProjectUuid()).isEqualTo("ABCD"); + assertThat(resource.getPath()).isNull(); + assertThat(resource.getName()).isEqualTo("Struts"); + assertThat(resource.getLongName()).isEqualTo("Apache Struts"); + assertThat(resource.getScope()).isEqualTo("PRJ"); + assertThat(resource.getDescription()).isEqualTo("the description"); + assertThat(resource.getLanguage()).isEqualTo("java"); + assertThat(resource.isEnabled()).isTrue(); + assertThat(resource.getAuthorizationUpdatedAt()).isNotNull(); + assertThat(resource.getCreatedAt()).isNotNull(); + } + + @Test + public void get_resource_by_uuid() { + setupData("fixture"); + + ResourceDto resource = dao.getResource("ABCD"); + + assertThat(resource.getUuid()).isEqualTo("ABCD"); + assertThat(resource.getProjectUuid()).isEqualTo("ABCD"); + assertThat(resource.getPath()).isNull(); + assertThat(resource.getName()).isEqualTo("Struts"); + assertThat(resource.getLongName()).isEqualTo("Apache Struts"); + assertThat(resource.getScope()).isEqualTo("PRJ"); + assertThat(resource.getDescription()).isEqualTo("the description"); + assertThat(resource.getLanguage()).isEqualTo("java"); + assertThat(resource.isEnabled()).isTrue(); + assertThat(resource.getAuthorizationUpdatedAt()).isNotNull(); + assertThat(resource.getCreatedAt()).isNotNull(); + } + + @Test + public void get_resource_path_and_module_key() { + setupData("fixture"); + + ResourceDto dir = dao.getResource(3L); + assertThat(dir.getPath()).isEqualTo("src/org/struts"); + + ResourceDto file = dao.getResource(4L); + assertThat(file.getPath()).isEqualTo("src/org/struts/RequestContext.java"); + } + + @Test + public void get_uuid() { + setupData("fixture"); + + ResourceDto file = dao.getResource(4L); + assertThat(file.getUuid()).isEqualTo("DEFG"); + assertThat(file.getProjectUuid()).isEqualTo("ABCD"); + assertThat(file.getModuleUuid()).isEqualTo("BCDE"); + assertThat(file.getModuleUuidPath()).isEqualTo(".ABCD.BCDE."); + } + + @Test + public void getResource_not_found() { + setupData("fixture"); + + assertThat(dao.getResource(987654321L)).isNull(); + } + + @Test + public void getResources_all() { + setupData("fixture"); + + List<ResourceDto> resources = dao.getResources(ResourceQuery.create()); + + assertThat(resources).hasSize(4); + } + + @Test + public void getResources_filter_by_qualifier() { + setupData("fixture"); + + List<ResourceDto> resources = dao.getResources(ResourceQuery.create().setQualifiers(new String[] {"TRK", "BRC"})); + assertThat(resources).extracting("qualifier").containsOnly("TRK", "BRC"); + + resources = dao.getResources(ResourceQuery.create().setQualifiers(new String[] {"XXX"})); + assertThat(resources).isEmpty(); + + resources = dao.getResources(ResourceQuery.create().setQualifiers(new String[] {})); + assertThat(resources).hasSize(4); + } + + @Test + public void getResources_filter_by_key() { + setupData("fixture"); + + ResourceQuery query = ResourceQuery.create().setKey("org.struts:struts-core"); + List<ResourceDto> resources = dao.getResources(query); + assertThat(resources).hasSize(1); + assertThat(resources.get(0).getKey()).isEqualTo("org.struts:struts-core"); + + assertThat(dao.getResource(query).getKey()).isEqualTo("org.struts:struts-core"); + } + + @Test + public void getResourceIds_all() { + setupData("fixture"); + + List<Long> ids = dao.getResourceIds(ResourceQuery.create()); + + assertThat(ids).hasSize(4); + } + + @Test + public void getResourceIds_filter_by_qualifier() { + setupData("fixture"); + + List<Long> ids = dao.getResourceIds(ResourceQuery.create().setQualifiers(new String[] {"TRK", "BRC"})); + assertThat(ids).containsOnly(1L, 2L); + + ids = dao.getResourceIds(ResourceQuery.create().setQualifiers(new String[] {"XXX"})); + assertThat(ids).isEmpty(); + + ids = dao.getResourceIds(ResourceQuery.create().setQualifiers(new String[] {})); + assertThat(ids).hasSize(4); + } + + @Test + public void getResources_exclude_disabled() { + setupData("getResources_exclude_disabled"); + + assertThat(dao.getResourceIds(ResourceQuery.create().setExcludeDisabled(false))).containsOnly(1L, 2L); + assertThat(dao.getResourceIds(ResourceQuery.create().setExcludeDisabled(true))).containsOnly(2L); + } + + @Test + public void find_root_project_by_component_key() { + setupData("fixture"); + + assertThat(dao.getRootProjectByComponentKey("org.struts:struts-core:src/org/struts/RequestContext.java").getKey()).isEqualTo("org.struts:struts"); + assertThat(dao.getRootProjectByComponentKey("org.struts:struts-core:src/org/struts").getKey()).isEqualTo("org.struts:struts"); + assertThat(dao.getRootProjectByComponentKey("org.struts:struts-core").getKey()).isEqualTo("org.struts:struts"); + assertThat(dao.getRootProjectByComponentKey("org.struts:struts").getKey()).isEqualTo("org.struts:struts"); + + assertThat(dao.getRootProjectByComponentKey("unknown")).isNull(); + } + + @Test + public void find_root_project_by_component_Id() { + setupData("fixture"); + + assertThat(dao.getRootProjectByComponentId(4l).getKey()).isEqualTo("org.struts:struts"); + assertThat(dao.getRootProjectByComponentId(3l).getKey()).isEqualTo("org.struts:struts"); + assertThat(dao.getRootProjectByComponentId(2l).getKey()).isEqualTo("org.struts:struts"); + assertThat(dao.getRootProjectByComponentId(1l).getKey()).isEqualTo("org.struts:struts"); + } + + @Test + public void find_parent_by_component_id() { + setupData("fixture"); + + assertThat(dao.getParentModuleByComponentId(4l, session).getKey()).isEqualTo("org.struts:struts"); + assertThat(dao.getParentModuleByComponentId(3l, session).getKey()).isEqualTo("org.struts:struts"); + assertThat(dao.getParentModuleByComponentId(2l, session).getKey()).isEqualTo("org.struts:struts"); + assertThat(dao.getParentModuleByComponentId(1l, session).getKey()).isEqualTo("org.struts:struts"); + } + + @Test + public void should_update() { + setupData("update"); + + ResourceDto project = new ResourceDto() + .setKey("org.struts:struts") + .setDeprecatedKey("deprecated key").setScope(Scopes.PROJECT).setQualifier(Qualifiers.PROJECT) + .setName("Struts").setLongName("Apache Struts").setLanguage("java").setDescription("MVC Framework") + .setPath("/foo/bar") + .setId(1L); + + dao.insertOrUpdate(project); + + assertThat(project.getId()).isNotNull(); + checkTables("update", "projects"); + } + + @Test + public void should_insert() { + setupData("insert"); + + ResourceDto file1 = new ResourceDto() + .setUuid("ABCD").setProjectUuid("EFGH").setModuleUuid("EFGH").setModuleUuidPath(".EFGH.") + .setKey("org.struts:struts:/src/main/java/org/struts/Action.java") + .setDeprecatedKey("org.struts:struts:org.struts.Action").setScope(Scopes.FILE).setQualifier(Qualifiers.FILE) + .setLanguage("java").setName("Action").setLongName("org.struts.Action").setPath("/foo/bar"); + ResourceDto file2 = new ResourceDto() + .setUuid("BCDE").setProjectUuid("FGHI").setModuleUuid("FGHI").setModuleUuidPath(".FGHI.") + .setKey("org.struts:struts:/src/main/java/org/struts/Filter.java") + .setDeprecatedKey("org.struts:struts:org.struts.Filter").setScope(Scopes.FILE).setQualifier(Qualifiers.FILE) + .setLanguage("java").setName("Filter").setLongName("org.struts.Filter"); + + dao.insertOrUpdate(file1, file2); + + assertThat(file1.getId()).isNotNull(); + assertThat(file2.getId()).isNotNull(); + checkTables("insert", new String[] {"authorization_updated_at", "created_at"}, "projects"); + + // SONAR-3636 : created_at must be fed when inserting a new entry in the 'projects' table + ResourceDto fileLoadedFromDB = dao.getResource(file1.getId()); + assertThat(fileLoadedFromDB.getCreatedAt()).isNotNull(); + assertThat(fileLoadedFromDB.getAuthorizationUpdatedAt()).isNotNull(); + } + + @Test + public void should_insert_using_existing_session() { + setupData("insert"); + + ResourceDto file1 = new ResourceDto().setUuid("ABCD") + .setKey("org.struts:struts:/src/main/java/org/struts/Action.java") + .setDeprecatedKey("org.struts:struts:org.struts.Action").setScope(Scopes.FILE).setQualifier(Qualifiers.FILE) + .setLanguage("java").setName("Action").setLongName("org.struts.Action"); + ResourceDto file2 = new ResourceDto().setUuid("BCDE") + .setKey("org.struts:struts:/src/main/java/org/struts/Filter.java") + .setDeprecatedKey("org.struts:struts:org.struts.Filter").setScope(Scopes.FILE).setQualifier(Qualifiers.FILE) + .setLanguage("java").setName("Filter").setLongName("org.struts.Filter"); + + SqlSession session = getMyBatis().openSession(); + + dao.insertUsingExistingSession(file1, session); + dao.insertUsingExistingSession(file2, session); + + session.rollback(); + + assertEmptyTables("projects"); + } + + @Test + public void insert_add_uuids_on_project_if_missing() { + setupData("insert"); + + ResourceDto project = new ResourceDto() + .setKey("org.struts:struts:struts") + .setScope(Scopes.PROJECT) + .setQualifier(Qualifiers.PROJECT); + + ResourceDto file = new ResourceDto() + .setKey("org.struts:struts:/src/main/java/org/struts/Action.java") + .setScope(Scopes.FILE) + .setQualifier(Qualifiers.FILE); + + dao.insertOrUpdate(project, file); + + assertThat(project.getUuid()).isNotNull(); + assertThat(project.getProjectUuid()).isEqualTo(project.getUuid()); + assertThat(project.getModuleUuidPath()).isEmpty(); + + assertThat(file.getUuid()).isNull(); + assertThat(file.getProjectUuid()).isNull(); + assertThat(file.getModuleUuidPath()).isNull(); + } + + @Test + public void should_find_component_by_key() { + setupData("fixture"); + + assertThat(dao.findByKey("org.struts:struts")).isNotNull(); + Component component = dao.findByKey("org.struts:struts-core:src/org/struts/RequestContext.java"); + assertThat(component).isNotNull(); + assertThat(component.path()).isEqualTo("src/org/struts/RequestContext.java"); + assertThat(dao.findByKey("unknown")).isNull(); + } + + @Test + public void should_find_component_by_id() { + setupData("fixture"); + + assertThat(dao.findById(1L, session)).isNotNull(); + assertThat(dao.findById(4L, session)).isNotNull(); + assertThat(dao.findById(555L, session)).isNull(); + } + + @Test + public void should_select_projects_by_qualifiers() { + setupData("fixture-including-ghost-projects-and-technical-project"); + + List<Component> components = dao.selectProjectsByQualifiers(newArrayList("TRK")); + assertThat(components).hasSize(1); + assertThat(components.get(0).key()).isEqualTo("org.struts:struts"); + assertThat(((ComponentDto) components.get(0)).getId()).isEqualTo(1L); + + assertThat(dao.selectProjectsIncludingNotCompletedOnesByQualifiers(newArrayList("unknown"))).isEmpty(); + assertThat(dao.selectProjectsIncludingNotCompletedOnesByQualifiers(Collections.<String>emptyList())).isEmpty(); + } + + @Test + public void should_select_projects_including_not_finished_by_qualifiers() { + setupData("fixture-including-ghost-projects-and-technical-project"); + + List<Component> components = dao.selectProjectsIncludingNotCompletedOnesByQualifiers(newArrayList("TRK")); + assertThat(getKeys(components)).containsOnly("org.struts:struts", "org.apache.shindig", "org.sample:sample"); + + assertThat(dao.selectProjectsIncludingNotCompletedOnesByQualifiers(newArrayList("unknown"))).isEmpty(); + assertThat(dao.selectProjectsIncludingNotCompletedOnesByQualifiers(Collections.<String>emptyList())).isEmpty(); + } + + @Test + public void should_select_ghosts_projects_by_qualifiers() { + setupData("fixture-including-ghost-projects-and-technical-project"); + + List<Component> components = dao.selectGhostsProjects(newArrayList("TRK")); + assertThat(components).hasSize(1); + assertThat(getKeys(components)).containsOnly("org.apache.shindig"); + + assertThat(dao.selectGhostsProjects(newArrayList("unknown"))).isEmpty(); + assertThat(dao.selectGhostsProjects(Collections.<String>emptyList())).isEmpty(); + } + + @Test + public void should_select_provisioned_projects_by_qualifiers() { + setupData("fixture-including-ghost-projects-and-technical-project"); + + List<ResourceDto> components = dao.selectProvisionedProjects(newArrayList("TRK")); + assertThat(components).hasSize(1); + assertThat(components.get(0).getKey()).isEqualTo("org.sample:sample"); + + assertThat(dao.selectProvisionedProjects(newArrayList("unknown"))).isEmpty(); + assertThat(dao.selectProvisionedProjects(Collections.<String>emptyList())).isEmpty(); + } + + @Test + public void should_select_provisioned_project_by_key() { + setupData("fixture-including-ghost-projects-and-technical-project"); + + String key = "org.sample:sample"; + assertThat(dao.selectProvisionedProject(key).getKey()).isEqualTo(key); + assertThat(dao.selectProvisionedProject("unknown")).isNull(); + } + + @Test + public void get_last_snapshot_by_component_uuid() { + setupData("get_last_snapshot_by_component_uuid"); + + SnapshotDto snapshotDto = dao.getLastSnapshotByResourceUuid("ABCD", session); + assertThat(snapshotDto.getId()).isEqualTo(1); + + assertThat(snapshotDto.getPeriodMode(1)).isEqualTo("previous_analysis"); + assertThat(snapshotDto.getPeriodModeParameter(1)).isNull(); + assertThat(snapshotDto.getPeriodDate(1)).isNull(); + + assertThat(snapshotDto.getPeriodMode(2)).isEqualTo("days"); + assertThat(snapshotDto.getPeriodModeParameter(2)).isEqualTo("30"); + assertThat(snapshotDto.getPeriodDate(2)).isEqualTo(1_316_815_200_000L); + + assertThat(snapshotDto.getPeriodMode(3)).isEqualTo("days"); + assertThat(snapshotDto.getPeriodModeParameter(3)).isEqualTo("90"); + assertThat(snapshotDto.getPeriodDate(3)).isEqualTo(1_311_631_200_000L); + + assertThat(snapshotDto.getPeriodMode(4)).isEqualTo("previous_analysis"); + assertThat(snapshotDto.getPeriodModeParameter(4)).isNull(); + assertThat(snapshotDto.getPeriodDate(4)).isNull(); + + assertThat(snapshotDto.getPeriodMode(5)).isEqualTo("previous_version"); + assertThat(snapshotDto.getPeriodModeParameter(5)).isNull(); + assertThat(snapshotDto.getPeriodDate(5)).isNull(); + + snapshotDto = dao.getLastSnapshotByResourceUuid("EFGH", session); + assertThat(snapshotDto.getId()).isEqualTo(2L); + + snapshotDto = dao.getLastSnapshotByResourceUuid("GHIJ", session); + assertThat(snapshotDto.getId()).isEqualTo(3L); + + assertThat(dao.getLastSnapshotByResourceUuid("UNKNOWN", session)).isNull(); + } + + @Test + public void update_authorization_date() { + setupData("update_authorization_date"); + + when(system2.now()).thenReturn(987654321L); + dao.updateAuthorizationDate(1L, session); + session.commit(); + + checkTables("update_authorization_date", "projects"); + } + + private List<String> getKeys(final List<Component> components) { + return newArrayList(Iterables.transform(components, new Function<Component, String>() { + @Override + public String apply(@Nullable Component input) { + return input.key(); + } + })); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/component/ResourceIndexerDaoTest.java b/sonar-db/src/test/java/org/sonar/db/component/ResourceIndexerDaoTest.java new file mode 100644 index 00000000000..90329d5842b --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/component/ResourceIndexerDaoTest.java @@ -0,0 +1,153 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.component; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import org.hamcrest.core.Is; +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.resources.Qualifiers; +import org.sonar.db.AbstractDaoTestCase; + +import static org.hamcrest.Matchers.greaterThan; +import static org.junit.Assert.assertThat; + +public class ResourceIndexerDaoTest extends AbstractDaoTestCase { + + private static ResourceIndexerDao dao; + + @Before + public void createDao() { + dao = new ResourceIndexerDao(getMyBatis()); + } + + @Test + public void shouldIndexResource() { + setupData("shouldIndexResource"); + + dao.indexResource(10, "ZipUtils", "FIL", 8); + + checkTables("shouldIndexResource", new String[] {"id"}, "resource_index"); + } + + @Test + public void shouldIndexProjects() { + setupData("shouldIndexProjects"); + + dao.indexProjects(); + + checkTables("shouldIndexProjects", new String[] {"id"}, "resource_index"); + } + + @Test + public void shouldIndexMultiModulesProject() { + setupData("shouldIndexMultiModulesProject"); + + dao.indexProject(1); + + checkTables("shouldIndexMultiModulesProject", new String[] {"id"}, "resource_index"); + } + + @Test + public void shouldReindexProjectAfterRenaming() { + setupData("shouldReindexProjectAfterRenaming"); + + dao.indexProject(1); + + checkTables("shouldReindexProjectAfterRenaming", new String[] {"id"}, "resource_index"); + } + + @Test + public void shouldNotIndexPackages() throws SQLException { + setupData("shouldNotIndexPackages"); + + dao.indexProject(1); + + Connection connection = getConnection(); + ResultSet rs = null; + try { + // project + rs = connection.createStatement().executeQuery("select count(resource_id) from resource_index where resource_id=1"); + rs.next(); + assertThat(rs.getInt(1), greaterThan(0)); + + // directory + rs = connection.createStatement().executeQuery("select count(resource_id) from resource_index where resource_id=2"); + rs.next(); + assertThat(rs.getInt(1), Is.is(0)); + + // file + rs = connection.createStatement().executeQuery("select count(resource_id) from resource_index where resource_id=3"); + rs.next(); + assertThat(rs.getInt(1), greaterThan(0)); + } finally { + if (null != rs) { + rs.close(); + } + } + } + + @Test + public void shouldIndexTwoLettersLongResources() { + setupData("shouldIndexTwoLettersLongResource"); + + dao.indexResource(10, "AB", Qualifiers.PROJECT, 3); + + checkTables("shouldIndexTwoLettersLongResource", new String[] {"id"}, "resource_index"); + } + + @Test + public void shouldReIndexTwoLettersLongResources() { + setupData("shouldReIndexTwoLettersLongResource"); + + dao.indexResource(1, "AS", Qualifiers.PROJECT, 1); + + checkTables("shouldReIndexTwoLettersLongResource", new String[] {"id"}, "resource_index"); + } + + @Test + public void shouldReIndexNewTwoLettersLongResource() { + setupData("shouldReIndexNewTwoLettersLongResource"); + + dao.indexResource(1, "AS", Qualifiers.PROJECT, 1); + + checkTables("shouldReIndexNewTwoLettersLongResource", new String[] {"id"}, "resource_index"); + } + + @Test + public void shouldReindexResource() { + setupData("shouldReindexResource"); + + dao.indexResource(1, "New Struts", Qualifiers.PROJECT, 1); + + checkTables("shouldReindexResource", new String[] {"id"}, "resource_index"); + } + + @Test + public void shouldNotReindexUnchangedResource() { + setupData("shouldNotReindexUnchangedResource"); + + dao.indexResource(1, "Struts", Qualifiers.PROJECT, 1); + + checkTables("shouldNotReindexUnchangedResource", new String[] {"id"}, "resource_index"); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/component/ResourceKeyUpdaterDaoTest.java b/sonar-db/src/test/java/org/sonar/db/component/ResourceKeyUpdaterDaoTest.java new file mode 100644 index 00000000000..13e46936fb8 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/component/ResourceKeyUpdaterDaoTest.java @@ -0,0 +1,110 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.component; + +import java.util.Map; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.db.AbstractDaoTestCase; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ResourceKeyUpdaterDaoTest extends AbstractDaoTestCase { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + private ResourceKeyUpdaterDao dao; + + @Before + public void createDao() { + dao = new ResourceKeyUpdaterDao(getMyBatis()); + } + + @Test + public void shouldUpdateKey() { + setupData("shared"); + + dao.updateKey(2, "struts:core"); + + checkTables("shouldUpdateKey", "projects"); + } + + @Test + public void shouldNotUpdateKey() { + setupData("shared"); + + thrown.expect(IllegalStateException.class); + thrown.expectMessage("Impossible to update key: a resource with \"org.struts:struts-ui\" key already exists."); + + dao.updateKey(2, "org.struts:struts-ui"); + } + + @Test + public void shouldBulkUpdateKey() { + setupData("shared"); + + dao.bulkUpdateKey(1, "org.struts", "org.apache.struts"); + + checkTables("shouldBulkUpdateKey", "projects"); + } + + @Test + public void shouldBulkUpdateKeyOnOnlyOneSubmodule() { + setupData("shared"); + + dao.bulkUpdateKey(1, "struts-ui", "struts-web"); + + checkTables("shouldBulkUpdateKeyOnOnlyOneSubmodule", "projects"); + } + + @Test + public void shouldFailBulkUpdateKeyIfKeyAlreadyExist() { + setupData("shared"); + + thrown.expect(IllegalStateException.class); + thrown.expectMessage("Impossible to update key: a resource with \"foo:struts-core\" key already exists."); + + dao.bulkUpdateKey(1, "org.struts", "foo"); + } + + @Test + public void shouldNotUpdateAllSubmodules() { + setupData("shouldNotUpdateAllSubmodules"); + + dao.bulkUpdateKey(1, "org.struts", "org.apache.struts"); + + checkTables("shouldNotUpdateAllSubmodules", "projects"); + } + + @Test + public void shouldCheckModuleKeysBeforeRenaming() { + setupData("shared"); + + Map<String, String> checkResults = dao.checkModuleKeysBeforeRenaming(1, "org.struts", "foo"); + assertThat(checkResults.size()).isEqualTo(3); + assertThat(checkResults.get("org.struts:struts")).isEqualTo("foo:struts"); + assertThat(checkResults.get("org.struts:struts-core")).isEqualTo("#duplicate_key#"); + assertThat(checkResults.get("org.struts:struts-ui")).isEqualTo("foo:struts-ui"); + } + +} diff --git a/sonar-db/src/test/java/org/sonar/db/component/SnapshotDtoTest.java b/sonar-db/src/test/java/org/sonar/db/component/SnapshotDtoTest.java new file mode 100644 index 00000000000..360fd739238 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/component/SnapshotDtoTest.java @@ -0,0 +1,107 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.component; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.sonar.api.utils.DateUtils.parseDate; + +public class SnapshotDtoTest { + + @Test + public void test_getter_and_setter() throws Exception { + SnapshotDto snapshotDto = new SnapshotDto() + .setId(10L) + .setParentId(2L) + .setRootId(3L) + .setRootProjectId(20L) + .setBuildDate(parseDate("2014-07-02").getTime()) + .setComponentId(21L) + .setLast(true) + .setScope("FIL") + .setQualifier("FIL") + .setVersion("1.0") + .setPath("3.2.") + .setDepth(1) + .setPeriodMode(1, "mode1") + .setPeriodMode(2, "mode2") + .setPeriodMode(3, "mode3") + .setPeriodMode(4, "mode4") + .setPeriodMode(5, "mode5") + .setPeriodParam(1, "param1") + .setPeriodParam(2, "param2") + .setPeriodParam(3, "param3") + .setPeriodParam(4, "param4") + .setPeriodParam(5, "param5") + .setPeriodDate(1, parseDate("2014-06-01").getTime()) + .setPeriodDate(2, parseDate("2014-06-02").getTime()) + .setPeriodDate(3, parseDate("2014-06-03").getTime()) + .setPeriodDate(4, parseDate("2014-06-04").getTime()) + .setPeriodDate(5, parseDate("2014-06-05").getTime()); + + assertThat(snapshotDto.getId()).isEqualTo(10L); + assertThat(snapshotDto.getParentId()).isEqualTo(2L); + assertThat(snapshotDto.getRootId()).isEqualTo(3L); + assertThat(snapshotDto.getRootProjectId()).isEqualTo(20L); + assertThat(snapshotDto.getBuildDate()).isEqualTo(parseDate("2014-07-02").getTime()); + assertThat(snapshotDto.getComponentId()).isEqualTo(21L); + assertThat(snapshotDto.getLast()).isTrue(); + assertThat(snapshotDto.getScope()).isEqualTo("FIL"); + assertThat(snapshotDto.getQualifier()).isEqualTo("FIL"); + assertThat(snapshotDto.getVersion()).isEqualTo("1.0"); + assertThat(snapshotDto.getPath()).isEqualTo("3.2."); + assertThat(snapshotDto.getDepth()).isEqualTo(1); + assertThat(snapshotDto.getPeriodMode(1)).isEqualTo("mode1"); + assertThat(snapshotDto.getPeriodMode(2)).isEqualTo("mode2"); + assertThat(snapshotDto.getPeriodMode(3)).isEqualTo("mode3"); + assertThat(snapshotDto.getPeriodMode(4)).isEqualTo("mode4"); + assertThat(snapshotDto.getPeriodMode(5)).isEqualTo("mode5"); + assertThat(snapshotDto.getPeriodModeParameter(1)).isEqualTo("param1"); + assertThat(snapshotDto.getPeriodModeParameter(2)).isEqualTo("param2"); + assertThat(snapshotDto.getPeriodModeParameter(3)).isEqualTo("param3"); + assertThat(snapshotDto.getPeriodModeParameter(4)).isEqualTo("param4"); + assertThat(snapshotDto.getPeriodModeParameter(5)).isEqualTo("param5"); + assertThat(snapshotDto.getPeriodDate(1)).isEqualTo(parseDate("2014-06-01").getTime()); + assertThat(snapshotDto.getPeriodDate(2)).isEqualTo(parseDate("2014-06-02").getTime()); + assertThat(snapshotDto.getPeriodDate(3)).isEqualTo(parseDate("2014-06-03").getTime()); + assertThat(snapshotDto.getPeriodDate(4)).isEqualTo(parseDate("2014-06-04").getTime()); + assertThat(snapshotDto.getPeriodDate(5)).isEqualTo(parseDate("2014-06-05").getTime()); + } + + @Test + public void get_root_id_if_when_it_is_not_null() { + SnapshotDto snapshot = new SnapshotDto().setRootId(123L).setId(456L); + + Long rootIdOrSelf = snapshot.getRootIdOrSelf(); + + assertThat(rootIdOrSelf).isEqualTo(123L); + } + + @Test + public void getRootIdOrSelf_return_own_id_when_root_id_is_null() { + SnapshotDto snapshot = new SnapshotDto().setRootId(null).setId(456L); + + Long rootIdOrSelf = snapshot.getRootIdOrSelf(); + + assertThat(rootIdOrSelf).isEqualTo(456L); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/component/SnapshotQueryTest.java b/sonar-db/src/test/java/org/sonar/db/component/SnapshotQueryTest.java new file mode 100644 index 00000000000..613686ec55b --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/component/SnapshotQueryTest.java @@ -0,0 +1,51 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.component; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.sonar.db.component.SnapshotQuery.SORT_FIELD.BY_DATE; +import static org.sonar.db.component.SnapshotQuery.SORT_ORDER.ASC; + +public class SnapshotQueryTest { + + @Test + public void test_setters_and_getters() throws Exception { + SnapshotQuery query = new SnapshotQuery() + .setComponentId(1L) + .setIsLast(true) + .setStatus("P") + .setVersion("1.0") + .setCreatedAfter(10L) + .setCreatedBefore(20L) + .setSort(BY_DATE, ASC); + + assertThat(query.getComponentId()).isEqualTo(1L); + assertThat(query.getIsLast()).isTrue(); + assertThat(query.getStatus()).isEqualTo("P"); + assertThat(query.getVersion()).isEqualTo("1.0"); + assertThat(query.getCreatedAfter()).isEqualTo(10L); + assertThat(query.getCreatedBefore()).isEqualTo(20L); + assertThat(query.getSortField()).isEqualTo("created_at"); + assertThat(query.getSortOrder()).isEqualTo("asc"); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/dashboard/ActiveDashboardDaoTest.java b/sonar-db/src/test/java/org/sonar/db/dashboard/ActiveDashboardDaoTest.java new file mode 100644 index 00000000000..8f320764923 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/dashboard/ActiveDashboardDaoTest.java @@ -0,0 +1,115 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.dashboard; + +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.sonar.db.DbTester; +import org.sonar.test.DbTests; + +import static org.assertj.core.api.Assertions.assertThat; + +@Category(DbTests.class) +public class ActiveDashboardDaoTest { + + @ClassRule + public static final DbTester dbTester = new DbTester(); + + private ActiveDashboardDao dao; + + @Before + public void createDao() { + dbTester.truncateTables(); + dao = new ActiveDashboardDao(dbTester.myBatis()); + } + + @Test + public void shouldInsert() { + dbTester.prepareDbUnit(getClass(), "shouldInsert.xml"); + + ActiveDashboardDto dashboard = new ActiveDashboardDto(); + dashboard.setDashboardId(2L); + dashboard.setUserId(3L); + dashboard.setOrderIndex(4); + dao.insert(dashboard); + + dbTester.assertDbUnit(getClass(), "shouldInsert-result.xml", "active_dashboards"); + } + + @Test + public void shouldInsertWithNoUser() { + dbTester.prepareDbUnit(getClass(), "shouldInsert.xml"); + + ActiveDashboardDto dashboard = new ActiveDashboardDto(); + dashboard.setDashboardId(2L); + dashboard.setOrderIndex(4); + dao.insert(dashboard); + + dbTester.assertDbUnit(getClass(), "shouldInsertWithNoUser-result.xml", "active_dashboards"); + } + + @Test + public void shouldGetMaxOrderIndexForNullUser() { + dbTester.prepareDbUnit(getClass(), "shouldGetMaxOrderIndexForNullUser.xml"); + + int index = dao.selectMaxOrderIndexForNullUser(); + + assertThat(index).isEqualTo(15); + } + + @Test + public void shouldGetZeroMaxOrderIndex() { + dbTester.prepareDbUnit(getClass(), "empty.xml"); + + int index = dao.selectMaxOrderIndexForNullUser(); + + assertThat(index).isZero(); + } + + @Test + public void should_get_dashboards_for_anonymous() { + dbTester.prepareDbUnit(getClass(), "shouldSelectDashboardsForAnonymous.xml"); + + assertThat(dao.selectGlobalDashboardsForUserLogin(null)).hasSize(2).extracting("id").containsExactly(2L, 1L); + } + + @Test + public void should_get_dashboards_for_user() { + dbTester.prepareDbUnit(getClass(), "shouldSelectDashboardsForUser.xml"); + + assertThat(dao.selectGlobalDashboardsForUserLogin("obiwan")).hasSize(2).extracting("id").containsExactly(2L, 1L); + } + + @Test + public void should_get_project_dashboards_for_anonymous() { + dbTester.prepareDbUnit(getClass(), "shouldSelectProjectDashboardsForAnonymous.xml"); + + assertThat(dao.selectProjectDashboardsForUserLogin(null)).hasSize(2).extracting("id").containsExactly(2L, 1L); + } + + @Test + public void should_get_project_dashboards_for_user() { + dbTester.prepareDbUnit(getClass(), "shouldSelectProjectDashboardsForUser.xml"); + + assertThat(dao.selectProjectDashboardsForUserLogin("obiwan")).hasSize(2).extracting("id").containsExactly(2L, 1L); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/dashboard/DashboardDaoTest.java b/sonar-db/src/test/java/org/sonar/db/dashboard/DashboardDaoTest.java new file mode 100644 index 00000000000..bcb505fc176 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/dashboard/DashboardDaoTest.java @@ -0,0 +1,130 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.dashboard; + +import java.util.Date; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.sonar.db.DbTester; +import org.sonar.test.DbTests; + +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThat; + +@Category(DbTests.class) +public class DashboardDaoTest { + + @ClassRule + public static final DbTester dbTester = new DbTester(); + + private DashboardDao dao; + + @Before + public void createDao() { + dbTester.truncateTables(); + dao = new DashboardDao(dbTester.myBatis()); + } + + @Test + public void shouldSelectGlobalDashboard() { + dbTester.prepareDbUnit(getClass(), "shouldSelectGlobalDashboard.xml"); + DashboardDto dashboard = dao.selectGlobalDashboard("SQALE"); + assertThat(dashboard.getId(), is(2L)); + assertThat(dashboard.getUserId(), nullValue()); + + assertNull(dao.selectGlobalDashboard("unknown")); + } + + @Test + public void shouldInsert() { + dbTester.prepareDbUnit(getClass(), "shouldInsert.xml"); + Date aDate = new Date(); + + DashboardDto dashboardDto = new DashboardDto(); + dashboardDto.setUserId(6L); + dashboardDto.setName("My Dashboard"); + dashboardDto.setDescription("This is a dashboard"); + dashboardDto.setColumnLayout("100%"); + dashboardDto.setShared(true); + dashboardDto.setGlobal(true); + dashboardDto.setCreatedAt(aDate); + dashboardDto.setUpdatedAt(aDate); + + WidgetDto widgetDto = new WidgetDto(); + widgetDto.setWidgetKey("code_coverage"); + widgetDto.setName("Code coverage"); + widgetDto.setDescription("Widget for code coverage"); + widgetDto.setColumnIndex(13); + widgetDto.setRowIndex(14); + widgetDto.setConfigured(true); + widgetDto.setCreatedAt(aDate); + widgetDto.setUpdatedAt(aDate); + dashboardDto.addWidget(widgetDto); + + WidgetPropertyDto property = new WidgetPropertyDto(); + property.setPropertyKey("displayITs"); + property.setTextValue("true"); + widgetDto.addWidgetProperty(property); + + dao.insert(dashboardDto); + + dbTester.assertDbUnit(getClass(), "shouldInsert-result.xml", new String[] {"created_at", "updated_at"}, "dashboards", "widgets", "widget_properties"); + } + + @Test + public void shouldInsertWithNullableColumns() { + dbTester.prepareDbUnit(getClass(), "shouldInsert.xml"); + + DashboardDto dashboardDto = new DashboardDto(); + dashboardDto.setUserId(null); + dashboardDto.setName(null); + dashboardDto.setDescription(null); + dashboardDto.setColumnLayout(null); + dashboardDto.setShared(true); + dashboardDto.setGlobal(false); + dashboardDto.setCreatedAt(null); + dashboardDto.setUpdatedAt(null); + + WidgetDto widgetDto = new WidgetDto(); + widgetDto.setWidgetKey("code_coverage"); + widgetDto.setName(null); + widgetDto.setDescription(null); + widgetDto.setColumnIndex(null); + widgetDto.setRowIndex(null); + widgetDto.setConfigured(true); + widgetDto.setCreatedAt(null); + widgetDto.setUpdatedAt(null); + dashboardDto.addWidget(widgetDto); + + WidgetPropertyDto property = new WidgetPropertyDto(); + property.setPropertyKey(null); + property.setTextValue(null); + widgetDto.addWidgetProperty(property); + + dao.insert(dashboardDto); + + dbTester.assertDbUnit(getClass(), "shouldInsertWithNullableColumns-result.xml", "dashboards", "widgets", "widget_properties"); + } + +} diff --git a/sonar-db/src/test/java/org/sonar/db/debt/CharacteristicDaoTest.java b/sonar-db/src/test/java/org/sonar/db/debt/CharacteristicDaoTest.java new file mode 100644 index 00000000000..504fe7d9246 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/debt/CharacteristicDaoTest.java @@ -0,0 +1,244 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.debt; + +import java.util.List; +import org.junit.After; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.sonar.api.utils.DateUtils; +import org.sonar.db.DbSession; +import org.sonar.db.DbTester; +import org.sonar.test.DbTests; + +import static com.google.common.collect.Lists.newArrayList; +import static org.assertj.core.api.Assertions.assertThat; + +@Category(DbTests.class) +public class CharacteristicDaoTest { + + private static final String[] EXCLUDED_COLUMNS = new String[] {"id", "root_id", "rule_id", "function_key", "factor_unit", "factor_value", "offset_unit", "offset_value"}; + + @ClassRule + public static DbTester db = new DbTester(); + + CharacteristicDao dao; + + DbSession session; + + @Before + public void createDao() { + db.truncateTables(); + session = db.myBatis().openSession(false); + dao = new CharacteristicDao(db.myBatis()); + } + + @After + public void tearDown() { + session.close(); + } + + @Test + public void select_enabled_characteristics() { + db.prepareDbUnit(getClass(), "shared.xml"); + + List<CharacteristicDto> dtos = dao.selectEnabledCharacteristics(); + + assertThat(dtos).hasSize(2); + + CharacteristicDto rootCharacteristic = dtos.get(0); + assertThat(rootCharacteristic.getId()).isEqualTo(1); + assertThat(rootCharacteristic.getKey()).isEqualTo("PORTABILITY"); + assertThat(rootCharacteristic.getName()).isEqualTo("Portability"); + assertThat(rootCharacteristic.getParentId()).isNull(); + assertThat(rootCharacteristic.getOrder()).isEqualTo(1); + assertThat(rootCharacteristic.isEnabled()).isTrue(); + assertThat(rootCharacteristic.getCreatedAt()).isNotNull(); + assertThat(rootCharacteristic.getUpdatedAt()).isNotNull(); + + CharacteristicDto characteristic = dtos.get(1); + assertThat(characteristic.getId()).isEqualTo(2); + assertThat(characteristic.getKey()).isEqualTo("COMPILER_RELATED_PORTABILITY"); + assertThat(characteristic.getName()).isEqualTo("Compiler related portability"); + assertThat(characteristic.getParentId()).isEqualTo(1); + assertThat(characteristic.getOrder()).isNull(); + assertThat(characteristic.isEnabled()).isTrue(); + assertThat(characteristic.getCreatedAt()).isNotNull(); + assertThat(characteristic.getUpdatedAt()).isNotNull(); + } + + @Test + public void select_characteristics() { + db.prepareDbUnit(getClass(), "shared.xml"); + + assertThat(dao.selectCharacteristics()).hasSize(4); + } + + @Test + public void select_enabled_root_characteristics() { + db.prepareDbUnit(getClass(), "select_enabled_root_characteristics.xml"); + + List<CharacteristicDto> dtos = dao.selectEnabledRootCharacteristics(); + + assertThat(dtos).hasSize(1); + + CharacteristicDto rootCharacteristic = dtos.get(0); + assertThat(rootCharacteristic.getId()).isEqualTo(1); + assertThat(rootCharacteristic.getKey()).isEqualTo("PORTABILITY"); + } + + @Test + public void select_enabled_root_characteristics_order_by_characteristic_order() { + db.prepareDbUnit(getClass(), "select_enabled_root_characteristics_order_by_characteristic_order.xml"); + + List<CharacteristicDto> dtos = dao.selectEnabledRootCharacteristics(); + + assertThat(dtos).hasSize(3); + assertThat(dtos.get(0).getKey()).isEqualTo("TESTABILITY"); + assertThat(dtos.get(1).getKey()).isEqualTo("PORTABILITY"); + assertThat(dtos.get(2).getKey()).isEqualTo("MAINTAINABILITY"); + } + + @Test + public void select_sub_characteristics_by_parent_id() { + db.prepareDbUnit(getClass(), "select_sub_characteristics_by_parent_id.xml"); + + assertThat(dao.selectCharacteristicsByParentId(1)).hasSize(2); + assertThat(dao.selectCharacteristicsByParentId(55)).isEmpty(); + } + + @Test + public void select_characteristics_by_ids() { + db.prepareDbUnit(getClass(), "shared.xml"); + + assertThat(dao.selectCharacteristicsByIds(newArrayList(1, 2))).hasSize(2); + assertThat(dao.selectCharacteristicsByIds(newArrayList(1))).hasSize(1); + + // Disabled characteristics are not returned + assertThat(dao.selectCharacteristicsByIds(newArrayList(4, 5))).isEmpty(); + } + + @Test + public void select_characteristic_by_key() { + db.prepareDbUnit(getClass(), "shared.xml"); + + CharacteristicDto dto = dao.selectByKey("COMPILER_RELATED_PORTABILITY"); + assertThat(dto).isNotNull(); + assertThat(dto.getId()).isEqualTo(2); + assertThat(dto.getParentId()).isEqualTo(1); + + dto = dao.selectByKey("PORTABILITY"); + assertThat(dto).isNotNull(); + assertThat(dto.getId()).isEqualTo(1); + assertThat(dto.getParentId()).isNull(); + + assertThat(dao.selectByKey("UNKNOWN")).isNull(); + } + + @Test + public void select_characteristic_by_name() { + db.prepareDbUnit(getClass(), "shared.xml"); + + assertThat(dao.selectByName("Portability")).isNotNull(); + assertThat(dao.selectByName("Compiler related portability")).isNotNull(); + assertThat(dao.selectByName("Unknown")).isNull(); + } + + @Test + public void select_characteristic_by_id() { + db.prepareDbUnit(getClass(), "shared.xml"); + + assertThat(dao.selectById(2)).isNotNull(); + assertThat(dao.selectById(1)).isNotNull(); + + assertThat(dao.selectById(10)).isNull(); + } + + @Test + public void select_max_characteristic_order() { + db.prepareDbUnit(getClass(), "shared.xml"); + + assertThat(dao.selectMaxCharacteristicOrder()).isEqualTo(1); + } + + @Test + public void select_max_characteristic_order_when_characteristics_are_all_disabled() { + db.prepareDbUnit(getClass(), "select_max_characteristic_order_when_characteristics_are_all_disabled.xml"); + + assertThat(dao.selectMaxCharacteristicOrder()).isEqualTo(0); + } + + @Test + public void insert_characteristic() { + CharacteristicDto dto = new CharacteristicDto() + .setKey("COMPILER_RELATED_PORTABILITY") + .setName("Compiler related portability") + .setOrder(1) + .setEnabled(true) + .setCreatedAt(DateUtils.parseDate("2013-11-20")); + + dao.insert(dto); + + db.assertDbUnit(getClass(), "insert_characteristic-result.xml", EXCLUDED_COLUMNS, "characteristics"); + } + + @Test + public void insert_characteristics() { + dao.insert(session, new CharacteristicDto() + .setKey("COMPILER_RELATED_PORTABILITY") + .setName("Compiler related portability") + .setOrder(1) + .setEnabled(true) + .setCreatedAt(DateUtils.parseDate("2013-11-20")), + new CharacteristicDto() + .setKey("PORTABILITY") + .setName("portability") + .setOrder(2) + .setEnabled(true) + .setCreatedAt(DateUtils.parseDate("2013-11-20"))); + session.commit(); + + assertThat(db.countRowsOfTable("characteristics")).isEqualTo(2); + } + + @Test + public void update_characteristic() { + db.prepareDbUnit(getClass(), "update_characteristic.xml"); + + CharacteristicDto dto = new CharacteristicDto() + .setId(1) + // The Key should not be changed + .setKey("NEW_KEY") + .setName("New name") + .setOrder(2) + // Created date should not changed + .setCreatedAt(DateUtils.parseDate("2013-11-22")) + .setUpdatedAt(DateUtils.parseDate("2014-03-19")) + .setEnabled(false); + + dao.update(dto); + + db.assertDbUnit(getClass(), "update_characteristic-result.xml", EXCLUDED_COLUMNS, "characteristics"); + } + +} diff --git a/sonar-db/src/test/java/org/sonar/db/debt/CharacteristicDtoTest.java b/sonar-db/src/test/java/org/sonar/db/debt/CharacteristicDtoTest.java new file mode 100644 index 00000000000..8ecfbb32dae --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/debt/CharacteristicDtoTest.java @@ -0,0 +1,84 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.debt; + +import java.util.Date; +import org.junit.Test; +import org.sonar.api.technicaldebt.batch.internal.DefaultCharacteristic; + +import static org.assertj.core.api.Assertions.assertThat; + +public class CharacteristicDtoTest { + + @Test + public void to_dto_from_characteristic() { + DefaultCharacteristic rootCharacteristic = new DefaultCharacteristic() + .setId(1) + .setKey("MEMORY_EFFICIENCY") + .setName("Memory use"); + + DefaultCharacteristic characteristic = new DefaultCharacteristic() + .setId(2) + .setKey("EFFICIENCY") + .setName("Efficiency") + .setParent(rootCharacteristic) + .setOrder(5) + .setCreatedAt(new Date()) + .setUpdatedAt(new Date()); + + CharacteristicDto dto = CharacteristicDto.toDto(characteristic, 1); + assertThat(dto.getId()).isNull(); + assertThat(dto.getParentId()).isEqualTo(1); + assertThat(dto.getKey()).isEqualTo("EFFICIENCY"); + assertThat(dto.getName()).isEqualTo("Efficiency"); + assertThat(dto.getOrder()).isEqualTo(5); + assertThat(dto.isEnabled()).isTrue(); + assertThat(dto.getCreatedAt()).isNotNull(); + assertThat(dto.getUpdatedAt()).isNotNull(); + } + + @Test + public void to_characteristic() { + DefaultCharacteristic rootCharacteristic = new DefaultCharacteristic() + .setId(1) + .setKey("MEMORY_EFFICIENCY") + .setName("Memory use"); + + CharacteristicDto dto = new CharacteristicDto() + .setId(2) + .setParentId(1) + .setKey("EFFICIENCY") + .setName("Efficiency") + .setOrder(5) + .setEnabled(false) + .setCreatedAt(new Date()) + .setUpdatedAt(new Date()); + + DefaultCharacteristic characteristic = dto.toCharacteristic(rootCharacteristic); + assertThat(characteristic.id()).isEqualTo(2); + assertThat(characteristic.parent()).isEqualTo(rootCharacteristic); + assertThat(characteristic.key()).isEqualTo("EFFICIENCY"); + assertThat(characteristic.name()).isEqualTo("Efficiency"); + assertThat(characteristic.order()).isEqualTo(5); + assertThat(characteristic.createdAt()).isNotNull(); + assertThat(characteristic.updatedAt()).isNotNull(); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/dialect/DialectUtilsTest.java b/sonar-db/src/test/java/org/sonar/db/dialect/DialectUtilsTest.java new file mode 100644 index 00000000000..32621935884 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/dialect/DialectUtilsTest.java @@ -0,0 +1,45 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.dialect; + +import org.junit.Test; +import org.sonar.api.utils.MessageException; + +import static org.assertj.core.api.Assertions.assertThat; + +public class DialectUtilsTest { + + @Test + public void testFindById() { + Dialect d = DialectUtils.find("mysql", null); + assertThat(d).isInstanceOf(MySql.class); + } + + @Test + public void testFindByJdbcUrl() { + Dialect d = DialectUtils.find(null, "jdbc:mysql:foo:bar"); + assertThat(d).isInstanceOf(MySql.class); + } + + @Test(expected = MessageException.class) + public void testFindNoMatch() { + DialectUtils.find("foo", "bar"); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/dialect/H2Test.java b/sonar-db/src/test/java/org/sonar/db/dialect/H2Test.java new file mode 100644 index 00000000000..bd230b1b580 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/dialect/H2Test.java @@ -0,0 +1,59 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.dialect; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class H2Test { + + H2 dialect = new H2(); + + @Test + public void matchesJdbcURL() { + assertThat(dialect.matchesJdbcURL("jdbc:h2:foo")).isTrue(); + assertThat(dialect.matchesJdbcURL("jdbc:hsql:foo")).isFalse(); + } + + @Test + public void testBooleanSqlValues() { + assertThat(dialect.getTrueSqlValue()).isEqualTo("true"); + assertThat(dialect.getFalseSqlValue()).isEqualTo("false"); + } + + @Test + public void should_configure() { + assertThat(dialect.getId()).isEqualTo("h2"); + assertThat(dialect.getActiveRecordDialectCode()).isEqualTo(".h2."); + assertThat(dialect.getDefaultDriverClassName()).isEqualTo("org.h2.Driver"); + assertThat(dialect.getValidationQuery()).isEqualTo("SELECT 1"); + } + + @Test + public void testFetchSizeForScrolling() throws Exception { + assertThat(dialect.getScrollDefaultFetchSize()).isEqualTo(200); + } + + @Test + public void h2_does_not_supportMigration() { + assertThat(dialect.supportsMigration()).isFalse(); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/dialect/MsSqlTest.java b/sonar-db/src/test/java/org/sonar/db/dialect/MsSqlTest.java new file mode 100644 index 00000000000..3b1ebb14989 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/dialect/MsSqlTest.java @@ -0,0 +1,57 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.dialect; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class MsSqlTest { + + private MsSql msSql = new MsSql(); + + @Test + public void matchesJdbcURL() { + assertThat(msSql.matchesJdbcURL("jdbc:jtds:sqlserver://localhost;databaseName=SONAR;SelectMethod=Cursor")).isTrue(); + assertThat(msSql.matchesJdbcURL("jdbc:microsoft:sqlserver://localhost:1433;databasename=sonar")).isTrue(); + + assertThat(msSql.matchesJdbcURL("jdbc:hsql:foo")).isFalse(); + assertThat(msSql.matchesJdbcURL("jdbc:mysql:foo")).isFalse(); + } + + @Test + public void testBooleanSqlValues() { + assertThat(msSql.getTrueSqlValue()).isEqualTo("1"); + assertThat(msSql.getFalseSqlValue()).isEqualTo("0"); + } + + @Test + public void should_configure() { + assertThat(msSql.getId()).isEqualTo("mssql"); + assertThat(msSql.getActiveRecordDialectCode()).isEqualTo("sqlserver"); + assertThat(msSql.getDefaultDriverClassName()).isEqualTo("net.sourceforge.jtds.jdbc.Driver"); + assertThat(msSql.getValidationQuery()).isEqualTo("SELECT 1"); + } + + @Test + public void msSql_does_supportMigration() { + assertThat(msSql.supportsMigration()).isTrue(); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/dialect/MySqlTest.java b/sonar-db/src/test/java/org/sonar/db/dialect/MySqlTest.java new file mode 100644 index 00000000000..c33aa898cb5 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/dialect/MySqlTest.java @@ -0,0 +1,63 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.dialect; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class MySqlTest { + + private MySql mySql = new MySql(); + + @Test + public void matchesJdbcURL() { + assertThat(mySql.matchesJdbcURL("jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8")).isTrue(); + assertThat(mySql.matchesJdbcURL("JDBC:MYSQL://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8")).isTrue(); + + assertThat(mySql.matchesJdbcURL("jdbc:hsql:foo")).isFalse(); + assertThat(mySql.matchesJdbcURL("jdbc:oracle:foo")).isFalse(); + } + + @Test + public void testBooleanSqlValues() { + assertThat(mySql.getTrueSqlValue()).isEqualTo("true"); + assertThat(mySql.getFalseSqlValue()).isEqualTo("false"); + } + + @Test + public void should_configure() { + assertThat(mySql.getId()).isEqualTo("mysql"); + assertThat(mySql.getActiveRecordDialectCode()).isEqualTo("mysql"); + assertThat(mySql.getDefaultDriverClassName()).isEqualTo("com.mysql.jdbc.Driver"); + assertThat(mySql.getValidationQuery()).isEqualTo("SELECT 1"); + } + + @Test + public void testFetchSizeForScrolling() throws Exception { + assertThat(mySql.getScrollDefaultFetchSize()).isEqualTo(Integer.MIN_VALUE); + assertThat(mySql.getScrollSingleRowFetchSize()).isEqualTo(Integer.MIN_VALUE); + } + + @Test + public void mysql_does_supportMigration() { + assertThat(mySql.supportsMigration()).isTrue(); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/dialect/OracleTest.java b/sonar-db/src/test/java/org/sonar/db/dialect/OracleTest.java new file mode 100644 index 00000000000..cc40aab20e1 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/dialect/OracleTest.java @@ -0,0 +1,60 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.dialect; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class OracleTest { + + Oracle dialect = new Oracle(); + + @Test + public void matchesJdbcURL() { + assertThat(dialect.matchesJdbcURL("jdbc:oracle:thin:@localhost/XE")).isTrue(); + assertThat(dialect.matchesJdbcURL("jdbc:hsql:foo")).isFalse(); + } + + @Test + public void testBooleanSqlValues() { + assertThat(dialect.getTrueSqlValue()).isEqualTo("1"); + assertThat(dialect.getFalseSqlValue()).isEqualTo("0"); + } + + @Test + public void should_configure() { + assertThat(dialect.getId()).isEqualTo("oracle"); + assertThat(dialect.getActiveRecordDialectCode()).isEqualTo("oracle"); + assertThat(dialect.getDefaultDriverClassName()).isEqualTo("oracle.jdbc.OracleDriver"); + assertThat(dialect.getValidationQuery()).isEqualTo("SELECT 1 FROM DUAL"); + } + + @Test + public void testFetchSizeForScrolling() throws Exception { + assertThat(dialect.getScrollDefaultFetchSize()).isEqualTo(200); + assertThat(dialect.getScrollSingleRowFetchSize()).isEqualTo(1); + } + + @Test + public void oracle_does_supportMigration() { + assertThat(dialect.supportsMigration()).isTrue(); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/dialect/PostgreSqlTest.java b/sonar-db/src/test/java/org/sonar/db/dialect/PostgreSqlTest.java new file mode 100644 index 00000000000..43cf2d0094f --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/dialect/PostgreSqlTest.java @@ -0,0 +1,64 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.dialect; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class PostgreSqlTest { + + PostgreSql dialect = new PostgreSql(); + + @Test + public void matchesJdbcURL() { + assertThat(dialect.matchesJdbcURL("jdbc:postgresql://localhost/sonar")).isTrue(); + assertThat(dialect.matchesJdbcURL("jdbc:hsql:foo")).isFalse(); + } + + @Test + public void should_set_connection_properties() { + assertThat(dialect.getConnectionInitStatements()).isEqualTo(PostgreSql.INIT_STATEMENTS); + } + + @Test + public void testBooleanSqlValues() { + assertThat(dialect.getTrueSqlValue()).isEqualTo("true"); + assertThat(dialect.getFalseSqlValue()).isEqualTo("false"); + } + + @Test + public void should_configure() { + assertThat(dialect.getId()).isEqualTo("postgresql"); + assertThat(dialect.getActiveRecordDialectCode()).isEqualTo("postgre"); + assertThat(dialect.getDefaultDriverClassName()).isEqualTo("org.postgresql.Driver"); + assertThat(dialect.getValidationQuery()).isEqualTo("SELECT 1"); + } + + @Test + public void testFetchSizeForScrolling() throws Exception { + assertThat(dialect.getScrollDefaultFetchSize()).isEqualTo(200); + } + + @Test + public void postgres_does_supportMigration() { + assertThat(dialect.supportsMigration()).isTrue(); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/duplication/DuplicationDaoTest.java b/sonar-db/src/test/java/org/sonar/db/duplication/DuplicationDaoTest.java new file mode 100644 index 00000000000..32705a7e5b1 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/duplication/DuplicationDaoTest.java @@ -0,0 +1,68 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.duplication; + +import java.util.Arrays; +import java.util.List; +import org.junit.Before; +import org.junit.Test; +import org.sonar.db.AbstractDaoTestCase; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + +public class DuplicationDaoTest extends AbstractDaoTestCase { + + private DuplicationDao dao; + + @Before + public void createDao() { + dao = new DuplicationDao(getMyBatis()); + } + + @Test + public void shouldGetByHash() { + setupData("shouldGetByHash"); + + List<DuplicationUnitDto> blocks = dao.selectCandidates(10, 7, "java"); + assertThat(blocks.size(), is(1)); + + DuplicationUnitDto block = blocks.get(0); + assertThat("block resourceId", block.getResourceKey(), is("bar-last")); + assertThat("block hash", block.getHash(), is("aa")); + assertThat("block index in file", block.getIndexInFile(), is(0)); + assertThat("block start line", block.getStartLine(), is(1)); + assertThat("block end line", block.getEndLine(), is(2)); + + // check null for lastSnapshotId + blocks = dao.selectCandidates(10, null, "java"); + assertThat(blocks.size(), is(2)); + } + + @Test + public void shouldInsert() { + setupData("shouldInsert"); + + dao.insert(Arrays.asList(new DuplicationUnitDto(1, 2, "bb", 0, 1, 2))); + + checkTables("shouldInsert", "duplications_index"); + } + +} diff --git a/sonar-db/src/test/java/org/sonar/db/event/EventDtoTest.java b/sonar-db/src/test/java/org/sonar/db/event/EventDtoTest.java new file mode 100644 index 00000000000..cf90cce47cd --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/event/EventDtoTest.java @@ -0,0 +1,52 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.event; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class EventDtoTest { + + @Test + public void test_getters_and_setters() throws Exception { + EventDto dto = new EventDto() + .setId(1L) + .setName("1.0") + .setCategory("Version") + .setDescription("Version 1.0") + .setData("some data") + .setDate(1413407091086L) + .setComponentUuid("ABCD") + .setSnapshotId(1000L) + .setCreatedAt(1225630680000L); + + assertThat(dto.getId()).isEqualTo(1L); + assertThat(dto.getName()).isEqualTo("1.0"); + assertThat(dto.getCategory()).isEqualTo("Version"); + assertThat(dto.getDescription()).isEqualTo("Version 1.0"); + assertThat(dto.getData()).isEqualTo("some data"); + assertThat(dto.getComponentUuid()).isEqualTo("ABCD"); + assertThat(dto.getSnapshotId()).isEqualTo(1000L); + assertThat(dto.getCreatedAt()).isEqualTo(1225630680000L); + } + +} diff --git a/sonar-db/src/test/java/org/sonar/db/issue/ActionPlanDaoTest.java b/sonar-db/src/test/java/org/sonar/db/issue/ActionPlanDaoTest.java new file mode 100644 index 00000000000..939fc01ed36 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/issue/ActionPlanDaoTest.java @@ -0,0 +1,122 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.issue; + +import java.util.Collection; +import java.util.List; +import org.apache.ibatis.session.SqlSession; +import org.junit.Before; +import org.junit.Test; +import org.sonar.db.AbstractDaoTestCase; +import org.sonar.db.MyBatis; + +import static com.google.common.collect.Lists.newArrayList; +import static org.assertj.core.api.Assertions.assertThat; + +public class ActionPlanDaoTest extends AbstractDaoTestCase { + + ActionPlanDao dao; + + @Before + public void createDao() { + dao = new ActionPlanDao(getMyBatis()); + } + + @Test + public void should_insert_new_action_plan() { + ActionPlanDto actionPlanDto = new ActionPlanDto().setKey("ABC").setName("Long term").setDescription("Long term action plan").setStatus("OPEN") + .setProjectId(1l).setUserLogin("arthur"); + + dao.save(actionPlanDto); + + checkTables("should_insert_new_action_plan", new String[] {"id", "created_at", "updated_at"}, "action_plans"); + } + + @Test + public void should_update_action_plan() { + setupData("should_update_action_plan"); + + ActionPlanDto actionPlanDto = new ActionPlanDto().setKey("ABC").setName("Long term").setDescription("Long term action plan").setStatus("OPEN") + .setProjectId(1l).setUserLogin("arthur"); + dao.update(actionPlanDto); + + checkTables("should_update_action_plan", new String[] {"id", "created_at", "updated_at"}, "action_plans"); + } + + @Test + public void should_delete_action_plan() { + setupData("should_delete_action_plan"); + + dao.delete("BCD"); + + checkTables("should_delete_action_plan", new String[] {"id", "created_at", "updated_at"}, "action_plans"); + } + + @Test + public void should_find_by_key() { + setupData("shared", "should_find_by_key"); + + ActionPlanDto result = dao.findByKey("ABC"); + assertThat(result).isNotNull(); + assertThat(result.getKey()).isEqualTo("ABC"); + assertThat(result.getProjectKey()).isEqualTo("org.sonar.Sample"); + } + + @Test + public void should_find_by_keys() { + setupData("shared", "should_find_by_keys"); + + Collection<ActionPlanDto> result = dao.findByKeys(newArrayList("ABC", "ABD", "ABE")); + assertThat(result).hasSize(3); + } + + @Test + public void should_find_by_keys_on_huge_number_of_keys() { + setupData("shared"); + + SqlSession session = getMyBatis().openSession(); + List<String> hugeNbOKeys = newArrayList(); + for (int i = 0; i < 4500; i++) { + hugeNbOKeys.add("ABCD" + i); + } + List<ActionPlanDto> result = dao.findByKeys(hugeNbOKeys); + MyBatis.closeQuietly(session); + + // The goal of this test is only to check that the query do no fail, not to check the number of results + assertThat(result).isEmpty(); + } + + @Test + public void should_find_open_by_project_id() { + setupData("shared", "should_find_open_by_project_id"); + + Collection<ActionPlanDto> result = dao.findOpenByProjectId(1l); + assertThat(result).hasSize(2); + } + + @Test + public void should_find_by_name_and_project_id() { + setupData("shared", "should_find_by_name_and_project_id"); + + Collection<ActionPlanDto> result = dao.findByNameAndProjectId("SHORT_TERM", 1l); + assertThat(result).hasSize(2); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/issue/ActionPlanStatsDaoTest.java b/sonar-db/src/test/java/org/sonar/db/issue/ActionPlanStatsDaoTest.java new file mode 100644 index 00000000000..a70e1a3d08e --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/issue/ActionPlanStatsDaoTest.java @@ -0,0 +1,52 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.issue; + +import java.util.Collection; +import org.junit.Before; +import org.junit.Test; +import org.sonar.db.AbstractDaoTestCase; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ActionPlanStatsDaoTest extends AbstractDaoTestCase { + + ActionPlanStatsDao dao; + + @Before + public void createDao() { + dao = new ActionPlanStatsDao(getMyBatis()); + } + + @Test + public void should_find_by_project() { + setupData("shared", "should_find_by_project"); + + Collection<ActionPlanStatsDto> result = dao.findByProjectId(1l); + assertThat(result).isNotEmpty(); + + ActionPlanStatsDto actionPlanStatsDto = result.iterator().next(); + assertThat(actionPlanStatsDto.getProjectKey()).isEqualTo("org.sonar.Sample"); + assertThat(actionPlanStatsDto.getTotalIssues()).isEqualTo(3); + assertThat(actionPlanStatsDto.getUnresolvedIssues()).isEqualTo(1); + } + +} diff --git a/sonar-db/src/test/java/org/sonar/db/issue/IssueChangeDaoTest.java b/sonar-db/src/test/java/org/sonar/db/issue/IssueChangeDaoTest.java new file mode 100644 index 00000000000..4510995aace --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/issue/IssueChangeDaoTest.java @@ -0,0 +1,197 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.issue; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.utils.DateUtils; +import org.sonar.core.issue.DefaultIssueComment; +import org.sonar.core.issue.FieldDiffs; +import org.sonar.db.AbstractDaoTestCase; +import org.sonar.db.DbSession; +import org.sonar.db.MyBatis; + +import static com.google.common.collect.Lists.newArrayList; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; + +public class IssueChangeDaoTest extends AbstractDaoTestCase { + + DbSession session; + + IssueChangeDao dao; + + @Before + public void createDao() { + session = getMyBatis().openSession(false); + dao = new IssueChangeDao(getMyBatis()); + } + + @After + public void tearDown() { + session.close(); + } + + @Test + public void select_comments_by_issues() { + setupData("shared"); + + DbSession session = getMyBatis().openSession(false); + List<DefaultIssueComment> comments = dao.selectCommentsByIssues(session, Arrays.asList("1000")); + MyBatis.closeQuietly(session); + assertThat(comments).hasSize(2); + + // chronological order + DefaultIssueComment first = comments.get(0); + assertThat(first.markdownText()).isEqualTo("old comment"); + + DefaultIssueComment second = comments.get(1); + assertThat(second.userLogin()).isEqualTo("arthur"); + assertThat(second.key()).isEqualTo("FGHIJ"); + assertThat(second.markdownText()).isEqualTo("recent comment"); + } + + @Test + public void select_comments_by_issues_on_huge_number_of_issues() { + setupData("shared"); + + DbSession session = getMyBatis().openSession(false); + List<String> hugeNbOfIssues = newArrayList(); + for (int i = 0; i < 4500; i++) { + hugeNbOfIssues.add("ABCD" + i); + } + List<DefaultIssueComment> comments = dao.selectCommentsByIssues(session, hugeNbOfIssues); + MyBatis.closeQuietly(session); + + // The goal of this test is only to check that the query do no fail, not to check the number of results + assertThat(comments).isEmpty(); + } + + @Test + public void select_comment_by_key() { + setupData("shared"); + + DefaultIssueComment comment = dao.selectCommentByKey("FGHIJ"); + assertThat(comment).isNotNull(); + assertThat(comment.key()).isEqualTo("FGHIJ"); + assertThat(comment.key()).isEqualTo("FGHIJ"); + assertThat(comment.userLogin()).isEqualTo("arthur"); + + assertThat(dao.selectCommentByKey("UNKNOWN")).isNull(); + } + + @Test + public void select_issue_changelog_from_issue_key() { + setupData("shared"); + + List<FieldDiffs> changelog = dao.selectChangelogByIssue("1000"); + assertThat(changelog).hasSize(1); + assertThat(changelog.get(0).diffs()).hasSize(1); + assertThat(changelog.get(0).diffs().get("severity").newValue()).isEqualTo("BLOCKER"); + assertThat(changelog.get(0).diffs().get("severity").oldValue()).isEqualTo("MAJOR"); + } + + @Test + public void selectChangelogOfNonClosedIssuesByComponent() { + setupData("selectChangelogOfNonClosedIssuesByComponent"); + + List<IssueChangeDto> dtos = dao.selectChangelogOfNonClosedIssuesByComponent("FILE_1"); + assertThat(dtos).extracting("id").containsExactly(100L, 103L); + } + + @Test + public void select_comments_by_issues_empty_input() { + // no need to connect to db + DbSession session = mock(DbSession.class); + List<DefaultIssueComment> comments = dao.selectCommentsByIssues(session, Collections.<String>emptyList()); + + assertThat(comments).isEmpty(); + } + + @Test + public void delete() { + setupData("delete"); + + assertThat(dao.delete("COMMENT-2")).isTrue(); + + checkTable("delete", "issue_changes"); + } + + @Test + public void delete_unknown_key() { + setupData("delete"); + + assertThat(dao.delete("UNKNOWN")).isFalse(); + } + + @Test + public void insert() { + setupData("empty"); + + IssueChangeDto changeDto = new IssueChangeDto() + .setKey("EFGH") + .setUserLogin("emmerik") + .setChangeData("Some text") + .setChangeType("comment") + .setIssueKey("ABCDE") + .setCreatedAt(1_500_000_000_000L) + .setUpdatedAt(1_501_000_000_000L) + .setIssueChangeCreationDate(1_502_000_000_000L); + + dao.insert(session, changeDto); + session.commit(); + + checkTable("insert", "issue_changes"); + } + + @Test + public void update() { + setupData("update"); + + IssueChangeDto change = new IssueChangeDto(); + change.setKey("COMMENT-2"); + + // Only the following fields can be updated: + change.setChangeData("new comment"); + change.setUpdatedAt(1_500_000_000_000L); + + assertThat(dao.update(change)).isTrue(); + + checkTable("update", "issue_changes"); + } + + @Test + public void update_unknown_key() { + setupData("update"); + + IssueChangeDto change = new IssueChangeDto(); + change.setKey("UNKNOWN"); + + // Only the following fields can be updated: + change.setChangeData("new comment"); + change.setUpdatedAt(DateUtils.parseDate("2013-06-30").getTime()); + + assertThat(dao.update(change)).isFalse(); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/issue/IssueChangeDtoTest.java b/sonar-db/src/test/java/org/sonar/db/issue/IssueChangeDtoTest.java new file mode 100644 index 00000000000..2d7cfdcb478 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/issue/IssueChangeDtoTest.java @@ -0,0 +1,141 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.issue; + +import org.junit.Test; +import org.sonar.api.utils.System2; +import org.sonar.core.issue.DefaultIssueComment; +import org.sonar.core.issue.FieldDiffs; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.sonar.api.utils.DateUtils.parseDate; + +public class IssueChangeDtoTest { + + @Test + public void create_from_comment() { + DefaultIssueComment comment = DefaultIssueComment.create("ABCDE", "emmerik", "the comment"); + + IssueChangeDto dto = IssueChangeDto.of(comment); + + assertThat(dto.getChangeData()).isEqualTo("the comment"); + assertThat(dto.getChangeType()).isEqualTo("comment"); + assertThat(dto.getCreatedAt()).isNotNull(); + assertThat(dto.getUpdatedAt()).isNotNull(); + assertThat(dto.getIssueChangeCreationDate()).isNotNull(); + assertThat(dto.getIssueKey()).isEqualTo("ABCDE"); + assertThat(dto.getUserLogin()).isEqualTo("emmerik"); + } + + @Test + public void create_from_comment_with_created_at() { + DefaultIssueComment comment = DefaultIssueComment.create("ABCDE", "emmerik", "the comment"); + comment.setCreatedAt(parseDate("2015-01-13")); + + IssueChangeDto dto = IssueChangeDto.of(comment); + + assertThat(dto.getIssueChangeCreationDate()).isEqualTo(parseDate("2015-01-13").getTime()); + } + + @Test + public void create_from_diff() { + FieldDiffs diffs = new FieldDiffs(); + diffs.setDiff("severity", "INFO", "BLOCKER"); + diffs.setUserLogin("emmerik"); + + IssueChangeDto dto = IssueChangeDto.of("ABCDE", diffs); + + assertThat(dto.getChangeData()).isEqualTo("severity=INFO|BLOCKER"); + assertThat(dto.getChangeType()).isEqualTo("diff"); + assertThat(dto.getCreatedAt()).isNotNull(); + assertThat(dto.getUpdatedAt()).isNotNull(); + assertThat(dto.getIssueChangeCreationDate()).isNull(); + assertThat(dto.getIssueKey()).isEqualTo("ABCDE"); + assertThat(dto.getUserLogin()).isEqualTo("emmerik"); + } + + @Test + public void create_from_diff_with_created_at() { + FieldDiffs diffs = new FieldDiffs(); + diffs.setDiff("severity", "INFO", "BLOCKER"); + diffs.setUserLogin("emmerik"); + diffs.setCreationDate(parseDate("2015-01-13")); + + IssueChangeDto dto = IssueChangeDto.of("ABCDE", diffs); + + assertThat(dto.getIssueChangeCreationDate()).isEqualTo(parseDate("2015-01-13").getTime()); + } + + @Test + public void to_comment() { + IssueChangeDto changeDto = new IssueChangeDto() + .setKey("EFGH") + .setUserLogin("emmerik") + .setChangeData("Some text") + .setIssueKey("ABCDE") + .setCreatedAt(System2.INSTANCE.now()) + .setUpdatedAt(System2.INSTANCE.now()); + + DefaultIssueComment comment = changeDto.toComment(); + assertThat(comment.key()).isEqualTo("EFGH"); + assertThat(comment.markdownText()).isEqualTo("Some text"); + assertThat(comment.createdAt()).isNotNull(); + assertThat(comment.updatedAt()).isNotNull(); + assertThat(comment.userLogin()).isEqualTo("emmerik"); + assertThat(comment.issueKey()).isEqualTo("ABCDE"); + } + + @Test + public void to_field_diffs_with_issue_creation_date() { + IssueChangeDto changeDto = new IssueChangeDto() + .setKey("EFGH") + .setUserLogin("emmerik") + .setChangeData("Some text") + .setIssueKey("ABCDE") + .setIssueChangeCreationDate(System2.INSTANCE.now()); + + FieldDiffs diffs = changeDto.toFieldDiffs(); + assertThat(diffs.userLogin()).isEqualTo("emmerik"); + assertThat(diffs.issueKey()).isEqualTo("ABCDE"); + assertThat(diffs.creationDate()).isNotNull(); + } + + @Test + public void to_field_diffs_with_create_at() { + IssueChangeDto changeDto = new IssueChangeDto() + .setKey("EFGH") + .setUserLogin("emmerik") + .setChangeData("Some text") + .setIssueKey("ABCDE") + .setCreatedAt(System2.INSTANCE.now()); + + FieldDiffs diffs = changeDto.toFieldDiffs(); + assertThat(diffs.userLogin()).isEqualTo("emmerik"); + assertThat(diffs.issueKey()).isEqualTo("ABCDE"); + assertThat(diffs.creationDate()).isNotNull(); + } + + @Test + public void to_string() { + DefaultIssueComment comment = DefaultIssueComment.create("ABCDE", "emmerik", "the comment"); + IssueChangeDto dto = IssueChangeDto.of(comment); + assertThat(dto.toString()).contains("ABCDE"); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/issue/IssueChangeMapperTest.java b/sonar-db/src/test/java/org/sonar/db/issue/IssueChangeMapperTest.java new file mode 100644 index 00000000000..dc2fef893e6 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/issue/IssueChangeMapperTest.java @@ -0,0 +1,76 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.issue; + +import org.apache.ibatis.session.SqlSession; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.sonar.db.AbstractDaoTestCase; +import org.sonar.db.MyBatis; + +public class IssueChangeMapperTest extends AbstractDaoTestCase { + SqlSession session; + IssueChangeMapper mapper; + + @Before + public void setUp() { + session = getMyBatis().openSession(); + mapper = session.getMapper(IssueChangeMapper.class); + } + + @After + public void tearDown() { + MyBatis.closeQuietly(session); + } + + @Test + public void insert_diff() { + IssueChangeDto dto = new IssueChangeDto(); + dto.setKey(null /* no key on field changes */); + dto.setUserLogin("emmerik"); + dto.setIssueKey("ABCDE"); + dto.setChangeType(IssueChangeDto.TYPE_FIELD_CHANGE); + dto.setChangeData("severity=INFO|BLOCKER"); + dto.setCreatedAt(1_500_000_000_000L); + dto.setUpdatedAt(1_500_000_000_000L); + dto.setIssueChangeCreationDate(1_500_000_000_000L); + mapper.insert(dto); + session.commit(); + + checkTables("insert_diff", new String[] {"id"}, "issue_changes"); + } + + @Test + public void insert_comment() { + IssueChangeDto dto = new IssueChangeDto(); + dto.setKey("COMMENT-1234"); + dto.setUserLogin("emmerik"); + dto.setIssueKey("ABCDE"); + dto.setChangeType(IssueChangeDto.TYPE_COMMENT); + dto.setChangeData("the comment"); + dto.setCreatedAt(1_500_000_000_000L); + dto.setUpdatedAt(1_500_000_000_000L); + mapper.insert(dto); + session.commit(); + + checkTables("insert_comment", new String[] {"id"}, "issue_changes"); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/issue/IssueDaoTest.java b/sonar-db/src/test/java/org/sonar/db/issue/IssueDaoTest.java new file mode 100644 index 00000000000..24f556df1e6 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/issue/IssueDaoTest.java @@ -0,0 +1,94 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.issue; + +import org.apache.ibatis.executor.result.DefaultResultHandler; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.sonar.db.AbstractDaoTestCase; +import org.sonar.db.DbSession; + +import static org.assertj.core.api.Assertions.assertThat; + +public class IssueDaoTest extends AbstractDaoTestCase { + + DbSession session; + + IssueDao dao; + + @Before + public void createDao() { + session = getMyBatis().openSession(false); + dao = new IssueDao(getMyBatis()); + } + + @After + public void tearDown() { + session.close(); + } + + @Test + public void select_non_closed_issues_by_module() { + setupData("shared", "should_select_non_closed_issues_by_module"); + + // 400 is a non-root module, we should find 2 issues from classes and one on itself + DefaultResultHandler handler = new DefaultResultHandler(); + dao.selectNonClosedIssuesByModule(400, handler); + assertThat(handler.getResultList()).hasSize(3); + + IssueDto issue = (IssueDto) handler.getResultList().get(0); + assertThat(issue.getRuleRepo()).isNotNull(); + assertThat(issue.getRule()).isNotNull(); + assertThat(issue.getComponentKey()).isNotNull(); + assertThat(issue.getProjectKey()).isEqualTo("struts"); + + // 399 is the root module, we should only find 1 issue on itself + handler = new DefaultResultHandler(); + dao.selectNonClosedIssuesByModule(399, handler); + assertThat(handler.getResultList()).hasSize(1); + + issue = (IssueDto) handler.getResultList().get(0); + assertThat(issue.getComponentKey()).isEqualTo("struts"); + assertThat(issue.getProjectKey()).isEqualTo("struts"); + } + + /** + * SONAR-5218 + */ + @Test + public void select_non_closed_issues_by_module_on_removed_project() { + // All issues are linked on a project that is not existing anymore + + setupData("shared", "should_select_non_closed_issues_by_module_on_removed_project"); + + // 400 is a non-root module, we should find 2 issues from classes and one on itself + DefaultResultHandler handler = new DefaultResultHandler(); + dao.selectNonClosedIssuesByModule(400, handler); + assertThat(handler.getResultList()).hasSize(3); + + IssueDto issue = (IssueDto) handler.getResultList().get(0); + assertThat(issue.getRuleRepo()).isNotNull(); + assertThat(issue.getRule()).isNotNull(); + assertThat(issue.getComponentKey()).isNotNull(); + assertThat(issue.getProjectKey()).isNull(); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/issue/IssueDtoTest.java b/sonar-db/src/test/java/org/sonar/db/issue/IssueDtoTest.java new file mode 100644 index 00000000000..3933f0302e3 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/issue/IssueDtoTest.java @@ -0,0 +1,150 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.issue; + +import java.util.Arrays; +import java.util.Calendar; +import java.util.Date; +import org.apache.commons.lang.time.DateUtils; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.api.issue.Issue; +import org.sonar.api.utils.Duration; +import org.sonar.core.issue.DefaultIssue; +import org.sonar.db.rule.RuleDto; + +import static org.assertj.core.api.Assertions.assertThat; + +public class IssueDtoTest { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void set_data_check_maximal_length() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Issue attributes must not exceed 4000 characters: "); + + StringBuilder s = new StringBuilder(4500); + for (int i = 0; i < 4500; i++) { + s.append('a'); + } + new IssueDto().setIssueAttributes(s.toString()); + } + + @Test + public void set_issue_fields() { + Date createdAt = DateUtils.addDays(new Date(), -5); + Date updatedAt = DateUtils.addDays(new Date(), -3); + Date closedAt = DateUtils.addDays(new Date(), -1); + + IssueDto dto = new IssueDto() + .setKee("100") + .setRuleId(1) + .setRuleKey("squid", "AvoidCycle") + .setLanguage("xoo") + .setComponentKey("org.sonar.sample:Sample") + .setComponentUuid("CDEF") + .setProjectUuid("GHIJ") + .setModuleUuid("BCDE") + .setModuleUuidPath("ABCD.BCDE.") + .setProjectKey("org.sonar.sample") + .setStatus(Issue.STATUS_CLOSED) + .setResolution(Issue.RESOLUTION_FALSE_POSITIVE) + .setEffortToFix(15.0) + .setDebt(10L) + .setLine(6) + .setSeverity("BLOCKER") + .setMessage("message") + .setManualSeverity(true) + .setReporter("arthur") + .setAssignee("perceval") + .setIssueAttributes("key=value") + .setAuthorLogin("pierre") + .setIssueCreationDate(createdAt) + .setIssueUpdateDate(updatedAt) + .setIssueCloseDate(closedAt); + + DefaultIssue issue = dto.toDefaultIssue(); + assertThat(issue.key()).isEqualTo("100"); + assertThat(issue.ruleKey().toString()).isEqualTo("squid:AvoidCycle"); + assertThat(issue.language()).isEqualTo("xoo"); + assertThat(issue.componentUuid()).isEqualTo("CDEF"); + assertThat(issue.projectUuid()).isEqualTo("GHIJ"); + assertThat(issue.componentKey()).isEqualTo("org.sonar.sample:Sample"); + assertThat(issue.moduleUuid()).isEqualTo("BCDE"); + assertThat(issue.moduleUuidPath()).isEqualTo("ABCD.BCDE."); + assertThat(issue.projectKey()).isEqualTo("org.sonar.sample"); + assertThat(issue.status()).isEqualTo(Issue.STATUS_CLOSED); + assertThat(issue.resolution()).isEqualTo(Issue.RESOLUTION_FALSE_POSITIVE); + assertThat(issue.effortToFix()).isEqualTo(15.0); + assertThat(issue.debt()).isEqualTo(Duration.create(10L)); + assertThat(issue.line()).isEqualTo(6); + assertThat(issue.severity()).isEqualTo("BLOCKER"); + assertThat(issue.message()).isEqualTo("message"); + assertThat(issue.manualSeverity()).isTrue(); + assertThat(issue.reporter()).isEqualTo("arthur"); + assertThat(issue.assignee()).isEqualTo("perceval"); + assertThat(issue.attribute("key")).isEqualTo("value"); + assertThat(issue.authorLogin()).isEqualTo("pierre"); + assertThat(issue.creationDate()).isEqualTo(DateUtils.truncate(createdAt, Calendar.SECOND)); + assertThat(issue.updateDate()).isEqualTo(DateUtils.truncate(updatedAt, Calendar.SECOND)); + assertThat(issue.closeDate()).isEqualTo(DateUtils.truncate(closedAt, Calendar.SECOND)); + assertThat(issue.isNew()).isFalse(); + } + + @Test + public void set_rule() { + IssueDto dto = new IssueDto() + .setKee("100") + .setRule(new RuleDto().setId(1).setRuleKey("AvoidCycle").setRepositoryKey("squid")) + .setLanguage("xoo"); + + assertThat(dto.getRuleId()).isEqualTo(1); + assertThat(dto.getRuleRepo()).isEqualTo("squid"); + assertThat(dto.getRule()).isEqualTo("AvoidCycle"); + assertThat(dto.getRuleKey().toString()).isEqualTo("squid:AvoidCycle"); + assertThat(dto.getLanguage()).isEqualTo("xoo"); + } + + @Test + public void set_tags() { + IssueDto dto = new IssueDto(); + assertThat(dto.getTags()).isEmpty(); + assertThat(dto.getTagsString()).isNull(); + + dto.setTags(Arrays.asList("tag1", "tag2", "tag3")); + assertThat(dto.getTags()).containsOnly("tag1", "tag2", "tag3"); + assertThat(dto.getTagsString()).isEqualTo("tag1,tag2,tag3"); + + dto.setTags(Arrays.<String>asList()); + assertThat(dto.getTags()).isEmpty(); + + dto.setTagsString("tag1, tag2 ,,tag3"); + assertThat(dto.getTags()).containsOnly("tag1", "tag2", "tag3"); + + dto.setTagsString(null); + assertThat(dto.getTags()).isEmpty(); + + dto.setTagsString(""); + assertThat(dto.getTags()).isEmpty(); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/issue/IssueFilterDaoTest.java b/sonar-db/src/test/java/org/sonar/db/issue/IssueFilterDaoTest.java new file mode 100644 index 00000000000..474eb8e8770 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/issue/IssueFilterDaoTest.java @@ -0,0 +1,129 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.issue; + +import java.util.List; +import org.junit.Before; +import org.junit.Test; +import org.sonar.db.AbstractDaoTestCase; + +import static org.assertj.core.api.Assertions.assertThat; + +public class IssueFilterDaoTest extends AbstractDaoTestCase { + + IssueFilterDao dao; + + @Before + public void createDao() { + dao = new IssueFilterDao(getMyBatis()); + } + + @Test + public void should_select_by_id() { + setupData("shared"); + + IssueFilterDto filter = dao.selectById(1L); + + assertThat(filter.getId()).isEqualTo(1L); + assertThat(filter.getName()).isEqualTo("Sonar Issues"); + assertThat(filter.isShared()).isTrue(); + + assertThat(dao.selectById(123L)).isNull(); + } + + @Test + public void should_select_by_user() { + setupData("should_select_by_user"); + + List<IssueFilterDto> results = dao.selectByUser("michael"); + + assertThat(results).hasSize(2); + } + + @Test + public void should_select_by_user_with_only_favorite_filters() { + setupData("should_select_by_user_with_only_favorite_filters"); + + List<IssueFilterDto> results = dao.selectFavoriteFiltersByUser("michael"); + + assertThat(results).hasSize(1); + IssueFilterDto issueFilterDto = results.get(0); + assertThat(issueFilterDto.getId()).isEqualTo(2L); + } + + @Test + public void should_select_shared() { + setupData("shared"); + + assertThat(dao.selectSharedFilters()).hasSize(1); + } + + @Test + public void should_select_provided_by_name() { + setupData("should_select_provided_by_name"); + + assertThat(dao.selectProvidedFilterByName("Unresolved Issues").getName()).isEqualTo("Unresolved Issues"); + assertThat(dao.selectProvidedFilterByName("My Unresolved Issues").getName()).isEqualTo("My Unresolved Issues"); + assertThat(dao.selectProvidedFilterByName("Unknown Filter")).isNull(); + } + + @Test + public void should_insert() { + setupData("shared"); + + IssueFilterDto filterDto = new IssueFilterDto(); + filterDto.setName("Sonar Open issues"); + filterDto.setUserLogin("michael"); + filterDto.setShared(true); + filterDto.setDescription("All open issues on Sonar"); + filterDto.setData("statuses=OPEN|componentRoots=org.codehaus.sonar"); + + dao.insert(filterDto); + + checkTables("should_insert", new String[] {"created_at", "updated_at"}, "issue_filters"); + } + + @Test + public void should_update() { + setupData("shared"); + + IssueFilterDto filterDto = new IssueFilterDto(); + filterDto.setId(2L); + filterDto.setName("Closed issues"); + filterDto.setShared(false); + filterDto.setDescription("All closed issues"); + filterDto.setData("statuses=CLOSED"); + filterDto.setUserLogin("bernard"); + + dao.update(filterDto); + + checkTables("should_update", new String[] {"created_at", "updated_at"}, "issue_filters"); + } + + @Test + public void should_delete() { + setupData("shared"); + + dao.delete(1l); + + checkTables("should_delete", new String[] {"created_at", "updated_at"}, "issue_filters"); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/issue/IssueFilterFavouriteDaoTest.java b/sonar-db/src/test/java/org/sonar/db/issue/IssueFilterFavouriteDaoTest.java new file mode 100644 index 00000000000..abe79583e69 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/issue/IssueFilterFavouriteDaoTest.java @@ -0,0 +1,99 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.issue; + +import java.util.List; +import org.junit.Before; +import org.junit.Test; +import org.sonar.db.AbstractDaoTestCase; + +import static org.assertj.core.api.Assertions.assertThat; + +public class IssueFilterFavouriteDaoTest extends AbstractDaoTestCase { + + IssueFilterFavouriteDao dao; + + @Before + public void createDao() { + dao = new IssueFilterFavouriteDao(getMyBatis()); + } + + @Test + public void should_select_by_id() { + setupData("shared"); + + IssueFilterFavouriteDto dto = dao.selectById(1L); + assertThat(dto.getId()).isEqualTo(1L); + assertThat(dto.getUserLogin()).isEqualTo("stephane"); + assertThat(dto.getIssueFilterId()).isEqualTo(10L); + assertThat(dto.getCreatedAt()).isNotNull(); + + assertThat(dao.selectById(999L)).isNull(); + } + + @Test + public void should_select_by_filter_id() { + setupData("shared"); + + List<IssueFilterFavouriteDto> dtos = dao.selectByFilterId(11L); + assertThat(dtos).hasSize(1); + IssueFilterFavouriteDto dto = dtos.get(0); + assertThat(dto.getId()).isEqualTo(2L); + assertThat(dto.getUserLogin()).isEqualTo("stephane"); + assertThat(dto.getIssueFilterId()).isEqualTo(11L); + assertThat(dto.getCreatedAt()).isNotNull(); + + assertThat(dao.selectByFilterId(10L)).hasSize(2); + assertThat(dao.selectByFilterId(999L)).isEmpty(); + } + + @Test + public void should_insert() { + setupData("shared"); + + IssueFilterFavouriteDto dto = new IssueFilterFavouriteDto(); + dto.setUserLogin("arthur"); + dto.setIssueFilterId(11L); + + dao.insert(dto); + + checkTables("should_insert", new String[] {"created_at"}, "issue_filter_favourites"); + } + + @Test + public void should_delete() { + setupData("shared"); + + dao.delete(3l); + + checkTables("should_delete", new String[] {"created_at"}, "issue_filter_favourites"); + } + + @Test + public void should_delete_by_issue_filter_id() { + setupData("shared"); + + dao.deleteByFilterId(10l); + + checkTables("should_delete_by_issue_filter_id", new String[] {"created_at"}, "issue_filter_favourites"); + } + +} diff --git a/sonar-db/src/test/java/org/sonar/db/issue/IssueMapperTest.java b/sonar-db/src/test/java/org/sonar/db/issue/IssueMapperTest.java new file mode 100644 index 00000000000..1e241b783ae --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/issue/IssueMapperTest.java @@ -0,0 +1,191 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.issue; + +import org.apache.ibatis.session.SqlSession; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.utils.DateUtils; +import org.sonar.db.AbstractDaoTestCase; +import org.sonar.db.MyBatis; + +import static org.assertj.core.api.Assertions.assertThat; + +public class IssueMapperTest extends AbstractDaoTestCase { + + SqlSession session; + IssueMapper mapper; + + @Before + public void setUp() { + session = getMyBatis().openSession(); + mapper = session.getMapper(IssueMapper.class); + } + + @After + public void tearDown() { + MyBatis.closeQuietly(session); + } + + @Test + public void insert() { + IssueDto dto = new IssueDto(); + dto.setComponentUuid("uuid-123"); + dto.setProjectUuid("uuid-100"); + dto.setRuleId(200); + dto.setKee("ABCDE"); + dto.setLine(500); + dto.setEffortToFix(3.14); + dto.setDebt(10L); + dto.setResolution("FIXED"); + dto.setStatus("RESOLVED"); + dto.setSeverity("BLOCKER"); + dto.setReporter("emmerik"); + dto.setAuthorLogin("morgan"); + dto.setAssignee("karadoc"); + dto.setActionPlanKey("current_sprint"); + dto.setIssueAttributes("JIRA=FOO-1234"); + dto.setChecksum("123456789"); + dto.setMessage("the message"); + + dto.setIssueCreationTime(1_401_000_000_000L); + dto.setIssueUpdateTime(1_402_000_000_000L); + dto.setIssueCloseTime(1_403_000_000_000L); + dto.setCreatedAt(1_400_000_000_000L); + dto.setUpdatedAt(1_500_000_000_000L); + + mapper.insert(dto); + session.commit(); + + checkTables("testInsert", new String[] {"id"}, "issues"); + } + + @Test + public void update() { + setupData("testUpdate"); + + IssueDto dto = new IssueDto(); + dto.setComponentUuid("uuid-123"); + dto.setProjectUuid("uuid-101"); + dto.setRuleId(200); + dto.setKee("ABCDE"); + dto.setLine(500); + dto.setEffortToFix(3.14); + dto.setDebt(10L); + dto.setResolution("FIXED"); + dto.setStatus("RESOLVED"); + dto.setSeverity("BLOCKER"); + dto.setReporter("emmerik"); + dto.setAuthorLogin("morgan"); + dto.setAssignee("karadoc"); + dto.setActionPlanKey("current_sprint"); + dto.setIssueAttributes("JIRA=FOO-1234"); + dto.setChecksum("123456789"); + dto.setMessage("the message"); + + dto.setIssueCreationTime(1_401_000_000_000L); + dto.setIssueUpdateTime(1_402_000_000_000L); + dto.setIssueCloseTime(1_403_000_000_000L); + dto.setCreatedAt(1_400_000_000_000L); + dto.setUpdatedAt(1_500_000_000_000L); + + mapper.update(dto); + session.commit(); + + checkTables("testUpdate", new String[] {"id"}, "issues"); + } + + @Test + public void updateBeforeSelectedDate_without_conflict() { + setupData("testUpdate"); + + IssueDto dto = new IssueDto(); + dto.setComponentUuid("uuid-123"); + dto.setProjectUuid("uuid-101"); + dto.setRuleId(200); + dto.setKee("ABCDE"); + dto.setLine(500); + dto.setEffortToFix(3.14); + dto.setDebt(10L); + dto.setResolution("FIXED"); + dto.setStatus("RESOLVED"); + dto.setSeverity("BLOCKER"); + dto.setReporter("emmerik"); + dto.setAuthorLogin("morgan"); + dto.setAssignee("karadoc"); + dto.setActionPlanKey("current_sprint"); + dto.setIssueAttributes("JIRA=FOO-1234"); + dto.setChecksum("123456789"); + dto.setMessage("the message"); + dto.setIssueCreationTime(1_401_000_000_000L); + dto.setIssueUpdateTime(1_402_000_000_000L); + dto.setIssueCloseTime(1_403_000_000_000L); + dto.setCreatedAt(1_400_000_000_000L); + dto.setUpdatedAt(1_500_000_000_000L); + + // selected after last update -> ok + dto.setSelectedAt(1500000000000L); + + int count = mapper.updateIfBeforeSelectedDate(dto); + assertThat(count).isEqualTo(1); + session.commit(); + + checkTables("testUpdate", new String[] {"id"}, "issues"); + } + + @Test + public void updateBeforeSelectedDate_with_conflict() { + setupData("updateBeforeSelectedDate_with_conflict"); + + IssueDto dto = new IssueDto(); + dto.setComponentUuid("uuid-123"); + dto.setProjectUuid("uuid-101"); + dto.setRuleId(200); + dto.setKee("ABCDE"); + dto.setLine(500); + dto.setEffortToFix(3.14); + dto.setDebt(10L); + dto.setResolution("FIXED"); + dto.setStatus("RESOLVED"); + dto.setSeverity("BLOCKER"); + dto.setReporter("emmerik"); + dto.setAuthorLogin("morgan"); + dto.setAssignee("karadoc"); + dto.setActionPlanKey("current_sprint"); + dto.setIssueAttributes("JIRA=FOO-1234"); + dto.setChecksum("123456789"); + dto.setMessage("the message"); + dto.setIssueCreationDate(DateUtils.parseDate("2013-05-18")); + dto.setIssueUpdateDate(DateUtils.parseDate("2013-05-19")); + dto.setIssueCloseDate(DateUtils.parseDate("2013-05-20")); + dto.setCreatedAt(1400000000000L); + dto.setUpdatedAt(1460000000000L); + + // selected before last update -> ko + dto.setSelectedAt(1400000000000L); + + int count = mapper.updateIfBeforeSelectedDate(dto); + assertThat(count).isEqualTo(0); + session.commit(); + + checkTables("updateBeforeSelectedDate_with_conflict", new String[] {"id"}, "issues"); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/loadedtemplate/LoadedTemplateDaoTest.java b/sonar-db/src/test/java/org/sonar/db/loadedtemplate/LoadedTemplateDaoTest.java new file mode 100644 index 00000000000..13253d6bef3 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/loadedtemplate/LoadedTemplateDaoTest.java @@ -0,0 +1,55 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.loadedtemplate; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.db.AbstractDaoTestCase; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + +public class LoadedTemplateDaoTest extends AbstractDaoTestCase { + + private LoadedTemplateDao dao; + + @Before + public void createDao() { + dao = new LoadedTemplateDao(getMyBatis()); + } + + @Test + public void shouldCountByTypeAndKey() { + setupData("shouldCountByTypeAndKey"); + assertThat(dao.countByTypeAndKey("DASHBOARD", "HOTSPOTS"), is(1)); + assertThat(dao.countByTypeAndKey("DASHBOARD", "UNKNOWN"), is(0)); + assertThat(dao.countByTypeAndKey("PROFILE", "HOTSPOTS"), is(0)); + } + + @Test + public void shouldInsert() { + setupData("shouldInsert"); + + LoadedTemplateDto template = new LoadedTemplateDto("SQALE", "DASHBOARD"); + dao.insert(template); + + checkTables("shouldInsert", "loaded_templates"); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/measure/MeasureDtoTest.java b/sonar-db/src/test/java/org/sonar/db/measure/MeasureDtoTest.java new file mode 100644 index 00000000000..058b0007c6c --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/measure/MeasureDtoTest.java @@ -0,0 +1,75 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.measure; + +import com.google.common.base.Strings; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class MeasureDtoTest { + + MeasureDto sut = new MeasureDto(); + + @Test + public void test_getter_and_setter() throws Exception { + sut + .setComponentKey("component") + .setMetricKey("metric") + .setId(10L) + .setValue(2d) + .setData("text value") + .setVariation(1, 1d) + .setVariation(2, 2d) + .setVariation(3, 3d) + .setVariation(4, 4d) + .setVariation(5, 5d); + + assertThat(sut.getId()).isEqualTo(10); + assertThat(sut.getValue()).isEqualTo(2d); + assertThat(sut.getData()).isNotNull(); + assertThat(sut.getVariation(1)).isEqualTo(1d); + assertThat(sut.getVariation(2)).isEqualTo(2d); + assertThat(sut.getVariation(3)).isEqualTo(3d); + assertThat(sut.getVariation(4)).isEqualTo(4d); + assertThat(sut.getVariation(5)).isEqualTo(5d); + } + + @Test + public void value_with_text_over_4000_characters() { + assertThat(sut.setData(Strings.repeat("1", 4001)).getData()).isNotNull(); + } + + @Test + public void text_value_under_4000_characters() { + assertThat(sut.setData("text value").getData()).isEqualTo("text value"); + } + + @Test(expected = IndexOutOfBoundsException.class) + public void fail_to_set_out_of_bounds_variation() { + sut.setVariation(6, 1d); + } + + @Test(expected = IndexOutOfBoundsException.class) + public void fail_to_get_out_of_bounds_variation() { + sut.getVariation(6); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/measure/MeasureFilterDaoTest.java b/sonar-db/src/test/java/org/sonar/db/measure/MeasureFilterDaoTest.java new file mode 100644 index 00000000000..06efb6a3825 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/measure/MeasureFilterDaoTest.java @@ -0,0 +1,68 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.measure; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.db.AbstractDaoTestCase; + +import static org.assertj.core.api.Assertions.assertThat; + +public class MeasureFilterDaoTest extends AbstractDaoTestCase { + private MeasureFilterDao dao; + + @Before + public void createDao() { + dao = new MeasureFilterDao(getMyBatis()); + } + + @Test + public void should_find_filter() { + setupData("shared"); + + MeasureFilterDto filter = dao.findSystemFilterByName("Projects"); + + assertThat(filter.getId()).isEqualTo(1L); + assertThat(filter.getName()).isEqualTo("Projects"); + } + + @Test + public void should_not_find_filter() { + setupData("shared"); + + assertThat(dao.findSystemFilterByName("Unknown")).isNull(); + } + + @Test + public void should_insert() { + setupData("shared"); + + MeasureFilterDto filterDto = new MeasureFilterDto(); + filterDto.setName("Project Treemap"); + filterDto.setUserId(123L); + filterDto.setShared(true); + filterDto.setDescription("Treemap of projects"); + filterDto.setData("qualifiers=TRK|display=treemap"); + + dao.insert(filterDto); + + checkTables("shouldInsert", new String[] {"created_at", "updated_at"}, "measure_filters"); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/measure/PastMeasureDtoTest.java b/sonar-db/src/test/java/org/sonar/db/measure/PastMeasureDtoTest.java new file mode 100644 index 00000000000..6b1176088fa --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/measure/PastMeasureDtoTest.java @@ -0,0 +1,72 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.measure; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class PastMeasureDtoTest { + + @Test + public void test_getter_and_setter() throws Exception { + PastMeasureDto dto = new PastMeasureDto() + .setId(10L) + .setValue(1d) + .setMetricId(2) + .setRuleId(3) + .setCharacteristicId(4) + .setPersonId(5); + + assertThat(dto.getId()).isEqualTo(10L); + assertThat(dto.hasValue()).isTrue(); + assertThat(dto.getValue()).isEqualTo(1d); + assertThat(dto.getMetricId()).isEqualTo(2); + assertThat(dto.getRuleId()).isEqualTo(3); + assertThat(dto.getCharacteristicId()).isEqualTo(4); + assertThat(dto.getPersonId()).isEqualTo(5); + } + + @Test + public void test_has_value() throws Exception { + PastMeasureDto measureWithValue = new PastMeasureDto() + .setId(10L) + .setValue(1d) + .setMetricId(2) + .setRuleId(3) + .setCharacteristicId(4) + .setPersonId(5); + assertThat(measureWithValue.hasValue()).isTrue(); + + PastMeasureDto measureWithoutValue = new PastMeasureDto() + .setId(10L) + .setMetricId(2) + .setRuleId(3) + .setCharacteristicId(4) + .setPersonId(5); + assertThat(measureWithoutValue.hasValue()).isFalse(); + } + + @Test(expected = NullPointerException.class) + public void get_value_throw_a_NPE_if_value_is_null() throws Exception { + new PastMeasureDto().getValue(); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/metric/MetricDtoTest.java b/sonar-db/src/test/java/org/sonar/db/metric/MetricDtoTest.java new file mode 100644 index 00000000000..47366890df9 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/metric/MetricDtoTest.java @@ -0,0 +1,64 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.metric; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class MetricDtoTest { + + @Test + public void getters_and_setters() { + MetricDto metricDto = new MetricDto() + .setId(1) + .setKey("coverage") + .setShortName("Coverage") + .setDescription("Coverage by unit tests") + .setDomain("Tests") + .setValueType("PERCENT") + .setQualitative(true) + .setUserManaged(false) + .setWorstValue(0d) + .setBestValue(100d) + .setOptimizedBestValue(true) + .setDirection(1) + .setHidden(true) + .setDeleteHistoricalData(true) + .setEnabled(true); + + assertThat(metricDto.getId()).isEqualTo(1); + assertThat(metricDto.getKey()).isEqualTo("coverage"); + assertThat(metricDto.getShortName()).isEqualTo("Coverage"); + assertThat(metricDto.getDescription()).isEqualTo("Coverage by unit tests"); + assertThat(metricDto.getDomain()).isEqualTo("Tests"); + assertThat(metricDto.getValueType()).isEqualTo("PERCENT"); + assertThat(metricDto.isQualitative()).isTrue(); + assertThat(metricDto.isUserManaged()).isFalse(); + assertThat(metricDto.getWorstValue()).isEqualTo(0d); + assertThat(metricDto.getBestValue()).isEqualTo(100d); + assertThat(metricDto.isOptimizedBestValue()).isTrue(); + assertThat(metricDto.getDirection()).isEqualTo(1); + assertThat(metricDto.isHidden()).isTrue(); + assertThat(metricDto.isDeleteHistoricalData()).isTrue(); + assertThat(metricDto.isEnabled()).isTrue(); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/notification/NotificationQueueDaoTest.java b/sonar-db/src/test/java/org/sonar/db/notification/NotificationQueueDaoTest.java new file mode 100644 index 00000000000..2c2f0ebd65c --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/notification/NotificationQueueDaoTest.java @@ -0,0 +1,85 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.notification; + +import java.util.Arrays; +import java.util.Collection; +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.notifications.Notification; +import org.sonar.db.AbstractDaoTestCase; + +import static org.assertj.core.api.Assertions.assertThat; + +public class NotificationQueueDaoTest extends AbstractDaoTestCase { + + NotificationQueueDao dao; + + @Before + public void createDao() { + dao = new NotificationQueueDao(getMyBatis()); + } + + @Test + public void should_insert_new_notification_queue() throws Exception { + NotificationQueueDto notificationQueueDto = NotificationQueueDto.toNotificationQueueDto(new Notification("email")); + + dao.insert(Arrays.asList(notificationQueueDto)); + + assertThat(dao.count()).isEqualTo(1); + assertThat(dao.findOldest(1).get(0).toNotification().getType()).isEqualTo("email"); + } + + @Test + public void should_count_notification_queue() { + NotificationQueueDto notificationQueueDto = NotificationQueueDto.toNotificationQueueDto(new Notification("email")); + + assertThat(dao.count()).isEqualTo(0); + + dao.insert(Arrays.asList(notificationQueueDto)); + + assertThat(dao.count()).isEqualTo(1); + } + + @Test + public void should_delete_notification() { + setupData("should_delete_notification"); + + NotificationQueueDto dto1 = new NotificationQueueDto().setId(1L); + NotificationQueueDto dto3 = new NotificationQueueDto().setId(3L); + + dao.delete(Arrays.asList(dto1, dto3)); + + checkTables("should_delete_notification", "notifications"); + } + + @Test + public void should_findOldest() { + setupData("should_findOldest"); + + Collection<NotificationQueueDto> result = dao.findOldest(3); + assertThat(result).hasSize(3); + assertThat(result).extracting("id").containsOnly(1L, 2L, 3L); + + result = dao.findOldest(6); + assertThat(result).hasSize(4); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/permission/GroupWithPermissionDaoTest.java b/sonar-db/src/test/java/org/sonar/db/permission/GroupWithPermissionDaoTest.java new file mode 100644 index 00000000000..c6f9f03760d --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/permission/GroupWithPermissionDaoTest.java @@ -0,0 +1,137 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.permission; + +import java.util.List; +import org.junit.Before; +import org.junit.Test; +import org.sonar.db.AbstractDaoTestCase; + +import static org.assertj.core.api.Assertions.assertThat; + +public class GroupWithPermissionDaoTest extends AbstractDaoTestCase { + + private static final long COMPONENT_ID = 100L; + + private PermissionDao dao; + + @Before + public void setUp() { + dao = new PermissionDao(getMyBatis()); + } + + @Test + public void select_groups_for_project_permission() { + setupData("groups_with_permissions"); + + PermissionQuery query = PermissionQuery.builder().permission("user").build(); + List<GroupWithPermissionDto> result = dao.selectGroups(query, COMPONENT_ID); + assertThat(result).hasSize(4); + + GroupWithPermissionDto anyone = result.get(0); + assertThat(anyone.getName()).isEqualTo("Anyone"); + assertThat(anyone.getDescription()).isNull(); + assertThat(anyone.getPermission()).isNotNull(); + + GroupWithPermissionDto group1 = result.get(1); + assertThat(group1.getName()).isEqualTo("sonar-administrators"); + assertThat(group1.getDescription()).isEqualTo("System administrators"); + assertThat(group1.getPermission()).isNotNull(); + + GroupWithPermissionDto group2 = result.get(2); + assertThat(group2.getName()).isEqualTo("sonar-reviewers"); + assertThat(group2.getDescription()).isEqualTo("Reviewers"); + assertThat(group2.getPermission()).isNull(); + + GroupWithPermissionDto group3 = result.get(3); + assertThat(group3.getName()).isEqualTo("sonar-users"); + assertThat(group3.getDescription()).isEqualTo("Any new users created will automatically join this group"); + assertThat(group3.getPermission()).isNotNull(); + } + + @Test + public void anyone_group_is_not_returned_when_it_has_no_permission() { + setupData("groups_with_permissions"); + + // Anyone group has not the permission 'admin', so it's not returned + PermissionQuery query = PermissionQuery.builder().permission("admin").build(); + List<GroupWithPermissionDto> result = dao.selectGroups(query, COMPONENT_ID); + assertThat(result).hasSize(3); + + GroupWithPermissionDto group1 = result.get(0); + assertThat(group1.getName()).isEqualTo("sonar-administrators"); + assertThat(group1.getPermission()).isNotNull(); + + GroupWithPermissionDto group2 = result.get(1); + assertThat(group2.getName()).isEqualTo("sonar-reviewers"); + assertThat(group2.getPermission()).isNull(); + + GroupWithPermissionDto group3 = result.get(2); + assertThat(group3.getName()).isEqualTo("sonar-users"); + assertThat(group3.getPermission()).isNull(); + } + + @Test + public void select_groups_for_global_permission() { + setupData("groups_with_permissions"); + + PermissionQuery query = PermissionQuery.builder().permission("admin").build(); + List<GroupWithPermissionDto> result = dao.selectGroups(query, null); + assertThat(result).hasSize(3); + + GroupWithPermissionDto group1 = result.get(0); + assertThat(group1.getName()).isEqualTo("sonar-administrators"); + assertThat(group1.getPermission()).isNotNull(); + + GroupWithPermissionDto group2 = result.get(1); + assertThat(group2.getName()).isEqualTo("sonar-reviewers"); + assertThat(group2.getPermission()).isNull(); + + GroupWithPermissionDto group3 = result.get(2); + assertThat(group3.getName()).isEqualTo("sonar-users"); + assertThat(group3.getPermission()).isNull(); + } + + @Test + public void search_by_groups_name() { + setupData("groups_with_permissions"); + + List<GroupWithPermissionDto> result = dao.selectGroups(PermissionQuery.builder().permission("user").search("aDMini").build(), COMPONENT_ID); + assertThat(result).hasSize(1); + assertThat(result.get(0).getName()).isEqualTo("sonar-administrators"); + + result = dao.selectGroups(PermissionQuery.builder().permission("user").search("sonar").build(), COMPONENT_ID); + assertThat(result).hasSize(3); + } + + @Test + public void search_groups_should_be_sorted_by_group_name() { + setupData("groups_with_permissions_should_be_sorted_by_group_name"); + + List<GroupWithPermissionDto> result = dao.selectGroups(PermissionQuery.builder().permission("user").build(), COMPONENT_ID); + assertThat(result).hasSize(4); + assertThat(result.get(0).getName()).isEqualTo("Anyone"); + assertThat(result.get(1).getName()).isEqualTo("sonar-administrators"); + assertThat(result.get(2).getName()).isEqualTo("sonar-reviewers"); + assertThat(result.get(3).getName()).isEqualTo("sonar-users"); + } + +} diff --git a/sonar-db/src/test/java/org/sonar/db/permission/GroupWithPermissionDtoTest.java b/sonar-db/src/test/java/org/sonar/db/permission/GroupWithPermissionDtoTest.java new file mode 100644 index 00000000000..04101abeb04 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/permission/GroupWithPermissionDtoTest.java @@ -0,0 +1,54 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.permission; + +import org.junit.Test; +import org.sonar.core.permission.GroupWithPermission; + +import static org.assertj.core.api.Assertions.assertThat; + +public class GroupWithPermissionDtoTest { + + @Test + public void to_group_with_permission_having_permission() { + GroupWithPermission group = new GroupWithPermissionDto() + .setName("users") + .setDescription("desc") + .setPermission("user") + .toGroupWithPermission(); + + assertThat(group.name()).isEqualTo("users"); + assertThat(group.description()).isEqualTo("desc"); + assertThat(group.hasPermission()).isTrue(); + } + + @Test + public void to_group_with_permission_not_having_permission() { + GroupWithPermission group = new GroupWithPermissionDto() + .setName("users") + .setPermission(null) + .toGroupWithPermission(); + + assertThat(group.name()).isEqualTo("users"); + assertThat(group.description()).isNull(); + assertThat(group.hasPermission()).isFalse(); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/permission/GroupWithPermissionTemplateDaoTest.java b/sonar-db/src/test/java/org/sonar/db/permission/GroupWithPermissionTemplateDaoTest.java new file mode 100644 index 00000000000..0cb583bded5 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/permission/GroupWithPermissionTemplateDaoTest.java @@ -0,0 +1,118 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.permission; + +import java.util.List; +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.utils.System2; +import org.sonar.db.AbstractDaoTestCase; + +import static org.assertj.core.api.Assertions.assertThat; + +public class GroupWithPermissionTemplateDaoTest extends AbstractDaoTestCase { + + private static final long TEMPLATE_ID = 50L; + + private PermissionTemplateDao dao; + + @Before + public void setUp() { + dao = new PermissionTemplateDao(getMyBatis(), System2.INSTANCE); + } + + @Test + public void select_groups() { + setupData("groups_with_permissions"); + + PermissionQuery query = PermissionQuery.builder().permission("user").build(); + List<GroupWithPermissionDto> result = dao.selectGroups(query, TEMPLATE_ID); + + assertThat(result).hasSize(4); + + GroupWithPermissionDto anyone = result.get(0); + assertThat(anyone.getName()).isEqualTo("Anyone"); + assertThat(anyone.getDescription()).isNull(); + assertThat(anyone.getPermission()).isNotNull(); + + GroupWithPermissionDto group1 = result.get(1); + assertThat(group1.getName()).isEqualTo("sonar-administrators"); + assertThat(group1.getDescription()).isEqualTo("System administrators"); + assertThat(group1.getPermission()).isNotNull(); + + GroupWithPermissionDto group2 = result.get(2); + assertThat(group2.getName()).isEqualTo("sonar-reviewers"); + assertThat(group2.getDescription()).isEqualTo("Reviewers"); + assertThat(group2.getPermission()).isNull(); + + GroupWithPermissionDto group3 = result.get(3); + assertThat(group3.getName()).isEqualTo("sonar-users"); + assertThat(group3.getDescription()).isEqualTo("Any new users created will automatically join this group"); + assertThat(group3.getPermission()).isNotNull(); + } + + @Test + public void anyone_group_is_not_returned_when_it_has_no_permission() { + setupData("groups_with_permissions"); + + // Anyone group has not the permission 'admin', so it's not returned + PermissionQuery query = PermissionQuery.builder().permission("admin").build(); + List<GroupWithPermissionDto> result = dao.selectGroups(query, TEMPLATE_ID); + assertThat(result).hasSize(3); + + GroupWithPermissionDto group1 = result.get(0); + assertThat(group1.getName()).isEqualTo("sonar-administrators"); + assertThat(group1.getPermission()).isNotNull(); + + GroupWithPermissionDto group2 = result.get(1); + assertThat(group2.getName()).isEqualTo("sonar-reviewers"); + assertThat(group2.getPermission()).isNull(); + + GroupWithPermissionDto group3 = result.get(2); + assertThat(group3.getName()).isEqualTo("sonar-users"); + assertThat(group3.getPermission()).isNull(); + } + + @Test + public void search_by_groups_name() { + setupData("groups_with_permissions"); + + List<GroupWithPermissionDto> result = dao.selectGroups(PermissionQuery.builder().permission("user").search("aDMini").build(), TEMPLATE_ID); + assertThat(result).hasSize(1); + assertThat(result.get(0).getName()).isEqualTo("sonar-administrators"); + + result = dao.selectGroups(PermissionQuery.builder().permission("user").search("sonar").build(), TEMPLATE_ID); + assertThat(result).hasSize(3); + } + + @Test + public void search_groups_should_be_sorted_by_group_name() { + setupData("groups_with_permissions_should_be_sorted_by_group_name"); + + List<GroupWithPermissionDto> result = dao.selectGroups(PermissionQuery.builder().permission("user").build(), TEMPLATE_ID); + assertThat(result).hasSize(4); + assertThat(result.get(0).getName()).isEqualTo("Anyone"); + assertThat(result.get(1).getName()).isEqualTo("sonar-administrators"); + assertThat(result.get(2).getName()).isEqualTo("sonar-reviewers"); + assertThat(result.get(3).getName()).isEqualTo("sonar-users"); + } + +} diff --git a/sonar-db/src/test/java/org/sonar/db/permission/GroupWithPermissionTest.java b/sonar-db/src/test/java/org/sonar/db/permission/GroupWithPermissionTest.java new file mode 100644 index 00000000000..7ddc78d1308 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/permission/GroupWithPermissionTest.java @@ -0,0 +1,56 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.permission; + +import org.junit.Test; +import org.sonar.core.permission.GroupWithPermission; + +import static org.assertj.core.api.Assertions.assertThat; + +public class GroupWithPermissionTest { + + @Test + public void test_setters_and_getters() throws Exception { + GroupWithPermission user = new GroupWithPermission() + .setName("users") + .hasPermission(true); + + assertThat(user.name()).isEqualTo("users"); + assertThat(user.hasPermission()).isTrue(); + } + + @Test + public void test_equals() throws Exception { + assertThat(new GroupWithPermission().setName("users")).isEqualTo(new GroupWithPermission().setName("users")); + assertThat(new GroupWithPermission().setName("users")).isNotEqualTo(new GroupWithPermission().setName("reviewers")); + + GroupWithPermission group = new GroupWithPermission() + .setName("users") + .hasPermission(true); + assertThat(group).isEqualTo(group); + } + + @Test + public void test_hashcode() throws Exception { + assertThat(new GroupWithPermission().setName("users").hashCode()).isEqualTo(new GroupWithPermission().setName("users").hashCode()); + assertThat(new GroupWithPermission().setName("users").hashCode()).isNotEqualTo(new GroupWithPermission().setName("reviewers").hashCode()); + } + +} diff --git a/sonar-db/src/test/java/org/sonar/db/permission/PermissionFacadeTest.java b/sonar-db/src/test/java/org/sonar/db/permission/PermissionFacadeTest.java new file mode 100644 index 00000000000..1a965020c71 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/permission/PermissionFacadeTest.java @@ -0,0 +1,218 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.permission; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.api.config.Settings; +import org.sonar.api.utils.System2; +import org.sonar.api.web.UserRole; +import org.sonar.db.AbstractDaoTestCase; +import org.sonar.db.DbSession; +import org.sonar.db.component.ResourceDao; +import org.sonar.db.user.RoleDao; +import org.sonar.db.user.UserDao; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class PermissionFacadeTest extends AbstractDaoTestCase { + + @Rule + public ExpectedException throwable = ExpectedException.none(); + + DbSession session; + System2 system2; + PermissionFacade permissionFacade; + PermissionTemplateDao permissionTemplateDao; + ResourceDao resourceDao; + + @Before + public void setUp() { + system2 = mock(System2.class); + when(system2.now()).thenReturn(123456789L); + + session = getMyBatis().openSession(false); + RoleDao roleDao = new RoleDao(); + UserDao userDao = new UserDao(getMyBatis(), system2); + permissionTemplateDao = new PermissionTemplateDao(getMyBatis(), System2.INSTANCE); + Settings settings = new Settings(); + resourceDao = new ResourceDao(getMyBatis(), system2); + permissionFacade = new PermissionFacade(roleDao, userDao, resourceDao, permissionTemplateDao, settings); + } + + @After + public void tearDown() { + session.close(); + } + + @Test + public void should_apply_permission_template() { + setupData("should_apply_permission_template"); + + assertThat(permissionFacade.selectGroupPermissions(session, "sonar-administrators", 123L)).isEmpty(); + assertThat(permissionFacade.selectGroupPermissions(session, "sonar-users", 123L)).isEmpty(); + assertThat(permissionFacade.selectGroupPermissions(session, "Anyone", 123L)).isEmpty(); + assertThat(permissionFacade.selectUserPermissions(session, "marius", 123L)).isEmpty(); + + permissionFacade.applyPermissionTemplate(session, "default_20130101_010203", 123L); + + assertThat(permissionFacade.selectGroupPermissions(session, "sonar-administrators", 123L)).containsOnly("admin", "issueadmin"); + assertThat(permissionFacade.selectGroupPermissions(session, "sonar-users", 123L)).containsOnly("user", "codeviewer"); + assertThat(permissionFacade.selectGroupPermissions(session, "Anyone", 123L)).containsOnly("user", "codeviewer"); + + assertThat(permissionFacade.selectUserPermissions(session, "marius", 123L)).containsOnly("admin"); + + assertThat(resourceDao.getResource(123L, session).getAuthorizationUpdatedAt()).isEqualTo(123456789L); + } + + @Test + public void should_count_component_permissions() { + setupData("should_count_component_permissions"); + + assertThat(permissionFacade.countComponentPermissions(session, 123L)).isEqualTo(2); + } + + @Test + public void should_add_user_permission() { + setupData("should_add_user_permission"); + + permissionFacade.insertUserPermission(123L, 200L, UserRole.ADMIN, session); + session.commit(); + + checkTable("should_add_user_permission", "user_roles", "user_id", "resource_id", "role"); + checkTable("should_add_user_permission", "projects", "authorization_updated_at"); + } + + @Test + public void should_delete_user_permission() { + setupData("should_delete_user_permission"); + + permissionFacade.deleteUserPermission(123L, 200L, UserRole.ADMIN, session); + session.commit(); + + checkTable("should_delete_user_permission", "user_roles", "user_id", "resource_id", "role"); + checkTable("should_delete_user_permission", "projects", "authorization_updated_at"); + } + + @Test + public void should_insert_group_permission() { + setupData("should_insert_group_permission"); + + permissionFacade.insertGroupPermission(123L, 100L, UserRole.USER, session); + session.commit(); + + checkTable("should_insert_group_permission", "group_roles", "group_id", "resource_id", "role"); + checkTable("should_insert_group_permission", "projects", "authorization_updated_at"); + } + + @Test + public void should_insert_group_name_permission() { + setupData("should_insert_group_permission"); + + permissionFacade.insertGroupPermission(123L, "devs", UserRole.USER, session); + session.commit(); + + checkTable("should_insert_group_permission", "group_roles", "group_id", "resource_id", "role"); + checkTable("should_insert_group_permission", "projects", "authorization_updated_at"); + } + + @Test + public void should_insert_anyone_group_permission() { + setupData("should_insert_anyone_group_permission"); + + permissionFacade.insertGroupPermission(123L, "Anyone", UserRole.USER, session); + session.commit(); + + checkTable("should_insert_anyone_group_permission", "group_roles", "group_id", "resource_id", "role"); + checkTable("should_insert_anyone_group_permission", "projects", "authorization_updated_at"); + } + + @Test + public void should_delete_group_permission() { + setupData("should_delete_group_permission"); + + permissionFacade.deleteGroupPermission(123L, 100L, UserRole.USER, session); + session.commit(); + + checkTable("should_delete_group_permission", "group_roles", "group_id", "resource_id", "role"); + checkTable("should_delete_group_permission", "projects", "authorization_updated_at"); + } + + @Test + public void should_delete_group_name_permission() { + setupData("should_delete_group_permission"); + + permissionFacade.deleteGroupPermission(123L, "devs", UserRole.USER, session); + session.commit(); + + checkTable("should_delete_group_permission", "group_roles", "group_id", "resource_id", "role"); + checkTable("should_delete_group_permission", "projects", "authorization_updated_at"); + } + + @Test + public void should_retrieve_permission_template() { + PermissionTemplateDto permissionTemplateDto = new PermissionTemplateDto().setName("Test template").setKee("test_template"); + PermissionTemplateDto templateWithPermissions = new PermissionTemplateDto().setKee("test_template"); + permissionTemplateDao = mock(PermissionTemplateDao.class); + when(permissionTemplateDao.selectTemplateByKey(session, "test_template")).thenReturn(permissionTemplateDto); + when(permissionTemplateDao.selectPermissionTemplate(session, "test_template")).thenReturn(templateWithPermissions); + + permissionFacade = new PermissionFacade(null, null, null, permissionTemplateDao, null); + + PermissionTemplateDto permissionTemplate = permissionFacade.getPermissionTemplateWithPermissions(session, "test_template"); + + assertThat(permissionTemplate).isSameAs(templateWithPermissions); + } + + @Test + public void should_fail_on_unmatched_template() { + throwable.expect(IllegalArgumentException.class); + + permissionTemplateDao = mock(PermissionTemplateDao.class); + + permissionFacade = new PermissionFacade(null, null, null, permissionTemplateDao, null); + permissionFacade.getPermissionTemplateWithPermissions(session, "unmatched"); + } + + @Test + public void should_remove_all_permissions() { + setupData("should_remove_all_permissions"); + + assertThat(permissionFacade.selectGroupPermissions(session, "devs", 123L)).hasSize(1); + assertThat(permissionFacade.selectGroupPermissions(session, "other", 123L)).isEmpty(); + assertThat(permissionFacade.selectUserPermissions(session, "dave.loper", 123L)).hasSize(1); + assertThat(permissionFacade.selectUserPermissions(session, "other.user", 123L)).isEmpty(); + + permissionFacade.removeAllPermissions(123L, session); + session.commit(); + + checkTable("should_remove_all_permissions", "group_roles", "group_id", "resource_id", "role"); + checkTable("should_remove_all_permissions", "user_roles", "user_id", "resource_id", "role"); + + assertThat(permissionFacade.selectGroupPermissions(session, "devs", 123L)).isEmpty(); + assertThat(permissionFacade.selectUserPermissions(session, "dave.loper", 123L)).isEmpty(); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/permission/PermissionTemplateDaoTest.java b/sonar-db/src/test/java/org/sonar/db/permission/PermissionTemplateDaoTest.java new file mode 100644 index 00000000000..14902f25566 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/permission/PermissionTemplateDaoTest.java @@ -0,0 +1,244 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.permission; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.utils.System2; +import org.sonar.db.AbstractDaoTestCase; +import org.sonar.db.DbSession; +import org.sonar.db.MyBatis; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class PermissionTemplateDaoTest extends AbstractDaoTestCase { + + Date now; + PermissionTemplateDao permissionTemplateDao; + DbSession session; + System2 system = mock(System2.class); + + @Before + public void setUpDao() throws ParseException { + session = getMyBatis().openSession(false); + now = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2013-01-02 01:04:05"); + when(system.now()).thenReturn(now.getTime()); + permissionTemplateDao = new PermissionTemplateDao(getMyBatis(), system); + } + + @After + public void after() { + this.session.close(); + } + + @Test + public void should_create_permission_template() { + setupData("createPermissionTemplate"); + PermissionTemplateDto permissionTemplate = permissionTemplateDao.createPermissionTemplate("my template", "my description", "myregexp"); + assertThat(permissionTemplate).isNotNull(); + assertThat(permissionTemplate.getId()).isEqualTo(1L); + checkTable("createPermissionTemplate", "permission_templates", "id", "name", "kee", "description"); + } + + @Test + public void should_normalize_kee_on_template_creation() { + setupData("createNonAsciiPermissionTemplate"); + PermissionTemplateDto permissionTemplate = permissionTemplateDao.createPermissionTemplate("Môü Gnô Gnèçà ß", "my description", null); + assertThat(permissionTemplate).isNotNull(); + assertThat(permissionTemplate.getId()).isEqualTo(1L); + checkTable("createNonAsciiPermissionTemplate", "permission_templates", "id", "name", "kee", "description"); + } + + @Test + public void should_skip_key_normalization_on_default_template() { + + PermissionTemplateMapper mapper = mock(PermissionTemplateMapper.class); + + DbSession session = mock(DbSession.class); + when(session.getMapper(PermissionTemplateMapper.class)).thenReturn(mapper); + + MyBatis myBatis = mock(MyBatis.class); + when(myBatis.openSession(false)).thenReturn(session); + + permissionTemplateDao = new PermissionTemplateDao(myBatis, system); + PermissionTemplateDto permissionTemplate = permissionTemplateDao.createPermissionTemplate(PermissionTemplateDto.DEFAULT.getName(), null, null); + + verify(mapper).insert(permissionTemplate); + verify(session).commit(); + + assertThat(permissionTemplate.getKee()).isEqualTo(PermissionTemplateDto.DEFAULT.getKee()); + } + + @Test + public void should_select_permission_template() { + setupData("selectPermissionTemplate"); + PermissionTemplateDto permissionTemplate = permissionTemplateDao.selectPermissionTemplate("my_template_20130102_030405"); + + assertThat(permissionTemplate).isNotNull(); + assertThat(permissionTemplate.getName()).isEqualTo("my template"); + assertThat(permissionTemplate.getKee()).isEqualTo("my_template_20130102_030405"); + assertThat(permissionTemplate.getDescription()).isEqualTo("my description"); + assertThat(permissionTemplate.getUsersPermissions()).hasSize(3); + assertThat(permissionTemplate.getUsersPermissions()).extracting("userId").containsOnly(1L, 2L, 1L); + assertThat(permissionTemplate.getUsersPermissions()).extracting("userLogin").containsOnly("login1", "login2", "login2"); + assertThat(permissionTemplate.getUsersPermissions()).extracting("userName").containsOnly("user1", "user2", "user2"); + assertThat(permissionTemplate.getUsersPermissions()).extracting("permission").containsOnly("user_permission1", "user_permission1", "user_permission2"); + assertThat(permissionTemplate.getGroupsPermissions()).hasSize(3); + assertThat(permissionTemplate.getGroupsPermissions()).extracting("groupId").containsOnly(1L, 2L, null); + assertThat(permissionTemplate.getGroupsPermissions()).extracting("groupName").containsOnly("group1", "group2", null); + assertThat(permissionTemplate.getGroupsPermissions()).extracting("permission").containsOnly("group_permission1", "group_permission1", "group_permission2"); + } + + @Test + public void should_select_empty_permission_template() { + setupData("selectEmptyPermissionTemplate"); + PermissionTemplateDto permissionTemplate = permissionTemplateDao.selectPermissionTemplate("my_template_20130102_030405"); + + assertThat(permissionTemplate).isNotNull(); + assertThat(permissionTemplate.getName()).isEqualTo("my template"); + assertThat(permissionTemplate.getDescription()).isEqualTo("my description"); + assertThat(permissionTemplate.getUsersPermissions()).isNull(); + assertThat(permissionTemplate.getGroupsPermissions()).isNull(); + } + + @Test + public void should_select_permission_template_by_key() { + setupData("selectPermissionTemplate"); + + PermissionTemplateDto permissionTemplate = permissionTemplateDao.selectTemplateByKey("my_template_20130102_030405"); + + assertThat(permissionTemplate).isNotNull(); + assertThat(permissionTemplate.getId()).isEqualTo(1L); + assertThat(permissionTemplate.getName()).isEqualTo("my template"); + assertThat(permissionTemplate.getKee()).isEqualTo("my_template_20130102_030405"); + assertThat(permissionTemplate.getDescription()).isEqualTo("my description"); + } + + @Test + public void should_select_all_permission_templates() { + setupData("selectAllPermissionTemplates"); + + List<PermissionTemplateDto> permissionTemplates = permissionTemplateDao.selectAllPermissionTemplates(); + + assertThat(permissionTemplates).hasSize(3); + assertThat(permissionTemplates).extracting("id").containsOnly(1L, 2L, 3L); + assertThat(permissionTemplates).extracting("name").containsOnly("template1", "template2", "template3"); + assertThat(permissionTemplates).extracting("kee").containsOnly("template1_20130102_030405", "template2_20130102_030405", "template3_20130102_030405"); + assertThat(permissionTemplates).extracting("description").containsOnly("description1", "description2", "description3"); + } + + @Test + public void should_update_permission_template() { + setupData("updatePermissionTemplate"); + + permissionTemplateDao.updatePermissionTemplate(1L, "new_name", "new_description", "new_regexp"); + + checkTable("updatePermissionTemplate", "permission_templates", "id", "name", "kee", "description"); + } + + @Test + public void should_delete_permission_template() { + setupData("deletePermissionTemplate"); + + permissionTemplateDao.deletePermissionTemplate(1L); + + checkTable("deletePermissionTemplate", "permission_templates", "id", "name", "description"); + checkTable("deletePermissionTemplate", "perm_templates_users", "id", "template_id", "user_id", "permission_reference"); + checkTable("deletePermissionTemplate", "perm_templates_groups", "id", "template_id", "group_id", "permission_reference"); + } + + @Test + public void should_add_user_permission_to_template() { + setupData("addUserPermissionToTemplate"); + permissionTemplateDao.addUserPermission(1L, 1L, "new_permission"); + + checkTable("addUserPermissionToTemplate", "permission_templates", "id", "name", "description"); + checkTable("addUserPermissionToTemplate", "perm_templates_users", "id", "template_id", "user_id", "permission_reference"); + checkTable("addUserPermissionToTemplate", "perm_templates_groups", "id", "template_id", "group_id", "permission_reference"); + } + + @Test + public void should_remove_user_permission_from_template() { + setupData("removeUserPermissionFromTemplate"); + permissionTemplateDao.removeUserPermission(1L, 2L, "permission_to_remove"); + + checkTable("removeUserPermissionFromTemplate", "permission_templates", "id", "name", "description"); + checkTable("removeUserPermissionFromTemplate", "perm_templates_users", "id", "template_id", "user_id", "permission_reference"); + checkTable("removeUserPermissionFromTemplate", "perm_templates_groups", "id", "template_id", "group_id", "permission_reference"); + } + + @Test + public void should_add_group_permission_to_template() { + setupData("addGroupPermissionToTemplate"); + permissionTemplateDao.addGroupPermission(1L, 1L, "new_permission"); + + checkTable("addGroupPermissionToTemplate", "permission_templates", "id", "name", "description"); + checkTable("addGroupPermissionToTemplate", "perm_templates_users", "id", "template_id", "user_id", "permission_reference"); + checkTable("addGroupPermissionToTemplate", "perm_templates_groups", "id", "template_id", "group_id", "permission_reference"); + } + + @Test + public void should_remove_group_permission_from_template() { + setupData("removeGroupPermissionFromTemplate"); + permissionTemplateDao.removeGroupPermission(1L, 2L, "permission_to_remove"); + + checkTable("removeGroupPermissionFromTemplate", "permission_templates", "id", "name", "description"); + checkTable("removeGroupPermissionFromTemplate", "perm_templates_users", "id", "template_id", "user_id", "permission_reference"); + checkTable("removeGroupPermissionFromTemplate", "perm_templates_groups", "id", "template_id", "group_id", "permission_reference"); + } + + @Test + public void remove_by_group() { + setupData("remove_by_group"); + permissionTemplateDao.removeByGroup(2L, session); + session.commit(); + + checkTable("remove_by_group", "perm_templates_groups", "id", "template_id", "group_id", "permission_reference"); + } + + @Test + public void should_add_group_permission_with_null_name() { + setupData("addNullGroupPermissionToTemplate"); + permissionTemplateDao.addGroupPermission(1L, null, "new_permission"); + + checkTable("addNullGroupPermissionToTemplate", "permission_templates", "id", "name", "description"); + checkTable("addNullGroupPermissionToTemplate", "perm_templates_users", "id", "template_id", "user_id", "permission_reference"); + checkTable("addNullGroupPermissionToTemplate", "perm_templates_groups", "id", "template_id", "group_id", "permission_reference"); + } + + @Test + public void should_remove_group_permission_with_null_name() { + setupData("removeNullGroupPermissionFromTemplate"); + permissionTemplateDao.removeGroupPermission(1L, null, "permission_to_remove"); + + checkTable("removeNullGroupPermissionFromTemplate", "permission_templates", "id", "name", "description"); + checkTable("removeNullGroupPermissionFromTemplate", "perm_templates_users", "id", "template_id", "user_id", "permission_reference"); + checkTable("removeNullGroupPermissionFromTemplate", "perm_templates_groups", "id", "template_id", "group_id", "permission_reference"); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/permission/UserWithPermissionDaoTest.java b/sonar-db/src/test/java/org/sonar/db/permission/UserWithPermissionDaoTest.java new file mode 100644 index 00000000000..7533cb88c83 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/permission/UserWithPermissionDaoTest.java @@ -0,0 +1,164 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.permission; + +import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; +import java.util.List; +import javax.annotation.Nullable; +import org.junit.Before; +import org.junit.Test; +import org.sonar.db.AbstractDaoTestCase; + +import static org.assertj.core.api.Assertions.assertThat; + +public class UserWithPermissionDaoTest extends AbstractDaoTestCase { + + private static final long COMPONENT_ID = 100L; + + private PermissionDao dao; + + @Before + public void setUp() { + dao = new PermissionDao(getMyBatis()); + } + + @Test + public void select_all_users_for_project_permission() { + setupData("users_with_permissions"); + + PermissionQuery query = PermissionQuery.builder().permission("user").build(); + List<UserWithPermissionDto> result = dao.selectUsers(query, COMPONENT_ID); + assertThat(result).hasSize(3); + + UserWithPermissionDto user1 = result.get(0); + assertThat(user1.getLogin()).isEqualTo("user1"); + assertThat(user1.getName()).isEqualTo("User1"); + assertThat(user1.getPermission()).isNotNull(); + + UserWithPermissionDto user2 = result.get(1); + assertThat(user2.getLogin()).isEqualTo("user2"); + assertThat(user2.getName()).isEqualTo("User2"); + assertThat(user2.getPermission()).isNotNull(); + + UserWithPermissionDto user3 = result.get(2); + assertThat(user3.getLogin()).isEqualTo("user3"); + assertThat(user3.getName()).isEqualTo("User3"); + assertThat(user3.getPermission()).isNull(); + } + + @Test + public void select_all_users_for_global_permission() { + setupData("users_with_permissions"); + + PermissionQuery query = PermissionQuery.builder().permission("admin").build(); + List<UserWithPermissionDto> result = dao.selectUsers(query, null); + assertThat(result).hasSize(3); + + UserWithPermissionDto user1 = result.get(0); + assertThat(user1.getName()).isEqualTo("User1"); + assertThat(user1.getPermission()).isNotNull(); + + UserWithPermissionDto user2 = result.get(1); + assertThat(user2.getName()).isEqualTo("User2"); + assertThat(user2.getPermission()).isNull(); + + UserWithPermissionDto user3 = result.get(2); + assertThat(user3.getName()).isEqualTo("User3"); + assertThat(user3.getPermission()).isNull(); + } + + @Test + public void select_only_user_with_permission() { + setupData("users_with_permissions"); + + // user1 and user2 have permission user + assertThat(dao.selectUsers(PermissionQuery.builder().permission("user").membership(PermissionQuery.IN).build(), COMPONENT_ID)).hasSize(2); + } + + @Test + public void select_only_user_without_permission() { + setupData("users_with_permissions"); + + // Only user3 has not the user permission + assertThat(dao.selectUsers(PermissionQuery.builder().permission("user").membership(PermissionQuery.OUT).build(), COMPONENT_ID)).hasSize(1); + } + + @Test + public void search_by_user_name() { + setupData("users_with_permissions"); + + List<UserWithPermissionDto> result = dao.selectUsers(PermissionQuery.builder().permission("user").search("SEr1").build(), COMPONENT_ID); + assertThat(result).hasSize(1); + assertThat(result.get(0).getName()).isEqualTo("User1"); + + result = dao.selectUsers(PermissionQuery.builder().permission("user").search("user").build(), COMPONENT_ID); + assertThat(result).hasSize(3); + } + + @Test + public void select_only_enable_users() { + setupData("select_only_enable_users"); + + PermissionQuery query = PermissionQuery.builder().permission("user").build(); + List<UserWithPermissionDto> result = dao.selectUsers(query, COMPONENT_ID); + assertThat(result).hasSize(3); + + // Disabled user should not be returned + assertThat(Iterables.find(result, new Predicate<UserWithPermissionDto>() { + @Override + public boolean apply(@Nullable UserWithPermissionDto input) { + return input.getLogin().equals("disabledUser"); + } + }, null)).isNull(); + } + + @Test + public void should_be_sorted_by_user_name() { + setupData("users_with_permissions_should_be_sorted_by_user_name"); + + List<UserWithPermissionDto> result = dao.selectUsers(PermissionQuery.builder().permission("user").build(), COMPONENT_ID); + assertThat(result).hasSize(3); + assertThat(result.get(0).getName()).isEqualTo("User1"); + assertThat(result.get(1).getName()).isEqualTo("User2"); + assertThat(result.get(2).getName()).isEqualTo("User3"); + } + + @Test + public void should_be_paginated() { + setupData("users_with_permissions"); + + List<UserWithPermissionDto> result = dao.selectUsers(PermissionQuery.builder().permission("user").build(), COMPONENT_ID, 0, 2); + assertThat(result).hasSize(2); + assertThat(result.get(0).getName()).isEqualTo("User1"); + assertThat(result.get(1).getName()).isEqualTo("User2"); + + result = dao.selectUsers(PermissionQuery.builder().permission("user").build(), COMPONENT_ID, 1, 2); + assertThat(result).hasSize(2); + assertThat(result.get(0).getName()).isEqualTo("User2"); + assertThat(result.get(1).getName()).isEqualTo("User3"); + + result = dao.selectUsers(PermissionQuery.builder().permission("user").build(), COMPONENT_ID, 2, 1); + assertThat(result).hasSize(1); + assertThat(result.get(0).getName()).isEqualTo("User3"); + } + +} diff --git a/sonar-db/src/test/java/org/sonar/db/permission/UserWithPermissionDtoTest.java b/sonar-db/src/test/java/org/sonar/db/permission/UserWithPermissionDtoTest.java new file mode 100644 index 00000000000..56d951ebb2d --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/permission/UserWithPermissionDtoTest.java @@ -0,0 +1,55 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.permission; + +import org.junit.Test; +import org.sonar.core.permission.UserWithPermission; + +import static org.assertj.core.api.Assertions.assertThat; + +public class UserWithPermissionDtoTest { + + @Test + public void to_user_with_permission_having_permission() { + UserWithPermission user = new UserWithPermissionDto() + .setName("Arthur") + .setLogin("arthur") + .setPermission("user") + .toUserWithPermission(); + + assertThat(user.name()).isEqualTo("Arthur"); + assertThat(user.login()).isEqualTo("arthur"); + assertThat(user.hasPermission()).isTrue(); + } + + @Test + public void to_user_with_permission_not_having_permission() { + UserWithPermission user = new UserWithPermissionDto() + .setName("Arthur") + .setLogin("arthur") + .setPermission(null) + .toUserWithPermission(); + + assertThat(user.name()).isEqualTo("Arthur"); + assertThat(user.login()).isEqualTo("arthur"); + assertThat(user.hasPermission()).isFalse(); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/permission/UserWithPermissionTemplateDaoTest.java b/sonar-db/src/test/java/org/sonar/db/permission/UserWithPermissionTemplateDaoTest.java new file mode 100644 index 00000000000..d142ce71cbf --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/permission/UserWithPermissionTemplateDaoTest.java @@ -0,0 +1,162 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.permission; + +import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; +import java.util.List; +import javax.annotation.Nullable; +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.utils.System2; +import org.sonar.db.AbstractDaoTestCase; + +import static org.assertj.core.api.Assertions.assertThat; + +public class UserWithPermissionTemplateDaoTest extends AbstractDaoTestCase { + + private static final Long TEMPLATE_ID = 50L; + + private PermissionTemplateDao dao; + + @Before + public void setUp() { + dao = new PermissionTemplateDao(getMyBatis(), System2.INSTANCE); + } + + @Test + public void select_all_users() { + setupData("users_with_permissions"); + + PermissionQuery query = PermissionQuery.builder().permission("user").build(); + List<UserWithPermissionDto> result = dao.selectUsers(query, TEMPLATE_ID); + assertThat(result).hasSize(3); + + UserWithPermissionDto user1 = result.get(0); + assertThat(user1.getLogin()).isEqualTo("user1"); + assertThat(user1.getName()).isEqualTo("User1"); + assertThat(user1.getPermission()).isNotNull(); + + UserWithPermissionDto user2 = result.get(1); + assertThat(user2.getLogin()).isEqualTo("user2"); + assertThat(user2.getName()).isEqualTo("User2"); + assertThat(user2.getPermission()).isNotNull(); + + UserWithPermissionDto user3 = result.get(2); + assertThat(user3.getLogin()).isEqualTo("user3"); + assertThat(user3.getName()).isEqualTo("User3"); + assertThat(user3.getPermission()).isNull(); + } + + @Test + public void return_nothing_on_unknown_template_key() { + setupData("users_with_permissions"); + + PermissionQuery query = PermissionQuery.builder().permission("user").build(); + List<UserWithPermissionDto> result = dao.selectUsers(query, 999L); + assertThat(result).hasSize(3); + + UserWithPermissionDto user1 = result.get(0); + assertThat(user1.getPermission()).isNull(); + + UserWithPermissionDto user2 = result.get(1); + assertThat(user2.getPermission()).isNull(); + + UserWithPermissionDto user3 = result.get(2); + assertThat(user3.getPermission()).isNull(); + } + + @Test + public void select_only_user_with_permission() { + setupData("users_with_permissions"); + + // user1 and user2 have permission user + assertThat(dao.selectUsers(PermissionQuery.builder().permission("user").membership(PermissionQuery.IN).build(), TEMPLATE_ID)).hasSize(2); + } + + @Test + public void select_only_user_without_permission() { + setupData("users_with_permissions"); + + // Only user3 has not the user permission + assertThat(dao.selectUsers(PermissionQuery.builder().permission("user").membership(PermissionQuery.OUT).build(), TEMPLATE_ID)).hasSize(1); + } + + @Test + public void select_only_enable_users() { + setupData("select_only_enable_users"); + + PermissionQuery query = PermissionQuery.builder().permission("user").build(); + List<UserWithPermissionDto> result = dao.selectUsers(query, 999L); + assertThat(result).hasSize(3); + + // Disabled user should not be returned + assertThat(Iterables.find(result, new Predicate<UserWithPermissionDto>() { + @Override + public boolean apply(@Nullable UserWithPermissionDto input) { + return input.getLogin().equals("disabledUser"); + } + }, null)).isNull(); + } + + @Test + public void search_by_user_name() { + setupData("users_with_permissions"); + + List<UserWithPermissionDto> result = dao.selectUsers(PermissionQuery.builder().permission("user").search("SEr1").build(), TEMPLATE_ID); + assertThat(result).hasSize(1); + assertThat(result.get(0).getName()).isEqualTo("User1"); + + result = dao.selectUsers(PermissionQuery.builder().permission("user").search("user").build(), TEMPLATE_ID); + assertThat(result).hasSize(3); + } + + @Test + public void should_be_sorted_by_user_name() { + setupData("users_with_permissions_should_be_sorted_by_user_name"); + + List<UserWithPermissionDto> result = dao.selectUsers(PermissionQuery.builder().permission("user").build(), TEMPLATE_ID); + assertThat(result).hasSize(3); + assertThat(result.get(0).getName()).isEqualTo("User1"); + assertThat(result.get(1).getName()).isEqualTo("User2"); + assertThat(result.get(2).getName()).isEqualTo("User3"); + } + + @Test + public void should_be_paginated() { + setupData("users_with_permissions"); + + List<UserWithPermissionDto> result = dao.selectUsers(PermissionQuery.builder().permission("user").build(), TEMPLATE_ID, 0, 2); + assertThat(result).hasSize(2); + assertThat(result.get(0).getName()).isEqualTo("User1"); + assertThat(result.get(1).getName()).isEqualTo("User2"); + + result = dao.selectUsers(PermissionQuery.builder().permission("user").build(), TEMPLATE_ID, 1, 2); + assertThat(result).hasSize(2); + assertThat(result.get(0).getName()).isEqualTo("User2"); + assertThat(result.get(1).getName()).isEqualTo("User3"); + + result = dao.selectUsers(PermissionQuery.builder().permission("user").build(), TEMPLATE_ID, 2, 1); + assertThat(result).hasSize(1); + assertThat(result.get(0).getName()).isEqualTo("User3"); + } + +} diff --git a/sonar-db/src/test/java/org/sonar/db/permission/UserWithPermissionTest.java b/sonar-db/src/test/java/org/sonar/db/permission/UserWithPermissionTest.java new file mode 100644 index 00000000000..baada745f8c --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/permission/UserWithPermissionTest.java @@ -0,0 +1,59 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.permission; + +import org.junit.Test; +import org.sonar.core.permission.UserWithPermission; + +import static org.assertj.core.api.Assertions.assertThat; + +public class UserWithPermissionTest { + + @Test + public void test_setters_and_getters() throws Exception { + UserWithPermission user = new UserWithPermission() + .setName("Arthur") + .setLogin("arthur") + .hasPermission(true); + + assertThat(user.name()).isEqualTo("Arthur"); + assertThat(user.login()).isEqualTo("arthur"); + assertThat(user.hasPermission()).isTrue(); + } + + @Test + public void test_equals() throws Exception { + assertThat(new UserWithPermission().setLogin("arthur")).isEqualTo(new UserWithPermission().setLogin("arthur")); + assertThat(new UserWithPermission().setLogin("arthur")).isNotEqualTo(new UserWithPermission().setLogin("john")); + + UserWithPermission user = new UserWithPermission() + .setName("Arthur") + .setLogin("arthur") + .hasPermission(true); + assertThat(user).isEqualTo(user); + } + + @Test + public void test_hashcode() throws Exception { + assertThat(new UserWithPermission().setLogin("arthur").hashCode()).isEqualTo(new UserWithPermission().setLogin("arthur").hashCode()); + assertThat(new UserWithPermission().setLogin("arthur").hashCode()).isNotEqualTo(new UserWithPermission().setLogin("john").hashCode()); + } + +} diff --git a/sonar-db/src/test/java/org/sonar/db/profiling/InvocationUtilsTest.java b/sonar-db/src/test/java/org/sonar/db/profiling/InvocationUtilsTest.java new file mode 100644 index 00000000000..dc2110c938e --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/profiling/InvocationUtilsTest.java @@ -0,0 +1,76 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.profiling; + +import java.sql.Connection; +import java.sql.SQLException; +import org.junit.Test; +import org.sonar.test.TestUtils; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class InvocationUtilsTest { + + @Test + public void should_return_result() throws Throwable { + String toString = "toString"; + Object target = mock(Object.class); + when(target.toString()).thenReturn(toString); + + assertThat(InvocationUtils.invokeQuietly(target, Object.class.getMethod("toString"), new Object[0])).isEqualTo(toString); + } + + @Test + public void should_throw_declared_exception() throws Throwable { + Connection target = mock(Connection.class); + String failSql = "any sql"; + when(target.prepareStatement(failSql)).thenThrow(new SQLException("Expected")); + + try { + InvocationUtils.invokeQuietly(target, Connection.class.getMethod("prepareStatement", String.class), new Object[] {failSql}); + fail(); + } catch (Throwable t) { + assertThat(t).isInstanceOf(SQLException.class); + } + } + + @Test + public void should_wrap_undeclared_exception() throws Throwable { + Connection target = mock(Connection.class); + String failSql = "any sql"; + when(target.prepareStatement(failSql)).thenThrow(new SQLException("Expected")); + + try { + InvocationUtils.invokeQuietly(target, Object.class.getMethod("wait"), new Object[0]); + fail(); + } catch (Throwable t) { + assertThat(t).isInstanceOf(IllegalStateException.class); + } + } + + @Test + public void only_static_methods() { + assertThat(TestUtils.hasOnlyPrivateConstructors(InvocationUtils.class)).isTrue(); + + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/profiling/ProfiledDataSourceTest.java b/sonar-db/src/test/java/org/sonar/db/profiling/ProfiledDataSourceTest.java new file mode 100644 index 00000000000..d52e95531f0 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/profiling/ProfiledDataSourceTest.java @@ -0,0 +1,102 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.profiling; + +import java.io.ByteArrayInputStream; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.sql.Connection; +import java.sql.Date; +import java.sql.PreparedStatement; +import java.sql.Statement; +import java.sql.Timestamp; +import org.apache.commons.dbcp.BasicDataSource; +import org.junit.Rule; +import org.junit.Test; +import org.sonar.api.utils.log.LogTester; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class ProfiledDataSourceTest { + + @Rule + public LogTester logTester = new LogTester(); + + @Test + public void log_sql_requests() throws Exception { + BasicDataSource originDataSource = mock(BasicDataSource.class); + + Connection connection = mock(Connection.class); + when(originDataSource.getConnection()).thenReturn(connection); + + String sql = "select 'polop' from dual;"; + String sqlWithParams = "insert into polop (col1, col2, col3, col4) values (?, ?, ?, ?, ?);"; + int param1 = 42; + String param2 = "plouf"; + Date param3 = new Date(System.currentTimeMillis()); + Timestamp param4 = new Timestamp(System.currentTimeMillis()); + byte[] param5 = "blob".getBytes("UTF-8"); + + PreparedStatement preparedStatement = mock(PreparedStatement.class); + when(connection.prepareStatement(sqlWithParams)).thenReturn(preparedStatement); + when(preparedStatement.execute()).thenReturn(true); + + Statement statement = mock(Statement.class); + when(connection.createStatement()).thenReturn(statement); + when(statement.execute(sql)).thenReturn(true); + + ProfiledDataSource ds = new ProfiledDataSource(originDataSource); + + assertThat(ds.getUrl()).isNull(); + assertThat(ds.getConnection().getClientInfo()).isNull(); + PreparedStatement preparedStatementProxy = ds.getConnection().prepareStatement(sqlWithParams); + preparedStatementProxy.setInt(1, param1); + preparedStatementProxy.setString(2, param2); + preparedStatementProxy.setDate(3, param3); + preparedStatementProxy.setTimestamp(4, param4); + preparedStatementProxy.setBlob(5, new ByteArrayInputStream(param5)); + assertThat(preparedStatementProxy.getConnection()).isNull(); + assertThat(preparedStatementProxy.execute()).isTrue(); + final Statement statementProxy = ds.getConnection().createStatement(); + assertThat(statementProxy.getConnection()).isNull(); + assertThat(statementProxy.execute(sql)).isTrue(); + + assertThat(logTester.logs()).hasSize(2); + assertThat(logTester.logs().get(1)).contains(sql); + } + + @Test + public void delegate_to_underlying_datasource() throws Exception { + BasicDataSource delegate = mock(BasicDataSource.class); + ProfiledDataSource proxy = new ProfiledDataSource(delegate); + + // painful to call all methods + // so using reflection to check that calls does not fail + // Limitation: methods with parameters are not tested and calls to + // underlying datasource are not verified + for (Method method : ProfiledDataSource.class.getDeclaredMethods()) { + if (method.getParameterTypes().length == 0 && Modifier.isPublic(method.getModifiers())) { + method.invoke(proxy); + } + } + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/property/PropertiesDaoTest.java b/sonar-db/src/test/java/org/sonar/db/property/PropertiesDaoTest.java new file mode 100644 index 00000000000..3ad2527f610 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/property/PropertiesDaoTest.java @@ -0,0 +1,340 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.property; + +import com.google.common.collect.ImmutableMap; +import java.util.Arrays; +import java.util.List; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.db.AbstractDaoTestCase; +import org.sonar.db.DbSession; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + +public class PropertiesDaoTest extends AbstractDaoTestCase { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + DbSession session; + PropertiesDao dao; + + @Before + public void createDao() { + dao = new PropertiesDao(getMyBatis()); + session = getMyBatis().openSession(false); + } + + @After + public void tearDown() { + session.close(); + } + + @Test + public void shouldFindUsersForNotification() { + setupData("shouldFindUsersForNotification"); + + List<String> users = dao.findUsersForNotification("NewViolations", "Email", null); + assertThat(users).isEmpty(); + + users = dao.findUsersForNotification("NewViolations", "Email", "uuid_78"); + assertThat(users).isEmpty(); + + users = dao.findUsersForNotification("NewViolations", "Email", "uuid_45"); + assertThat(users).hasSize(1); + assertThat(users).containsOnly("user2"); + + users = dao.findUsersForNotification("NewViolations", "Twitter", null); + assertThat(users).hasSize(1); + assertThat(users).containsOnly("user3"); + + users = dao.findUsersForNotification("NewViolations", "Twitter", "uuid_78"); + assertThat(users).isEmpty(); + + users = dao.findUsersForNotification("NewViolations", "Twitter", "uuid_56"); + assertThat(users).hasSize(2); + assertThat(users).containsOnly("user1", "user3"); + } + + @Test + public void findNotificationSubscribers() { + setupData("findNotificationSubscribers"); + + // Nobody is subscribed + List<String> users = dao.findNotificationSubscribers("NotSexyDispatcher", "Email", "org.apache:struts"); + assertThat(users).isEmpty(); + + // Global subscribers + users = dao.findNotificationSubscribers("DispatcherWithGlobalSubscribers", "Email", "org.apache:struts"); + assertThat(users).containsOnly("simon"); + + users = dao.findNotificationSubscribers("DispatcherWithGlobalSubscribers", "Email", null); + assertThat(users).containsOnly("simon"); + + // Project subscribers + users = dao.findNotificationSubscribers("DispatcherWithProjectSubscribers", "Email", "org.apache:struts"); + assertThat(users).containsOnly("eric"); + + // Global + Project subscribers + users = dao.findNotificationSubscribers("DispatcherWithGlobalAndProjectSubscribers", "Email", "org.apache:struts"); + assertThat(users).containsOnly("eric", "simon"); + } + + @Test + public void hasNotificationSubscribers() { + setupData("findNotificationSubscribers"); + + // Nobody is subscribed + assertThat(dao.hasProjectNotificationSubscribersForDispatchers("PROJECT_A", Arrays.asList("NotSexyDispatcher"))).isFalse(); + + // Global subscribers + assertThat(dao.hasProjectNotificationSubscribersForDispatchers("PROJECT_A", Arrays.asList("DispatcherWithGlobalSubscribers"))).isTrue(); + + // Project subscribers + assertThat(dao.hasProjectNotificationSubscribersForDispatchers("PROJECT_A", Arrays.asList("DispatcherWithProjectSubscribers"))).isTrue(); + assertThat(dao.hasProjectNotificationSubscribersForDispatchers("PROJECT_B", Arrays.asList("DispatcherWithProjectSubscribers"))).isFalse(); + + // Global + Project subscribers + assertThat(dao.hasProjectNotificationSubscribersForDispatchers("PROJECT_A", Arrays.asList("DispatcherWithGlobalAndProjectSubscribers"))).isTrue(); + assertThat(dao.hasProjectNotificationSubscribersForDispatchers("PROJECT_B", Arrays.asList("DispatcherWithGlobalAndProjectSubscribers"))).isTrue(); + } + + @Test + public void selectGlobalProperties() { + setupData("selectGlobalProperties"); + List<PropertyDto> properties = dao.selectGlobalProperties(); + assertThat(properties.size(), is(2)); + + PropertyDto first = findById(properties, 1); + assertThat(first.getKey(), is("global.one")); + assertThat(first.getValue(), is("one")); + + PropertyDto second = findById(properties, 2); + assertThat(second.getKey(), is("global.two")); + assertThat(second.getValue(), is("two")); + } + + @Test + public void selectGlobalProperty() { + setupData("selectGlobalProperties"); + + PropertyDto prop = dao.selectGlobalProperty("global.one"); + assertThat(prop).isNotNull(); + assertThat(prop.getValue(), is("one")); + + assertThat(dao.selectGlobalProperty("project.one")).isNull(); + assertThat(dao.selectGlobalProperty("user.one")).isNull(); + assertThat(dao.selectGlobalProperty("unexisting")).isNull(); + } + + @Test + public void selectProjectProperties() { + setupData("selectProjectProperties"); + List<PropertyDto> properties = dao.selectProjectProperties("org.struts:struts"); + assertThat(properties.size(), is(1)); + + PropertyDto first = properties.get(0); + assertThat(first.getKey(), is("struts.one")); + assertThat(first.getValue(), is("one")); + } + + @Test + public void select_module_properties_tree() { + setupData("select_module_properties_tree"); + + List<PropertyDto> properties = dao.selectEnabledDescendantModuleProperties("ABCD", session); + assertThat(properties.size(), is(4)); + assertThat(properties).extracting("key").containsOnly("struts.one", "core.one", "core.two", "data.one"); + assertThat(properties).extracting("value").containsOnly("one", "two"); + + properties = dao.selectEnabledDescendantModuleProperties("EFGH", session); + assertThat(properties.size(), is(3)); + assertThat(properties).extracting("key").containsOnly("core.one", "core.two", "data.one"); + + properties = dao.selectEnabledDescendantModuleProperties("FGHI", session); + assertThat(properties.size(), is(1)); + assertThat(properties).extracting("key").containsOnly("data.one"); + + assertThat(dao.selectEnabledDescendantModuleProperties("unknown", session).size(), is(0)); + } + + @Test + public void selectProjectProperty() { + setupData("selectProjectProperties"); + PropertyDto property = dao.selectProjectProperty(11L, "commonslang.one"); + + assertThat(property.getKey(), is("commonslang.one")); + assertThat(property.getValue(), is("two")); + } + + @Test + public void select_by_query() { + setupData("select_by_query"); + + List<PropertyDto> results = dao.selectByQuery(PropertyQuery.builder().setKey("user.two").setComponentId(10L).setUserId(100).build(), session); + assertThat(results).hasSize(1); + assertThat(results.get(0).getValue()).isEqualTo("two"); + + results = dao.selectByQuery(PropertyQuery.builder().setKey("user.one").setUserId(100).build(), session); + assertThat(results).hasSize(1); + assertThat(results.get(0).getValue()).isEqualTo("one"); + } + + @Test + public void setProperty_update() { + setupData("update"); + + dao.setProperty(new PropertyDto().setKey("global.key").setValue("new_global")); + dao.setProperty(new PropertyDto().setKey("project.key").setResourceId(10L).setValue("new_project")); + dao.setProperty(new PropertyDto().setKey("user.key").setUserId(100L).setValue("new_user")); + dao.setProperty(new PropertyDto().setKey("null.value").setValue(null)); + + checkTables("update", "properties"); + } + + @Test + public void setProperty_insert() { + setupData("insert"); + + dao.setProperty(new PropertyDto().setKey("global.key").setValue("new_global")); + dao.setProperty(new PropertyDto().setKey("project.key").setResourceId(10L).setValue("new_project")); + dao.setProperty(new PropertyDto().setKey("user.key").setUserId(100L).setValue("new_user")); + + checkTables("insert", "properties"); + } + + @Test + public void delete_project_property() { + setupData("delete_project_property"); + + dao.deleteProjectProperty("struts.one", 10L); + + checkTables("delete_project_property", "properties"); + } + + @Test + public void delete_project_properties() { + setupData("delete_project_properties"); + + dao.deleteProjectProperties("sonar.profile.java", "Sonar Way"); + + checkTables("delete_project_properties", "properties"); + } + + @Test + public void deleteGlobalProperties() { + setupData("deleteGlobalProperties"); + + dao.deleteGlobalProperties(); + + checkTables("deleteGlobalProperties", "properties"); + } + + @Test + public void deleteGlobalProperty() { + setupData("deleteGlobalProperty"); + + dao.deleteGlobalProperty("to_be_deleted"); + + checkTables("deleteGlobalProperty", "properties"); + } + + @Test + public void deleteAllProperties() { + setupData("deleteAllProperties"); + + dao.deleteAllProperties("to_be_deleted"); + + checkTables("deleteAllProperties", "properties"); + } + + @Test + public void insertGlobalProperties() { + setupData("insertGlobalProperties"); + + dao.saveGlobalProperties(ImmutableMap.of("to_be_inserted", "inserted")); + + checkTable("insertGlobalProperties", "properties", "prop_key", "text_value", "resource_id", "user_id"); + } + + @Test + public void updateGlobalProperties() { + setupData("updateGlobalProperties"); + + dao.saveGlobalProperties(ImmutableMap.of("to_be_updated", "updated")); + + checkTable("updateGlobalProperties", "properties", "prop_key", "text_value", "resource_id", "user_id"); + } + + @Test + public void renamePropertyKey() { + setupData("renamePropertyKey"); + + dao.renamePropertyKey("sonar.license.secured", "sonar.license"); + + checkTable("renamePropertyKey", "properties", "prop_key", "text_value", "resource_id", "user_id"); + } + + @Test + public void should_not_rename_if_same_key() { + setupData("should_not_rename_if_same_key"); + + dao.renamePropertyKey("foo", "foo"); + + checkTable("should_not_rename_if_same_key", "properties", "prop_key", "text_value", "resource_id", "user_id"); + } + + @Test + public void should_not_rename_with_empty_key() { + thrown.expect(IllegalArgumentException.class); + dao.renamePropertyKey("foo", ""); + } + + @Test + public void should_not_rename_an_empty_key() { + thrown.expect(IllegalArgumentException.class); + dao.renamePropertyKey(null, "foo"); + } + + @Test + public void updatePropertiesFromKeyAndValueToNewValue() { + setupData("updatePropertiesFromKeyAndValueToNewValue"); + + dao.updateProperties("sonar.profile.java", "Sonar Way", "Default"); + + checkTable("updatePropertiesFromKeyAndValueToNewValue", "properties", "prop_key", "text_value", "resource_id", "user_id"); + } + + private PropertyDto findById(List<PropertyDto> properties, int id) { + for (PropertyDto property : properties) { + if (property.getId() == id) { + return property; + } + } + return null; + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/property/PropertyDtoTest.java b/sonar-db/src/test/java/org/sonar/db/property/PropertyDtoTest.java new file mode 100644 index 00000000000..796260782b2 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/property/PropertyDtoTest.java @@ -0,0 +1,50 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.property; + +import org.junit.Test; +import org.sonar.db.AbstractDaoTestCase; + +import static org.assertj.core.api.Assertions.assertThat; + +public class PropertyDtoTest extends AbstractDaoTestCase { + + private PropertiesDao dao; + + @Test + public void testEquals() { + assertThat(new PropertyDto().setKey("123").setResourceId(123L)).isEqualTo(new PropertyDto().setKey("123").setResourceId(123L)); + assertThat(new PropertyDto().setKey("1234").setResourceId(123L)).isNotEqualTo(new PropertyDto().setKey("123").setResourceId(123L)); + assertThat(new PropertyDto().setKey("1234").setResourceId(123L)).isNotEqualTo(null); + assertThat(new PropertyDto().setKey("1234").setResourceId(123L)).isNotEqualTo(new Object()); + } + + @Test + public void testHashCode() { + assertThat(new PropertyDto().setKey("123").setResourceId(123L).hashCode()).isNotNull(); + assertThat(new PropertyDto().setKey("123").setResourceId(123L).hashCode()) + .isEqualTo(new PropertyDto().setKey("123").setResourceId(123L).hashCode()); + } + + @Test + public void testToString() { + assertThat(new PropertyDto().setKey("foo:bar").setValue("value").setResourceId(123L).setUserId(456L).toString()).isEqualTo("PropertyDto{foo:bar, value, 123, 456}"); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/purge/DbCleanerTestUtils.java b/sonar-db/src/test/java/org/sonar/db/purge/DbCleanerTestUtils.java new file mode 100644 index 00000000000..c148aab159d --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/purge/DbCleanerTestUtils.java @@ -0,0 +1,44 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.purge; + +import org.sonar.api.utils.DateUtils; + +public final class DbCleanerTestUtils { + + private DbCleanerTestUtils() { + } + + public static PurgeableSnapshotDto createSnapshotWithDate(long snapshotId, String date) { + PurgeableSnapshotDto snapshot = new PurgeableSnapshotDto(); + snapshot.setSnapshotId(snapshotId); + snapshot.setDate(DateUtils.parseDate(date).getTime()); + return snapshot; + } + + public static PurgeableSnapshotDto createSnapshotWithDateTime(long snapshotId, String datetime) { + PurgeableSnapshotDto snapshot = new PurgeableSnapshotDto(); + snapshot.setSnapshotId(snapshotId); + snapshot.setDate(DateUtils.parseDateTime(datetime).getTime()); + return snapshot; + } + +} diff --git a/sonar-db/src/test/java/org/sonar/db/purge/IdUuidPairsTest.java b/sonar-db/src/test/java/org/sonar/db/purge/IdUuidPairsTest.java new file mode 100644 index 00000000000..21e527c1765 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/purge/IdUuidPairsTest.java @@ -0,0 +1,53 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.purge; + +import com.google.common.collect.Lists; +import java.util.List; +import org.junit.Test; +import org.sonar.test.TestUtils; + +import static org.assertj.core.api.Assertions.assertThat; + +public class IdUuidPairsTest { + @Test + public void extract_ids() { + List<IdUuidPair> idUuidPairList = Lists.newArrayList(new IdUuidPair(1L, "ABCD"), new IdUuidPair(2L, "EFGH")); + + List<Long> ids = IdUuidPairs.ids(idUuidPairList); + + assertThat(ids).containsOnly(1L, 2L); + } + + @Test + public void is_non_instantiable() { + assertThat(TestUtils.hasOnlyPrivateConstructors(IdUuidPairs.class)).isTrue(); + } + + @Test + public void extract_uuids() { + List<IdUuidPair> idUuidPairList = Lists.newArrayList(new IdUuidPair(1L, "ABCD"), new IdUuidPair(2L, "EFGH")); + + List<String> uuids = IdUuidPairs.uuids(idUuidPairList); + + assertThat(uuids).containsOnly("ABCD", "EFGH"); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/purge/PurgeCommandsTest.java b/sonar-db/src/test/java/org/sonar/db/purge/PurgeCommandsTest.java new file mode 100644 index 00000000000..0da36e52b04 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/purge/PurgeCommandsTest.java @@ -0,0 +1,153 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.purge; + +import java.util.List; +import org.apache.ibatis.session.SqlSession; +import org.junit.Before; +import org.junit.Test; +import org.sonar.db.AbstractDaoTestCase; +import org.sonar.db.MyBatis; + +import static com.google.common.collect.Lists.newArrayList; + +public class PurgeCommandsTest extends AbstractDaoTestCase { + + private PurgeProfiler profiler; + + @Before + public void prepare() { + profiler = new PurgeProfiler(); + } + + /** + * Test that all related data is deleted. + */ + @Test + public void shouldDeleteSnapshot() { + setupData("shouldDeleteSnapshot"); + + SqlSession session = getMyBatis().openSession(); + try { + new PurgeCommands(session, profiler).deleteSnapshots(PurgeSnapshotQuery.create().setId(5L)); + } finally { + MyBatis.closeQuietly(session); + } + checkTables("shouldDeleteSnapshot", "snapshots", "project_measures", "duplications_index", "events"); + } + + /** + * Test that SQL queries execution do not fail with a huge number of parameter + */ + @Test + public void should_not_fail_when_deleting_huge_number_of_snapshots() { + SqlSession session = getMyBatis().openSession(); + try { + new PurgeCommands(session, profiler).deleteSnapshots(getHugeNumberOfIds()); + } finally { + MyBatis.closeQuietly(session); + } + // The goal of this test is only to check that the query do no fail, not to check result + } + + /** + * Test that all related data is purged. + */ + @Test + public void shouldPurgeSnapshot() { + setupData("shouldPurgeSnapshot"); + + SqlSession session = getMyBatis().openSession(); + try { + new PurgeCommands(session, profiler).purgeSnapshots(PurgeSnapshotQuery.create().setId(1L)); + } finally { + MyBatis.closeQuietly(session); + } + checkTables("shouldPurgeSnapshot", "snapshots", "project_measures", "duplications_index", "events"); + } + + @Test + public void delete_wasted_measures_when_purging_snapshot() { + setupData("shouldDeleteWastedMeasuresWhenPurgingSnapshot"); + + SqlSession session = getMyBatis().openSession(); + try { + new PurgeCommands(session, profiler).purgeSnapshots(PurgeSnapshotQuery.create().setId(1L)); + } finally { + MyBatis.closeQuietly(session); + } + checkTables("shouldDeleteWastedMeasuresWhenPurgingSnapshot", "project_measures"); + } + + /** + * Test that SQL queries execution do not fail with a huge number of parameter + */ + @Test + public void should_not_fail_when_purging_huge_number_of_snapshots() { + SqlSession session = getMyBatis().openSession(); + try { + new PurgeCommands(session, profiler).purgeSnapshots(getHugeNumberOfIds()); + } finally { + MyBatis.closeQuietly(session); + } + // The goal of this test is only to check that the query do no fail, not to check result + } + + @Test + public void shouldDeleteResource() { + setupData("shouldDeleteResource"); + try (SqlSession session = getMyBatis().openSession()) { + new PurgeCommands(session, profiler).deleteResources(newArrayList(new IdUuidPair(1L, "1"))); + } + + assertEmptyTables("projects", "snapshots", "events", "issues", "issue_changes", "authors"); + } + + /** + * Test that SQL queries execution do not fail with a huge number of parameter + */ + @Test + public void should_not_fail_when_deleting_huge_number_of_resources() { + SqlSession session = getMyBatis().openSession(); + try { + new PurgeCommands(session, profiler).deleteResources(getHugeNumberOfIdUuids()); + } finally { + MyBatis.closeQuietly(session); + } + // The goal of this test is only to check that the query do no fail, not to check result + } + + private List<IdUuidPair> getHugeNumberOfIdUuids() { + List<IdUuidPair> hugeNbOfSnapshotIds = newArrayList(); + for (long i = 0; i < 4500; i++) { + hugeNbOfSnapshotIds.add(new IdUuidPair(i, String.valueOf(i))); + } + return hugeNbOfSnapshotIds; + } + + private List<Long> getHugeNumberOfIds() { + List<Long> hugeNbOfSnapshotIds = newArrayList(); + for (long i = 0; i < 4500; i++) { + hugeNbOfSnapshotIds.add(i); + } + return hugeNbOfSnapshotIds; + } + +} diff --git a/sonar-db/src/test/java/org/sonar/db/purge/PurgeConfigurationTest.java b/sonar-db/src/test/java/org/sonar/db/purge/PurgeConfigurationTest.java new file mode 100644 index 00000000000..a150c84ebd1 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/purge/PurgeConfigurationTest.java @@ -0,0 +1,76 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.purge; + +import java.util.Date; +import org.junit.Test; +import org.sonar.api.config.Settings; +import org.sonar.api.resources.Scopes; +import org.sonar.api.utils.DateUtils; +import org.sonar.core.config.PurgeConstants; + +import static org.assertj.core.api.Assertions.assertThat; + +public class PurgeConfigurationTest { + @Test + public void should_delete_all_closed_issues() { + PurgeConfiguration conf = new PurgeConfiguration(new IdUuidPair(1L, "1"), new String[0], 0); + assertThat(conf.maxLiveDateOfClosedIssues()).isNull(); + + conf = new PurgeConfiguration(new IdUuidPair(1L, "1"), new String[0], -1); + assertThat(conf.maxLiveDateOfClosedIssues()).isNull(); + } + + @Test + public void should_delete_only_old_closed_issues() { + Date now = DateUtils.parseDate("2013-05-18"); + + PurgeConfiguration conf = new PurgeConfiguration(new IdUuidPair(1L, "1"), new String[0], 30); + Date toDate = conf.maxLiveDateOfClosedIssues(now); + + assertThat(toDate.getYear()).isEqualTo(113);// =2013 + assertThat(toDate.getMonth()).isEqualTo(3); // means April + assertThat(toDate.getDate()).isEqualTo(18); + } + + @Test + public void do_not_delete_directory_by_default() { + Settings settings = new Settings(); + settings.setProperty(PurgeConstants.PROPERTY_CLEAN_DIRECTORY, false); + settings.setProperty(PurgeConstants.DAYS_BEFORE_DELETING_CLOSED_ISSUES, 5); + Date now = new Date(); + + PurgeConfiguration sut = PurgeConfiguration.newDefaultPurgeConfiguration(settings, new IdUuidPair(42L, "any-uuid")); + + assertThat(sut.scopesWithoutHistoricalData()).contains(Scopes.FILE) + .doesNotContain(Scopes.DIRECTORY); + assertThat(sut.maxLiveDateOfClosedIssues(now)).isEqualTo(DateUtils.addDays(now, -5)); + } + + @Test + public void delete_directory_if_in_settings() { + Settings settings = new Settings(); + settings.setProperty(PurgeConstants.PROPERTY_CLEAN_DIRECTORY, true); + + PurgeConfiguration sut = PurgeConfiguration.newDefaultPurgeConfiguration(settings, new IdUuidPair(42L, "any-uuid")); + + assertThat(sut.scopesWithoutHistoricalData()).contains(Scopes.DIRECTORY, Scopes.FILE); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/purge/PurgeDaoTest.java b/sonar-db/src/test/java/org/sonar/db/purge/PurgeDaoTest.java new file mode 100644 index 00000000000..592e42b406e --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/purge/PurgeDaoTest.java @@ -0,0 +1,159 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.purge; + +import java.util.List; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.resources.Scopes; +import org.sonar.api.utils.System2; +import org.sonar.db.AbstractDaoTestCase; +import org.sonar.db.DbSession; +import org.sonar.db.MyBatis; +import org.sonar.db.component.ResourceDao; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class PurgeDaoTest extends AbstractDaoTestCase { + + private PurgeDao sut; + private System2 system2; + private DbSession dbSession; + + private static PurgeableSnapshotDto getById(List<PurgeableSnapshotDto> snapshots, long id) { + for (PurgeableSnapshotDto snapshot : snapshots) { + if (snapshot.getSnapshotId() == id) { + return snapshot; + } + } + return null; + } + + @Before + public void before() { + system2 = mock(System2.class); + when(system2.now()).thenReturn(1450000000000L); + dbSession = getMyBatis().openSession(false); + + sut = new PurgeDao(getMyBatis(), new ResourceDao(getMyBatis(), system2), new PurgeProfiler(), system2); + } + + @After + public void after() { + MyBatis.closeQuietly(dbSession); + } + + @Test + public void shouldDeleteAbortedBuilds() { + setupData("shouldDeleteAbortedBuilds"); + sut.purge(newConfigurationWith30Days(), PurgeListener.EMPTY); + checkTables("shouldDeleteAbortedBuilds", "snapshots"); + } + + @Test + public void should_purge_project() { + setupData("shouldPurgeProject"); + sut.purge(newConfigurationWith30Days(), PurgeListener.EMPTY); + checkTables("shouldPurgeProject", "projects", "snapshots"); + } + + private PurgeConfiguration newConfigurationWith30Days() { + return new PurgeConfiguration(new IdUuidPair(1L, "1"), new String[0], 30); + } + + private PurgeConfiguration newConfigurationWith30Days(System2 system2) { + return new PurgeConfiguration(new IdUuidPair(1L, "1"), new String[0], 30, system2); + } + + @Test + public void delete_file_sources_of_disabled_resources() { + setupData("delete_file_sources_of_disabled_resources"); + sut.purge(newConfigurationWith30Days(system2), PurgeListener.EMPTY); + checkTables("delete_file_sources_of_disabled_resources", "file_sources"); + } + + @Test + public void shouldDeleteHistoricalDataOfDirectoriesAndFiles() { + setupData("shouldDeleteHistoricalDataOfDirectoriesAndFiles"); + sut.purge(new PurgeConfiguration(new IdUuidPair(1L, "1"), new String[] {Scopes.DIRECTORY, Scopes.FILE}, 30), PurgeListener.EMPTY); + checkTables("shouldDeleteHistoricalDataOfDirectoriesAndFiles", "projects", "snapshots"); + } + + @Test + public void disable_resources_without_last_snapshot() { + setupData("disable_resources_without_last_snapshot"); + sut.purge(newConfigurationWith30Days(system2), PurgeListener.EMPTY); + checkTables("disable_resources_without_last_snapshot", new String[] {"issue_close_date", "issue_update_date"}, "projects", "snapshots", "issues"); + } + + @Test + public void shouldDeleteSnapshots() { + setupData("shouldDeleteSnapshots"); + sut.deleteSnapshots(PurgeSnapshotQuery.create().setIslast(false).setResourceId(1L)); + checkTables("shouldDeleteSnapshots", "snapshots"); + } + + @Test + public void shouldSelectPurgeableSnapshots() { + setupData("shouldSelectPurgeableSnapshots"); + List<PurgeableSnapshotDto> snapshots = sut.selectPurgeableSnapshots(1L); + + assertThat(snapshots).hasSize(3); + assertThat(getById(snapshots, 1L).isLast()).isTrue(); + assertThat(getById(snapshots, 1L).hasEvents()).isFalse(); + assertThat(getById(snapshots, 4L).isLast()).isFalse(); + assertThat(getById(snapshots, 4L).hasEvents()).isFalse(); + assertThat(getById(snapshots, 5L).isLast()).isFalse(); + assertThat(getById(snapshots, 5L).hasEvents()).isTrue(); + } + + @Test + public void should_delete_project_and_associated_data() { + setupData("shouldDeleteProject"); + sut.deleteResourceTree(new IdUuidPair(1L, "A")); + assertEmptyTables("projects", "snapshots", "action_plans", "issues", "issue_changes", "file_sources"); + } + + @Test + public void should_delete_old_closed_issues() { + setupData("should_delete_old_closed_issues"); + sut.purge(newConfigurationWith30Days(), PurgeListener.EMPTY); + checkTables("should_delete_old_closed_issues", "issues", "issue_changes"); + } + + @Test + public void should_delete_all_closed_issues() { + setupData("should_delete_all_closed_issues"); + sut.purge(new PurgeConfiguration(new IdUuidPair(1L, "1"), new String[0], 0), PurgeListener.EMPTY); + checkTables("should_delete_all_closed_issues", "issues", "issue_changes"); + } + + @Test + public void select_purgeable_file_uuids_and_only_them() { + setupData("select_purgeable_file_uuids"); + + List<String> uuids = sut.selectPurgeableFiles(dbSession, 1L); + + assertThat(uuids).containsOnly("GHIJ"); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/purge/PurgeProfilerTest.java b/sonar-db/src/test/java/org/sonar/db/purge/PurgeProfilerTest.java new file mode 100644 index 00000000000..2823ee39d75 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/purge/PurgeProfilerTest.java @@ -0,0 +1,95 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.purge; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.utils.log.Logger; + +import static org.mockito.Matchers.contains; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +public class PurgeProfilerTest { + + private MockedClock clock; + private PurgeProfiler profiler; + private Logger logger; + + @Before + public void prepare() { + clock = new MockedClock(); + profiler = new PurgeProfiler(clock); + logger = mock(Logger.class); + } + + @Test + public void shouldProfilePurge() { + profiler.start("foo"); + clock.sleep(10); + profiler.stop(); + + profiler.start("bar"); + clock.sleep(5); + profiler.stop(); + + profiler.start("foo"); + clock.sleep(8); + profiler.stop(); + + profiler.dump(50, logger); + verify(logger).info(contains("foo: 18ms")); + verify(logger).info(contains("bar: 5ms")); + } + + @Test + public void shouldResetPurgeProfiling() { + profiler.start("foo"); + clock.sleep(10); + profiler.stop(); + + profiler.reset(); + + profiler.start("bar"); + clock.sleep(5); + profiler.stop(); + + profiler.start("foo"); + clock.sleep(8); + profiler.stop(); + + profiler.dump(50, logger); + verify(logger).info(contains("foo: 8ms")); + verify(logger).info(contains("bar: 5ms")); + } + + private class MockedClock extends PurgeProfiler.Clock { + private long now = 0; + + @Override + public long now() { + return now; + } + + public void sleep(long duration) { + now += duration; + } + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/purge/PurgeableSnapshotDtoTest.java b/sonar-db/src/test/java/org/sonar/db/purge/PurgeableSnapshotDtoTest.java new file mode 100644 index 00000000000..ec61f04f4fd --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/purge/PurgeableSnapshotDtoTest.java @@ -0,0 +1,56 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.purge; + +import org.junit.Test; + +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +public class PurgeableSnapshotDtoTest { + @Test + public void testEquals() { + PurgeableSnapshotDto dto1 = new PurgeableSnapshotDto().setSnapshotId(3L); + PurgeableSnapshotDto dto2 = new PurgeableSnapshotDto().setSnapshotId(4L); + assertThat(dto1.equals(dto2), is(false)); + assertThat(dto2.equals(dto1), is(false)); + assertThat(dto1.equals(dto1), is(true)); + assertThat(dto1.equals(new PurgeableSnapshotDto().setSnapshotId(3L)), is(true)); + assertThat(dto1.equals("bi_bop_a_lou_la"), is(false)); + assertThat(dto1.equals(null), is(false)); + } + + @Test + public void testHasCode() { + PurgeableSnapshotDto dto = new PurgeableSnapshotDto().setSnapshotId(3L); + assertThat(dto.hashCode(), is(dto.hashCode())); + + // no id + dto = new PurgeableSnapshotDto(); + assertThat(dto.hashCode(), is(dto.hashCode())); + } + + @Test + public void testToString() { + PurgeableSnapshotDto dto = new PurgeableSnapshotDto().setSnapshotId(3L); + assertThat(dto.toString().length(), greaterThan(0)); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/purge/period/DefaultPeriodCleanerTest.java b/sonar-db/src/test/java/org/sonar/db/purge/period/DefaultPeriodCleanerTest.java new file mode 100644 index 00000000000..1aa9d8aebcb --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/purge/period/DefaultPeriodCleanerTest.java @@ -0,0 +1,93 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.purge.period; + +import java.util.Arrays; +import org.apache.commons.lang.ObjectUtils; +import org.hamcrest.BaseMatcher; +import org.junit.Test; +import org.mockito.ArgumentMatcher; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.sonar.api.utils.System2; +import org.sonar.db.DbSession; +import org.sonar.db.purge.PurgeDao; +import org.sonar.db.purge.PurgeSnapshotQuery; +import org.sonar.db.purge.PurgeableSnapshotDto; + +import static org.mockito.Mockito.anyListOf; +import static org.mockito.Mockito.argThat; +import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class DefaultPeriodCleanerTest { + + @Test + public void doClean() { + PurgeDao dao = mock(PurgeDao.class); + DbSession session = mock(DbSession.class); + when(dao.selectPurgeableSnapshots(123L, session)).thenReturn(Arrays.asList( + new PurgeableSnapshotDto().setSnapshotId(999L).setDate(System2.INSTANCE.now()))); + Filter filter1 = newLazyFilter(); + Filter filter2 = newLazyFilter(); + + DefaultPeriodCleaner cleaner = new DefaultPeriodCleaner(dao); + cleaner.doClean(123L, Arrays.asList(filter1, filter2), session); + + verify(filter1).log(); + verify(filter2).log(); + verify(dao, times(2)).deleteSnapshots(argThat(newRootSnapshotQuery()), eq(session)); + verify(dao, times(2)).deleteSnapshots(argThat(newSnapshotIdQuery()), eq(session)); + } + + private BaseMatcher<PurgeSnapshotQuery> newRootSnapshotQuery() { + return new ArgumentMatcher<PurgeSnapshotQuery>() { + @Override + public boolean matches(Object o) { + PurgeSnapshotQuery query = (PurgeSnapshotQuery) o; + return ObjectUtils.equals(query.getRootSnapshotId(), 999L); + } + }; + } + + private BaseMatcher<PurgeSnapshotQuery> newSnapshotIdQuery() { + return new ArgumentMatcher<PurgeSnapshotQuery>() { + @Override + public boolean matches(Object o) { + PurgeSnapshotQuery query = (PurgeSnapshotQuery) o; + return ObjectUtils.equals(query.getId(), 999L); + } + }; + } + + private Filter newLazyFilter() { + Filter filter1 = mock(Filter.class); + when(filter1.filter(anyListOf(PurgeableSnapshotDto.class))).thenAnswer(new Answer<Object>() { + public Object answer(InvocationOnMock invocation) throws Throwable { + return invocation.getArguments()[0]; + } + }); + return filter1; + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/purge/period/DeleteAllFilterTest.java b/sonar-db/src/test/java/org/sonar/db/purge/period/DeleteAllFilterTest.java new file mode 100644 index 00000000000..7f59cb68a8c --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/purge/period/DeleteAllFilterTest.java @@ -0,0 +1,46 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.purge.period; + +import java.util.Arrays; +import java.util.List; +import org.junit.Test; +import org.sonar.api.utils.DateUtils; +import org.sonar.db.purge.DbCleanerTestUtils; +import org.sonar.db.purge.PurgeableSnapshotDto; + +import static org.assertj.core.api.Assertions.assertThat; + +public class DeleteAllFilterTest { + + @Test + public void shouldDeleteAllSnapshotsPriorToDate() { + Filter filter = new DeleteAllFilter(DateUtils.parseDate("2011-12-25")); + + List<PurgeableSnapshotDto> toDelete = filter.filter(Arrays.asList( + DbCleanerTestUtils.createSnapshotWithDate(1L, "2010-01-01"), + DbCleanerTestUtils.createSnapshotWithDate(2L, "2010-12-25"), + DbCleanerTestUtils.createSnapshotWithDate(3L, "2012-01-01") + )); + + assertThat(toDelete).extracting("snapshotId").containsOnly(1L, 2L); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/purge/period/IntervalTest.java b/sonar-db/src/test/java/org/sonar/db/purge/period/IntervalTest.java new file mode 100644 index 00000000000..dbae556bfa4 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/purge/period/IntervalTest.java @@ -0,0 +1,109 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.purge.period; + +import java.util.Arrays; +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.List; +import org.junit.Test; +import org.sonar.api.utils.DateUtils; +import org.sonar.db.purge.DbCleanerTestUtils; +import org.sonar.db.purge.PurgeableSnapshotDto; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + +public class IntervalTest { + static int calendarField(Interval interval, int field) { + if (interval.count() == 0) { + return -1; + } + + PurgeableSnapshotDto first = interval.get().iterator().next(); + GregorianCalendar cal = new GregorianCalendar(); + cal.setTime(first.getDate()); + return cal.get(field); + } + + @Test + public void shouldGroupByIntervals() { + List<PurgeableSnapshotDto> snapshots = Arrays.asList( + DbCleanerTestUtils.createSnapshotWithDate(1L, "2011-04-03"), + + DbCleanerTestUtils.createSnapshotWithDate(2L, "2011-05-01"), + DbCleanerTestUtils.createSnapshotWithDate(3L, "2011-05-19"), + + DbCleanerTestUtils.createSnapshotWithDate(4L, "2011-06-02"), + DbCleanerTestUtils.createSnapshotWithDate(5L, "2011-06-20"), + + DbCleanerTestUtils.createSnapshotWithDate(6L, "2012-06-29") // out of scope + ); + + List<Interval> intervals = Interval.group(snapshots, DateUtils.parseDate("2010-01-01"), DateUtils.parseDate("2011-12-31"), Calendar.MONTH); + assertThat(intervals.size(), is(3)); + + assertThat(intervals.get(0).count(), is(1)); + assertThat(calendarField(intervals.get(0), Calendar.MONTH), is(Calendar.APRIL)); + + assertThat(intervals.get(1).count(), is(2)); + assertThat(calendarField(intervals.get(1), Calendar.MONTH), is(Calendar.MAY)); + + assertThat(intervals.get(2).count(), is(2)); + assertThat(calendarField(intervals.get(2), Calendar.MONTH), is(Calendar.JUNE)); + } + + @Test + public void shouldNotJoinMonthsOfDifferentYears() { + List<PurgeableSnapshotDto> snapshots = Arrays.asList( + DbCleanerTestUtils.createSnapshotWithDate(1L, "2010-04-03"), + DbCleanerTestUtils.createSnapshotWithDate(2L, "2011-04-13") + ); + + List<Interval> intervals = Interval.group(snapshots, + DateUtils.parseDateTime("2010-01-01T00:00:00+0100"), DateUtils.parseDateTime("2011-12-31T00:00:00+0100"), Calendar.MONTH); + assertThat(intervals.size(), is(2)); + + assertThat(intervals.get(0).count(), is(1)); + assertThat(calendarField(intervals.get(0), Calendar.MONTH), is(Calendar.APRIL)); + assertThat(calendarField(intervals.get(0), Calendar.YEAR), is(2010)); + + assertThat(intervals.get(1).count(), is(1)); + assertThat(calendarField(intervals.get(1), Calendar.MONTH), is(Calendar.APRIL)); + assertThat(calendarField(intervals.get(1), Calendar.YEAR), is(2011)); + } + + @Test + public void shouldIgnoreTimeWhenGroupingByIntervals() { + List<PurgeableSnapshotDto> snapshots = Arrays.asList( + DbCleanerTestUtils.createSnapshotWithDateTime(1L, "2011-05-25T00:16:48+0100"), + DbCleanerTestUtils.createSnapshotWithDateTime(2L, "2012-01-26T00:16:48+0100"), + DbCleanerTestUtils.createSnapshotWithDateTime(3L, "2012-01-27T00:16:48+0100") + ); + + List<Interval> intervals = Interval.group(snapshots, + DateUtils.parseDateTime("2011-05-25T00:00:00+0100"), + DateUtils.parseDateTime("2012-01-26T00:00:00+0100"), Calendar.MONTH); + assertThat(intervals.size(), is(1)); + assertThat(intervals.get(0).count(), is(1)); + assertThat(intervals.get(0).get().get(0).getSnapshotId(), is(2L)); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/purge/period/KeepOneFilterTest.java b/sonar-db/src/test/java/org/sonar/db/purge/period/KeepOneFilterTest.java new file mode 100644 index 00000000000..94845f431ae --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/purge/period/KeepOneFilterTest.java @@ -0,0 +1,93 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.purge.period; + +import com.google.common.base.Function; +import com.google.common.collect.Iterables; +import java.util.Arrays; +import java.util.Calendar; +import java.util.List; +import javax.annotation.Nullable; +import org.junit.Test; +import org.sonar.api.utils.DateUtils; +import org.sonar.db.purge.DbCleanerTestUtils; +import org.sonar.db.purge.PurgeableSnapshotDto; + +import static com.google.common.collect.Lists.newArrayList; +import static org.assertj.core.api.Assertions.assertThat; + +public class KeepOneFilterTest { + + private static List<Long> snapshotIds(List<PurgeableSnapshotDto> snapshotDtos) { + return newArrayList(Iterables.transform(snapshotDtos, new Function<PurgeableSnapshotDto, Long>() { + @Override + public Long apply(@Nullable PurgeableSnapshotDto input) { + return input != null ? input.getSnapshotId() : null; + } + })); + } + + @Test + public void shouldOnlyOneSnapshotPerInterval() { + Filter filter = new KeepOneFilter(DateUtils.parseDate("2011-03-25"), DateUtils.parseDate("2011-08-25"), Calendar.MONTH, "month"); + + List<PurgeableSnapshotDto> toDelete = filter.filter(Arrays.<PurgeableSnapshotDto>asList( + DbCleanerTestUtils.createSnapshotWithDate(1L, "2010-01-01"), // out of scope -> keep + DbCleanerTestUtils.createSnapshotWithDate(2L, "2011-05-01"), // may -> keep + DbCleanerTestUtils.createSnapshotWithDate(3L, "2011-05-02"), // may -> to be deleted + DbCleanerTestUtils.createSnapshotWithDate(4L, "2011-05-19"), // may -> to be deleted + DbCleanerTestUtils.createSnapshotWithDate(5L, "2011-06-01"), // june -> keep + DbCleanerTestUtils.createSnapshotWithDate(6L, "2012-01-01") // out of scope -> keep + )); + + assertThat(toDelete).hasSize(2); + + List<Long> snapshotIds = snapshotIds(toDelete); + assertThat(snapshotIds).contains(3L); + assertThat(snapshotIds.contains(4L)); + } + + @Test + public void shouldKeepNonDeletableSnapshots() { + Filter filter = new KeepOneFilter(DateUtils.parseDate("2011-03-25"), DateUtils.parseDate("2011-08-25"), Calendar.MONTH, "month"); + + List<PurgeableSnapshotDto> toDelete = filter.filter(Arrays.<PurgeableSnapshotDto>asList( + DbCleanerTestUtils.createSnapshotWithDate(1L, "2011-05-01"), // to be deleted + DbCleanerTestUtils.createSnapshotWithDate(2L, "2011-05-02").setLast(true), + DbCleanerTestUtils.createSnapshotWithDate(3L, "2011-05-19").setHasEvents(true).setLast(false), + DbCleanerTestUtils.createSnapshotWithDate(4L, "2011-05-23") // to be deleted + )); + + assertThat(toDelete).hasSize(2); + + List<Long> snapshotIds = snapshotIds(toDelete); + assertThat(snapshotIds).contains(1L); + assertThat(snapshotIds.contains(4L)); + } + + @Test + public void test_isDeletable() { + assertThat(KeepOneFilter.isDeletable(DbCleanerTestUtils.createSnapshotWithDate(1L, "2011-05-01"))).isTrue(); + assertThat(KeepOneFilter.isDeletable(DbCleanerTestUtils.createSnapshotWithDate(1L, "2011-05-01").setLast(true))).isFalse(); + assertThat(KeepOneFilter.isDeletable(DbCleanerTestUtils.createSnapshotWithDate(1L, "2011-05-01").setHasEvents(true))).isFalse(); + } + +} diff --git a/sonar-db/src/test/java/org/sonar/db/qualitygate/ProjectQgateAssociationDaoTest.java b/sonar-db/src/test/java/org/sonar/db/qualitygate/ProjectQgateAssociationDaoTest.java new file mode 100644 index 00000000000..e9fc43db574 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/qualitygate/ProjectQgateAssociationDaoTest.java @@ -0,0 +1,83 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.qualitygate; + +import java.util.List; +import org.junit.Before; +import org.junit.Test; +import org.sonar.db.AbstractDaoTestCase; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ProjectQgateAssociationDaoTest extends AbstractDaoTestCase { + + private ProjectQgateAssociationDao dao; + + @Before + public void setUp() { + dao = new ProjectQgateAssociationDao(getMyBatis()); + } + + @Test + public void select_all_projects_by_query() { + setupData("shared"); + + ProjectQgateAssociationQuery query = ProjectQgateAssociationQuery.builder().gateId("42").build(); + List<ProjectQgateAssociationDto> result = dao.selectProjects(query, 42L); + assertThat(result).hasSize(5); + } + + @Test + public void select_projects_by_query() { + setupData("shared"); + + assertThat(dao.selectProjects(ProjectQgateAssociationQuery.builder().gateId("42").membership(ProjectQgateAssociationQuery.IN).build(), 42L)).hasSize(3); + assertThat(dao.selectProjects(ProjectQgateAssociationQuery.builder().gateId("42").membership(ProjectQgateAssociationQuery.OUT).build(), 42L)).hasSize(2); + } + + @Test + public void search_by_project_name() { + setupData("shared"); + + List<ProjectQgateAssociationDto> result = dao.selectProjects(ProjectQgateAssociationQuery.builder().gateId("42").projectSearch("one").build(), 42L); + assertThat(result).hasSize(1); + + assertThat(result.get(0).getName()).isEqualTo("Project One"); + + result = dao.selectProjects(ProjectQgateAssociationQuery.builder().gateId("42").projectSearch("one").build(), 42L); + assertThat(result).hasSize(1); + result = dao.selectProjects(ProjectQgateAssociationQuery.builder().gateId("42").projectSearch("project").build(), 42L); + assertThat(result).hasSize(2); + } + + @Test + public void should_be_sorted_by_project_name() { + setupData("shared"); + + List<ProjectQgateAssociationDto> result = dao.selectProjects(ProjectQgateAssociationQuery.builder().gateId("42").build(), 42L); + assertThat(result).hasSize(5); + assertThat(result.get(0).getName()).isEqualTo("Project Five"); + assertThat(result.get(1).getName()).isEqualTo("Project Four"); + assertThat(result.get(2).getName()).isEqualTo("Project One"); + assertThat(result.get(3).getName()).isEqualTo("Project Three"); + assertThat(result.get(4).getName()).isEqualTo("Project Two"); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/qualitygate/ProjectQgateAssociationDtoTest.java b/sonar-db/src/test/java/org/sonar/db/qualitygate/ProjectQgateAssociationDtoTest.java new file mode 100644 index 00000000000..2b51c8f450c --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/qualitygate/ProjectQgateAssociationDtoTest.java @@ -0,0 +1,55 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.qualitygate; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ProjectQgateAssociationDtoTest { + + @Test + public void to_assoc_with_project_having_assoc() { + ProjectQgateAssociation project = new ProjectQgateAssociationDto() + .setId(1L) + .setName("polop") + .setGateId("10") + .toQgateAssociation(); + + assertThat(project.id()).isEqualTo(1); + assertThat(project.name()).isEqualTo("polop"); + assertThat(project.isMember()).isTrue(); + } + + @Test + public void to_assoc_with_project_not_having_assoc() { + ProjectQgateAssociation project = new ProjectQgateAssociationDto() + .setId(1L) + .setName("polop") + .setGateId(null) + .toQgateAssociation(); + + assertThat(project.id()).isEqualTo(1); + assertThat(project.name()).isEqualTo("polop"); + assertThat(project.isMember()).isFalse(); + } + +} diff --git a/sonar-db/src/test/java/org/sonar/db/qualitygate/ProjectQgateAssociationQueryTest.java b/sonar-db/src/test/java/org/sonar/db/qualitygate/ProjectQgateAssociationQueryTest.java new file mode 100644 index 00000000000..e8b12e11569 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/qualitygate/ProjectQgateAssociationQueryTest.java @@ -0,0 +1,57 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.qualitygate; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.fail; + +public class ProjectQgateAssociationQueryTest { + + @Test + public void fail_on_null_login() { + ProjectQgateAssociationQuery.Builder builder = ProjectQgateAssociationQuery.builder(); + builder.gateId(null); + + try { + builder.build(); + fail(); + } catch (Exception e) { + assertThat(e).isInstanceOf(NullPointerException.class).hasMessage("Gate ID cant be null."); + } + } + + @Test + public void fail_on_invalid_membership() { + ProjectQgateAssociationQuery.Builder builder = ProjectQgateAssociationQuery.builder(); + builder.gateId("nelson"); + builder.membership("unknwown"); + + try { + builder.build(); + fail(); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("Membership is not valid (got unknwown). Availables values are [all, selected, deselected]"); + } + } + +} diff --git a/sonar-db/src/test/java/org/sonar/db/qualitygate/QualityGateConditionDaoTest.java b/sonar-db/src/test/java/org/sonar/db/qualitygate/QualityGateConditionDaoTest.java new file mode 100644 index 00000000000..8e2840e09df --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/qualitygate/QualityGateConditionDaoTest.java @@ -0,0 +1,92 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.qualitygate; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.db.AbstractDaoTestCase; + +import static org.assertj.core.api.Assertions.assertThat; + +public class QualityGateConditionDaoTest extends AbstractDaoTestCase { + + private static final String[] COLUMNS_WITHOUT_TIMESTAMPS = { + "id", "qgate_id", "metric_id", "operator", "value_warning", "value_error", "period" + }; + + private static QualityGateConditionDao dao; + + @Before + public void createDao() { + dao = new QualityGateConditionDao(getMyBatis()); + } + + @Test + public void testInsert() throws Exception { + setupData("insert"); + QualityGateConditionDto newCondition = new QualityGateConditionDto() + .setQualityGateId(1L).setMetricId(2L).setOperator("GT").setWarningThreshold("10").setErrorThreshold("20").setPeriod(3); + dao.insert(newCondition); + checkTable("insert", "quality_gate_conditions", "metric_id", "operator", "error_value", "warning_value", "period"); + assertThat(newCondition.getId()).isNotNull(); + } + + @Test + public void testSelectForQualityGate() throws Exception { + setupData("selectForQualityGate"); + assertThat(dao.selectForQualityGate(1L)).hasSize(3); + assertThat(dao.selectForQualityGate(2L)).hasSize(2); + } + + @Test + public void testSelectById() throws Exception { + setupData("selectForQualityGate"); + QualityGateConditionDto selectById = dao.selectById(1L); + assertThat(selectById).isNotNull(); + assertThat(selectById.getId()).isNotNull().isNotEqualTo(0L); + assertThat(selectById.getMetricId()).isEqualTo(2L); + assertThat(selectById.getOperator()).isEqualTo("<"); + assertThat(selectById.getPeriod()).isEqualTo(3); + assertThat(selectById.getQualityGateId()).isEqualTo(1L); + assertThat(selectById.getWarningThreshold()).isEqualTo("10"); + assertThat(selectById.getErrorThreshold()).isEqualTo("20"); + assertThat(dao.selectById(42L)).isNull(); + } + + @Test + public void testDelete() throws Exception { + setupData("selectForQualityGate"); + dao.delete(new QualityGateConditionDto().setId(1L)); + checkTable("delete", "quality_gate_conditions", COLUMNS_WITHOUT_TIMESTAMPS); + } + + @Test + public void testUpdate() throws Exception { + setupData("selectForQualityGate"); + dao.update(new QualityGateConditionDto().setId(1L).setMetricId(7L).setOperator(">").setPeriod(1).setWarningThreshold("50").setErrorThreshold("80")); + checkTable("update", "quality_gate_conditions", COLUMNS_WITHOUT_TIMESTAMPS); + } + + public void shouldCleanConditions() { + setupData("shouldCleanConditions"); + dao.deleteConditionsWithInvalidMetrics(); + checkTables("shouldCleanConditions", "quality_gate_conditions"); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/qualitygate/QualityGateConditionDtoTest.java b/sonar-db/src/test/java/org/sonar/db/qualitygate/QualityGateConditionDtoTest.java new file mode 100644 index 00000000000..84e7bbc46df --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/qualitygate/QualityGateConditionDtoTest.java @@ -0,0 +1,61 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.qualitygate; + +import org.junit.Test; +import org.sonar.api.measures.Metric.ValueType; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.sonar.api.measures.Metric.ValueType.BOOL; +import static org.sonar.api.measures.Metric.ValueType.DATA; +import static org.sonar.api.measures.Metric.ValueType.FLOAT; +import static org.sonar.api.measures.Metric.ValueType.INT; +import static org.sonar.api.measures.Metric.ValueType.LEVEL; +import static org.sonar.api.measures.Metric.ValueType.MILLISEC; +import static org.sonar.api.measures.Metric.ValueType.PERCENT; +import static org.sonar.api.measures.Metric.ValueType.RATING; +import static org.sonar.api.measures.Metric.ValueType.STRING; +import static org.sonar.db.qualitygate.QualityGateConditionDto.isOperatorAllowed; + +public class QualityGateConditionDtoTest { + + @Test + public void should_validate_operators_for_metric_type() { + assertThat(isOperatorAllowed("WHATEVER", null)).isFalse(); + assertThat(isOperatorAllowed("WHATEVER", DATA)).isFalse(); + + assertThat(isOperatorAllowed("EQ", BOOL)).isTrue(); + assertThat(isOperatorAllowed("NE", BOOL)).isFalse(); + assertThat(isOperatorAllowed("LT", BOOL)).isFalse(); + assertThat(isOperatorAllowed("GT", BOOL)).isFalse(); + + assertThat(isOperatorAllowed("EQ", LEVEL)).isTrue(); + assertThat(isOperatorAllowed("NE", LEVEL)).isTrue(); + assertThat(isOperatorAllowed("LT", LEVEL)).isFalse(); + assertThat(isOperatorAllowed("GT", LEVEL)).isFalse(); + + for (ValueType type : new ValueType[] {STRING, INT, FLOAT, PERCENT, MILLISEC, RATING}) { + assertThat(isOperatorAllowed("EQ", type)).isTrue(); + assertThat(isOperatorAllowed("NE", type)).isTrue(); + assertThat(isOperatorAllowed("LT", type)).isTrue(); + assertThat(isOperatorAllowed("GT", type)).isTrue(); + } + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/qualitygate/QualityGateDaoTest.java b/sonar-db/src/test/java/org/sonar/db/qualitygate/QualityGateDaoTest.java new file mode 100644 index 00000000000..707bd159e5e --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/qualitygate/QualityGateDaoTest.java @@ -0,0 +1,86 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.qualitygate; + +import java.util.Collection; +import java.util.Iterator; +import org.junit.Before; +import org.junit.Test; +import org.sonar.db.AbstractDaoTestCase; + +import static org.assertj.core.api.Assertions.assertThat; + +public class QualityGateDaoTest extends AbstractDaoTestCase { + + private static QualityGateDao dao; + + @Before + public void createDao() { + dao = new QualityGateDao(getMyBatis()); + } + + @Test + public void testInsert() throws Exception { + setupData("insert"); + QualityGateDto newQgate = new QualityGateDto().setName("My Quality Gate"); + dao.insert(newQgate); + checkTable("insert", "quality_gates", "name"); + assertThat(newQgate.getId()).isNotNull(); + } + + @Test + public void testSelectAll() throws Exception { + setupData("selectAll"); + Collection<QualityGateDto> allQualityGates = dao.selectAll(); + assertThat(allQualityGates).hasSize(3); + Iterator<QualityGateDto> gatesIterator = allQualityGates.iterator(); + assertThat(gatesIterator.next().getName()).isEqualTo("Balanced"); + assertThat(gatesIterator.next().getName()).isEqualTo("Lenient"); + assertThat(gatesIterator.next().getName()).isEqualTo("Very strict"); + } + + @Test + public void testSelectByName() throws Exception { + setupData("selectAll"); + assertThat(dao.selectByName("Balanced").getName()).isEqualTo("Balanced"); + assertThat(dao.selectByName("Unknown")).isNull(); + } + + @Test + public void testSelectById() throws Exception { + setupData("selectAll"); + assertThat(dao.selectById(1L).getName()).isEqualTo("Very strict"); + assertThat(dao.selectById(42L)).isNull(); + } + + @Test + public void testDelete() throws Exception { + setupData("selectAll"); + dao.delete(new QualityGateDto().setId(1L)); + checkTable("delete", "quality_gates", "id", "name"); + } + + @Test + public void testUpdate() throws Exception { + setupData("selectAll"); + dao.update(new QualityGateDto().setId(1L).setName("Not so strict")); + checkTable("update", "quality_gates", "id", "name"); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/qualityprofile/ActiveRuleDaoTest.java b/sonar-db/src/test/java/org/sonar/db/qualityprofile/ActiveRuleDaoTest.java new file mode 100644 index 00000000000..7c3eeaa1d08 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/qualityprofile/ActiveRuleDaoTest.java @@ -0,0 +1,71 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.qualityprofile; + +import java.util.List; +import org.junit.Before; +import org.junit.Test; +import org.sonar.db.AbstractDaoTestCase; +import org.sonar.db.DbSession; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ActiveRuleDaoTest extends AbstractDaoTestCase { + + ActiveRuleDao dao; + + @Before + public void before() { + dao = new ActiveRuleDao(getMyBatis()); + } + + @Test + public void select_by_profile() { + setupData("shared"); + + List<ActiveRuleDto> result = dao.selectByProfileKey("parent"); + assertThat(result).hasSize(2); + } + + @Test + public void insert_parameter() { + setupData("empty"); + + DbSession session = getMyBatis().openSession(false); + ActiveRuleParamDto dto = new ActiveRuleParamDto() + .setActiveRuleId(1) + .setRulesParameterId(1) + .setKey("max") + .setValue("20"); + dao.insert(dto, session); + session.commit(); + session.close(); + + checkTables("insert_parameter", "active_rule_parameters"); + } + + @Test + public void select_params_by_profile_id() { + setupData("shared"); + + assertThat(dao.selectParamsByProfileKey("child")).hasSize(2); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/qualityprofile/ActiveRuleKeyTest.java b/sonar-db/src/test/java/org/sonar/db/qualityprofile/ActiveRuleKeyTest.java new file mode 100644 index 00000000000..e89f7d81213 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/qualityprofile/ActiveRuleKeyTest.java @@ -0,0 +1,101 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.qualityprofile; + +import org.junit.Test; +import org.sonar.api.rule.RuleKey; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.fail; + +public class ActiveRuleKeyTest { + + @Test + public void of() { + RuleKey ruleKey = RuleKey.of("xoo", "R1"); + ActiveRuleKey key = ActiveRuleKey.of("P1", ruleKey); + assertThat(key.qProfile()).isEqualTo("P1"); + assertThat(key.ruleKey()).isSameAs(ruleKey); + assertThat(key.toString()).isEqualTo("P1:xoo:R1"); + } + + @Test + public void rule_key_can_contain_colons() { + RuleKey ruleKey = RuleKey.of("squid", "Key:With:Some::Colons"); + ActiveRuleKey key = ActiveRuleKey.of("P1", ruleKey); + assertThat(key.qProfile()).isEqualTo("P1"); + assertThat(key.ruleKey()).isSameAs(ruleKey); + assertThat(key.toString()).isEqualTo("P1:squid:Key:With:Some::Colons"); + } + + @Test + public void profile_must_not_be_null() { + try { + ActiveRuleKey.of(null, RuleKey.of("xoo", "R1")); + fail(); + } catch (NullPointerException e) { + assertThat(e).hasMessage("QProfile is missing"); + } + } + + @Test + public void rule_key_must_not_be_null() { + try { + ActiveRuleKey.of("P1", null); + fail(); + } catch (NullPointerException e) { + assertThat(e).hasMessage("RuleKey is missing"); + } + } + + @Test + public void parse() { + ActiveRuleKey key = ActiveRuleKey.parse("P1:xoo:R1"); + assertThat(key.qProfile()).isEqualTo("P1"); + assertThat(key.ruleKey().repository()).isEqualTo("xoo"); + assertThat(key.ruleKey().rule()).isEqualTo("R1"); + } + + @Test + public void parse_fail_when_less_than_three_colons() { + try { + ActiveRuleKey.parse("P1:xoo"); + fail(); + } catch (IllegalArgumentException e) { + assertThat(e).hasMessage("Bad format of activeRule key: P1:xoo"); + } + } + + @Test + public void equals_and_hashcode() { + ActiveRuleKey key1 = ActiveRuleKey.parse("P1:xoo:R1"); + ActiveRuleKey key1b = ActiveRuleKey.parse("P1:xoo:R1"); + ActiveRuleKey key2 = ActiveRuleKey.parse("P1:xoo:R2"); + ActiveRuleKey key3 = ActiveRuleKey.parse("P2:xoo:R1"); + assertThat(key1.equals(key1)).isTrue(); + assertThat(key1.equals(key1b)).isTrue(); + assertThat(key1.equals(null)).isFalse(); + assertThat(key1.equals("P1:xoo:R1")).isFalse(); + assertThat(key1.equals(key2)).isFalse(); + assertThat(key1.equals(key3)).isFalse(); + + assertThat(key1.hashCode()).isEqualTo(key1.hashCode()); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/qualityprofile/ActiveRuleParamDtoTest.java b/sonar-db/src/test/java/org/sonar/db/qualityprofile/ActiveRuleParamDtoTest.java new file mode 100644 index 00000000000..43a5ff98305 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/qualityprofile/ActiveRuleParamDtoTest.java @@ -0,0 +1,42 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.qualityprofile; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ActiveRuleParamDtoTest { + + @Test + public void groupByKey() { + assertThat(ActiveRuleParamDto.groupByKey(Collections.<ActiveRuleParamDto>emptyList())).isEmpty(); + + Collection<ActiveRuleParamDto> dtos = Arrays.asList( + new ActiveRuleParamDto().setKey("foo"), new ActiveRuleParamDto().setKey("bar") + ); + Map<String, ActiveRuleParamDto> group = ActiveRuleParamDto.groupByKey(dtos); + assertThat(group.keySet()).containsOnly("foo", "bar"); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/qualityprofile/QualityProfileDaoTest.java b/sonar-db/src/test/java/org/sonar/db/qualityprofile/QualityProfileDaoTest.java new file mode 100644 index 00000000000..a70307ea49e --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/qualityprofile/QualityProfileDaoTest.java @@ -0,0 +1,255 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.qualityprofile; + +import java.util.List; +import org.assertj.core.data.MapEntry; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.utils.System2; +import org.sonar.core.util.UtcDateUtils; +import org.sonar.db.AbstractDaoTestCase; +import org.sonar.db.DbSession; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class QualityProfileDaoTest extends AbstractDaoTestCase { + + QualityProfileDao dao; + DbSession session; + System2 system = mock(System2.class); + + @Before + public void createDao() { + this.session = getMyBatis().openSession(false); + dao = new QualityProfileDao(getMyBatis(), system); + when(system.now()).thenReturn(UtcDateUtils.parseDateTime("2014-01-20T12:00:00+0000").getTime()); + } + + @After + public void after() { + this.session.close(); + } + + @Test + public void insert() { + setupData("shared"); + + QualityProfileDto dto = QualityProfileDto.createFor("abcde") + .setName("ABCDE") + .setLanguage("xoo"); + + dao.insert(dto); + + checkTables("insert", new String[] {"created_at", "updated_at", "rules_updated_at"}, "rules_profiles"); + } + + @Test + public void update() { + setupData("shared"); + + QualityProfileDto dto = new QualityProfileDto() + .setId(1) + .setName("New Name") + .setLanguage("js") + .setParentKee("fghij") + .setDefault(false); + + dao.update(dto); + + checkTables("update", new String[] {"created_at", "updated_at", "rules_updated_at"}, "rules_profiles"); + } + + @Test + public void delete() { + setupData("shared"); + + dao.delete(1); + + checkTables("delete", "rules_profiles"); + } + + @Test + public void find_all() { + setupData("shared"); + + DbSession session = getMyBatis().openSession(false); + try { + List<QualityProfileDto> dtos = dao.findAll(session); + + assertThat(dtos).hasSize(2); + + QualityProfileDto dto1 = dtos.get(0); + assertThat(dto1.getId()).isEqualTo(1); + assertThat(dto1.getName()).isEqualTo("Sonar Way"); + assertThat(dto1.getLanguage()).isEqualTo("java"); + assertThat(dto1.getParentKee()).isNull(); + + QualityProfileDto dto2 = dtos.get(1); + assertThat(dto2.getId()).isEqualTo(2); + assertThat(dto2.getName()).isEqualTo("Sonar Way"); + assertThat(dto2.getLanguage()).isEqualTo("js"); + assertThat(dto2.getParentKee()).isNull(); + } finally { + session.close(); + } + } + + @Test + public void find_all_is_sorted_by_profile_name() { + setupData("select_all_is_sorted_by_profile_name"); + + List<QualityProfileDto> dtos = dao.findAll(); + + assertThat(dtos).hasSize(3); + assertThat(dtos.get(0).getName()).isEqualTo("First"); + assertThat(dtos.get(1).getName()).isEqualTo("Second"); + assertThat(dtos.get(2).getName()).isEqualTo("Third"); + } + + @Test + public void get_default_profile() { + setupData("shared"); + + QualityProfileDto java = dao.getDefaultProfile("java"); + assertThat(java).isNotNull(); + assertThat(java.getKey()).isEqualTo("java_sonar_way"); + + assertThat(dao.getDefaultProfile("js")).isNull(); + } + + @Test + public void get_by_name_and_language() { + setupData("shared"); + + QualityProfileDto dto = dao.getByNameAndLanguage("Sonar Way", "java"); + assertThat(dto.getId()).isEqualTo(1); + assertThat(dto.getName()).isEqualTo("Sonar Way"); + assertThat(dto.getLanguage()).isEqualTo("java"); + assertThat(dto.getParentKee()).isNull(); + + assertThat(dao.getByNameAndLanguage("Sonar Way", "java")).isNotNull(); + assertThat(dao.getByNameAndLanguage("Sonar Way", "unknown")).isNull(); + } + + @Test + public void find_by_language() { + setupData("select_by_language"); + + List<QualityProfileDto> result = dao.findByLanguage("java"); + assertThat(result).hasSize(2); + assertThat(result.get(0).getName()).isEqualTo("Sonar Way 1"); + assertThat(result.get(1).getName()).isEqualTo("Sonar Way 2"); + } + + @Test + public void get_by_id() { + setupData("shared"); + + QualityProfileDto dto = dao.getById(1); + assertThat(dto.getId()).isEqualTo(1); + assertThat(dto.getName()).isEqualTo("Sonar Way"); + assertThat(dto.getLanguage()).isEqualTo("java"); + assertThat(dto.getParentKee()).isNull(); + + assertThat(dao.getById(555)).isNull(); + } + + @Test + public void get_parent_by_id() { + setupData("inheritance"); + + QualityProfileDto dto = dao.getParentById(1); + assertThat(dto.getId()).isEqualTo(3); + } + + @Test + public void find_children() { + setupData("inheritance"); + + DbSession session = getMyBatis().openSession(false); + try { + List<QualityProfileDto> dtos = dao.findChildren(session, "java_parent"); + + assertThat(dtos).hasSize(2); + + QualityProfileDto dto1 = dtos.get(0); + assertThat(dto1.getId()).isEqualTo(1); + assertThat(dto1.getName()).isEqualTo("Child1"); + assertThat(dto1.getLanguage()).isEqualTo("java"); + assertThat(dto1.getParentKee()).isEqualTo("java_parent"); + + QualityProfileDto dto2 = dtos.get(1); + assertThat(dto2.getId()).isEqualTo(2); + assertThat(dto2.getName()).isEqualTo("Child2"); + assertThat(dto2.getLanguage()).isEqualTo("java"); + assertThat(dto2.getParentKee()).isEqualTo("java_parent"); + + } finally { + session.close(); + } + } + + @Test + public void select_projects() { + setupData("projects"); + + assertThat(dao.selectProjects("Sonar Way", "java")).hasSize(2); + } + + @Test + public void count_projects() { + setupData("projects"); + + assertThat(dao.countProjects("Sonar Way", "java")).isEqualTo(2); + } + + @Test + public void count_projects_by_profile() { + setupData("projects"); + + assertThat(dao.countProjectsByProfileKey()).containsOnly( + MapEntry.entry("java_sonar_way", 2L), + MapEntry.entry("js_sonar_way", 2L)); + } + + @Test + public void select_by_project_id_and_language() { + setupData("projects"); + + QualityProfileDto dto = dao.getByProjectAndLanguage(1L, "java"); + assertThat(dto.getId()).isEqualTo(1); + } + + @Test + public void select_by_project_key_and_language() { + setupData("projects"); + + QualityProfileDto dto = dao.getByProjectAndLanguage("org.codehaus.sonar:sonar", "java", session); + assertThat(dto.getId()).isEqualTo(1); + + assertThat(dao.getByProjectAndLanguage("org.codehaus.sonar:sonar", "unkown", session)).isNull(); + assertThat(dao.getByProjectAndLanguage("unknown", "java", session)).isNull(); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/rule/RuleDaoTest.java b/sonar-db/src/test/java/org/sonar/db/rule/RuleDaoTest.java new file mode 100644 index 00000000000..34736c205ac --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/rule/RuleDaoTest.java @@ -0,0 +1,77 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.rule; + +import java.util.List; +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.rule.RuleStatus; +import org.sonar.db.AbstractDaoTestCase; + +import static org.assertj.core.api.Assertions.assertThat; + +public class RuleDaoTest extends AbstractDaoTestCase { + + private static RuleDao dao; + + @Before + public void createDao() { + dao = new RuleDao(getMyBatis()); + } + + @Test + public void select_enables_and_non_manual() { + setupData("select_enables_and_non_manual"); + List<RuleDto> ruleDtos = dao.selectEnablesAndNonManual(); + + assertThat(ruleDtos.size()).isEqualTo(1); + RuleDto ruleDto = ruleDtos.get(0); + assertThat(ruleDto.getId()).isEqualTo(1); + assertThat(ruleDto.getName()).isEqualTo("Avoid Null"); + assertThat(ruleDto.getDescription()).isEqualTo("Should avoid NULL"); + assertThat(ruleDto.getDescriptionFormat()).isEqualTo(RuleDto.Format.HTML); + assertThat(ruleDto.getStatus()).isEqualTo(RuleStatus.READY); + assertThat(ruleDto.getRepositoryKey()).isEqualTo("checkstyle"); + assertThat(ruleDto.getNoteData()).isEqualTo("Rule note with accents \u00e9\u00e8\u00e0"); + assertThat(ruleDto.getSubCharacteristicId()).isEqualTo(100); + assertThat(ruleDto.getDefaultSubCharacteristicId()).isEqualTo(101); + assertThat(ruleDto.getRemediationFunction()).isEqualTo("LINEAR"); + assertThat(ruleDto.getDefaultRemediationFunction()).isEqualTo("LINEAR_OFFSET"); + assertThat(ruleDto.getRemediationCoefficient()).isEqualTo("1h"); + assertThat(ruleDto.getDefaultRemediationCoefficient()).isEqualTo("5d"); + assertThat(ruleDto.getRemediationOffset()).isEqualTo("5min"); + assertThat(ruleDto.getDefaultRemediationOffset()).isEqualTo("10h"); + assertThat(ruleDto.getEffortToFixDescription()).isEqualTo("squid.S115.effortToFix"); + } + + @Test + public void select_parameters() { + setupData("selectParameters"); + List<RuleParamDto> ruleDtos = dao.selectParameters(); + + assertThat(ruleDtos.size()).isEqualTo(1); + RuleParamDto ruleDto = ruleDtos.get(0); + assertThat(ruleDto.getId()).isEqualTo(1); + assertThat(ruleDto.getName()).isEqualTo("myParameter"); + assertThat(ruleDto.getDescription()).isEqualTo("My Parameter"); + assertThat(ruleDto.getType()).isEqualTo("plop"); + assertThat(ruleDto.getDefaultValue()).isEqualTo("plouf"); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/semaphore/SemaphoreDaoTest.java b/sonar-db/src/test/java/org/sonar/db/semaphore/SemaphoreDaoTest.java new file mode 100644 index 00000000000..30adc2b980e --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/semaphore/SemaphoreDaoTest.java @@ -0,0 +1,304 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.semaphore; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.atomic.AtomicInteger; +import org.apache.ibatis.session.SqlSession; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.api.utils.Semaphores; +import org.sonar.api.utils.System2; +import org.sonar.db.AbstractDaoTestCase; +import org.sonar.db.MyBatis; + +import static org.assertj.core.api.Assertions.assertThat; + +public class SemaphoreDaoTest extends AbstractDaoTestCase { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + private SemaphoreDao dao; + private System2 system; + + @Before + public void before() { + system = System2.INSTANCE; + dao = new SemaphoreDao(getMyBatis(), system); + } + + @Test + public void should_fail_to_acquire_if_null_semaphore_name() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Semaphore name must not be empty"); + + SemaphoreDao dao = new SemaphoreDao(getMyBatis(), system); + dao.acquire(null, 5000); + } + + @Test + public void should_fail_to_acquire_if_blank_semaphore_name() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Semaphore name must not be empty"); + + SemaphoreDao dao = new SemaphoreDao(getMyBatis(), system); + dao.acquire("", 5000); + } + + @Test + public void should_fail_to_acquire_if_negative_timeout() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Semaphore max age must be positive: -5000"); + + SemaphoreDao dao = new SemaphoreDao(getMyBatis(), system); + dao.acquire("foo", -5000); + } + + @Test + public void should_fail_to_release_if_blank_semaphore_name() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Semaphore name must not be empty"); + + SemaphoreDao dao = new SemaphoreDao(getMyBatis(), system); + dao.release(null); + } + + @Test + public void create_and_acquire_semaphore() { + Semaphores.Semaphore lock = dao.acquire("foo", 60); + assertThat(lock.isLocked()).isTrue(); + assertThat(lock.getDurationSinceLocked()).isNull(); + + SemaphoreDto semaphore = selectSemaphore("foo"); + assertThat(semaphore).isNotNull(); + assertThat(semaphore.getName()).isEqualTo("foo"); + assertThat(isRecent(semaphore.getCreatedAt())).isTrue(); + assertThat(isRecent(semaphore.getUpdatedAt())).isTrue(); + assertThat(isRecent(semaphore.getLockedAt())).isTrue(); + + dao.release("foo"); + assertThat(selectSemaphore("foo")).isNull(); + } + + @Test + public void create_and_acquire_and_update_semaphore() throws Exception { + Semaphores.Semaphore lock = dao.acquire("foo", 60); + assertThat(lock.isLocked()).isTrue(); + assertThat(lock.getDurationSinceLocked()).isNull(); + + SemaphoreDto semaphore = selectSemaphore("foo"); + assertThat(semaphore.getCreatedAt()).isEqualTo(semaphore.getUpdatedAt()); + + Thread.sleep(1000); + + dao.update(lock); + + semaphore = selectSemaphore("foo"); + assertThat(semaphore.getCreatedAt()).isLessThan(semaphore.getUpdatedAt()); + + dao.release("foo"); + assertThat(selectSemaphore("foo")).isNull(); + } + + @Test + public void fail_to_update_null_semaphore() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Semaphore must not be null"); + + dao.update(null); + } + + @Test + public void create_and_acquire_semaphore_when_maxage_is_zeo() { + Semaphores.Semaphore lock = dao.acquire("foo", 0); + assertThat(lock.isLocked()).isTrue(); + assertThat(lock.getDurationSinceLocked()).isNull(); + + SemaphoreDto semaphore = selectSemaphore("foo"); + assertThat(semaphore).isNotNull(); + assertThat(semaphore.getName()).isEqualTo("foo"); + assertThat(isRecent(semaphore.getCreatedAt())).isTrue(); + assertThat(isRecent(semaphore.getUpdatedAt())).isTrue(); + assertThat(isRecent(semaphore.getLockedAt())).isTrue(); + + dao.release("foo"); + assertThat(selectSemaphore("foo")).isNull(); + } + + @Test + public void create_and_acquire_semaphore_when_no_timeout() { + Semaphores.Semaphore lock = dao.acquire("foo"); + assertThat(lock.isLocked()).isTrue(); + assertThat(lock.getDurationSinceLocked()).isNull(); + + SemaphoreDto semaphore = selectSemaphore("foo"); + assertThat(semaphore).isNotNull(); + assertThat(semaphore.getName()).isEqualTo("foo"); + assertThat(isRecent(semaphore.getCreatedAt())).isTrue(); + assertThat(isRecent(semaphore.getUpdatedAt())).isTrue(); + assertThat(isRecent(semaphore.getLockedAt())).isTrue(); + + dao.release("foo"); + assertThat(selectSemaphore("foo")).isNull(); + } + + @Test + public void fail_to_acquire_locked_semaphore() { + setupData("old_semaphore"); + Semaphores.Semaphore lock = dao.acquire("foo", Integer.MAX_VALUE); + assertThat(lock.isLocked()).isFalse(); + assertThat(lock.getDurationSinceLocked()).isNotNull(); + + SemaphoreDto semaphore = selectSemaphore("foo"); + assertThat(semaphore).isNotNull(); + assertThat(semaphore.getName()).isEqualTo("foo"); + assertThat(isRecent(semaphore.getCreatedAt())).isFalse(); + assertThat(isRecent(semaphore.getUpdatedAt())).isFalse(); + assertThat(isRecent(semaphore.getLockedAt())).isFalse(); + } + + @Test + public void acquire_long_locked_semaphore() { + setupData("old_semaphore"); + Semaphores.Semaphore lock = dao.acquire("foo", 60); + assertThat(lock.isLocked()).isTrue(); + assertThat(lock.getDurationSinceLocked()).isNull(); + + SemaphoreDto semaphore = selectSemaphore("foo"); + assertThat(semaphore).isNotNull(); + assertThat(semaphore.getName()).isEqualTo("foo"); + assertThat(isRecent(semaphore.getCreatedAt())).isFalse(); + assertThat(isRecent(semaphore.getUpdatedAt())).isTrue(); + assertThat(isRecent(semaphore.getLockedAt())).isTrue(); + } + + @Test + public void acquire_locked_semaphore_when_timeout_is_zero() { + setupData("old_semaphore"); + Semaphores.Semaphore lock = dao.acquire("foo", 0); + assertThat(lock.isLocked()).isTrue(); + assertThat(lock.getDurationSinceLocked()).isNull(); + + SemaphoreDto semaphore = selectSemaphore("foo"); + assertThat(semaphore).isNotNull(); + assertThat(semaphore.getName()).isEqualTo("foo"); + assertThat(isRecent(semaphore.getCreatedAt())).isFalse(); + assertThat(isRecent(semaphore.getUpdatedAt())).isTrue(); + assertThat(isRecent(semaphore.getLockedAt())).isTrue(); + + dao.release("foo"); + assertThat(selectSemaphore("foo")).isNull(); + } + + @Test + public void fail_to_acquire_locked_semaphore_when_no_timeout() { + setupData("old_semaphore"); + Semaphores.Semaphore lock = dao.acquire("foo"); + assertThat(lock.isLocked()).isFalse(); + assertThat(lock.getDurationSinceLocked()).isNotNull(); + + SemaphoreDto semaphore = selectSemaphore("foo"); + assertThat(semaphore).isNotNull(); + assertThat(semaphore.getName()).isEqualTo("foo"); + assertThat(isRecent(semaphore.getCreatedAt())).isFalse(); + assertThat(isRecent(semaphore.getUpdatedAt())).isFalse(); + assertThat(isRecent(semaphore.getLockedAt())).isFalse(); + } + + @Test + public void should_select_semaphore_return_current_semaphore_when_acquiring() { + dao.acquire("foo"); + + SemaphoreDto semaphore = selectSemaphore("foo"); + assertThat(semaphore).isNotNull(); + assertThat(semaphore.getName()).isEqualTo("foo"); + assertThat(semaphore.getCreatedAt()).isNotNull(); + assertThat(semaphore.getUpdatedAt()).isNotNull(); + assertThat(semaphore.getLockedAt()).isNotNull(); + } + + @Test + public void test_concurrent_locks() throws Exception { + for (int tests = 0; tests < 5; tests++) { + dao.release("my-lock"); + int size = 5; + CyclicBarrier barrier = new CyclicBarrier(size); + CountDownLatch latch = new CountDownLatch(size); + + AtomicInteger locks = new AtomicInteger(0); + for (int i = 0; i < size; i++) { + new Runner(dao, locks, barrier, latch).start(); + } + latch.await(); + + // semaphore was locked only 1 time + assertThat(locks.get()).isEqualTo(1); + } + } + + private SemaphoreDto selectSemaphore(String name) { + SqlSession session = getMyBatis().openSession(); + try { + return dao.selectSemaphore(name, session); + } finally { + MyBatis.closeQuietly(session); + } + } + + private boolean isRecent(Long date) { + int oneMinuteInMs = 60 * 1000; + long future = system.now() + oneMinuteInMs; + long past = system.now() - oneMinuteInMs; + return date > past && date < future; + } + + private static class Runner extends Thread { + SemaphoreDao dao; + AtomicInteger locks; + CountDownLatch latch; + CyclicBarrier barrier; + + Runner(SemaphoreDao dao, AtomicInteger atomicSeq, CyclicBarrier barrier, CountDownLatch latch) { + this.dao = dao; + this.locks = atomicSeq; + this.latch = latch; + this.barrier = barrier; + } + + @Override + public void run() { + try { + barrier.await(); + for (int i = 0; i < 100; i++) { + if (dao.acquire("my-lock", 60 * 60 * 24).isLocked()) { + locks.incrementAndGet(); + } + } + latch.countDown(); + + } catch (Exception e) { + e.printStackTrace(); + } + } + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/semaphore/SemaphoreUpdaterTest.java b/sonar-db/src/test/java/org/sonar/db/semaphore/SemaphoreUpdaterTest.java new file mode 100644 index 00000000000..129a8914ce0 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/semaphore/SemaphoreUpdaterTest.java @@ -0,0 +1,74 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.semaphore; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.api.utils.Semaphores; +import org.sonar.db.AbstractDaoTestCase; + +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +public class SemaphoreUpdaterTest extends AbstractDaoTestCase { + + private SemaphoreUpdater updater; + private SemaphoreDao dao; + + @Before + public void before() { + dao = mock(SemaphoreDao.class); + updater = new SemaphoreUpdater(dao); + } + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void testScheduleUpdate() throws Exception { + Semaphores.Semaphore semaphore = new Semaphores.Semaphore().setName("foo"); + updater.scheduleForUpdate(semaphore, 1); + + Thread.sleep(2000); + + verify(dao, atLeastOnce()).update(semaphore); + } + + @Test + public void testCancelUpdate() throws Exception { + Semaphores.Semaphore semaphore = new Semaphores.Semaphore().setName("foo"); + updater.scheduleForUpdate(semaphore, 1); + updater.stopUpdate("foo"); + + Thread.sleep(2000); + + verify(dao, never()).update(semaphore); + } + + @Test + public void shouldNotFailWhenCancelNotExistingSemaphore() { + updater.stopUpdate("foo"); + } + +} diff --git a/sonar-db/src/test/java/org/sonar/db/semaphore/SemaphoresImplTest.java b/sonar-db/src/test/java/org/sonar/db/semaphore/SemaphoresImplTest.java new file mode 100644 index 00000000000..a8d13641fdd --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/semaphore/SemaphoresImplTest.java @@ -0,0 +1,51 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.semaphore; + +import org.junit.Test; +import org.sonar.api.utils.Semaphores; + +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class SemaphoresImplTest { + + @Test + public void should_be_a_bridge_over_dao() { + SemaphoreDao dao = mock(SemaphoreDao.class); + SemaphoreUpdater updater = mock(SemaphoreUpdater.class); + Semaphores.Semaphore semaphore = new Semaphores.Semaphore(); + when(dao.acquire(anyString(), anyInt())).thenReturn(semaphore); + + SemaphoresImpl impl = new SemaphoresImpl(dao, updater); + + impl.acquire("do-xxx", 50000, 10); + verify(dao).acquire("do-xxx", 50000); + + impl.acquire("do-xxx"); + verify(dao).acquire("do-xxx"); + + impl.release("do-xxx"); + verify(dao).release("do-xxx"); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/source/FileSourceDtoTest.java b/sonar-db/src/test/java/org/sonar/db/source/FileSourceDtoTest.java new file mode 100644 index 00000000000..624dd4262cb --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/source/FileSourceDtoTest.java @@ -0,0 +1,49 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.source; + +import java.util.Arrays; +import java.util.List; +import org.junit.Test; +import org.sonar.server.source.db.FileSourceDb; + +import static org.assertj.core.api.Assertions.assertThat; + +public class FileSourceDtoTest { + + @Test + public void encode_and_decode_test_data() { + List<FileSourceDb.Test> tests = Arrays.asList( + FileSourceDb.Test.newBuilder() + .setName("name#1") + .build(), + FileSourceDb.Test.newBuilder() + .setName("name#2") + .build() + ); + + FileSourceDto sut = new FileSourceDto() + .setTestData(tests); + + assertThat(sut.getTestData()).hasSize(2); + assertThat(sut.getTestData().get(0).getName()).isEqualTo("name#1"); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/user/AuthorDaoTest.java b/sonar-db/src/test/java/org/sonar/db/user/AuthorDaoTest.java new file mode 100644 index 00000000000..9cda23c3417 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/user/AuthorDaoTest.java @@ -0,0 +1,129 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.user; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.utils.System2; +import org.sonar.db.AbstractDaoTestCase; +import org.sonar.db.component.ResourceDao; +import org.sonar.db.component.ResourceDto; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.fail; + +public class AuthorDaoTest extends AbstractDaoTestCase { + + private AuthorDao dao; + + @Before + public void setUp() { + dao = new AuthorDao(getMyBatis(), new ResourceDao(getMyBatis(), System2.INSTANCE)); + } + + @Test + public void shouldSelectByLogin() { + setupData("shouldSelectByLogin"); + + AuthorDto authorDto = dao.selectByLogin("godin"); + assertThat(authorDto.getId()).isEqualTo(1L); + assertThat(authorDto.getPersonId()).isEqualTo(13L); + assertThat(authorDto.getLogin()).isEqualTo("godin"); + + assertThat(dao.selectByLogin("simon")).isNull(); + } + + @Test + public void shouldInsertAuthor() { + setupData("shouldInsertAuthor"); + + dao.insertAuthor("godin", 13L); + + checkTables("shouldInsertAuthor", new String[] {"created_at", "updated_at"}, "authors"); + } + + @Test + public void countDeveloperLogins() { + setupData("countDeveloperLogins"); + + assertThat(dao.countDeveloperLogins(1L)).isEqualTo(2); + assertThat(dao.countDeveloperLogins(98765L)).isEqualTo(0); + } + + @Test + public void shouldInsertAuthorAndDeveloper() { + setupData("shouldInsertAuthorAndDeveloper"); + + String login = "developer@company.net"; + ResourceDto resourceDto = new ResourceDto().setName(login).setQualifier("DEV").setUuid("ABCD").setProjectUuid("ABCD").setModuleUuidPath("."); + dao.insertAuthorAndDeveloper(login, resourceDto); + + checkTables("shouldInsertAuthorAndDeveloper", + new String[] {"created_at", "updated_at", "copy_resource_id", "description", "enabled", "kee", "deprecated_kee", "path", "language", "long_name", "person_id", "root_id", + "scope", "authorization_updated_at"}, + "authors", "projects"); + } + + @Test + public void add_missing_module_uuid_path() { + setupData("add_missing_module_uuid_path"); + + dao.insertAuthorAndDeveloper("developer@company.net", new ResourceDto().setName("developer@company.net").setQualifier("DEV").setUuid("ABCD").setProjectUuid("ABCD") + .setModuleUuidPath("")); + dao.insertAuthorAndDeveloper("developer2@company.net", new ResourceDto().setName("developer2@company.net").setQualifier("DEV").setUuid("BCDE").setProjectUuid("BCDE")); + + checkTables("add_missing_module_uuid_path", + new String[] {"created_at", "updated_at", "copy_resource_id", "description", "enabled", "kee", "deprecated_kee", "path", "language", "long_name", "person_id", "root_id", + "scope", "authorization_updated_at"}, + "authors", "projects"); + } + + @Test + public void shouldPreventAuthorsDuplication() { + setupData("shouldPreventAuthorsDuplication"); + + try { + dao.insertAuthor("godin", 20L); + fail(); + } catch (RuntimeException ex) { + } + + checkTables("shouldPreventAuthorsDuplication", new String[] {"created_at", "updated_at"}, "authors"); + } + + @Test + public void shouldPreventAuthorsAndDevelopersDuplication() { + setupData("shouldPreventAuthorsAndDevelopersDuplication"); + + String login = "developer@company.net"; + ResourceDto resourceDto = new ResourceDto().setName(login).setQualifier("DEV"); + + try { + dao.insertAuthorAndDeveloper("developer@company.net", resourceDto); + fail(); + } catch (RuntimeException ex) { + } + + checkTables("shouldPreventAuthorsAndDevelopersDuplication", + new String[] {"created_at", "updated_at", "copy_resource_id", "description", "enabled", "kee", "deprecated_kee", "path", "language", "long_name", "person_id", "root_id", + "scope", "authorization_updated_at"}, + "authors", "projects"); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/user/AuthorizationDaoTest.java b/sonar-db/src/test/java/org/sonar/db/user/AuthorizationDaoTest.java new file mode 100644 index 00000000000..ce5990951f9 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/user/AuthorizationDaoTest.java @@ -0,0 +1,295 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.user; + +import com.google.common.collect.Sets; +import java.util.Collection; +import java.util.Collections; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.sonar.db.AbstractDaoTestCase; +import org.sonar.db.DbSession; + +import static org.assertj.core.api.Assertions.assertThat; + +public class AuthorizationDaoTest extends AbstractDaoTestCase { + + private static final int USER = 100; + private static final Long PROJECT_ID = 300L; + private static final Long PROJECT_ID_WITHOUT_SNAPSHOT = 400L; + private static final String PROJECT = "pj-w-snapshot"; + private static final String PROJECT_WIHOUT_SNAPSHOT = "pj-wo-snapshot"; + + DbSession session; + + AuthorizationDao authorization; + + @Before + public void setUp() { + session = getMyBatis().openSession(false); + authorization = new AuthorizationDao(getMyBatis()); + } + + @After + public void tearDown() { + session.close(); + } + + @Test + public void user_should_be_authorized() { + // but user is not in an authorized group + setupData("user_should_be_authorized"); + + Collection<Long> componentIds = authorization.keepAuthorizedProjectIds(session, + Sets.newHashSet(PROJECT_ID, PROJECT_ID_WITHOUT_SNAPSHOT), + USER, "user"); + + assertThat(componentIds).containsOnly(PROJECT_ID, PROJECT_ID_WITHOUT_SNAPSHOT); + + // user does not have the role "admin" + componentIds = authorization.keepAuthorizedProjectIds(session, + Sets.newHashSet(PROJECT_ID), + USER, "admin"); + assertThat(componentIds).isEmpty(); + + assertThat(authorization.keepAuthorizedProjectIds(session, + Collections.<Long>emptySet(), + USER, "admin")).isEmpty(); + } + + @Test + public void keep_authorized_project_ids_for_user() { + setupData("keep_authorized_project_ids_for_user"); + + assertThat(authorization.keepAuthorizedProjectIds(session, Sets.newHashSet(PROJECT_ID, PROJECT_ID_WITHOUT_SNAPSHOT), USER, "user")).containsOnly(PROJECT_ID); + + // user does not have the role "admin" + assertThat(authorization.keepAuthorizedProjectIds(session, Sets.newHashSet(PROJECT_ID), USER, "admin")).isEmpty(); + + // Empty list + assertThat(authorization.keepAuthorizedProjectIds(session, Collections.<Long>emptySet(), USER, "admin")).isEmpty(); + } + + @Test + public void keep_authorized_project_ids_for_group() { + setupData("keep_authorized_project_ids_for_group"); + + assertThat(authorization.keepAuthorizedProjectIds(session, Sets.newHashSet(PROJECT_ID, PROJECT_ID_WITHOUT_SNAPSHOT), USER, "user")).containsOnly(PROJECT_ID); + + // user does not have the role "admin" + assertThat(authorization.keepAuthorizedProjectIds(session, Sets.newHashSet(PROJECT_ID), USER, "admin")).isEmpty(); + + // Empty list + assertThat(authorization.keepAuthorizedProjectIds(session, Collections.<Long>emptySet(), USER, "admin")).isEmpty(); + } + + @Test + public void keep_authorized_project_ids_for_anonymous() { + setupData("keep_authorized_project_ids_for_anonymous"); + + assertThat(authorization.keepAuthorizedProjectIds(session, Sets.newHashSet(PROJECT_ID, PROJECT_ID_WITHOUT_SNAPSHOT), null, "user")).containsOnly(PROJECT_ID); + + // user does not have the role "admin" + assertThat(authorization.keepAuthorizedProjectIds(session, Sets.newHashSet(PROJECT_ID), null, "admin")).isEmpty(); + + // Empty list + assertThat(authorization.keepAuthorizedProjectIds(session, Collections.<Long>emptySet(), null, "admin")).isEmpty(); + } + + @Test + public void is_authorized_component_key_for_user() { + setupData("keep_authorized_project_ids_for_user"); + + assertThat(authorization.isAuthorizedComponentKey(PROJECT, USER, "user")).isTrue(); + assertThat(authorization.isAuthorizedComponentKey(PROJECT_WIHOUT_SNAPSHOT, USER, "user")).isFalse(); + + // user does not have the role "admin" + assertThat(authorization.isAuthorizedComponentKey(PROJECT, USER, "admin")).isFalse(); + } + + @Test + public void is_authorized_component_key_for_group() { + setupData("keep_authorized_project_ids_for_group"); + + assertThat(authorization.isAuthorizedComponentKey(PROJECT, USER, "user")).isTrue(); + assertThat(authorization.isAuthorizedComponentKey(PROJECT_WIHOUT_SNAPSHOT, USER, "user")).isFalse(); + + // user does not have the role "admin" + assertThat(authorization.isAuthorizedComponentKey(PROJECT, USER, "admin")).isFalse(); + } + + @Test + public void is_authorized_component_key_for_anonymous() { + setupData("keep_authorized_project_ids_for_anonymous"); + + assertThat(authorization.isAuthorizedComponentKey(PROJECT, null, "user")).isTrue(); + assertThat(authorization.isAuthorizedComponentKey(PROJECT_WIHOUT_SNAPSHOT, null, "user")).isFalse(); + assertThat(authorization.isAuthorizedComponentKey(PROJECT, null, "admin")).isFalse(); + } + + @Test + public void group_should_be_authorized() { + // user is in an authorized group + setupData("group_should_be_authorized"); + + Collection<Long> componentIds = authorization.keepAuthorizedProjectIds(session, + Sets.newHashSet(PROJECT_ID, PROJECT_ID_WITHOUT_SNAPSHOT), + USER, "user"); + + assertThat(componentIds).containsOnly(PROJECT_ID, PROJECT_ID_WITHOUT_SNAPSHOT); + + // group does not have the role "admin" + componentIds = authorization.keepAuthorizedProjectIds(session, + Sets.newHashSet(PROJECT_ID, PROJECT_ID_WITHOUT_SNAPSHOT), + USER, "admin"); + assertThat(componentIds).isEmpty(); + } + + @Test + public void anonymous_should_be_authorized() { + setupData("anonymous_should_be_authorized"); + + Collection<Long> componentIds = authorization.keepAuthorizedProjectIds(session, + Sets.newHashSet(PROJECT_ID, PROJECT_ID_WITHOUT_SNAPSHOT), + null, "user"); + + assertThat(componentIds).containsOnly(PROJECT_ID, PROJECT_ID_WITHOUT_SNAPSHOT); + + // group does not have the role "admin" + componentIds = authorization.keepAuthorizedProjectIds(session, + Sets.newHashSet(PROJECT_ID), + null, "admin"); + assertThat(componentIds).isEmpty(); + } + + @Test + public void should_return_root_project_keys_for_user() { + setupData("should_return_root_project_keys_for_user"); + + Collection<String> rootProjectIds = authorization.selectAuthorizedRootProjectsKeys(USER, "user"); + + assertThat(rootProjectIds).containsOnly(PROJECT); + + // user does not have the role "admin" + rootProjectIds = authorization.selectAuthorizedRootProjectsKeys(USER, "admin"); + assertThat(rootProjectIds).isEmpty(); + } + + @Test + public void should_return_root_project_keys_for_group() { + // but user is not in an authorized group + setupData("should_return_root_project_keys_for_group"); + + Collection<String> rootProjectIds = authorization.selectAuthorizedRootProjectsKeys(USER, "user"); + + assertThat(rootProjectIds).containsOnly(PROJECT); + + // user does not have the role "admin" + rootProjectIds = authorization.selectAuthorizedRootProjectsKeys(USER, "admin"); + assertThat(rootProjectIds).isEmpty(); + } + + @Test + public void should_return_root_project_keys_for_anonymous() { + setupData("should_return_root_project_keys_for_anonymous"); + + Collection<String> rootProjectIds = authorization.selectAuthorizedRootProjectsKeys(null, "user"); + + assertThat(rootProjectIds).containsOnly(PROJECT); + + // group does not have the role "admin" + rootProjectIds = authorization.selectAuthorizedRootProjectsKeys(null, "admin"); + assertThat(rootProjectIds).isEmpty(); + } + + @Test + public void should_return_root_project_uuids_for_user() { + setupData("should_return_root_project_keys_for_user"); + + Collection<String> rootProjectUuids = authorization.selectAuthorizedRootProjectsUuids(USER, "user"); + + assertThat(rootProjectUuids).containsOnly("ABCD"); + + // user does not have the role "admin" + rootProjectUuids = authorization.selectAuthorizedRootProjectsKeys(USER, "admin"); + assertThat(rootProjectUuids).isEmpty(); + } + + @Test + public void should_return_root_project_uuids_for_group() { + // but user is not in an authorized group + setupData("should_return_root_project_keys_for_group"); + + Collection<String> rootProjectUuids = authorization.selectAuthorizedRootProjectsUuids(USER, "user"); + + assertThat(rootProjectUuids).containsOnly("ABCD"); + + // user does not have the role "admin" + rootProjectUuids = authorization.selectAuthorizedRootProjectsKeys(USER, "admin"); + assertThat(rootProjectUuids).isEmpty(); + } + + @Test + public void should_return_root_project_uuids_for_anonymous() { + setupData("should_return_root_project_keys_for_anonymous"); + + Collection<String> rootProjectUuids = authorization.selectAuthorizedRootProjectsUuids(null, "user"); + + assertThat(rootProjectUuids).containsOnly("ABCD"); + + // group does not have the role "admin" + rootProjectUuids = authorization.selectAuthorizedRootProjectsKeys(null, "admin"); + assertThat(rootProjectUuids).isEmpty(); + } + + @Test + public void should_return_user_global_permissions() { + setupData("should_return_user_global_permissions"); + + assertThat(authorization.selectGlobalPermissions("john")).containsOnly("user", "admin"); + assertThat(authorization.selectGlobalPermissions("arthur")).containsOnly("user"); + assertThat(authorization.selectGlobalPermissions("none")).isEmpty(); + } + + @Test + public void should_return_group_global_permissions() { + setupData("should_return_group_global_permissions"); + + assertThat(authorization.selectGlobalPermissions("john")).containsOnly("user", "admin"); + assertThat(authorization.selectGlobalPermissions("arthur")).containsOnly("user"); + assertThat(authorization.selectGlobalPermissions("none")).isEmpty(); + } + + @Test + public void should_return_global_permissions_for_anonymous() { + setupData("should_return_global_permissions_for_anonymous"); + + assertThat(authorization.selectGlobalPermissions(null)).containsOnly("user", "admin"); + } + + @Test + public void should_return_global_permissions_for_group_anyone() { + setupData("should_return_global_permissions_for_group_anyone"); + + assertThat(authorization.selectGlobalPermissions("anyone_user")).containsOnly("user", "profileadmin"); + } + +} diff --git a/sonar-db/src/test/java/org/sonar/db/user/GroupDtoTest.java b/sonar-db/src/test/java/org/sonar/db/user/GroupDtoTest.java new file mode 100644 index 00000000000..35d79814cfc --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/user/GroupDtoTest.java @@ -0,0 +1,42 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.user; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class GroupDtoTest { + + @Test + public void getter_and_setter() { + GroupDto dto = new GroupDto() + .setId(1L) + .setName("sonar-users") + .setDescription("Sonar users"); + + assertThat(dto.getKey()).isEqualTo("sonar-users"); + assertThat(dto.getName()).isEqualTo("sonar-users"); + assertThat(dto.getId()).isEqualTo(1L); + assertThat(dto.getDescription()).isEqualTo("Sonar users"); + } + +} diff --git a/sonar-db/src/test/java/org/sonar/db/user/GroupMembershipDaoTest.java b/sonar-db/src/test/java/org/sonar/db/user/GroupMembershipDaoTest.java new file mode 100644 index 00000000000..f5327223d39 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/user/GroupMembershipDaoTest.java @@ -0,0 +1,299 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.user; + +import com.google.common.collect.Multimap; +import java.util.Arrays; +import java.util.List; +import org.junit.After; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.sonar.db.DbSession; +import org.sonar.db.DbTester; +import org.sonar.db.MyBatis; +import org.sonar.test.DbTests; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.data.MapEntry.entry; + +@Category(DbTests.class) +public class GroupMembershipDaoTest { + + @ClassRule + public static final DbTester dbTester = new DbTester(); + + private GroupMembershipDao dao; + + private DbSession dbSession; + + @Before + public void setUp() { + dbTester.truncateTables(); + dao = new GroupMembershipDao(dbTester.myBatis()); + dbSession = dbTester.myBatis().openSession(false); + } + + @After + public void tearDown() { + MyBatis.closeQuietly(dbSession); + } + + @Test + public void select_all_groups_by_query() { + dbTester.prepareDbUnit(getClass(), "shared.xml"); + + GroupMembershipQuery query = GroupMembershipQuery.builder().login("arthur").build(); + List<GroupMembershipDto> result = dao.selectGroups(query, 200L); + assertThat(result).hasSize(3); + } + + @Test + public void select_user_group() { + dbTester.prepareDbUnit(getClass(), "select_user_group.xml"); + + GroupMembershipQuery query = GroupMembershipQuery.builder().login("arthur").build(); + List<GroupMembershipDto> result = dao.selectGroups(query, 201L); + assertThat(result).hasSize(1); + + GroupMembershipDto dto = result.get(0); + assertThat(dto.getId()).isEqualTo(101L); + assertThat(dto.getName()).isEqualTo("sonar-users"); + assertThat(dto.getDescription()).isEqualTo("Any new users created will automatically join this group"); + assertThat(dto.getUserId()).isEqualTo(201L); + } + + @Test + public void select_user_groups_by_query() { + dbTester.prepareDbUnit(getClass(), "shared.xml"); + + // 200 is member of 3 groups + assertThat(dao.selectGroups(GroupMembershipQuery.builder().login("arthur").membership(GroupMembershipQuery.IN).build(), 200L)).hasSize(3); + // 201 is member of 1 group on 3 + assertThat(dao.selectGroups(GroupMembershipQuery.builder().login("arthur").membership(GroupMembershipQuery.IN).build(), 201L)).hasSize(1); + // 999 is member of 0 group + assertThat(dao.selectGroups(GroupMembershipQuery.builder().login("arthur").membership(GroupMembershipQuery.IN).build(), 999L)).isEmpty(); + } + + @Test + public void select_groups_not_affected_to_a_user_by_query() { + dbTester.prepareDbUnit(getClass(), "shared.xml"); + + // 200 is member of 3 groups + assertThat(dao.selectGroups(GroupMembershipQuery.builder().login("arthur").membership(GroupMembershipQuery.OUT).build(), 200L)).isEmpty(); + // 201 is member of 1 group on 3 + assertThat(dao.selectGroups(GroupMembershipQuery.builder().login("arthur").membership(GroupMembershipQuery.OUT).build(), 201L)).hasSize(2); + // 999 is member of 0 group + assertThat(dao.selectGroups(GroupMembershipQuery.builder().login("arthur").membership(GroupMembershipQuery.OUT).build(), 2999L)).hasSize(3); + } + + @Test + public void search_by_group_name() { + dbTester.prepareDbUnit(getClass(), "shared.xml"); + + List<GroupMembershipDto> result = dao.selectGroups(GroupMembershipQuery.builder().login("arthur").groupSearch("user").build(), 200L); + assertThat(result).hasSize(1); + + assertThat(result.get(0).getName()).isEqualTo("sonar-users"); + + result = dao.selectGroups(GroupMembershipQuery.builder().login("arthur").groupSearch("sonar").build(), 200L); + assertThat(result).hasSize(3); + } + + @Test + public void search_by_group_name_with_capitalization() { + dbTester.prepareDbUnit(getClass(), "shared.xml"); + + List<GroupMembershipDto> result = dao.selectGroups(GroupMembershipQuery.builder().login("arthur").groupSearch("UsER").build(), 200L); + assertThat(result).hasSize(1); + + assertThat(result.get(0).getName()).isEqualTo("sonar-users"); + + result = dao.selectGroups(GroupMembershipQuery.builder().login("arthur").groupSearch("sonar").build(), 200L); + assertThat(result).hasSize(3); + } + + @Test + public void should_be_sorted_by_group_name() { + dbTester.prepareDbUnit(getClass(), "should_be_sorted_by_group_name.xml"); + + List<GroupMembershipDto> result = dao.selectGroups(GroupMembershipQuery.builder().login("arthur").build(), 200L); + assertThat(result).hasSize(3); + assertThat(result.get(0).getName()).isEqualTo("sonar-administrators"); + assertThat(result.get(1).getName()).isEqualTo("sonar-reviewers"); + assertThat(result.get(2).getName()).isEqualTo("sonar-users"); + } + + @Test + public void should_be_paginated() { + dbTester.prepareDbUnit(getClass(), "shared.xml"); + + List<GroupMembershipDto> result = dao.selectGroups(GroupMembershipQuery.builder().login("arthur").build(), 200L, 0, 2); + assertThat(result).hasSize(2); + assertThat(result.get(0).getName()).isEqualTo("sonar-administrators"); + assertThat(result.get(1).getName()).isEqualTo("sonar-reviewers"); + + result = dao.selectGroups(GroupMembershipQuery.builder().login("arthur").build(), 200L, 1, 2); + assertThat(result).hasSize(2); + assertThat(result.get(0).getName()).isEqualTo("sonar-reviewers"); + assertThat(result.get(1).getName()).isEqualTo("sonar-users"); + + result = dao.selectGroups(GroupMembershipQuery.builder().login("arthur").build(), 200L, 2, 1); + assertThat(result).hasSize(1); + assertThat(result.get(0).getName()).isEqualTo("sonar-users"); + } + + @Test + public void count_groups() { + dbTester.prepareDbUnit(getClass(), "shared.xml"); + + // 200 is member of 3 groups + assertThat(dao.countGroups(dbSession, GroupMembershipQuery.builder().login("arthur").membership(GroupMembershipQuery.IN).build(), 200L)).isEqualTo(3); + assertThat(dao.countGroups(dbSession, GroupMembershipQuery.builder().login("arthur").membership(GroupMembershipQuery.OUT).build(), 200L)).isZero(); + // 201 is member of 1 group on 3 + assertThat(dao.countGroups(dbSession, GroupMembershipQuery.builder().login("arthur").membership(GroupMembershipQuery.IN).build(), 201L)).isEqualTo(1); + assertThat(dao.countGroups(dbSession, GroupMembershipQuery.builder().login("arthur").membership(GroupMembershipQuery.OUT).build(), 201L)).isEqualTo(2); + // 999 is member of 0 group + assertThat(dao.countGroups(dbSession, GroupMembershipQuery.builder().login("arthur").membership(GroupMembershipQuery.IN).build(), 999L)).isZero(); + assertThat(dao.countGroups(dbSession, GroupMembershipQuery.builder().login("arthur").membership(GroupMembershipQuery.OUT).build(), 2999L)).isEqualTo(3); + } + + @Test + public void count_users_by_group() { + dbTester.prepareDbUnit(getClass(), "shared_plus_empty_group.xml"); + + assertThat(dao.countUsersByGroups(dbSession, Arrays.asList(100L, 101L, 102L, 103L))).containsOnly( + entry("sonar-users", 2), entry("sonar-reviewers", 1), entry("sonar-administrators", 1), entry("sonar-nobody", 0)); + assertThat(dao.countUsersByGroups(dbSession, Arrays.asList(100L, 103L))).containsOnly( + entry("sonar-administrators", 1), entry("sonar-nobody", 0)); + } + + @Test + public void count_groups_by_login() { + dbTester.prepareDbUnit(getClass(), "shared.xml"); + + assertThat(dao.selectGroupsByLogins(dbSession, Arrays.<String>asList()).keys()).isEmpty(); + Multimap<String, String> groupsByLogin = dao.selectGroupsByLogins(dbSession, Arrays.asList("two-hundred", "two-hundred-one", "two-hundred-two")); + assertThat(groupsByLogin.get("two-hundred")).containsOnly("sonar-administrators", "sonar-users", "sonar-reviewers"); + assertThat(groupsByLogin.get("two-hundred-one")).containsOnly("sonar-users"); + assertThat(groupsByLogin.get("two-hundred-two")).isEmpty(); + } + + @Test + public void count_members() { + dbTester.prepareDbUnit(getClass(), "shared_plus_empty_group.xml"); + + // 100 has 1 member and 1 non member + assertThat(dao.countMembers(dbSession, UserMembershipQuery.builder().groupId(100L).membership(UserMembershipQuery.IN).build())).isEqualTo(1); + assertThat(dao.countMembers(dbSession, UserMembershipQuery.builder().groupId(100L).membership(UserMembershipQuery.OUT).build())).isEqualTo(1); + // 101 has 2 members + assertThat(dao.countMembers(dbSession, UserMembershipQuery.builder().groupId(101L).membership(UserMembershipQuery.IN).build())).isEqualTo(2); + assertThat(dao.countMembers(dbSession, UserMembershipQuery.builder().groupId(101L).membership(UserMembershipQuery.OUT).build())).isZero(); + // 102 has 1 member and 1 non member + assertThat(dao.countMembers(dbSession, UserMembershipQuery.builder().groupId(102L).membership(UserMembershipQuery.IN).build())).isEqualTo(1); + assertThat(dao.countMembers(dbSession, UserMembershipQuery.builder().groupId(102L).membership(UserMembershipQuery.OUT).build())).isEqualTo(1); + // 103 has no member + assertThat(dao.countMembers(dbSession, UserMembershipQuery.builder().groupId(103L).membership(UserMembershipQuery.IN).build())).isZero(); + assertThat(dao.countMembers(dbSession, UserMembershipQuery.builder().groupId(103L).membership(UserMembershipQuery.OUT).build())).isEqualTo(2); + } + + @Test + public void select_group_members_by_query() { + dbTester.prepareDbUnit(getClass(), "shared_plus_empty_group.xml"); + + // 100 has 1 member + assertThat(dao.selectMembers(dbSession, UserMembershipQuery.builder().groupId(100L).membership(UserMembershipQuery.IN).build(), 0, 10)).hasSize(1); + // 101 has 2 members + assertThat(dao.selectMembers(dbSession, UserMembershipQuery.builder().groupId(101L).membership(UserMembershipQuery.IN).build(), 0, 10)).hasSize(2); + // 102 has 1 member + assertThat(dao.selectMembers(dbSession, UserMembershipQuery.builder().groupId(102L).membership(UserMembershipQuery.IN).build(), 0, 10)).hasSize(1); + // 103 has no member + assertThat(dao.selectMembers(dbSession, UserMembershipQuery.builder().groupId(103L).membership(UserMembershipQuery.IN).build(), 0, 10)).isEmpty(); + } + + @Test + public void select_users_not_affected_to_a_group_by_query() { + dbTester.prepareDbUnit(getClass(), "shared_plus_empty_group.xml"); + + // 100 has 1 member + assertThat(dao.selectMembers(dbSession, UserMembershipQuery.builder().groupId(100L).membership(UserMembershipQuery.OUT).build(), 0, 10)).hasSize(1); + // 101 has 2 members + assertThat(dao.selectMembers(dbSession, UserMembershipQuery.builder().groupId(101L).membership(UserMembershipQuery.OUT).build(), 0, 10)).isEmpty(); + // 102 has 1 member + assertThat(dao.selectMembers(dbSession, UserMembershipQuery.builder().groupId(102L).membership(UserMembershipQuery.OUT).build(), 0, 10)).hasSize(1); + // 103 has no member + assertThat(dao.selectMembers(dbSession, UserMembershipQuery.builder().groupId(103L).membership(UserMembershipQuery.OUT).build(), 0, 10)).hasSize(2); + } + + @Test + public void search_by_user_name_or_login() { + dbTester.prepareDbUnit(getClass(), "shared_plus_empty_group.xml"); + + List<UserMembershipDto> result = dao.selectMembers(dbSession, UserMembershipQuery.builder().groupId(100L).memberSearch("admin").build(), 0, 10); + assertThat(result).hasSize(2); + + assertThat(result.get(0).getName()).isEqualTo("Admin"); + assertThat(result.get(1).getName()).isEqualTo("Not Admin"); + + result = dao.selectMembers(dbSession, UserMembershipQuery.builder().groupId(100L).memberSearch("not").build(), 0, 10); + assertThat(result).hasSize(1); + } + + @Test + public void search_by_login_or_name_with_capitalization() { + dbTester.prepareDbUnit(getClass(), "shared_plus_empty_group.xml"); + + List<UserMembershipDto> result = dao.selectMembers(dbSession, UserMembershipQuery.builder().groupId(100L).memberSearch("admin").build(), 0, 10); + assertThat(result).hasSize(2); + + result = dao.selectMembers(dbSession, UserMembershipQuery.builder().groupId(100L).memberSearch("AdMiN").build(), 0, 10); + assertThat(result).hasSize(2); + + } + + @Test + public void should_be_sorted_by_user_name() { + dbTester.prepareDbUnit(getClass(), "shared_plus_empty_group.xml"); + + List<UserMembershipDto> result = dao.selectMembers(dbSession, UserMembershipQuery.builder().groupId(100L).build(), 0, 10); + assertThat(result).hasSize(2); + assertThat(result.get(0).getName()).isEqualTo("Admin"); + assertThat(result.get(1).getName()).isEqualTo("Not Admin"); + } + + @Test + public void members_should_be_paginated() { + dbTester.prepareDbUnit(getClass(), "shared_plus_empty_group.xml"); + + List<UserMembershipDto> result = dao.selectMembers(dbSession, UserMembershipQuery.builder().groupId(100L).build(), 0, 2); + assertThat(result).hasSize(2); + assertThat(result.get(0).getName()).isEqualTo("Admin"); + assertThat(result.get(1).getName()).isEqualTo("Not Admin"); + + result = dao.selectMembers(dbSession, UserMembershipQuery.builder().groupId(100L).build(), 1, 2); + assertThat(result).hasSize(1); + assertThat(result.get(0).getName()).isEqualTo("Not Admin"); + + result = dao.selectMembers(dbSession, UserMembershipQuery.builder().groupId(100L).build(), 2, 1); + assertThat(result).isEmpty(); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/user/GroupMembershipDtoTest.java b/sonar-db/src/test/java/org/sonar/db/user/GroupMembershipDtoTest.java new file mode 100644 index 00000000000..c8a1dadb4c3 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/user/GroupMembershipDtoTest.java @@ -0,0 +1,60 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.user; + +import org.junit.Test; +import org.sonar.core.user.GroupMembership; + +import static org.assertj.core.api.Assertions.assertThat; + +public class GroupMembershipDtoTest { + + @Test + public void to_group_with_permission_having_permission() { + GroupMembership group = new GroupMembershipDto() + .setId(1L) + .setName("users") + .setDescription("description") + .setUserId(10L) + .toGroupMembership(); + + assertThat(group.id()).isEqualTo(1); + assertThat(group.name()).isEqualTo("users"); + assertThat(group.description()).isEqualTo("description"); + assertThat(group.isMember()).isTrue(); + } + + @Test + public void to_group_with_permission_not_having_permission() { + GroupMembership group = new GroupMembershipDto() + .setId(1L) + .setName("users") + .setDescription("description") + .setUserId(null) + .toGroupMembership(); + + assertThat(group.id()).isEqualTo(1); + assertThat(group.name()).isEqualTo("users"); + assertThat(group.description()).isEqualTo("description"); + assertThat(group.isMember()).isFalse(); + } + +} diff --git a/sonar-db/src/test/java/org/sonar/db/user/GroupMembershipQueryTest.java b/sonar-db/src/test/java/org/sonar/db/user/GroupMembershipQueryTest.java new file mode 100644 index 00000000000..3edbcf430ef --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/user/GroupMembershipQueryTest.java @@ -0,0 +1,57 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.user; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.fail; + +public class GroupMembershipQueryTest { + + @Test + public void fail_on_null_login() { + GroupMembershipQuery.Builder builder = GroupMembershipQuery.builder(); + builder.login(null); + + try { + builder.build(); + fail(); + } catch (Exception e) { + assertThat(e).isInstanceOf(NullPointerException.class).hasMessage("User login cant be null."); + } + } + + @Test + public void fail_on_invalid_membership() { + GroupMembershipQuery.Builder builder = GroupMembershipQuery.builder(); + builder.login("nelson"); + builder.membership("unknwown"); + + try { + builder.build(); + fail(); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("Membership is not valid (got unknwown). Availables values are [ANY, IN, OUT]"); + } + } + +} diff --git a/sonar-db/src/test/java/org/sonar/db/user/GroupMembershipTest.java b/sonar-db/src/test/java/org/sonar/db/user/GroupMembershipTest.java new file mode 100644 index 00000000000..9838d364417 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/user/GroupMembershipTest.java @@ -0,0 +1,52 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.user; + +import org.junit.Test; +import org.sonar.core.user.GroupMembership; + +import static org.assertj.core.api.Assertions.assertThat; + +public class GroupMembershipTest { + + @Test + public void test_setters_and_getters() throws Exception { + GroupMembership group = new GroupMembership() + .setId(1L) + .setName("users") + .setMember(true); + + assertThat(group.id()).isEqualTo(1L); + assertThat(group.name()).isEqualTo("users"); + assertThat(group.isMember()).isTrue(); + } + + @Test + public void test_equals() throws Exception { + assertThat(new GroupMembership().setName("users")).isEqualTo(new GroupMembership().setName("users")); + assertThat(new GroupMembership().setName("users")).isNotEqualTo(new GroupMembership().setName("reviewers")); + + GroupMembership group = new GroupMembership() + .setId(1L) + .setName("users") + .setMember(true); + assertThat(group).isEqualTo(group); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/user/RoleDaoTest.java b/sonar-db/src/test/java/org/sonar/db/user/RoleDaoTest.java new file mode 100644 index 00000000000..df2470f74f7 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/user/RoleDaoTest.java @@ -0,0 +1,152 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.user; + +import org.junit.After; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.sonar.api.security.DefaultGroups; +import org.sonar.api.web.UserRole; +import org.sonar.core.permission.GlobalPermissions; +import org.sonar.db.DbSession; +import org.sonar.db.DbTester; +import org.sonar.test.DbTests; + +import static org.assertj.core.api.Assertions.assertThat; + +@Category(DbTests.class) +public class RoleDaoTest { + + @ClassRule + public static final DbTester dbTester = new DbTester(); + + DbSession session; + + RoleDao dao; + + @Before + public void setUp() { + dbTester.truncateTables(); + session = dbTester.myBatis().openSession(false); + dao = new RoleDao(); + } + + @After + public void tearDown() { + session.close(); + } + + @Test + public void retrieve_global_user_permissions() { + dbTester.prepareDbUnit(getClass(), "globalUserPermissions.xml"); + + assertThat(dao.selectUserPermissions(session, "admin_user", null)).containsOnly(GlobalPermissions.SYSTEM_ADMIN, GlobalPermissions.QUALITY_PROFILE_ADMIN); + assertThat(dao.selectUserPermissions(session, "profile_admin_user", null)).containsOnly(GlobalPermissions.QUALITY_PROFILE_ADMIN); + } + + @Test + public void retrieve_resource_user_permissions() { + dbTester.prepareDbUnit(getClass(), "resourceUserPermissions.xml"); + + assertThat(dao.selectUserPermissions(session, "admin_user", 1L)).containsOnly(UserRole.ADMIN, UserRole.USER); + assertThat(dao.selectUserPermissions(session, "browse_admin_user", 1L)).containsOnly(UserRole.USER); + } + + @Test + public void retrieve_global_group_permissions() { + dbTester.prepareDbUnit(getClass(), "globalGroupPermissions.xml"); + + assertThat(dao.selectGroupPermissions(session, "sonar-administrators", null)).containsOnly(GlobalPermissions.SYSTEM_ADMIN, GlobalPermissions.QUALITY_PROFILE_ADMIN, + GlobalPermissions.DASHBOARD_SHARING); + assertThat(dao.selectGroupPermissions(session, "sonar-users", null)).containsOnly(GlobalPermissions.DASHBOARD_SHARING); + assertThat(dao.selectGroupPermissions(session, DefaultGroups.ANYONE, null)).containsOnly(GlobalPermissions.PREVIEW_EXECUTION, GlobalPermissions.SCAN_EXECUTION); + assertThat(dao.selectGroupPermissions(session, "anyone", null)).containsOnly(GlobalPermissions.PREVIEW_EXECUTION, GlobalPermissions.SCAN_EXECUTION); + assertThat(dao.selectGroupPermissions(session, "AnYoNe", null)).containsOnly(GlobalPermissions.PREVIEW_EXECUTION, GlobalPermissions.SCAN_EXECUTION); + } + + @Test + public void retrieve_resource_group_permissions() { + dbTester.prepareDbUnit(getClass(), "resourceGroupPermissions.xml"); + + assertThat(dao.selectGroupPermissions(session, "sonar-administrators", 1L)).containsOnly(UserRole.ADMIN, UserRole.CODEVIEWER); + assertThat(dao.selectGroupPermissions(session, "sonar-users", 1L)).containsOnly(UserRole.CODEVIEWER); + } + + @Test + public void delete_global_user_permission() { + dbTester.prepareDbUnit(getClass(), "globalUserPermissions.xml"); + + UserRoleDto userRoleToDelete = new UserRoleDto().setUserId(200L).setRole(GlobalPermissions.QUALITY_PROFILE_ADMIN); + + dao.deleteUserRole(userRoleToDelete, session); + session.commit(); + + dbTester.assertDbUnit(getClass(), "globalUserPermissions-result.xml", "user_roles"); + } + + @Test + public void delete_resource_user_permission() { + dbTester.prepareDbUnit(getClass(), "resourceUserPermissions.xml"); + + UserRoleDto userRoleToDelete = new UserRoleDto().setUserId(200L).setRole(UserRole.USER).setResourceId(1L); + + dao.deleteUserRole(userRoleToDelete, session); + session.commit(); + + dbTester.assertDbUnit(getClass(), "resourceUserPermissions-result.xml", "user_roles"); + } + + @Test + public void delete_global_group_permission() { + dbTester.prepareDbUnit(getClass(), "globalGroupPermissions.xml"); + + GroupRoleDto groupRoleToDelete = new GroupRoleDto().setGroupId(100L).setRole(GlobalPermissions.QUALITY_PROFILE_ADMIN); + + dao.deleteGroupRole(groupRoleToDelete, session); + session.commit(); + + dbTester.assertDbUnit(getClass(), "globalGroupPermissions-result.xml", "group_roles"); + } + + @Test + public void delete_resource_group_permission() { + dbTester.prepareDbUnit(getClass(), "resourceGroupPermissions.xml"); + + GroupRoleDto groupRoleToDelete = new GroupRoleDto().setGroupId(100L).setRole(UserRole.CODEVIEWER).setResourceId(1L); + + dao.deleteGroupRole(groupRoleToDelete, session); + session.commit(); + + dbTester.assertDbUnit(getClass(), "resourceGroupPermissions-result.xml", "group_roles"); + } + + @Test + public void delete_all_group_permissions_by_group_id() { + dbTester.prepareDbUnit(getClass(), "deleteGroupPermissionsByGroupId.xml"); + + dao.deleteGroupRolesByGroupId(session, 100L); + session.commit(); + + dbTester.assertDbUnit(getClass(), "deleteGroupPermissionsByGroupId-result.xml", "group_roles"); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/user/RoleMapperTest.java b/sonar-db/src/test/java/org/sonar/db/user/RoleMapperTest.java new file mode 100644 index 00000000000..8c7f671c029 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/user/RoleMapperTest.java @@ -0,0 +1,78 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.user; + +import org.apache.ibatis.session.SqlSession; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.sonar.db.AbstractDaoTestCase; +import org.sonar.db.MyBatis; + +import static org.assertj.core.api.Assertions.assertThat; + +public class RoleMapperTest extends AbstractDaoTestCase { + + private SqlSession session; + + @Before + public void openSession() { + session = getMyBatis().openSession(); + } + + @After + public void closeSession() { + MyBatis.closeQuietly(session); + } + + @Test + public void count_roles() { + setupData("countRoles"); + + RoleMapper mapper = session.getMapper(RoleMapper.class); + assertThat(mapper.countResourceGroupRoles(123L)).isEqualTo(2); + assertThat(mapper.countResourceUserRoles(123L)).isEqualTo(1); + } + + @Test + public void delete_roles_by_resource_id() { + setupData("deleteRolesByResourceId"); + + RoleMapper mapper = session.getMapper(RoleMapper.class); + mapper.deleteGroupRolesByResourceId(123L); + mapper.deleteUserRolesByResourceId(123L); + session.commit(); + + checkTables("deleteRolesByResourceId", "group_roles", "user_roles"); + } + + @Test + public void insert_roles() { + setupData("insertRoles"); + + RoleMapper mapper = session.getMapper(RoleMapper.class); + mapper.insertGroupRole(new GroupRoleDto().setRole("admin").setGroupId(100L).setResourceId(123L)); + mapper.insertGroupRole(new GroupRoleDto().setRole("user").setResourceId(123L));// Anyone + mapper.insertUserRole(new UserRoleDto().setRole("codeviewer").setUserId(200L).setResourceId(123L));// Anyone + session.commit(); + + checkTables("insertRoles", "group_roles", "user_roles"); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/user/UserDaoTest.java b/sonar-db/src/test/java/org/sonar/db/user/UserDaoTest.java new file mode 100644 index 00000000000..01536c72643 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/user/UserDaoTest.java @@ -0,0 +1,271 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.user; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.user.UserQuery; +import org.sonar.api.utils.DateUtils; +import org.sonar.api.utils.System2; +import org.sonar.db.AbstractDaoTestCase; +import org.sonar.db.DbSession; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class UserDaoTest extends AbstractDaoTestCase { + + UserDao dao; + + System2 system2; + + DbSession session; + + @Before + public void setUp() { + session = getMyBatis().openSession(false); + system2 = mock(System2.class); + dao = new UserDao(getMyBatis(), system2); + } + + @After + public void tearDown() { + session.close(); + } + + @Test + public void selectUserByLogin_ignore_inactive() { + setupData("selectActiveUserByLogin"); + + UserDto user = dao.getUser(50); + assertThat(user.getLogin()).isEqualTo("inactive_user"); + + user = dao.selectActiveUserByLogin("inactive_user"); + assertThat(user).isNull(); + } + + @Test + public void selectUserByLogin_not_found() { + setupData("selectActiveUserByLogin"); + + UserDto user = dao.selectActiveUserByLogin("not_found"); + assertThat(user).isNull(); + } + + @Test + public void selectUsersByLogins() { + setupData("selectUsersByLogins"); + + Collection<UserDto> users = dao.selectUsersByLogins(Arrays.asList("marius", "inactive_user", "other")); + assertThat(users).hasSize(2); + assertThat(users).extracting("login").containsOnly("marius", "inactive_user"); + } + + @Test + public void selectUsersByLogins_empty_logins() { + // no need to access db + Collection<UserDto> users = dao.selectUsersByLogins(Collections.<String>emptyList()); + assertThat(users).isEmpty(); + } + + @Test + public void selectUsersByQuery_all() { + setupData("selectUsersByQuery"); + + UserQuery query = UserQuery.builder().includeDeactivated().build(); + List<UserDto> users = dao.selectUsers(query); + assertThat(users).hasSize(2); + } + + @Test + public void selectUsersByQuery_only_actives() { + setupData("selectUsersByQuery"); + + UserQuery query = UserQuery.ALL_ACTIVES; + List<UserDto> users = dao.selectUsers(query); + assertThat(users).hasSize(1); + assertThat(users.get(0).getName()).isEqualTo("Marius"); + } + + @Test + public void selectUsersByQuery_filter_by_login() { + setupData("selectUsersByQuery"); + + UserQuery query = UserQuery.builder().logins("marius", "john").build(); + List<UserDto> users = dao.selectUsers(query); + assertThat(users).hasSize(1); + assertThat(users.get(0).getName()).isEqualTo("Marius"); + } + + @Test + public void selectUsersByQuery_search_by_login_text() { + setupData("selectUsersByText"); + + UserQuery query = UserQuery.builder().searchText("sbr").build(); + List<UserDto> users = dao.selectUsers(query); + assertThat(users).hasSize(1); + assertThat(users.get(0).getLogin()).isEqualTo("sbrandhof"); + } + + @Test + public void selectUsersByQuery_search_by_name_text() { + setupData("selectUsersByText"); + + UserQuery query = UserQuery.builder().searchText("Simon").build(); + List<UserDto> users = dao.selectUsers(query); + assertThat(users).hasSize(1); + assertThat(users.get(0).getLogin()).isEqualTo("sbrandhof"); + } + + @Test + public void selectUsersByQuery_escape_special_characters_in_like() { + setupData("selectUsersByText"); + + UserQuery query = UserQuery.builder().searchText("%s%").build(); + // we expect really a login or name containing the 3 characters "%s%" + + List<UserDto> users = dao.selectUsers(query); + assertThat(users).isEmpty(); + } + + @Test + public void selectGroupByName() { + setupData("selectGroupByName"); + + GroupDto group = dao.selectGroupByName("sonar-users"); + assertThat(group).isNotNull(); + assertThat(group.getId()).isEqualTo(1L); + assertThat(group.getName()).isEqualTo("sonar-users"); + assertThat(group.getDescription()).isEqualTo("Sonar Users"); + assertThat(group.getCreatedAt()).isNotNull(); + assertThat(group.getUpdatedAt()).isNotNull(); + } + + @Test + public void selectGroupByName_not_found() { + setupData("selectGroupByName"); + + GroupDto group = dao.selectGroupByName("not-found"); + assertThat(group).isNull(); + } + + @Test + public void insert_user() { + Long date = DateUtils.parseDate("2014-06-20").getTime(); + + UserDto userDto = new UserDto() + .setId(1L) + .setLogin("john") + .setName("John") + .setEmail("jo@hn.com") + .setScmAccounts(",jo.hn,john2,") + .setActive(true) + .setSalt("1234") + .setCryptedPassword("abcd") + .setCreatedAt(date) + .setUpdatedAt(date); + dao.insert(session, userDto); + session.commit(); + + UserDto user = dao.selectActiveUserByLogin("john"); + assertThat(user).isNotNull(); + assertThat(user.getId()).isNotNull(); + assertThat(user.getLogin()).isEqualTo("john"); + assertThat(user.getName()).isEqualTo("John"); + assertThat(user.getEmail()).isEqualTo("jo@hn.com"); + assertThat(user.isActive()).isTrue(); + assertThat(user.getScmAccounts()).isEqualTo(",jo.hn,john2,"); + assertThat(user.getSalt()).isEqualTo("1234"); + assertThat(user.getCryptedPassword()).isEqualTo("abcd"); + assertThat(user.getCreatedAt()).isEqualTo(date); + assertThat(user.getUpdatedAt()).isEqualTo(date); + } + + @Test + public void update_user() { + setupData("update_user"); + + Long date = DateUtils.parseDate("2014-06-21").getTime(); + + UserDto userDto = new UserDto() + .setId(1L) + .setLogin("john") + .setName("John Doo") + .setEmail("jodoo@hn.com") + .setScmAccounts(",jo.hn,john2,johndoo,") + .setActive(false) + .setSalt("12345") + .setCryptedPassword("abcde") + .setUpdatedAt(date); + dao.update(session, userDto); + session.commit(); + + UserDto user = dao.getUser(1); + assertThat(user).isNotNull(); + assertThat(user.getId()).isEqualTo(1L); + assertThat(user.getLogin()).isEqualTo("john"); + assertThat(user.getName()).isEqualTo("John Doo"); + assertThat(user.getEmail()).isEqualTo("jodoo@hn.com"); + assertThat(user.isActive()).isFalse(); + assertThat(user.getScmAccounts()).isEqualTo(",jo.hn,john2,johndoo,"); + assertThat(user.getSalt()).isEqualTo("12345"); + assertThat(user.getCryptedPassword()).isEqualTo("abcde"); + assertThat(user.getCreatedAt()).isEqualTo(1418215735482L); + assertThat(user.getUpdatedAt()).isEqualTo(date); + } + + @Test + public void deactivate_user() { + setupData("deactivate_user"); + + when(system2.now()).thenReturn(1500000000000L); + + String login = "marius"; + boolean deactivated = dao.deactivateUserByLogin(login); + assertThat(deactivated).isTrue(); + + assertThat(dao.selectActiveUserByLogin(login)).isNull(); + + UserDto userDto = dao.getUser(100); + assertThat(userDto.isActive()).isFalse(); + assertThat(userDto.getUpdatedAt()).isEqualTo(1500000000000L); + + checkTables("deactivate_user", + "dashboards", "active_dashboards", "groups_users", "issue_filters", + "issue_filter_favourites", "measure_filters", "measure_filter_favourites", + "properties", "user_roles"); + } + + @Test + public void deactivate_missing_user() { + setupData("deactivate_user"); + + String login = "does_not_exist"; + boolean deactivated = dao.deactivateUserByLogin(login); + assertThat(deactivated).isFalse(); + assertThat(dao.selectActiveUserByLogin(login)).isNull(); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/user/UserDtoTest.java b/sonar-db/src/test/java/org/sonar/db/user/UserDtoTest.java new file mode 100644 index 00000000000..74e21d9fe94 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/user/UserDtoTest.java @@ -0,0 +1,44 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.user; + +import java.util.Arrays; +import java.util.Collections; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class UserDtoTest { + + @Test + public void encode_scm_accounts() { + assertThat(UserDto.encodeScmAccounts(null)).isNull(); + assertThat(UserDto.encodeScmAccounts(Collections.<String>emptyList())).isNull(); + assertThat(UserDto.encodeScmAccounts(Arrays.asList("foo"))).isEqualTo("\nfoo\n"); + assertThat(UserDto.encodeScmAccounts(Arrays.asList("foo", "bar"))).isEqualTo("\nfoo\nbar\n"); + } + + @Test + public void decode_scm_accounts() { + assertThat(UserDto.decodeScmAccounts(null)).isEmpty(); + assertThat(UserDto.decodeScmAccounts("\nfoo\n")).containsOnly("foo"); + assertThat(UserDto.decodeScmAccounts("\nfoo\nbar\n")).containsOnly("foo", "bar"); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/version/DatabaseVersionTest.java b/sonar-db/src/test/java/org/sonar/db/version/DatabaseVersionTest.java new file mode 100644 index 00000000000..05f8f056bf2 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/version/DatabaseVersionTest.java @@ -0,0 +1,53 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.version; + +import org.junit.Test; +import org.sonar.db.AbstractDaoTestCase; + +import static org.assertj.core.api.Assertions.assertThat; + +public class DatabaseVersionTest extends AbstractDaoTestCase { + @Test + public void getVersion() { + setupData("getVersion"); + + Integer version = new DatabaseVersion(getMyBatis()).getVersion(); + + assertThat(version).isEqualTo(123); + } + + @Test + public void getVersion_no_rows() { + setupData("getVersion_no_rows"); + + Integer version = new DatabaseVersion(getMyBatis()).getVersion(); + + assertThat(version).isNull(); + } + + @Test + public void getStatus() { + assertThat(DatabaseVersion.getStatus(null, 150)).isEqualTo(DatabaseVersion.Status.FRESH_INSTALL); + assertThat(DatabaseVersion.getStatus(123, 150)).isEqualTo(DatabaseVersion.Status.REQUIRES_UPGRADE); + assertThat(DatabaseVersion.getStatus(150, 150)).isEqualTo(DatabaseVersion.Status.UP_TO_DATE); + assertThat(DatabaseVersion.getStatus(200, 150)).isEqualTo(DatabaseVersion.Status.REQUIRES_DOWNGRADE); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/version/v44/ChangeLogTest.java b/sonar-db/src/test/java/org/sonar/db/version/v44/ChangeLogTest.java new file mode 100644 index 00000000000..b260b793146 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/version/v44/ChangeLogTest.java @@ -0,0 +1,37 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.version.v44; + +import org.junit.Test; + +import static com.google.code.beanmatchers.BeanMatchers.hasValidBeanConstructor; +import static com.google.code.beanmatchers.BeanMatchers.hasValidGettersAndSetters; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.allOf; + +public class ChangeLogTest { + + @Test + public void test_bean() throws Exception { + assertThat(ChangeLog.class, allOf( + hasValidBeanConstructor(), + hasValidGettersAndSetters())); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/version/v44/ProfileMeasureTest.java b/sonar-db/src/test/java/org/sonar/db/version/v44/ProfileMeasureTest.java new file mode 100644 index 00000000000..050408aa4cd --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/version/v44/ProfileMeasureTest.java @@ -0,0 +1,37 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.version.v44; + +import org.junit.Test; + +import static com.google.code.beanmatchers.BeanMatchers.hasValidBeanConstructor; +import static com.google.code.beanmatchers.BeanMatchers.hasValidGettersAndSetters; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.allOf; + +public class ProfileMeasureTest { + + @Test + public void test_bean() throws Exception { + assertThat(ProfileMeasure.class, allOf( + hasValidBeanConstructor(), + hasValidGettersAndSetters())); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/version/v50/ComponentTest.java b/sonar-db/src/test/java/org/sonar/db/version/v50/ComponentTest.java new file mode 100644 index 00000000000..409d2b1b35b --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/version/v50/ComponentTest.java @@ -0,0 +1,37 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.db.version.v50; + +import org.junit.Test; + +import static com.google.code.beanmatchers.BeanMatchers.hasValidGettersAndSetters; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.allOf; + +public class ComponentTest { + + @Test + public void test_bean() throws Exception { + assertThat(Component.class, allOf( + hasValidGettersAndSetters())); + } + +} diff --git a/sonar-db/src/test/java/org/sonar/jpa/test/AbstractDbUnitTestCase.java b/sonar-db/src/test/java/org/sonar/jpa/test/AbstractDbUnitTestCase.java new file mode 100644 index 00000000000..d4743f578cc --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/jpa/test/AbstractDbUnitTestCase.java @@ -0,0 +1,229 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.jpa.test; + +import java.io.InputStream; +import java.sql.SQLException; +import org.apache.commons.io.IOUtils; +import org.apache.ibatis.session.SqlSession; +import org.dbunit.Assertion; +import org.dbunit.DataSourceDatabaseTester; +import org.dbunit.DatabaseUnitException; +import org.dbunit.IDatabaseTester; +import org.dbunit.database.DatabaseConfig; +import org.dbunit.database.IDatabaseConnection; +import org.dbunit.dataset.CompositeDataSet; +import org.dbunit.dataset.IDataSet; +import org.dbunit.dataset.ITable; +import org.dbunit.dataset.ReplacementDataSet; +import org.dbunit.dataset.filter.DefaultColumnFilter; +import org.dbunit.dataset.xml.FlatXmlDataSet; +import org.dbunit.ext.mssql.InsertIdentityOperation; +import org.dbunit.operation.DatabaseOperation; +import org.junit.Before; +import org.junit.BeforeClass; +import org.sonar.db.Database; +import org.sonar.db.DatabaseCommands; +import org.sonar.db.H2Database; +import org.sonar.db.MyBatis; +import org.sonar.db.deprecated.NullQueue; +import org.sonar.db.version.DatabaseVersion; +import org.sonar.db.version.SchemaMigrationMapper; + +import static org.junit.Assert.fail; + +/** + * @deprecated this class does not support non-H2 databases + */ +@Deprecated +public abstract class AbstractDbUnitTestCase { + private static Database database; + private static MyBatis myBatis; + private static DatabaseCommands databaseCommands; + private IDatabaseTester databaseTester; + + @BeforeClass + public static void startDatabase() throws SQLException { + if (database == null) { + database = new H2Database("sonarHibernate", true); + database.start(); + + databaseCommands = DatabaseCommands.forDialect(database.getDialect()); + + myBatis = new MyBatis(database, new NullQueue()); + myBatis.start(); + try (SqlSession session = myBatis.openSession(false)) { + session.getMapper(SchemaMigrationMapper.class).insert(String.valueOf(DatabaseVersion.LAST_VERSION)); + session.commit(); + } + } + } + + @Before + public void startDbUnit() throws Exception { + databaseCommands.truncateDatabase(database.getDataSource()); + databaseTester = new DataSourceDatabaseTester(database.getDataSource()); + } + + protected MyBatis getMyBatis() { + return myBatis; + } + + protected Database getDatabase() { + return database; + } + + protected void setupData(String... testNames) { + InputStream[] streams = new InputStream[testNames.length]; + try { + for (int i = 0; i < testNames.length; i++) { + String className = getClass().getName(); + className = String.format("/%s/%s.xml", className.replace(".", "/"), testNames[i]); + streams[i] = getClass().getResourceAsStream(className); + if (streams[i] == null) { + throw new RuntimeException("Test not found :" + className); + } + } + + setupData(streams); + databaseCommands.resetPrimaryKeys(database.getDataSource()); + } catch (SQLException e) { + throw translateException("Could not setup DBUnit data", e); + } finally { + for (InputStream stream : streams) { + IOUtils.closeQuietly(stream); + } + } + } + + private void setupData(InputStream... dataSetStream) { + IDatabaseConnection connection = null; + try { + IDataSet[] dataSets = new IDataSet[dataSetStream.length]; + for (int i = 0; i < dataSetStream.length; i++) { + dataSets[i] = getData(dataSetStream[i]); + } + databaseTester.setDataSet(new CompositeDataSet(dataSets)); + + connection = createConnection(); + + new InsertIdentityOperation(DatabaseOperation.INSERT).execute(connection, databaseTester.getDataSet()); + } catch (Exception e) { + throw translateException("Could not setup DBUnit data", e); + } finally { + closeQuietly(connection); + } + } + + private void closeQuietly(IDatabaseConnection connection) { + try { + if (connection != null) { + connection.close(); + } + } catch (SQLException ignored) { + + } + } + + protected void checkTables(String testName, String... tables) { + checkTables(testName, new String[0], tables); + } + + protected void checkTables(String testName, String[] excludedColumnNames, String... tables) { + IDatabaseConnection connection = null; + try { + connection = createConnection(); + + IDataSet dataSet = connection.createDataSet(); + IDataSet expectedDataSet = getExpectedData(testName); + for (String table : tables) { + ITable filteredTable = DefaultColumnFilter.excludedColumnsTable(dataSet.getTable(table), excludedColumnNames); + ITable filteredExpectedTable = DefaultColumnFilter.excludedColumnsTable(expectedDataSet.getTable(table), excludedColumnNames); + Assertion.assertEquals(filteredExpectedTable, filteredTable); + } + } catch (DatabaseUnitException e) { + fail(e.getMessage()); + } catch (SQLException e) { + throw translateException("Error while checking results", e); + } finally { + closeQuietly(connection); + } + } + + protected void checkTable(String testName, String table, String... columns) { + IDatabaseConnection connection = null; + try { + connection = createConnection(); + + IDataSet dataSet = connection.createDataSet(); + IDataSet expectedDataSet = getExpectedData(testName); + ITable filteredTable = DefaultColumnFilter.includedColumnsTable(dataSet.getTable(table), columns); + ITable filteredExpectedTable = DefaultColumnFilter.includedColumnsTable(expectedDataSet.getTable(table), columns); + Assertion.assertEquals(filteredExpectedTable, filteredTable); + + } catch (DatabaseUnitException e) { + fail(e.getMessage()); + } catch (SQLException e) { + throw translateException("Error while checking results", e); + } finally { + closeQuietly(connection); + } + } + + private IDatabaseConnection createConnection() { + try { + IDatabaseConnection connection = databaseTester.getConnection(); + connection.getConfig().setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, databaseCommands.getDbUnitFactory()); + return connection; + } catch (Exception e) { + throw translateException("Error while getting connection", e); + } + } + + private IDataSet getExpectedData(String testName) { + String className = getClass().getName(); + className = String.format("/%s/%s-result.xml", className.replace('.', '/'), testName); + + InputStream in = getClass().getResourceAsStream(className); + try { + return getData(in); + } finally { + IOUtils.closeQuietly(in); + } + } + + private IDataSet getData(InputStream stream) { + try { + ReplacementDataSet dataSet = new ReplacementDataSet(new FlatXmlDataSet(stream)); + dataSet.addReplacementObject("[null]", null); + dataSet.addReplacementObject("[false]", Boolean.FALSE); + dataSet.addReplacementObject("[true]", Boolean.TRUE); + return dataSet; + } catch (Exception e) { + throw translateException("Could not read the dataset stream", e); + } + } + + private static RuntimeException translateException(String msg, Exception cause) { + RuntimeException runtimeException = new RuntimeException(String.format("%s: [%s] %s", msg, cause.getClass().getName(), cause.getMessage())); + runtimeException.setStackTrace(cause.getStackTrace()); + return runtimeException; + } +} diff --git a/sonar-db/src/test/resources/logback-test.xml b/sonar-db/src/test/resources/logback-test.xml new file mode 100644 index 00000000000..4b0ff6da04b --- /dev/null +++ b/sonar-db/src/test/resources/logback-test.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<configuration> + + <appender name="STDOUT" + class="ch.qos.logback.core.ConsoleAppender"> + <encoder> + <pattern> + %d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n + </pattern> + </encoder> + </appender> + + <logger name="org.dbunit"> + <level value="WARN"/> + </logger> + + <!-- set to level DEBUG to log SQL requests executed by MyBatis --> + <logger name="java.sql"> + <level value="WARN"/> + </logger> + + <!-- required for DryRunDatabaseFactoryTest --> + <logger name="org.elasticsearch"> + <level value="WARN"/> + </logger> + + <root> + <level value="INFO"/> + <appender-ref ref="STDOUT"/> + </root> + +</configuration> diff --git a/sonar-db/src/test/resources/org/sonar/api/database/configuration/DatabaseConfigurationTest/some-properties.xml b/sonar-db/src/test/resources/org/sonar/api/database/configuration/DatabaseConfigurationTest/some-properties.xml new file mode 100644 index 00000000000..64c38fb55ea --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/api/database/configuration/DatabaseConfigurationTest/some-properties.xml @@ -0,0 +1,6 @@ +<dataset> + + <properties prop_key="key1" resource_id="[null]" text_value="value1" user_id="[null]"/> + <properties prop_key="key2" resource_id="[null]" text_value="value2" user_id="[null]"/> + +</dataset>
\ No newline at end of file diff --git a/sonar-db/src/test/resources/org/sonar/core/qualitymodel/DefaultModelFinderTest/shared.xml b/sonar-db/src/test/resources/org/sonar/core/qualitymodel/DefaultModelFinderTest/shared.xml new file mode 100644 index 00000000000..6e9cab1c815 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/core/qualitymodel/DefaultModelFinderTest/shared.xml @@ -0,0 +1,13 @@ +<dataset> + <quality_models id="1" name="M1"/> + <quality_models id="2" name="M2"/> + + <characteristics id="1" kee="M1C1" name="M1C1" parent_id="[null]" root_id="[null]" rule_id="[null]" + characteristic_order="1" enabled="true"/> + <characteristics id="2" kee="M1C2" name="M1C2" parent_id="[null]" root_id="[null]" ule_id="[null]" + characteristic_order="1" enabled="true"/> + <characteristics id="3" kee="M2C1" name="M2C1" parent_id="[null]" root_id="[null]" rule_id="[null]" + characteristic_order="1" enabled="true"/> + + <characteristic_edges child_id="2" parent_id="1"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/fail_when_no_default_template_is_defined.xml b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/fail_when_no_default_template_is_defined.xml new file mode 100644 index 00000000000..1fffc1facb2 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/fail_when_no_default_template_is_defined.xml @@ -0,0 +1,5 @@ +<dataset> + + <projects id="123" kee="project"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantDefaultRoles-result.xml b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantDefaultRoles-result.xml new file mode 100644 index 00000000000..5318ae07093 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantDefaultRoles-result.xml @@ -0,0 +1,33 @@ +<dataset> + <projects id="123" kee="com.foo:bar"/> + + <groups id="100" name="sonar-administrators"/> + <groups id="101" name="sonar-users"/> + <users id="200" login="marius" name="Marius" email="[null]" active="[true]"/> + + <!-- on other resources --> + <group_roles id="1" group_id="100" resource_id="1" role="admin"/> + <group_roles id="2" group_id="101" resource_id="1" role="user"/> + <user_roles id="1" user_id="200" resource_id="1" role="admin"/> + + <!-- + new rows : sonar-administrators (admin), sonar-users (user & codeviewer), Anyone (user & codeviewer), + --> + <group_roles id="3" group_id="100" resource_id="123" role="admin"/> + <group_roles id="4" group_id="101" resource_id="123" role="user"/> + <group_roles id="5" group_id="[null]" resource_id="123" role="user"/> + <group_roles id="6" group_id="101" resource_id="123" role="codeviewer"/> + <group_roles id="7" group_id="[null]" resource_id="123" role="codeviewer"/> + + <!-- default permission template for all qualifiers --> + <permission_templates id="1" name="default" kee="default_template_20130101_010203"/> + + <perm_templates_groups id="1" template_id="1" group_id="100" permission_reference="admin"/> + <perm_templates_groups id="2" template_id="1" group_id="101" permission_reference="user"/> + <perm_templates_groups id="3" template_id="1" group_id="[null]" permission_reference="user"/> + <perm_templates_groups id="4" template_id="1" group_id="101" permission_reference="codeviewer"/> + <perm_templates_groups id="5" template_id="1" group_id="[null]" permission_reference="codeviewer"/> + + <perm_templates_users/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantDefaultRoles.xml b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantDefaultRoles.xml new file mode 100644 index 00000000000..1291c08b42a --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantDefaultRoles.xml @@ -0,0 +1,26 @@ +<dataset> + + <projects id="123" kee="com.foo:bar"/> + + <groups id="100" name="sonar-administrators"/> + <groups id="101" name="sonar-users"/> + <users id="200" login="marius" name="Marius" email="[null]" active="[true]"/> + + <!-- on other resources --> + <group_roles id="1" group_id="100" resource_id="1" role="admin"/> + <group_roles id="2" group_id="101" resource_id="1" role="user"/> + <user_roles id="1" user_id="200" resource_id="1" role="admin"/> + + + <!-- default permission template for all qualifiers --> + <permission_templates id="1" name="default" kee="default_template_20130101_010203"/> + + <perm_templates_groups id="1" template_id="1" group_id="100" permission_reference="admin"/> + <perm_templates_groups id="2" template_id="1" group_id="101" permission_reference="user"/> + <perm_templates_groups id="3" template_id="1" group_id="[null]" permission_reference="user"/> + <perm_templates_groups id="4" template_id="1" group_id="101" permission_reference="codeviewer"/> + <perm_templates_groups id="5" template_id="1" group_id="[null]" permission_reference="codeviewer"/> + + <perm_templates_users/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantDefaultRolesPattern-result.xml b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantDefaultRolesPattern-result.xml new file mode 100644 index 00000000000..9ada7f379cb --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantDefaultRolesPattern-result.xml @@ -0,0 +1,35 @@ +<dataset> + <projects id="123" kee="foo.project"/> + + <groups id="100" name="sonar-administrators"/> + <groups id="101" name="sonar-users"/> + <groups id="102" name="sonar-foos"/> + <groups id="103" name="sonar-bars"/> + + <users id="200" login="foo" name="Foo" email="[null]" active="[true]"/> + <users id="201" login="bar" name="Bar" email="[null]" active="[true]"/> + + <!-- on other resources --> + <group_roles id="1" group_id="100" resource_id="1" role="admin"/> + <group_roles id="2" group_id="101" resource_id="1" role="user"/> + <user_roles id="1" user_id="200" resource_id="1" role="admin"/> + + <!-- + new rows + --> + <group_roles id="3" group_id="102" resource_id="123" role="user"/> + + <!-- default permission template for all qualifiers --> + <permission_templates id="1" name="default" kee="default" key_pattern="[null]"/> + + <permission_templates id="2" name="Start with foo" kee="foo_tmpl" key_pattern="foo\..*"/> + <permission_templates id="3" name="Start with bar" kee="bar_tmpl" key_pattern="bar\..*"/> + + <perm_templates_groups id="1" template_id="1" group_id="100" permission_reference="admin"/> + + <perm_templates_groups id="2" template_id="2" group_id="102" permission_reference="user"/> + <perm_templates_groups id="3" template_id="3" group_id="103" permission_reference="user"/> + + <perm_templates_users/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantDefaultRolesPattern.xml b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantDefaultRolesPattern.xml new file mode 100644 index 00000000000..667ef671ce1 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantDefaultRolesPattern.xml @@ -0,0 +1,31 @@ +<dataset> + <projects id="123" kee="foo.project"/> + + <groups id="100" name="sonar-administrators"/> + <groups id="101" name="sonar-users"/> + <groups id="102" name="sonar-foos"/> + <groups id="103" name="sonar-bars"/> + + <users id="200" login="foo" name="Foo" email="[null]" active="[true]"/> + <users id="201" login="bar" name="Bar" email="[null]" active="[true]"/> + + <!-- on other resources --> + <group_roles id="1" group_id="100" resource_id="1" role="admin"/> + <group_roles id="2" group_id="101" resource_id="1" role="user"/> + <user_roles id="1" user_id="200" resource_id="1" role="admin"/> + + + <!-- default permission template for all qualifiers --> + <permission_templates id="1" name="default" kee="default" key_pattern="[null]"/> + + <permission_templates id="2" name="Start with foo" kee="foo_tmpl" key_pattern="foo\..*"/> + <permission_templates id="3" name="Start with bar" kee="bar_tmpl" key_pattern="bar\..*"/> + + <perm_templates_groups id="1" template_id="1" group_id="100" permission_reference="admin"/> + + <perm_templates_groups id="2" template_id="2" group_id="102" permission_reference="user"/> + <perm_templates_groups id="3" template_id="3" group_id="103" permission_reference="user"/> + + <perm_templates_users/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantDefaultRolesProject-result.xml b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantDefaultRolesProject-result.xml new file mode 100644 index 00000000000..a70196dc547 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantDefaultRolesProject-result.xml @@ -0,0 +1,44 @@ +<dataset> + <projects id="123" kee="foo.project"/> + + <groups id="100" name="sonar-administrators"/> + <groups id="101" name="sonar-users"/> + <users id="200" login="marius" name="Marius" email="[null]" active="[true]"/> + + <!-- on other resources --> + <group_roles id="1" group_id="100" resource_id="1" role="admin"/> + <group_roles id="2" group_id="101" resource_id="1" role="user"/> + <user_roles id="1" user_id="200" resource_id="1" role="admin"/> + + <!-- created permissions should be based on the TRK template --> + <group_roles id="3" group_id="100" resource_id="123" role="admin"/> + <group_roles id="4" group_id="101" resource_id="123" role="admin"/> + <group_roles id="5" group_id="100" resource_id="123" role="user"/> + <group_roles id="6" group_id="100" resource_id="123" role="codeviewer"/> + <group_roles id="7" group_id="[null]" resource_id="123" role="codeviewer"/> + + <user_roles id="2" user_id="200" resource_id="123" role="codeviewer"/> + + + <!-- default permission template for all qualifiers --> + <permission_templates id="1" name="default"/> + + <perm_templates_groups id="1" template_id="1" group_id="100" permission_reference="admin"/> + <perm_templates_groups id="2" template_id="1" group_id="101" permission_reference="user"/> + <perm_templates_groups id="3" template_id="1" group_id="[null]" permission_reference="user"/> + <perm_templates_groups id="4" template_id="1" group_id="101" permission_reference="codeviewer"/> + <perm_templates_groups id="5" template_id="1" group_id="[null]" permission_reference="codeviewer"/> + + + <!-- default permission template for TRK --> + <permission_templates id="2" name="default_for_TRK"/> + + <perm_templates_groups id="6" template_id="2" group_id="100" permission_reference="admin"/> + <perm_templates_groups id="7" template_id="2" group_id="101" permission_reference="admin"/> + <perm_templates_groups id="8" template_id="2" group_id="100" permission_reference="user"/> + <perm_templates_groups id="9" template_id="2" group_id="100" permission_reference="codeviewer"/> + <perm_templates_groups id="10" template_id="2" group_id="[null]" permission_reference="codeviewer"/> + + <perm_templates_users id="1" template_id="2" user_id="200" permission_reference="codeviewer"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantDefaultRolesProject.xml b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantDefaultRolesProject.xml new file mode 100644 index 00000000000..3b60c1c78d4 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantDefaultRolesProject.xml @@ -0,0 +1,35 @@ +<dataset> + <projects id="123" kee="foo.project"/> + + <groups id="100" name="sonar-administrators"/> + <groups id="101" name="sonar-users"/> + <users id="200" login="marius" name="Marius" email="[null]" active="[true]"/> + + <!-- on other resources --> + <group_roles id="1" group_id="100" resource_id="1" role="admin"/> + <group_roles id="2" group_id="101" resource_id="1" role="user"/> + <user_roles id="1" user_id="200" resource_id="1" role="admin"/> + + + <!-- default permission template for all qualifiers --> + <permission_templates id="1" name="default" kee="default_20130101_010203"/> + + <perm_templates_groups id="1" template_id="1" group_id="100" permission_reference="admin"/> + <perm_templates_groups id="2" template_id="1" group_id="101" permission_reference="user"/> + <perm_templates_groups id="3" template_id="1" group_id="[null]" permission_reference="user"/> + <perm_templates_groups id="4" template_id="1" group_id="101" permission_reference="codeviewer"/> + <perm_templates_groups id="5" template_id="1" group_id="[null]" permission_reference="codeviewer"/> + + + <!-- default permission template for TRK --> + <permission_templates id="2" name="default_for_TRK" kee="default_for_trk_20130101_010203"/> + + <perm_templates_groups id="6" template_id="2" group_id="100" permission_reference="admin"/> + <perm_templates_groups id="7" template_id="2" group_id="101" permission_reference="admin"/> + <perm_templates_groups id="8" template_id="2" group_id="100" permission_reference="user"/> + <perm_templates_groups id="9" template_id="2" group_id="100" permission_reference="codeviewer"/> + <perm_templates_groups id="10" template_id="2" group_id="[null]" permission_reference="codeviewer"/> + + <perm_templates_users id="1" template_id="2" user_id="200" permission_reference="codeviewer"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantDefaultRolesSeveralPattern.xml b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantDefaultRolesSeveralPattern.xml new file mode 100644 index 00000000000..25fdc99252c --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantDefaultRolesSeveralPattern.xml @@ -0,0 +1,31 @@ +<dataset> + <projects id="123" kee="foo.project"/> + + <groups id="100" name="sonar-administrators"/> + <groups id="101" name="sonar-users"/> + <groups id="102" name="sonar-foos"/> + <groups id="103" name="sonar-bars"/> + + <users id="200" login="foo" name="Foo" email="[null]" active="[true]"/> + <users id="201" login="bar" name="Bar" email="[null]" active="[true]"/> + + <!-- on other resources --> + <group_roles id="1" group_id="100" resource_id="1" role="admin"/> + <group_roles id="2" group_id="101" resource_id="1" role="user"/> + <user_roles id="1" user_id="200" resource_id="1" role="admin"/> + + + <!-- default permission template for all qualifiers --> + <permission_templates id="1" name="default" kee="default" key_pattern="[null]"/> + + <permission_templates id="2" name="Start with foo" kee="foo_tmpl" key_pattern="foo\..*"/> + <permission_templates id="3" name="Start with foo again" kee="foo2_tmpl" key_pattern="foo.*"/> + + <perm_templates_groups id="1" template_id="1" group_id="100" permission_reference="admin"/> + + <perm_templates_groups id="2" template_id="2" group_id="102" permission_reference="user"/> + <perm_templates_groups id="3" template_id="3" group_id="103" permission_reference="user"/> + + <perm_templates_users/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantDefaultRoles_unknown_group-result.xml b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantDefaultRoles_unknown_group-result.xml new file mode 100644 index 00000000000..ea9b6e062fc --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantDefaultRoles_unknown_group-result.xml @@ -0,0 +1,20 @@ +<dataset> + <projects id="123" kee="foo.project"/> + + <groups id="100" name="sonar-administrators"/> + <groups id="101" name="sonar-users"/> + <users id="200" login="marius" name="Marius" email="[null]" active="[true]"/> + + <!-- on other resources --> + <group_roles id="1" group_id="100" resource_id="1" role="admin"/> + <group_roles id="2" group_id="101" resource_id="1" role="user"/> + <user_roles id="1" user_id="200" resource_id="1" role="admin"/> + + <!-- new rows : sonar-administrators (admin) --> + <group_roles id="3" group_id="100" resource_id="123" role="admin"/> + + <!-- default permission template --> + <permission_templates id="1" name="default_template" kee="default_template_20130101_010203"/> + <perm_templates_groups id="1" template_id="1" group_id="100" permission_reference="admin"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantDefaultRoles_unknown_group.xml b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantDefaultRoles_unknown_group.xml new file mode 100644 index 00000000000..d1b61aa180c --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantDefaultRoles_unknown_group.xml @@ -0,0 +1,19 @@ +<dataset> + <projects id="123" kee="foo.project"/> + + <groups id="100" name="sonar-administrators"/> + <groups id="101" name="sonar-users"/> + <users id="200" login="marius" name="Marius" email="[null]" active="[true]"/> + + <!-- on other resources --> + <group_roles id="1" group_id="100" resource_id="1" role="admin"/> + <group_roles id="2" group_id="101" resource_id="1" role="user"/> + <user_roles id="1" user_id="200" resource_id="1" role="admin"/> + + <!-- default permission template for TRK --> + <permission_templates id="1" name="default_template" kee="default_template_20130101_010203"/> + + <perm_templates_groups id="1" template_id="1" group_id="100" permission_reference="admin"/> + <perm_templates_groups id="2" template_id="1" group_id="999" permission_reference="admin"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantDefaultRoles_users-result.xml b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantDefaultRoles_users-result.xml new file mode 100644 index 00000000000..319040d44b5 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantDefaultRoles_users-result.xml @@ -0,0 +1,23 @@ +<dataset> + <projects id="123" kee="foo.project"/> + + <groups id="100" name="sonar-administrators"/> + <groups id="101" name="sonar-users"/> + <users id="200" login="marius" name="Marius" email="[null]" active="[true]"/> + <users id="201" login="disabled" name="Disabled" email="[null]" active="[false]"/> + + <!-- on other resources --> + <group_roles id="1" group_id="100" resource_id="1" role="admin"/> + <group_roles id="2" group_id="101" resource_id="1" role="user"/> + <user_roles id="1" user_id="200" resource_id="1" role="admin"/> + + <!-- new row : marius (admin) --> + <user_roles id="2" user_id="200" resource_id="123" role="admin"/> + + <!-- default permission template for TRK --> + <permission_templates id="1" name="default_for_TRK" kee="default_for_trk_20130101_010203"/> + + <perm_templates_users id="1" template_id="1" user_id="200" permission_reference="admin"/> + <perm_templates_users id="2" template_id="1" user_id="201" permission_reference="admin"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantDefaultRoles_users.xml b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantDefaultRoles_users.xml new file mode 100644 index 00000000000..72a71613609 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantDefaultRoles_users.xml @@ -0,0 +1,20 @@ +<dataset> + <projects id="123" kee="foo.project"/> + + <groups id="100" name="sonar-administrators"/> + <groups id="101" name="sonar-users"/> + <users id="200" login="marius" name="Marius" email="[null]" active="[true]"/> + <users id="201" login="disabled" name="Disabled" email="[null]" active="[false]"/> + + <!-- on other resources --> + <group_roles id="1" group_id="100" resource_id="1" role="admin"/> + <group_roles id="2" group_id="101" resource_id="1" role="user"/> + <user_roles id="1" user_id="200" resource_id="1" role="admin"/> + + <!-- default permission template for TRK --> + <permission_templates id="1" name="default_for_TRK" kee="default_for_trk_20130101_010203"/> + + <perm_templates_users id="1" template_id="1" user_id="200" permission_reference="admin"/> + <perm_templates_users id="2" template_id="1" user_id="201" permission_reference="admin"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantGroupRole-result.xml b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantGroupRole-result.xml new file mode 100644 index 00000000000..9d3ae472eb6 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantGroupRole-result.xml @@ -0,0 +1,6 @@ +<dataset> + <groups id="100" name="sonar-administrators"/> + <groups id="101" name="sonar-users"/> + + <group_roles group_id="100" resource_id="123" role="admin"/> +</dataset>
\ No newline at end of file diff --git a/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantGroupRole.xml b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantGroupRole.xml new file mode 100644 index 00000000000..8e0c38ff39f --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantGroupRole.xml @@ -0,0 +1,4 @@ +<dataset> + <groups id="100" name="sonar-administrators"/> + <groups id="101" name="sonar-users"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantGroupRole_anyone-result.xml b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantGroupRole_anyone-result.xml new file mode 100644 index 00000000000..62ecece0705 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantGroupRole_anyone-result.xml @@ -0,0 +1,6 @@ +<dataset> + <groups id="100" name="sonar-administrators"/> + <groups id="101" name="sonar-users"/> + + <group_roles id="1" group_id="[null]" resource_id="123" role="admin"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantGroupRole_anyone.xml b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantGroupRole_anyone.xml new file mode 100644 index 00000000000..8e0c38ff39f --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantGroupRole_anyone.xml @@ -0,0 +1,4 @@ +<dataset> + <groups id="100" name="sonar-administrators"/> + <groups id="101" name="sonar-users"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantGroupRole_ignore_if_group_not_found-result.xml b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantGroupRole_ignore_if_group_not_found-result.xml new file mode 100644 index 00000000000..41ed8af1f82 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantGroupRole_ignore_if_group_not_found-result.xml @@ -0,0 +1,7 @@ +<dataset> + <groups id="100" name="sonar-administrators"/> + <groups id="101" name="sonar-users"/> + + <!-- already existed --> + <group_roles id="1" group_id="[null]" resource_id="123" role="admin"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantGroupRole_ignore_if_group_not_found.xml b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantGroupRole_ignore_if_group_not_found.xml new file mode 100644 index 00000000000..41ed8af1f82 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantGroupRole_ignore_if_group_not_found.xml @@ -0,0 +1,7 @@ +<dataset> + <groups id="100" name="sonar-administrators"/> + <groups id="101" name="sonar-users"/> + + <!-- already existed --> + <group_roles id="1" group_id="[null]" resource_id="123" role="admin"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantGroupRole_ignore_if_not_persisted-result.xml b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantGroupRole_ignore_if_not_persisted-result.xml new file mode 100644 index 00000000000..41ed8af1f82 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantGroupRole_ignore_if_not_persisted-result.xml @@ -0,0 +1,7 @@ +<dataset> + <groups id="100" name="sonar-administrators"/> + <groups id="101" name="sonar-users"/> + + <!-- already existed --> + <group_roles id="1" group_id="[null]" resource_id="123" role="admin"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantGroupRole_ignore_if_not_persisted.xml b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantGroupRole_ignore_if_not_persisted.xml new file mode 100644 index 00000000000..41ed8af1f82 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantGroupRole_ignore_if_not_persisted.xml @@ -0,0 +1,7 @@ +<dataset> + <groups id="100" name="sonar-administrators"/> + <groups id="101" name="sonar-users"/> + + <!-- already existed --> + <group_roles id="1" group_id="[null]" resource_id="123" role="admin"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantUserRole-result.xml b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantUserRole-result.xml new file mode 100644 index 00000000000..7f154cd1915 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantUserRole-result.xml @@ -0,0 +1,6 @@ +<dataset> + <users id="200" login="marius" name="Marius" email="[null]" active="[true]"/> + + <user_roles user_id="200" resource_id="123" role="admin"/> + +</dataset>
\ No newline at end of file diff --git a/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantUserRole.xml b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantUserRole.xml new file mode 100644 index 00000000000..24349836265 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/grantUserRole.xml @@ -0,0 +1,3 @@ +<dataset> + <users id="200" login="marius" name="Marius" email="[null]" active="[true]"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/hasRoles.xml b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/hasRoles.xml new file mode 100644 index 00000000000..3d5f9a5ecf2 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/hasRoles.xml @@ -0,0 +1,16 @@ +<dataset> + <groups id="100" name="sonar-administrators"/> + <groups id="101" name="sonar-users"/> + <users id="200" login="marius" name="Marius" email="[null]" active="[true]"/> + + <!-- only_users --> + <user_roles id="1" user_id="200" resource_id="1" role="admin"/> + + <!-- only_groups --> + <group_roles id="1" group_id="100" resource_id="2" role="admin"/> + + <!-- groups_and_users --> + <group_roles id="2" group_id="101" resource_id="3" role="user"/> + <user_roles id="2" user_id="200" resource_id="3" role="admin"/> + +</dataset>
\ No newline at end of file diff --git a/sonar-db/src/test/resources/org/sonar/core/user/DeprecatedUserFinderTest/fixture.xml b/sonar-db/src/test/resources/org/sonar/core/user/DeprecatedUserFinderTest/fixture.xml new file mode 100644 index 00000000000..9d370e86a70 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/core/user/DeprecatedUserFinderTest/fixture.xml @@ -0,0 +1,6 @@ +<dataset> + + <users id="1" login="simon" name="Simon Brandhof" email="simon.brandhof@sonarsource.com"/> + <users id="2" login="godin" name="Evgeny Mandrikov" email="evgeny.mandrikov@sonarsource.com"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ResourceDaoTest/fixture-including-ghost-projects-and-technical-project.xml b/sonar-db/src/test/resources/org/sonar/db/component/ResourceDaoTest/fixture-including-ghost-projects-and-technical-project.xml new file mode 100644 index 00000000000..01781afd684 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/component/ResourceDaoTest/fixture-including-ghost-projects-and-technical-project.xml @@ -0,0 +1,134 @@ +<dataset> + + <!-- root project --> + <projects id="1" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" + description="the description" long_name="Apache Struts" + uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" module_uuid_path="." + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" + authorization_updated_at="[null]"/> + <snapshots id="1" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" + version="[null]" path=""/> + <snapshots id="10" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[false]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228136280000" build_date="1228136280000" + version="[null]" path=""/> + + <!-- project --> + <projects id="2" root_id="1" kee="org.struts:struts-core" name="Struts Core" + scope="PRJ" qualifier="BRC" long_name="Struts Core" + uuid="EFGH" project_uuid="ABCD" module_uuid="[null]" module_uuid_path=".ABCD." + description="[null]" enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" + authorization_updated_at="[null]"/> + <snapshots id="2" project_id="2" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="BRC" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="1."/> + + <!-- directory --> + <projects long_name="org.struts" id="3" scope="DIR" qualifier="PAC" kee="org.struts:struts:org.struts" + name="org.struts" root_id="1" + description="[null]" + uuid="GHIJ" project_uuid="ABCD" module_uuid="EFGH" module_uuid_path=".ABCD.EFGH." + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" + authorization_updated_at="[null]"/> + <snapshots id="3" project_id="3" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="DIR" qualifier="PAC" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="1.2."/> + + <!-- file --> + <projects long_name="org.struts.RequestContext" id="4" scope="FIL" qualifier="CLA" + kee="org.struts:struts:org.struts.RequestContext" + name="RequestContext" root_id="1" + uuid="KLMN" project_uuid="ABCD" module_uuid="EFGH" module_uuid_path=".ABCD.EFGH." + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" + authorization_updated_at="[null]"/> + + <snapshots id="4" project_id="4" parent_snapshot_id="3" root_project_id="1" root_snapshot_id="1" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="FIL" qualifier="CLA" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="1.2.3."/> + + <!-- technical project --> + <projects id="5" root_id="[null]" scope="PRJ" qualifier="TRK" kee="COPYorg.struts:struts" name="Struts" + uuid="TECHPROJECT" project_uuid="[null]" module_uuid="[null]" module_uuid_path="." + description="the description" long_name="Apache Struts" + enabled="[true]" language="java" copy_resource_id="1" person_id="[null]" authorization_updated_at="[null]"/> + + <!-- project without snapshot status=P--> + <projects id="6" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.apache.shindig" name="Shinding" + uuid="ONLYERRORS" project_uuid="[null]" module_uuid="[null]" module_uuid_path="." + description="the description" long_name="Shinding" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"/> + <snapshots id="6" project_id="6" parent_snapshot_id="[null]" root_project_id="6" root_snapshot_id="[null]" + status="U" islast="[false]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" + version="[null]" path=""/> + <snapshots id="7" project_id="6" parent_snapshot_id="6" root_project_id="6" root_snapshot_id="6" + status="U" islast="[false]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228309080000" build_date="1228309080000" + version="[null]" path=""/> + + + <!-- project without snapshot --> + <projects id="7" root_id="[null]" kee="org.sample:sample" name="Sample" + scope="PRJ" qualifier="TRK" long_name="Sample" + uuid="NOSNAPSHOT" project_uuid="[null]" module_uuid="[null]" module_uuid_path="." + description="[null]" enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" + authorization_updated_at="[null]"/> + + <!-- project not enabled --> + <projects id="8" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.apache:tika" name="Tika" + description="the description" long_name="Tika" + uuid="DISABLED" project_uuid="[null]" module_uuid="[null]" module_uuid_path="." + enabled="[false]" language="java" copy_resource_id="[null]" person_id="[null]"/> + <snapshots id="8" project_id="8" parent_snapshot_id="[null]" root_project_id="8" root_snapshot_id="[null]" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" + version="[null]" path=""/> + + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ResourceDaoTest/fixture.xml b/sonar-db/src/test/resources/org/sonar/db/component/ResourceDaoTest/fixture.xml new file mode 100644 index 00000000000..76692345910 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/component/ResourceDaoTest/fixture.xml @@ -0,0 +1,86 @@ +<dataset> + + <!-- Struts projects is authorized for all user --> + <group_roles id="1" group_id="[null]" resource_id="1" role="user"/> + + + <!-- root project --> + <projects id="1" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" + uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" module_uuid_path="." + description="the description" long_name="Apache Struts" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + created_at="2008-12-02" authorization_updated_at="123456789"/> + <snapshots id="1" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" + version="[null]" path=""/> + <snapshots id="10" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[false]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228136280000" build_date="1228136280000" + version="[null]" path=""/> + + <!-- module --> + <projects id="2" root_id="1" kee="org.struts:struts-core" name="Struts Core" + uuid="BCDE" project_uuid="ABCD" module_uuid="[null]" module_uuid_path=".ABCD." + scope="PRJ" qualifier="BRC" long_name="Struts Core" + description="[null]" enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" + created_at="2008-12-02" authorization_updated_at="[null]"/> + <snapshots id="2" project_id="2" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="BRC" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="1."/> + + <!-- directory --> + <projects long_name="org.struts" id="3" scope="DIR" qualifier="DIR" kee="org.struts:struts-core:src/org/struts" + uuid="CDEF" project_uuid="ABCD" module_uuid="BCDE" module_uuid_path=".ABCD.BCDE." + name="src/org/struts" root_id="2" + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" path="src/org/struts" + created_at="2008-12-02" authorization_updated_at="[null]"/> + <snapshots id="3" project_id="3" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="DIR" qualifier="PAC" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="1.2."/> + + <!-- file --> + <projects long_name="org.struts.RequestContext" id="4" scope="FIL" qualifier="FIL" + kee="org.struts:struts-core:src/org/struts/RequestContext.java" + uuid="DEFG" project_uuid="ABCD" module_uuid="BCDE" module_uuid_path=".ABCD.BCDE." + name="RequestContext.java" root_id="2" + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" + path="src/org/struts/RequestContext.java" + created_at="2008-12-02" authorization_updated_at="[null]"/> + + <snapshots id="4" project_id="4" parent_snapshot_id="3" root_project_id="1" root_snapshot_id="1" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="FIL" qualifier="CLA" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="1.2.3."/> + + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ResourceDaoTest/getResources_exclude_disabled.xml b/sonar-db/src/test/resources/org/sonar/db/component/ResourceDaoTest/getResources_exclude_disabled.xml new file mode 100644 index 00000000000..f1bf15b6b7c --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/component/ResourceDaoTest/getResources_exclude_disabled.xml @@ -0,0 +1,16 @@ +<dataset> + + <!-- disabled --> + <projects id="1" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" + description="the description" long_name="Apache Struts" + uuid="DISABLED" project_uuid="[null]" module_uuid="[null]" module_uuid_path="." + enabled="[false]" language="java" copy_resource_id="[null]" person_id="[null]" + authorization_updated_at="[null]"/> + + <!-- enabled --> + <projects id="2" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" + description="the description" long_name="Apache Struts" + uuid="ENABLED" project_uuid="[null]" module_uuid="[null]" module_uuid_path="." + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" + authorization_updated_at="[null]"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ResourceDaoTest/get_last_snapshot_by_component_uuid.xml b/sonar-db/src/test/resources/org/sonar/db/component/ResourceDaoTest/get_last_snapshot_by_component_uuid.xml new file mode 100644 index 00000000000..9304e9363b6 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/component/ResourceDaoTest/get_last_snapshot_by_component_uuid.xml @@ -0,0 +1,85 @@ +<dataset> + + <!-- Struts projects is authorized for all user --> + <group_roles id="1" group_id="[null]" resource_id="1" role="user"/> + + + <!-- root project --> + <projects id="1" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" + uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" module_uuid_path="." + description="the description" long_name="Apache Struts" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + authorization_updated_at="[null]"/> + <snapshots id="1" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[true]" purge_status="[null]" + period1_mode="previous_analysis" period1_param="[null]" period1_date="[null]" + period2_mode="days" period2_param="30" period2_date="1316815200000" + period3_mode="days" period3_param="90" period3_date="1311631200000" + period4_mode="previous_analysis" period4_param="[null]" period4_date="[null]" + period5_mode="previous_version" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" + version="[null]" path=""/> + <snapshots id="10" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[false]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228136280000" build_date="1228136280000" + version="[null]" path=""/> + + <!-- module --> + <projects id="2" root_id="1" kee="org.struts:struts-core" name="Struts Core" + uuid="EFGH" project_uuid="ABCD" module_uuid="[null]" module_uuid_path=".ABCD." + scope="PRJ" qualifier="BRC" long_name="Struts Core" + description="[null]" enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" + authorization_updated_at="[null]"/> + <snapshots id="2" project_id="2" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="BRC" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="1."/> + + <!-- directory --> + <projects long_name="org.struts" id="3" scope="DIR" qualifier="DIR" kee="org.struts:struts-core:src/org/struts" + uuid="GHIJ" project_uuid="ABCD" module_uuid="EFGH" module_uuid_path=".ABCD.EFGH." + name="src/org/struts" root_id="2" + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" path="src/org/struts" + authorization_updated_at="[null]"/> + <snapshots id="3" project_id="3" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="DIR" qualifier="PAC" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="1.2."/> + + <!-- file --> + <projects long_name="org.struts.RequestContext" id="4" scope="FIL" qualifier="FIL" + kee="org.struts:struts-core:src/org/struts/RequestContext.java" + uuid="KLMN" project_uuid="ABCD" module_uuid="EFGH" module_uuid_path=".ABCD.EFGH." + name="RequestContext.java" root_id="2" + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" + path="src/org/struts/RequestContext.java" authorization_updated_at="[null]"/> + + <snapshots id="4" project_id="4" parent_snapshot_id="3" root_project_id="1" root_snapshot_id="1" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="FIL" qualifier="CLA" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="1.2.3."/> + + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ResourceDaoTest/insert-result.xml b/sonar-db/src/test/resources/org/sonar/db/component/ResourceDaoTest/insert-result.xml new file mode 100644 index 00000000000..1c3af66e6fd --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/component/ResourceDaoTest/insert-result.xml @@ -0,0 +1,17 @@ +<dataset> + + <projects id="1" root_id="[null]" uuid="ABCD" project_uuid="EFGH" module_uuid="EFGH" module_uuid_path=".EFGH." + scope="FIL" qualifier="FIL" kee="org.struts:struts:/src/main/java/org/struts/Action.java" name="Action" + description="[null]" long_name="org.struts.Action" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" created_at="[ignore]" + path="/foo/bar" deprecated_kee="org.struts:struts:org.struts.Action" + authorization_updated_at="123456789"/> + + <projects id="2" root_id="[null]" uuid="BCDE" project_uuid="FGHI" module_uuid="FGHI" module_uuid_path=".FGHI." + scope="FIL" qualifier="FIL" kee="org.struts:struts:/src/main/java/org/struts/Filter.java" name="Filter" + description="[null]" long_name="org.struts.Filter" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" created_at="[ignore]" + path="[null]" deprecated_kee="org.struts:struts:org.struts.Filter" + authorization_updated_at="123456789"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ResourceDaoTest/insert.xml b/sonar-db/src/test/resources/org/sonar/db/component/ResourceDaoTest/insert.xml new file mode 100644 index 00000000000..871dedcb5e9 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/component/ResourceDaoTest/insert.xml @@ -0,0 +1,3 @@ +<dataset> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ResourceDaoTest/update-result.xml b/sonar-db/src/test/resources/org/sonar/db/component/ResourceDaoTest/update-result.xml new file mode 100644 index 00000000000..34afce983b9 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/component/ResourceDaoTest/update-result.xml @@ -0,0 +1,10 @@ +<dataset> + + <projects id="1" root_id="[null]" uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" module_uuid_path="." + scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" + description="MVC Framework" long_name="Apache Struts" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" created_at="[null]" + path="/foo/bar" deprecated_kee="deprecated key" + authorization_updated_at="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ResourceDaoTest/update.xml b/sonar-db/src/test/resources/org/sonar/db/component/ResourceDaoTest/update.xml new file mode 100644 index 00000000000..69e73cdb6df --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/component/ResourceDaoTest/update.xml @@ -0,0 +1,10 @@ +<dataset> + + <projects id="1" root_id="200" uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" module_uuid_path="." + scope="PRJ" qualifier="TRK" kee="old key" name="old name" + description="old name" long_name="old long name" + enabled="[false]" language="old" copy_resource_id="2" person_id="3" created_at="[null]" path="/old/foo/bar" + deprecated_kee="old deprecated key" + authorization_updated_at="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ResourceDaoTest/update_authorization_date-result.xml b/sonar-db/src/test/resources/org/sonar/db/component/ResourceDaoTest/update_authorization_date-result.xml new file mode 100644 index 00000000000..a6abf2fab1b --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/component/ResourceDaoTest/update_authorization_date-result.xml @@ -0,0 +1,10 @@ +<dataset> + + <projects id="1" root_id="200" uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" module_uuid_path="." + scope="PRJ" qualifier="TRK" kee="old key" name="old name" + description="old name" long_name="old long name" + enabled="[false]" language="old" copy_resource_id="2" person_id="3" created_at="[null]" path="/old/foo/bar" + deprecated_kee="old deprecated key" + authorization_updated_at="987654321"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ResourceDaoTest/update_authorization_date.xml b/sonar-db/src/test/resources/org/sonar/db/component/ResourceDaoTest/update_authorization_date.xml new file mode 100644 index 00000000000..69e73cdb6df --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/component/ResourceDaoTest/update_authorization_date.xml @@ -0,0 +1,10 @@ +<dataset> + + <projects id="1" root_id="200" uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" module_uuid_path="." + scope="PRJ" qualifier="TRK" kee="old key" name="old name" + description="old name" long_name="old long name" + enabled="[false]" language="old" copy_resource_id="2" person_id="3" created_at="[null]" path="/old/foo/bar" + deprecated_kee="old deprecated key" + authorization_updated_at="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldIndexMultiModulesProject-result.xml b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldIndexMultiModulesProject-result.xml new file mode 100644 index 00000000000..48899d945c3 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldIndexMultiModulesProject-result.xml @@ -0,0 +1,69 @@ +<dataset> + + <!-- project "struts" -> module "struts-core" -> package org.struts -> file "RequestContext" --> + <projects long_name="[null]" id="1" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" + uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" module_uuid_path="." + root_id="[null]" + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"/> + + <projects long_name="[null]" id="2" scope="PRJ" qualifier="BRC" kee="org.struts:struts-core" name="Struts Core" + uuid="BCDE" project_uuid="ABCD" module_uuid="ABCD" module_uuid_path=".ABCD." + root_id="1" + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"/> + + <!-- note that the root_id of package/file is wrong. It references the module but not the root project --> + <projects long_name="org.struts" id="3" scope="DIR" qualifier="PAC" kee="org.struts:struts-core:org.struts" + uuid="CDEF" project_uuid="ABCD" module_uuid="BCDE" module_uuid_path=".ABCD.BCDE" + name="org.struts" root_id="2" + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"/> + + <projects long_name="org.struts.RequestContext" id="4" scope="CLA" qualifier="CLA" + uuid="DEFG" project_uuid="ABCD" module_uuid="BCDE" module_uuid_path=".ABCD.BCDE" + kee="org.struts:struts-core:org.struts.RequestContext" + name="RequestContext" root_id="2" + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"/> + + <snapshots purge_status="[null]" id="1" islast="[true]" root_project_id="1" project_id="1"/> + <snapshots purge_status="[null]" id="2" islast="[true]" root_project_id="1" project_id="2"/> + <snapshots purge_status="[null]" id="3" islast="[true]" root_project_id="1" project_id="3"/> + <snapshots purge_status="[null]" id="4" islast="[true]" root_project_id="1" project_id="4"/> + + <!-- The major goal is to test root_project_id --> + + <!-- RequestContext --> + <resource_index kee="requestcontext" position="0" name_size="14" resource_id="4" root_project_id="1" qualifier="CLA"/> + <resource_index kee="equestcontext" position="1" name_size="14" resource_id="4" root_project_id="1" qualifier="CLA"/> + <resource_index kee="questcontext" position="2" name_size="14" resource_id="4" root_project_id="1" qualifier="CLA"/> + <resource_index kee="uestcontext" position="3" name_size="14" resource_id="4" root_project_id="1" qualifier="CLA"/> + <resource_index kee="estcontext" position="4" name_size="14" resource_id="4" root_project_id="1" qualifier="CLA"/> + <resource_index kee="stcontext" position="5" name_size="14" resource_id="4" root_project_id="1" qualifier="CLA"/> + <resource_index kee="tcontext" position="6" name_size="14" resource_id="4" root_project_id="1" qualifier="CLA"/> + <resource_index kee="context" position="7" name_size="14" resource_id="4" root_project_id="1" qualifier="CLA"/> + <resource_index kee="ontext" position="8" name_size="14" resource_id="4" root_project_id="1" qualifier="CLA"/> + <resource_index kee="ntext" position="9" name_size="14" resource_id="4" root_project_id="1" qualifier="CLA"/> + <resource_index kee="text" position="10" name_size="14" resource_id="4" root_project_id="1" qualifier="CLA"/> + <resource_index kee="ext" position="11" name_size="14" resource_id="4" root_project_id="1" qualifier="CLA"/> + + <!-- Struts --> + <resource_index kee="struts" position="0" name_size="6" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index kee="truts" position="1" name_size="6" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index kee="ruts" position="2" name_size="6" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index kee="uts" position="3" name_size="6" resource_id="1" root_project_id="1" qualifier="TRK"/> + + <!-- Struts Core --> + <resource_index kee="struts core" position="0" name_size="11" resource_id="2" root_project_id="1" qualifier="BRC"/> + <resource_index kee="truts core" position="1" name_size="11" resource_id="2" root_project_id="1" qualifier="BRC"/> + <resource_index kee="ruts core" position="2" name_size="11" resource_id="2" root_project_id="1" qualifier="BRC"/> + <resource_index kee="uts core" position="3" name_size="11" resource_id="2" root_project_id="1" qualifier="BRC"/> + <resource_index kee="ts core" position="4" name_size="11" resource_id="2" root_project_id="1" qualifier="BRC"/> + <resource_index kee="s core" position="5" name_size="11" resource_id="2" root_project_id="1" qualifier="BRC"/> + <resource_index kee=" core" position="6" name_size="11" resource_id="2" root_project_id="1" qualifier="BRC"/> + <resource_index kee="core" position="7" name_size="11" resource_id="2" root_project_id="1" qualifier="BRC"/> + <resource_index kee="ore" position="8" name_size="11" resource_id="2" root_project_id="1" qualifier="BRC"/> + + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldIndexMultiModulesProject.xml b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldIndexMultiModulesProject.xml new file mode 100644 index 00000000000..a1cd4ef6f5a --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldIndexMultiModulesProject.xml @@ -0,0 +1,34 @@ +<dataset> + + <!-- project "struts" -> module "struts-core" -> package org.struts -> file "RequestContext" --> + <projects long_name="[null]" id="1" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" + uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" module_uuid_path="." + root_id="[null]" + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"/> + + <projects long_name="[null]" id="2" scope="PRJ" qualifier="BRC" kee="org.struts:struts-core" name="Struts Core" + uuid="BCDE" project_uuid="ABCD" module_uuid="ABCD" module_uuid_path=".ABCD." + root_id="1" + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"/> + + <!-- note that the root_id of package/file is wrong. It references the module but not the root project --> + <projects long_name="org.struts" id="3" scope="DIR" qualifier="PAC" kee="org.struts:struts-core:org.struts" + uuid="CDEF" project_uuid="ABCD" module_uuid="BCDE" module_uuid_path=".ABCD.BCDE" + name="org.struts" root_id="2" + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"/> + + <projects long_name="org.struts.RequestContext" id="4" scope="FIL" qualifier="CLA" + uuid="DEFG" project_uuid="ABCD" module_uuid="BCDE" module_uuid_path=".ABCD.BCDE" + kee="org.struts:struts-core:org.struts.RequestContext" + name="RequestContext" root_id="2" + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"/> + + <snapshots purge_status="[null]" id="1" islast="[true]" root_project_id="1" project_id="1"/> + <snapshots purge_status="[null]" id="2" islast="[true]" root_project_id="1" project_id="2"/> + <snapshots purge_status="[null]" id="3" islast="[true]" root_project_id="1" project_id="3"/> + <snapshots purge_status="[null]" id="4" islast="[true]" root_project_id="1" project_id="4"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldIndexProjects-result.xml b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldIndexProjects-result.xml new file mode 100644 index 00000000000..ee9ab480a7c --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldIndexProjects-result.xml @@ -0,0 +1,52 @@ +<dataset> + + <!-- project --> + <projects long_name="[null]" id="1" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" + uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" module_uuid_path="." + root_id="[null]" + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"/> + + <!-- directory --> + <projects long_name="org.struts" id="2" scope="DIR" qualifier="PAC" kee="org.struts:struts:org.struts" + uuid="BCDE" project_uuid="ABCD" module_uuid="ABCD" module_uuid_path=".ABCD." + name="org.struts" root_id="1" + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"/> + + <!-- file --> + <projects long_name="org.struts.RequestContext" id="3" scope="CLA" qualifier="CLA" + uuid="CDEF" project_uuid="ABCD" module_uuid="ABCD" module_uuid_path=".ABCD." + kee="org.struts:struts:org.struts.RequestContext" + name="RequestContext" root_id="1" + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"/> + + <snapshots purge_status="[null]" id="1" islast="[true]" root_project_id="1" project_id="1" scope="PRJ" + qualifier="TRK"/> + <snapshots purge_status="[null]" id="2" islast="[true]" root_project_id="1" project_id="2" scope="DIR" + qualifier="PAC"/> + <snapshots purge_status="[null]" id="3" islast="[true]" root_project_id="1" project_id="3" scope="CLA" + qualifier="CLA"/> + + <!-- RequestContext --> + <resource_index kee="requestcontext" position="0" name_size="14" resource_id="3" root_project_id="1" qualifier="CLA"/> + <resource_index kee="equestcontext" position="1" name_size="14" resource_id="3" root_project_id="1" qualifier="CLA"/> + <resource_index kee="questcontext" position="2" name_size="14" resource_id="3" root_project_id="1" qualifier="CLA"/> + <resource_index kee="uestcontext" position="3" name_size="14" resource_id="3" root_project_id="1" qualifier="CLA"/> + <resource_index kee="estcontext" position="4" name_size="14" resource_id="3" root_project_id="1" qualifier="CLA"/> + <resource_index kee="stcontext" position="5" name_size="14" resource_id="3" root_project_id="1" qualifier="CLA"/> + <resource_index kee="tcontext" position="6" name_size="14" resource_id="3" root_project_id="1" qualifier="CLA"/> + <resource_index kee="context" position="7" name_size="14" resource_id="3" root_project_id="1" qualifier="CLA"/> + <resource_index kee="ontext" position="8" name_size="14" resource_id="3" root_project_id="1" qualifier="CLA"/> + <resource_index kee="ntext" position="9" name_size="14" resource_id="3" root_project_id="1" qualifier="CLA"/> + <resource_index kee="text" position="10" name_size="14" resource_id="3" root_project_id="1" qualifier="CLA"/> + <resource_index kee="ext" position="11" name_size="14" resource_id="3" root_project_id="1" qualifier="CLA"/> + + <!-- Struts --> + <resource_index kee="struts" position="0" name_size="6" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index kee="truts" position="1" name_size="6" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index kee="ruts" position="2" name_size="6" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index kee="uts" position="3" name_size="6" resource_id="1" root_project_id="1" qualifier="TRK"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldIndexProjects.xml b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldIndexProjects.xml new file mode 100644 index 00000000000..0043b4ced0b --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldIndexProjects.xml @@ -0,0 +1,31 @@ +<dataset> + + <!-- project --> + <projects long_name="[null]" id="1" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" + uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" module_uuid_path="." + root_id="[null]" + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"/> + + <!-- directory --> + <projects long_name="org.struts" id="2" scope="DIR" qualifier="PAC" kee="org.struts:struts:org.struts" + uuid="BCDE" project_uuid="ABCD" module_uuid="ABCD" module_uuid_path=".ABCD." + name="org.struts" root_id="1" + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"/> + + <!-- file --> + <projects long_name="org.struts.RequestContext" id="3" scope="FIL" qualifier="CLA" + kee="org.struts:struts:org.struts.RequestContext" + uuid="CDEF" project_uuid="ABCD" module_uuid="ABCD" module_uuid_path=".ABCD." + name="RequestContext" root_id="1" + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"/> + + <snapshots purge_status="[null]" id="1" islast="[true]" root_project_id="1" project_id="1" scope="PRJ" + qualifier="TRK"/> + <snapshots purge_status="[null]" id="2" islast="[true]" root_project_id="1" project_id="2" scope="DIR" + qualifier="PAC"/> + <snapshots purge_status="[null]" id="3" islast="[true]" root_project_id="1" project_id="3" scope="FIL" + qualifier="CLA"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldIndexResource-result.xml b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldIndexResource-result.xml new file mode 100644 index 00000000000..f4cf0805ede --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldIndexResource-result.xml @@ -0,0 +1,8 @@ +<dataset> + <resource_index kee="ziputils" position="0" name_size="8" resource_id="10" root_project_id="8" qualifier="FIL"/> + <resource_index kee="iputils" position="1" name_size="8" resource_id="10" root_project_id="8" qualifier="FIL"/> + <resource_index kee="putils" position="2" name_size="8" resource_id="10" root_project_id="8" qualifier="FIL"/> + <resource_index kee="utils" position="3" name_size="8" resource_id="10" root_project_id="8" qualifier="FIL"/> + <resource_index kee="tils" position="4" name_size="8" resource_id="10" root_project_id="8" qualifier="FIL"/> + <resource_index kee="ils" position="5" name_size="8" resource_id="10" root_project_id="8" qualifier="FIL"/> +</dataset>
\ No newline at end of file diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldIndexResource.xml b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldIndexResource.xml new file mode 100644 index 00000000000..5a4a28b7df3 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldIndexResource.xml @@ -0,0 +1 @@ +<dataset></dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldIndexTwoLettersLongResource-result.xml b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldIndexTwoLettersLongResource-result.xml new file mode 100644 index 00000000000..c9941e492bd --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldIndexTwoLettersLongResource-result.xml @@ -0,0 +1,3 @@ +<dataset> + <resource_index kee="ab" position="0" name_size="2" resource_id="10" root_project_id="3" qualifier="TRK"/> +</dataset>
\ No newline at end of file diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldIndexTwoLettersLongResource.xml b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldIndexTwoLettersLongResource.xml new file mode 100644 index 00000000000..5a4a28b7df3 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldIndexTwoLettersLongResource.xml @@ -0,0 +1 @@ +<dataset></dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldNotIndexPackages.xml b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldNotIndexPackages.xml new file mode 100644 index 00000000000..0043b4ced0b --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldNotIndexPackages.xml @@ -0,0 +1,31 @@ +<dataset> + + <!-- project --> + <projects long_name="[null]" id="1" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" + uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" module_uuid_path="." + root_id="[null]" + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"/> + + <!-- directory --> + <projects long_name="org.struts" id="2" scope="DIR" qualifier="PAC" kee="org.struts:struts:org.struts" + uuid="BCDE" project_uuid="ABCD" module_uuid="ABCD" module_uuid_path=".ABCD." + name="org.struts" root_id="1" + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"/> + + <!-- file --> + <projects long_name="org.struts.RequestContext" id="3" scope="FIL" qualifier="CLA" + kee="org.struts:struts:org.struts.RequestContext" + uuid="CDEF" project_uuid="ABCD" module_uuid="ABCD" module_uuid_path=".ABCD." + name="RequestContext" root_id="1" + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"/> + + <snapshots purge_status="[null]" id="1" islast="[true]" root_project_id="1" project_id="1" scope="PRJ" + qualifier="TRK"/> + <snapshots purge_status="[null]" id="2" islast="[true]" root_project_id="1" project_id="2" scope="DIR" + qualifier="PAC"/> + <snapshots purge_status="[null]" id="3" islast="[true]" root_project_id="1" project_id="3" scope="FIL" + qualifier="CLA"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldNotReindexUnchangedResource-result.xml b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldNotReindexUnchangedResource-result.xml new file mode 100644 index 00000000000..4292af5708d --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldNotReindexUnchangedResource-result.xml @@ -0,0 +1,6 @@ +<dataset> + <resource_index kee="struts" position="0" name_size="6" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index kee="truts" position="1" name_size="6" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index kee="ruts" position="2" name_size="6" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index kee="uts" position="3" name_size="6" resource_id="1" root_project_id="1" qualifier="TRK"/> +</dataset>
\ No newline at end of file diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldNotReindexUnchangedResource.xml b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldNotReindexUnchangedResource.xml new file mode 100644 index 00000000000..89a3a8c465d --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldNotReindexUnchangedResource.xml @@ -0,0 +1,6 @@ +<dataset> + <resource_index id="1" kee="struts" position="0" name_size="6" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index id="2" kee="truts" position="1" name_size="6" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index id="3" kee="ruts" position="2" name_size="6" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index id="4" kee="uts" position="3" name_size="6" resource_id="1" root_project_id="1" qualifier="TRK"/> +</dataset>
\ No newline at end of file diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldReIndexNewTwoLettersLongResource-result.xml b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldReIndexNewTwoLettersLongResource-result.xml new file mode 100644 index 00000000000..52db35f3ad4 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldReIndexNewTwoLettersLongResource-result.xml @@ -0,0 +1,3 @@ +<dataset> + <resource_index kee="as" position="0" name_size="2" resource_id="1" root_project_id="1" qualifier="TRK"/> +</dataset>
\ No newline at end of file diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldReIndexNewTwoLettersLongResource.xml b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldReIndexNewTwoLettersLongResource.xml new file mode 100644 index 00000000000..af5863edbda --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldReIndexNewTwoLettersLongResource.xml @@ -0,0 +1,18 @@ +<dataset> + + <projects long_name="[null]" id="1" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="AS" + uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" module_uuid_path="." + root_id="[null]" + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"/> + + <snapshots purge_status="[null]" id="1" islast="[true]" root_project_id="1" project_id="1" scope="PRJ" + qualifier="TRK"/> + + <!-- the index is on the old name "ST" but not on "AS" --> + <resource_index id="1" kee="struts" position="0" name_size="6" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index id="2" kee="truts" position="1" name_size="6" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index id="3" kee="ruts" position="2" name_size="6" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index id="4" kee="uts" position="3" name_size="6" resource_id="1" root_project_id="1" qualifier="TRK"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldReIndexTwoLettersLongResource-result.xml b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldReIndexTwoLettersLongResource-result.xml new file mode 100644 index 00000000000..52db35f3ad4 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldReIndexTwoLettersLongResource-result.xml @@ -0,0 +1,3 @@ +<dataset> + <resource_index kee="as" position="0" name_size="2" resource_id="1" root_project_id="1" qualifier="TRK"/> +</dataset>
\ No newline at end of file diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldReIndexTwoLettersLongResource.xml b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldReIndexTwoLettersLongResource.xml new file mode 100644 index 00000000000..529e83c1a44 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldReIndexTwoLettersLongResource.xml @@ -0,0 +1,15 @@ +<dataset> + + <projects long_name="[null]" id="1" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="AS" + uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" module_uuid_path="." + root_id="[null]" + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"/> + + <snapshots purge_status="[null]" id="1" islast="[true]" root_project_id="1" project_id="1" scope="PRJ" + qualifier="TRK"/> + + <!-- the index is on the old name "ST" but not on "AS" --> + <resource_index id="1" kee="st" position="0" name_size="2" resource_id="1" root_project_id="1" qualifier="TRK"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldReindexProjectAfterRenaming-result.xml b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldReindexProjectAfterRenaming-result.xml new file mode 100644 index 00000000000..e28b5945816 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldReindexProjectAfterRenaming-result.xml @@ -0,0 +1,24 @@ +<dataset> + + <projects long_name="[null]" id="1" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Apache Struts" + uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" module_uuid_path="." + root_id="[null]" + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"/> + + <snapshots purge_status="[null]" id="1" islast="[true]" root_project_id="1" project_id="1" scope="PRJ" + qualifier="TRK"/> + + <resource_index kee="apache struts" position="0" name_size="13" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index kee="pache struts" position="1" name_size="13" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index kee="ache struts" position="2" name_size="13" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index kee="che struts" position="3" name_size="13" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index kee="he struts" position="4" name_size="13" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index kee="e struts" position="5" name_size="13" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index kee=" struts" position="6" name_size="13" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index kee="struts" position="7" name_size="13" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index kee="truts" position="8" name_size="13" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index kee="ruts" position="9" name_size="13" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index kee="uts" position="10" name_size="13" resource_id="1" root_project_id="1" qualifier="TRK"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldReindexProjectAfterRenaming.xml b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldReindexProjectAfterRenaming.xml new file mode 100644 index 00000000000..84815e52e64 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldReindexProjectAfterRenaming.xml @@ -0,0 +1,18 @@ +<dataset> + + <projects long_name="[null]" id="1" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Apache Struts" + uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" module_uuid_path="." + root_id="[null]" + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"/> + + <snapshots purge_status="[null]" id="1" islast="[true]" root_project_id="1" project_id="1" scope="PRJ" + qualifier="TRK"/> + + <!-- the index is on the old name "Struts" but not on "Apache Struts --> + <resource_index id="1" kee="struts" position="0" name_size="6" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index id="2" kee="truts" position="1" name_size="6" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index id="3" kee="ruts" position="2" name_size="6" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index id="4" kee="uts" position="3" name_size="6" resource_id="1" root_project_id="1" qualifier="TRK"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldReindexResource-result.xml b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldReindexResource-result.xml new file mode 100644 index 00000000000..b9f39157aea --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldReindexResource-result.xml @@ -0,0 +1,10 @@ +<dataset> + <resource_index kee="new struts" position="0" name_size="10" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index kee="ew struts" position="1" name_size="10" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index kee="w struts" position="2" name_size="10" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index kee=" struts" position="3" name_size="10" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index kee="struts" position="4" name_size="10" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index kee="truts" position="5" name_size="10" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index kee="ruts" position="6" name_size="10" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index kee="uts" position="7" name_size="10" resource_id="1" root_project_id="1" qualifier="TRK"/> +</dataset>
\ No newline at end of file diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldReindexResource.xml b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldReindexResource.xml new file mode 100644 index 00000000000..89a3a8c465d --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/shouldReindexResource.xml @@ -0,0 +1,6 @@ +<dataset> + <resource_index id="1" kee="struts" position="0" name_size="6" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index id="2" kee="truts" position="1" name_size="6" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index id="3" kee="ruts" position="2" name_size="6" resource_id="1" root_project_id="1" qualifier="TRK"/> + <resource_index id="4" kee="uts" position="3" name_size="6" resource_id="1" root_project_id="1" qualifier="TRK"/> +</dataset>
\ No newline at end of file diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ResourceKeyUpdaterDaoTest/shared.xml b/sonar-db/src/test/resources/org/sonar/db/component/ResourceKeyUpdaterDaoTest/shared.xml new file mode 100644 index 00000000000..400243b4d19 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/component/ResourceKeyUpdaterDaoTest/shared.xml @@ -0,0 +1,72 @@ +<dataset> + + <!-- root project --> + <projects id="1" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" uuid="A" + project_uuid="A" module_uuid="[null]" module_uuid_path="." + description="[null]" long_name="Apache Struts" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" created_at="[null]" + path="[null]" deprecated_kee="org.struts:struts" + authorization_updated_at="[null]"/> + + + <!-- **************** First sub project **************** --> + <projects id="2" root_id="1" kee="org.struts:struts-core" name="Struts Core" uuid="B" project_uuid="A" + module_uuid="[null]" module_uuid_path=".A." + scope="PRJ" qualifier="BRC" long_name="Struts Core" + description="[null]" enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" + created_at="[null]" path="[null]" deprecated_kee="org.struts:struts-core" + authorization_updated_at="[null]"/> + + <!-- directory --> + <projects long_name="org.struts" id="3" scope="DIR" qualifier="DIR" kee="org.struts:struts-core:/src/org/struts" + name="org.struts" root_id="2" uuid="C" project_uuid="A" module_uuid="B" module_uuid_path=".A.B." + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" created_at="[null]" + path="[null]" deprecated_kee="org.struts:struts-core:org.struts" + authorization_updated_at="[null]"/> + + <!-- file --> + <projects long_name="org.struts.RequestContext" id="4" scope="FIL" qualifier="CLA" + kee="org.struts:struts-core:/src/org/struts/RequestContext.java" + name="RequestContext" root_id="2" uuid="D" project_uuid="A" module_uuid="B" module_uuid_path=".A.B." + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" created_at="[null]" + path="[null]" deprecated_kee="org.struts:struts-core:org.struts.RequestContext" + authorization_updated_at="[null]"/> + + + <!-- **************** Second sub project **************** --> + <projects id="5" root_id="1" kee="org.struts:struts-ui" name="Struts UI" uuid="E" project_uuid="[null]" + module_uuid="[null]" module_uuid_path=".E." + scope="PRJ" qualifier="BRC" long_name="Struts UI" + description="[null]" enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" + created_at="[null]" path="[null]" deprecated_kee="org.struts:struts-ui" + authorization_updated_at="[null]"/> + + <!-- directory --> + <projects long_name="org.struts" id="6" scope="DIR" qualifier="DIR" kee="org.struts:struts-ui:/src/org/struts" + name="org.struts" root_id="5" uuid="F" project_uuid="[null]" module_uuid="[null]" module_uuid_path=".E." + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" created_at="[null]" + path="[null]" deprecated_kee="org.struts:struts-ui:org.struts" + authorization_updated_at="[null]"/> + + <!-- file --> + <projects long_name="org.struts.RequestContext" id="7" scope="FIL" qualifier="CLA" + kee="org.struts:struts-ui:/src/org/struts/RequestContext.java" + name="RequestContext" root_id="5" uuid="G" project_uuid="[null]" module_uuid="[null]" module_uuid_path=".E." + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" created_at="[null]" + path="[null]" deprecated_kee="org.struts:struts-ui:org.struts.RequestContext" + authorization_updated_at="[null]"/> + + + <!-- **************** Another independent project **************** --> + <projects id="8" root_id="[null]" kee="foo:struts-core" name="Foo Struts Core" uuid="H" project_uuid="[null]" + module_uuid="[null]" module_uuid_path=".H." + scope="PRJ" qualifier="BRC" long_name="Foo Struts Core" + description="[null]" enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" + created_at="[null]" path="[null]" deprecated_kee="foo:struts-core" + authorization_updated_at="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ResourceKeyUpdaterDaoTest/shouldBulkUpdateKey-result.xml b/sonar-db/src/test/resources/org/sonar/db/component/ResourceKeyUpdaterDaoTest/shouldBulkUpdateKey-result.xml new file mode 100644 index 00000000000..962995f42b6 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/component/ResourceKeyUpdaterDaoTest/shouldBulkUpdateKey-result.xml @@ -0,0 +1,73 @@ +<dataset> + + <!-- root project --> + <projects id="1" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.apache.struts:struts" name="Struts" uuid="A" + project_uuid="A" module_uuid="[null]" module_uuid_path="." + description="[null]" long_name="Apache Struts" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" created_at="[null]" + path="[null]" deprecated_kee="org.apache.struts:struts" + authorization_updated_at="[null]"/> + + + <!-- **************** First sub project **************** --> + <projects id="2" root_id="1" kee="org.apache.struts:struts-core" name="Struts Core" uuid="B" project_uuid="A" + module_uuid="[null]" module_uuid_path=".A." + scope="PRJ" qualifier="BRC" long_name="Struts Core" + description="[null]" enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" + created_at="[null]" path="[null]" deprecated_kee="org.apache.struts:struts-core" + authorization_updated_at="[null]"/> + + <!-- directory --> + <projects long_name="org.struts" id="3" scope="DIR" qualifier="DIR" + kee="org.apache.struts:struts-core:/src/org/struts" + name="org.struts" root_id="2" uuid="C" project_uuid="A" module_uuid="B" module_uuid_path=".A.B." + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" created_at="[null]" + path="[null]" deprecated_kee="org.apache.struts:struts-core:org.struts" + authorization_updated_at="[null]"/> + + <!-- file --> + <projects long_name="org.struts.RequestContext" id="4" scope="FIL" qualifier="CLA" + kee="org.apache.struts:struts-core:/src/org/struts/RequestContext.java" + name="RequestContext" root_id="2" uuid="D" project_uuid="A" module_uuid="B" module_uuid_path=".A.B." + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" created_at="[null]" + path="[null]" deprecated_kee="org.apache.struts:struts-core:org.struts.RequestContext" + authorization_updated_at="[null]"/> + + + <!-- **************** Second sub project **************** --> + <projects id="5" root_id="1" kee="org.apache.struts:struts-ui" name="Struts UI" uuid="E" project_uuid="[null]" + module_uuid="[null]" module_uuid_path=".E." + scope="PRJ" qualifier="BRC" long_name="Struts UI" + description="[null]" enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" + created_at="[null]" path="[null]" deprecated_kee="org.apache.struts:struts-ui" + authorization_updated_at="[null]"/> + + <!-- directory --> + <projects long_name="org.struts" id="6" scope="DIR" qualifier="DIR" kee="org.apache.struts:struts-ui:/src/org/struts" + name="org.struts" root_id="5" uuid="F" project_uuid="[null]" module_uuid="[null]" module_uuid_path=".E." + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" created_at="[null]" + path="[null]" deprecated_kee="org.apache.struts:struts-ui:org.struts" + authorization_updated_at="[null]"/> + + <!-- file --> + <projects long_name="org.struts.RequestContext" id="7" scope="FIL" qualifier="CLA" + kee="org.apache.struts:struts-ui:/src/org/struts/RequestContext.java" + name="RequestContext" root_id="5" uuid="G" project_uuid="[null]" module_uuid="[null]" module_uuid_path=".E." + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" created_at="[null]" + path="[null]" deprecated_kee="org.apache.struts:struts-ui:org.struts.RequestContext" + authorization_updated_at="[null]"/> + + + <!-- **************** Another independent project **************** --> + <projects id="8" root_id="[null]" kee="foo:struts-core" name="Foo Struts Core" uuid="H" project_uuid="[null]" + module_uuid="[null]" module_uuid_path=".H." + scope="PRJ" qualifier="BRC" long_name="Foo Struts Core" + description="[null]" enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" + created_at="[null]" path="[null]" deprecated_kee="foo:struts-core" + authorization_updated_at="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ResourceKeyUpdaterDaoTest/shouldBulkUpdateKeyOnOnlyOneSubmodule-result.xml b/sonar-db/src/test/resources/org/sonar/db/component/ResourceKeyUpdaterDaoTest/shouldBulkUpdateKeyOnOnlyOneSubmodule-result.xml new file mode 100644 index 00000000000..81e4290832e --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/component/ResourceKeyUpdaterDaoTest/shouldBulkUpdateKeyOnOnlyOneSubmodule-result.xml @@ -0,0 +1,72 @@ +<dataset> + + <!-- root project --> + <projects id="1" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" uuid="A" + project_uuid="A" module_uuid="[null]" module_uuid_path="." + description="[null]" long_name="Apache Struts" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" created_at="[null]" + path="[null]" deprecated_kee="org.struts:struts" + authorization_updated_at="[null]"/> + + + <!-- **************** First sub project **************** --> + <projects id="2" root_id="1" kee="org.struts:struts-core" name="Struts Core" uuid="B" project_uuid="A" + module_uuid="[null]" module_uuid_path=".A." + scope="PRJ" qualifier="BRC" long_name="Struts Core" + description="[null]" enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" + created_at="[null]" path="[null]" deprecated_kee="org.struts:struts-core" + authorization_updated_at="[null]"/> + + <!-- directory --> + <projects long_name="org.struts" id="3" scope="DIR" qualifier="DIR" kee="org.struts:struts-core:/src/org/struts" + name="org.struts" root_id="2" uuid="C" project_uuid="A" module_uuid="B" module_uuid_path=".A.B." + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" created_at="[null]" + path="[null]" deprecated_kee="org.struts:struts-core:org.struts" + authorization_updated_at="[null]"/> + + <!-- file --> + <projects long_name="org.struts.RequestContext" id="4" scope="FIL" qualifier="CLA" + kee="org.struts:struts-core:/src/org/struts/RequestContext.java" + name="RequestContext" root_id="2" uuid="D" project_uuid="A" module_uuid="B" module_uuid_path=".A.B." + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" created_at="[null]" + path="[null]" deprecated_kee="org.struts:struts-core:org.struts.RequestContext" + authorization_updated_at="[null]"/> + + + <!-- **************** Second sub project **************** --> + <projects id="5" root_id="1" kee="org.struts:struts-web" name="Struts UI" uuid="E" project_uuid="[null]" + module_uuid="[null]" module_uuid_path=".E." + scope="PRJ" qualifier="BRC" long_name="Struts UI" + description="[null]" enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" + created_at="[null]" path="[null]" deprecated_kee="org.struts:struts-web" + authorization_updated_at="[null]"/> + + <!-- directory --> + <projects long_name="org.struts" id="6" scope="DIR" qualifier="DIR" kee="org.struts:struts-web:/src/org/struts" + name="org.struts" root_id="5" uuid="F" project_uuid="[null]" module_uuid="[null]" module_uuid_path=".E." + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" created_at="[null]" + path="[null]" deprecated_kee="org.struts:struts-web:org.struts" + authorization_updated_at="[null]"/> + + <!-- file --> + <projects long_name="org.struts.RequestContext" id="7" scope="FIL" qualifier="CLA" + kee="org.struts:struts-web:/src/org/struts/RequestContext.java" + name="RequestContext" root_id="5" uuid="G" project_uuid="[null]" module_uuid="[null]" module_uuid_path=".E." + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" created_at="[null]" + path="[null]" deprecated_kee="org.struts:struts-web:org.struts.RequestContext" + authorization_updated_at="[null]"/> + + + <!-- **************** Another independent project **************** --> + <projects id="8" root_id="[null]" kee="foo:struts-core" name="Foo Struts Core" uuid="H" project_uuid="[null]" + module_uuid="[null]" module_uuid_path=".H." + scope="PRJ" qualifier="BRC" long_name="Foo Struts Core" + description="[null]" enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" + created_at="[null]" path="[null]" deprecated_kee="foo:struts-core" + authorization_updated_at="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ResourceKeyUpdaterDaoTest/shouldNotUpdateAllSubmodules-result.xml b/sonar-db/src/test/resources/org/sonar/db/component/ResourceKeyUpdaterDaoTest/shouldNotUpdateAllSubmodules-result.xml new file mode 100644 index 00000000000..83686f2ba90 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/component/ResourceKeyUpdaterDaoTest/shouldNotUpdateAllSubmodules-result.xml @@ -0,0 +1,64 @@ +<dataset> + + <!-- root project --> + <projects id="1" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.apache.struts:struts" name="Struts" uuid="A" + project_uuid="A" module_uuid="[null]" module_uuid_path="." + description="[null]" long_name="Apache Struts" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" created_at="[null]" + path="[null]" deprecated_kee="org.apache.struts:struts" + authorization_updated_at="[null]"/> + + + <!-- **************** First sub project **************** --> + <projects id="2" root_id="1" kee="org.apache.struts:struts-core" name="Struts Core" uuid="B" project_uuid="A" + module_uuid="[null]" module_uuid_path=".A." + scope="PRJ" qualifier="BRC" long_name="Struts Core" + description="[null]" enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" + created_at="[null]" path="[null]" deprecated_kee="org.apache.struts:struts-core" + authorization_updated_at="[null]"/> + + <!-- directory --> + <projects long_name="org.struts" id="3" scope="DIR" qualifier="PAC" + kee="org.apache.struts:struts-core:/src/org/struts" + name="org.struts" root_id="2" uuid="C" project_uuid="A" module_uuid="B" module_uuid_path=".A.B." + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" created_at="[null]" + path="[null]" deprecated_kee="org.apache.struts:struts-core:org.struts" + authorization_updated_at="[null]"/> + + <!-- file --> + <projects long_name="org.struts.RequestContext" id="4" scope="FIL" qualifier="CLA" + kee="org.apache.struts:struts-core:/src/org/struts/RequestContext.java" + name="RequestContext" root_id="2" uuid="D" project_uuid="A" module_uuid="B" module_uuid_path=".A.B." + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" created_at="[null]" + path="[null]" deprecated_kee="org.apache.struts:struts-core:org.struts.RequestContext" + authorization_updated_at="[null]"/> + + + <!-- **************** Second sub project THAT HAS A DIFFERENT GROUP ID => MUST NOT BE UPDATED **************** --> + <projects id="5" root_id="1" kee="foo:struts-ui" name="Struts UI" uuid="E" project_uuid="[null]" module_uuid="[null]" + module_uuid_path=".E." + scope="PRJ" qualifier="BRC" long_name="Struts UI" + description="[null]" enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" + created_at="[null]" path="[null]" deprecated_kee="foo:struts-ui" + authorization_updated_at="[null]"/> + + <!-- directory --> + <projects long_name="org.struts" id="6" scope="DIR" qualifier="PAC" kee="foo:struts-ui:/src/org/struts" + name="org.struts" root_id="5" uuid="F" project_uuid="[null]" module_uuid="[null]" module_uuid_path=".E." + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" created_at="[null]" + path="[null]" deprecated_kee="foo:struts-ui:org.struts" + authorization_updated_at="[null]"/> + + <!-- file --> + <projects long_name="org.struts.RequestContext" id="7" scope="FIL" qualifier="CLA" + kee="foo:struts-ui:/src/org/struts/RequestContext.java" + name="RequestContext" root_id="5" uuid="G" project_uuid="[null]" module_uuid="[null]" module_uuid_path=".E." + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" created_at="[null]" + path="[null]" deprecated_kee="foo:struts-ui:org.struts.RequestContext" + authorization_updated_at="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ResourceKeyUpdaterDaoTest/shouldNotUpdateAllSubmodules.xml b/sonar-db/src/test/resources/org/sonar/db/component/ResourceKeyUpdaterDaoTest/shouldNotUpdateAllSubmodules.xml new file mode 100644 index 00000000000..5021b0c56bc --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/component/ResourceKeyUpdaterDaoTest/shouldNotUpdateAllSubmodules.xml @@ -0,0 +1,63 @@ +<dataset> + + <!-- root project --> + <projects id="1" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" uuid="A" + project_uuid="A" module_uuid="[null]" module_uuid_path="." + description="[null]" long_name="Apache Struts" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" created_at="[null]" + path="[null]" deprecated_kee="org.struts:struts" + authorization_updated_at="[null]"/> + + + <!-- **************** First sub project **************** --> + <projects id="2" root_id="1" kee="org.struts:struts-core" name="Struts Core" uuid="B" project_uuid="A" + module_uuid="[null]" module_uuid_path=".A." + scope="PRJ" qualifier="BRC" long_name="Struts Core" + description="[null]" enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" + created_at="[null]" path="[null]" deprecated_kee="org.struts:struts-core" + authorization_updated_at="[null]"/> + + <!-- directory --> + <projects long_name="org.struts" id="3" scope="DIR" qualifier="PAC" kee="org.struts:struts-core:/src/org/struts" + name="org.struts" root_id="2" uuid="C" project_uuid="A" module_uuid="B" module_uuid_path=".A.B." + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" created_at="[null]" + path="[null]" deprecated_kee="org.struts:struts-core:org.struts" + authorization_updated_at="[null]"/> + + <!-- file --> + <projects long_name="org.struts.RequestContext" id="4" scope="FIL" qualifier="CLA" + kee="org.struts:struts-core:/src/org/struts/RequestContext.java" + name="RequestContext" root_id="2" uuid="D" project_uuid="A" module_uuid="B" module_uuid_path=".A.B." + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" created_at="[null]" + path="[null]" deprecated_kee="org.struts:struts-core:org.struts.RequestContext" + authorization_updated_at="[null]"/> + + + <!-- **************** Second sub project THAT HAS A DIFFERENT GROUP ID => MUST NOT BE UPDATED **************** --> + <projects id="5" root_id="1" kee="foo:struts-ui" name="Struts UI" uuid="E" project_uuid="[null]" module_uuid="[null]" + module_uuid_path=".E." + scope="PRJ" qualifier="BRC" long_name="Struts UI" + description="[null]" enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" + created_at="[null]" path="[null]" deprecated_kee="foo:struts-ui" + authorization_updated_at="[null]"/> + + <!-- directory --> + <projects long_name="org.struts" id="6" scope="DIR" qualifier="PAC" kee="foo:struts-ui:/src/org/struts" + name="org.struts" root_id="5" uuid="F" project_uuid="[null]" module_uuid="[null]" module_uuid_path=".E." + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" created_at="[null]" + path="[null]" deprecated_kee="foo:struts-ui:org.struts" + authorization_updated_at="[null]"/> + + <!-- file --> + <projects long_name="org.struts.RequestContext" id="7" scope="FIL" qualifier="CLA" + kee="foo:struts-ui:/src/org/struts/RequestContext.java" + name="RequestContext" root_id="5" uuid="G" project_uuid="[null]" module_uuid="[null]" module_uuid_path=".E." + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" created_at="[null]" + path="[null]" deprecated_kee="foo:struts-ui:org.struts.RequestContext" + authorization_updated_at="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ResourceKeyUpdaterDaoTest/shouldUpdateKey-result.xml b/sonar-db/src/test/resources/org/sonar/db/component/ResourceKeyUpdaterDaoTest/shouldUpdateKey-result.xml new file mode 100644 index 00000000000..a7a9d68d42a --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/component/ResourceKeyUpdaterDaoTest/shouldUpdateKey-result.xml @@ -0,0 +1,74 @@ +<dataset> + + <!-- root project --> + <projects id="1" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" uuid="A" + project_uuid="A" module_uuid="[null]" module_uuid_path="." + description="[null]" long_name="Apache Struts" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" created_at="[null]" + path="[null]" deprecated_kee="org.struts:struts" + authorization_updated_at="[null]"/> + + + <!-- **************** First sub project **************** --> + <!-- ONLY THIS PROJECT MUST HAVE BEEN UPDATED --> + <!-- --> + <projects id="2" root_id="1" kee="struts:core" name="Struts Core" uuid="B" project_uuid="A" module_uuid="[null]" + module_uuid_path=".A." + scope="PRJ" qualifier="BRC" long_name="Struts Core" + description="[null]" enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" + created_at="[null]" path="[null]" deprecated_kee="struts:core" + authorization_updated_at="[null]"/> + + <!-- directory --> + <projects long_name="org.struts" id="3" scope="DIR" qualifier="DIR" kee="struts:core:/src/org/struts" + name="org.struts" root_id="2" uuid="C" project_uuid="A" module_uuid="B" module_uuid_path=".A.B." + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" created_at="[null]" + path="[null]" deprecated_kee="struts:core:org.struts" + authorization_updated_at="[null]"/> + + <!-- file --> + <projects long_name="org.struts.RequestContext" id="4" scope="FIL" qualifier="CLA" + kee="struts:core:/src/org/struts/RequestContext.java" + name="RequestContext" root_id="2" uuid="D" project_uuid="A" module_uuid="B" module_uuid_path=".A.B." + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" created_at="[null]" + path="[null]" deprecated_kee="struts:core:org.struts.RequestContext" + authorization_updated_at="[null]"/> + + + <!-- **************** Second sub project **************** --> + <projects id="5" root_id="1" kee="org.struts:struts-ui" name="Struts UI" uuid="E" project_uuid="[null]" + module_uuid="[null]" module_uuid_path=".E." + scope="PRJ" qualifier="BRC" long_name="Struts UI" + description="[null]" enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" + created_at="[null]" path="[null]" deprecated_kee="org.struts:struts-ui" + authorization_updated_at="[null]"/> + + <!-- directory --> + <projects long_name="org.struts" id="6" scope="DIR" qualifier="DIR" kee="org.struts:struts-ui:/src/org/struts" + name="org.struts" root_id="5" uuid="F" project_uuid="[null]" module_uuid="[null]" module_uuid_path=".E." + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" created_at="[null]" + path="[null]" deprecated_kee="org.struts:struts-ui:org.struts" + authorization_updated_at="[null]"/> + + <!-- file --> + <projects long_name="org.struts.RequestContext" id="7" scope="FIL" qualifier="CLA" + kee="org.struts:struts-ui:/src/org/struts/RequestContext.java" + name="RequestContext" root_id="5" uuid="G" project_uuid="[null]" module_uuid="[null]" module_uuid_path=".E." + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" created_at="[null]" + path="[null]" deprecated_kee="org.struts:struts-ui:org.struts.RequestContext" + authorization_updated_at="[null]"/> + + + <!-- **************** Another independent project **************** --> + <projects id="8" root_id="[null]" kee="foo:struts-core" name="Foo Struts Core" uuid="H" project_uuid="[null]" + module_uuid="[null]" module_uuid_path=".H." + scope="PRJ" qualifier="BRC" long_name="Foo Struts Core" + description="[null]" enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" + created_at="[null]" path="[null]" deprecated_kee="foo:struts-core" + authorization_updated_at="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/dashboard/ActiveDashboardDaoTest/empty.xml b/sonar-db/src/test/resources/org/sonar/db/dashboard/ActiveDashboardDaoTest/empty.xml new file mode 100644 index 00000000000..871dedcb5e9 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/dashboard/ActiveDashboardDaoTest/empty.xml @@ -0,0 +1,3 @@ +<dataset> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/dashboard/ActiveDashboardDaoTest/shouldGetMaxOrderIndexForNullUser.xml b/sonar-db/src/test/resources/org/sonar/db/dashboard/ActiveDashboardDaoTest/shouldGetMaxOrderIndexForNullUser.xml new file mode 100644 index 00000000000..1a3d92374b6 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/dashboard/ActiveDashboardDaoTest/shouldGetMaxOrderIndexForNullUser.xml @@ -0,0 +1,21 @@ +<dataset> + + <active_dashboards + id="1" + dashboard_id="1" + user_id="[null]" + order_index="1"/> + + <active_dashboards + id="2" + dashboard_id="2" + user_id="[null]" + order_index="15"/> + + <active_dashboards + id="3" + dashboard_id="3" + user_id="3" + order_index="25"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/dashboard/ActiveDashboardDaoTest/shouldInsert-result.xml b/sonar-db/src/test/resources/org/sonar/db/dashboard/ActiveDashboardDaoTest/shouldInsert-result.xml new file mode 100644 index 00000000000..75fb1670ce7 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/dashboard/ActiveDashboardDaoTest/shouldInsert-result.xml @@ -0,0 +1,9 @@ +<dataset> + + <active_dashboards + id="1" + dashboard_id="2" + user_id="3" + order_index="4"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/dashboard/ActiveDashboardDaoTest/shouldInsert.xml b/sonar-db/src/test/resources/org/sonar/db/dashboard/ActiveDashboardDaoTest/shouldInsert.xml new file mode 100644 index 00000000000..871dedcb5e9 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/dashboard/ActiveDashboardDaoTest/shouldInsert.xml @@ -0,0 +1,3 @@ +<dataset> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/dashboard/ActiveDashboardDaoTest/shouldInsertWithNoUser-result.xml b/sonar-db/src/test/resources/org/sonar/db/dashboard/ActiveDashboardDaoTest/shouldInsertWithNoUser-result.xml new file mode 100644 index 00000000000..a247a4f7c4d --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/dashboard/ActiveDashboardDaoTest/shouldInsertWithNoUser-result.xml @@ -0,0 +1,9 @@ +<dataset> + + <active_dashboards + id="1" + dashboard_id="2" + user_id="[null]" + order_index="4"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/dashboard/ActiveDashboardDaoTest/shouldSelectDashboardsForAnonymous.xml b/sonar-db/src/test/resources/org/sonar/db/dashboard/ActiveDashboardDaoTest/shouldSelectDashboardsForAnonymous.xml new file mode 100644 index 00000000000..0fbe3bcf9ec --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/dashboard/ActiveDashboardDaoTest/shouldSelectDashboardsForAnonymous.xml @@ -0,0 +1,68 @@ +<dataset> + + <users id="42" login="obiwan" name="Obiwan" email="obiwan@keno.bi" + created_at="1418215735482" updated_at="1418215735482" active="[true]"/> + + <dashboards + id="1" + user_id="1" + name="My Dashboard" + description="Dashboard shared by admin" + column_layout="100%" + shared="[true]" + is_global="[true]" + /> + <dashboards + id="2" + user_id="[null]" + name="Default Dashboard" + description="Dashboard provided by system" + column_layout="100%" + shared="[true]" + is_global="[true]" + /> + <dashboards + id="3" + user_id="[null]" + name="Project Dashboard" + description="Won't appear, not global" + column_layout="100%" + shared="[true]" + is_global="[false]" + /> + <dashboards + id="4" + user_id="[null]" + name="User Dashboard" + description="Won't appear, not anonymous" + column_layout="100%" + shared="[true]" + is_global="[true]" + /> + + <!-- Dashboard with ID 1 appears after ID 2 --> + <active_dashboards + id="1" + dashboard_id="1" + user_id="[null]" + order_index="2"/> + <!-- Dashboard with ID 2 appears before ID 1 --> + <active_dashboards + id="2" + dashboard_id="2" + user_id="[null]" + order_index="1"/> + <!-- Dashboard with ID 3 does not appear (not global) --> + <active_dashboards + id="3" + dashboard_id="3" + user_id="[null]" + order_index="1"/> + <!-- Dashboard with ID 4 does not appear (not anonymous) --> + <active_dashboards + id="4" + dashboard_id="4" + user_id="42" + order_index="1"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/dashboard/ActiveDashboardDaoTest/shouldSelectDashboardsForUser.xml b/sonar-db/src/test/resources/org/sonar/db/dashboard/ActiveDashboardDaoTest/shouldSelectDashboardsForUser.xml new file mode 100644 index 00000000000..fd674277db0 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/dashboard/ActiveDashboardDaoTest/shouldSelectDashboardsForUser.xml @@ -0,0 +1,85 @@ +<dataset> + + <users id="24" login="anakin" name="Anakin" email="anakin@skywalk.er" + created_at="1418215735482" updated_at="1418215735482" active="[true]"/> + <users id="42" login="obiwan" name="Obiwan" email="obiwan@keno.bi" + created_at="1418215735482" updated_at="1418215735482" active="[true]"/> + + <dashboards + id="1" + user_id="1" + name="My Dashboard" + description="Dashboard shared by admin" + column_layout="100%" + shared="[true]" + is_global="[true]" + /> + <dashboards + id="2" + user_id="[null]" + name="Default Dashboard" + description="Dashboard provided by system" + column_layout="100%" + shared="[true]" + is_global="[true]" + /> + <dashboards + id="3" + user_id="[null]" + name="Project Dashboard" + description="Won't appear, not global" + column_layout="100%" + shared="[true]" + is_global="[false]" + /> + <dashboards + id="4" + user_id="[null]" + name="Anonymous Dashboard" + description="Won't appear, anonymous" + column_layout="100%" + shared="[true]" + is_global="[true]" + /> + <dashboards + id="5" + user_id="[null]" + name="Another User Dashboard" + description="Won't appear, different user" + column_layout="100%" + shared="[true]" + is_global="[true]" + /> + + <!-- Dashboard with ID 1 appears after ID 2 --> + <active_dashboards + id="1" + dashboard_id="1" + user_id="42" + order_index="2"/> + <!-- Dashboard with ID 2 appears before ID 1 --> + <active_dashboards + id="2" + dashboard_id="2" + user_id="42" + order_index="1"/> + <!-- Dashboard with ID 3 does not appear (not global) --> + <active_dashboards + id="3" + dashboard_id="3" + user_id="42" + order_index="1"/> + <!-- Dashboard with ID 4 does not appear (anonymous) --> + <active_dashboards + id="4" + dashboard_id="4" + user_id="[null]" + order_index="1"/> + <!-- Dashboard with ID 5 does not appear (another user) --> + <active_dashboards + id="5" + dashboard_id="5" + user_id="24" + order_index="1"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/dashboard/ActiveDashboardDaoTest/shouldSelectProjectDashboardsForAnonymous.xml b/sonar-db/src/test/resources/org/sonar/db/dashboard/ActiveDashboardDaoTest/shouldSelectProjectDashboardsForAnonymous.xml new file mode 100644 index 00000000000..0160b3a25d4 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/dashboard/ActiveDashboardDaoTest/shouldSelectProjectDashboardsForAnonymous.xml @@ -0,0 +1,68 @@ +<dataset> + + <users id="42" login="obiwan" name="Obiwan" email="obiwan@keno.bi" + created_at="1418215735482" updated_at="1418215735482" active="[true]"/> + + <dashboards + id="1" + user_id="1" + name="My Dashboard" + description="Dashboard shared by admin" + column_layout="100%" + shared="[true]" + is_global="[false]" + /> + <dashboards + id="2" + user_id="[null]" + name="Default Dashboard" + description="Dashboard provided by system" + column_layout="100%" + shared="[true]" + is_global="[false]" + /> + <dashboards + id="3" + user_id="[null]" + name="Project Dashboard" + description="Won't appear, global" + column_layout="100%" + shared="[true]" + is_global="[true]" + /> + <dashboards + id="4" + user_id="[null]" + name="User Dashboard" + description="Won't appear, not anonymous" + column_layout="100%" + shared="[true]" + is_global="[false]" + /> + + <!-- Dashboard with ID 1 appears after ID 2 --> + <active_dashboards + id="1" + dashboard_id="1" + user_id="[null]" + order_index="2"/> + <!-- Dashboard with ID 2 appears before ID 1 --> + <active_dashboards + id="2" + dashboard_id="2" + user_id="[null]" + order_index="1"/> + <!-- Dashboard with ID 3 does not appear (global) --> + <active_dashboards + id="3" + dashboard_id="3" + user_id="[null]" + order_index="1"/> + <!-- Dashboard with ID 4 does not appear (not anonymous) --> + <active_dashboards + id="4" + dashboard_id="4" + user_id="42" + order_index="1"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/dashboard/ActiveDashboardDaoTest/shouldSelectProjectDashboardsForUser.xml b/sonar-db/src/test/resources/org/sonar/db/dashboard/ActiveDashboardDaoTest/shouldSelectProjectDashboardsForUser.xml new file mode 100644 index 00000000000..3f70d81896f --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/dashboard/ActiveDashboardDaoTest/shouldSelectProjectDashboardsForUser.xml @@ -0,0 +1,85 @@ +<dataset> + + <users id="24" login="anakin" name="Anakin" email="anakin@skywalk.er" + created_at="1418215735482" updated_at="1418215735482" active="[true]"/> + <users id="42" login="obiwan" name="Obiwan" email="obiwan@keno.bi" + created_at="1418215735482" updated_at="1418215735482" active="[true]"/> + + <dashboards + id="1" + user_id="1" + name="My Dashboard" + description="Dashboard shared by admin" + column_layout="100%" + shared="[true]" + is_global="[false]" + /> + <dashboards + id="2" + user_id="[null]" + name="Default Dashboard" + description="Dashboard provided by system" + column_layout="100%" + shared="[true]" + is_global="[false]" + /> + <dashboards + id="3" + user_id="[null]" + name="Project Dashboard" + description="Won't appear, global" + column_layout="100%" + shared="[true]" + is_global="[true]" + /> + <dashboards + id="4" + user_id="[null]" + name="Anonymous Dashboard" + description="Won't appear, anonymous" + column_layout="100%" + shared="[true]" + is_global="[false]" + /> + <dashboards + id="5" + user_id="[null]" + name="Another User Dashboard" + description="Won't appear, different user" + column_layout="100%" + shared="[true]" + is_global="[false]" + /> + + <!-- Dashboard with ID 1 appears after ID 2 --> + <active_dashboards + id="1" + dashboard_id="1" + user_id="42" + order_index="2"/> + <!-- Dashboard with ID 2 appears before ID 1 --> + <active_dashboards + id="2" + dashboard_id="2" + user_id="42" + order_index="1"/> + <!-- Dashboard with ID 3 does not appear (global) --> + <active_dashboards + id="3" + dashboard_id="3" + user_id="42" + order_index="1"/> + <!-- Dashboard with ID 4 does not appear (anonymous) --> + <active_dashboards + id="4" + dashboard_id="4" + user_id="[null]" + order_index="1"/> + <!-- Dashboard with ID 5 does not appear (another user) --> + <active_dashboards + id="5" + dashboard_id="5" + user_id="24" + order_index="1"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/dashboard/DashboardDaoTest/shouldInsert-result.xml b/sonar-db/src/test/resources/org/sonar/db/dashboard/DashboardDaoTest/shouldInsert-result.xml new file mode 100644 index 00000000000..86d9180988f --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/dashboard/DashboardDaoTest/shouldInsert-result.xml @@ -0,0 +1,32 @@ +<dataset> + + <dashboards + id="1" + user_id="6" + name="My Dashboard" + description="This is a dashboard" + column_layout="100%" + shared="[true]" + is_global="[true]" + /> + + <widgets + id="1" + dashboard_id="1" + widget_key="code_coverage" + name="Code coverage" + description="Widget for code coverage" + column_index="13" + row_index="14" + configured="[true]" + resource_id="[null]" + /> + + <widget_properties + id="1" + widget_id="1" + kee="displayITs" + text_value="true" + /> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/dashboard/DashboardDaoTest/shouldInsert.xml b/sonar-db/src/test/resources/org/sonar/db/dashboard/DashboardDaoTest/shouldInsert.xml new file mode 100644 index 00000000000..871dedcb5e9 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/dashboard/DashboardDaoTest/shouldInsert.xml @@ -0,0 +1,3 @@ +<dataset> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/dashboard/DashboardDaoTest/shouldInsertWithNullableColumns-result.xml b/sonar-db/src/test/resources/org/sonar/db/dashboard/DashboardDaoTest/shouldInsertWithNullableColumns-result.xml new file mode 100644 index 00000000000..00257e4b937 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/dashboard/DashboardDaoTest/shouldInsertWithNullableColumns-result.xml @@ -0,0 +1,36 @@ +<dataset> + + <dashboards + id="1" + user_id="[null]" + name="[null]" + description="[null]" + column_layout="[null]" + shared="[true]" + is_global="[false]" + created_at="[null]" + updated_at="[null]" + /> + + <widgets + id="1" + dashboard_id="1" + widget_key="code_coverage" + name="[null]" + description="[null]" + column_index="[null]" + row_index="[null]" + configured="[true]" + created_at="[null]" + updated_at="[null]" + resource_id="[null]" + /> + + <widget_properties + id="1" + widget_id="1" + kee="[null]" + text_value="[null]" + /> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/dashboard/DashboardDaoTest/shouldSelectGlobalDashboard.xml b/sonar-db/src/test/resources/org/sonar/db/dashboard/DashboardDaoTest/shouldSelectGlobalDashboard.xml new file mode 100644 index 00000000000..110e760f9ad --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/dashboard/DashboardDaoTest/shouldSelectGlobalDashboard.xml @@ -0,0 +1,21 @@ +<dataset> + + <dashboards + id="1" + user_id="6" + name="SQALE" + description="User SQALE dashboard" + column_layout="100%" + shared="[true]" + /> + + <dashboards + id="2" + user_id="[null]" + name="SQALE" + description="Global SQALE dashboard" + column_layout="100%" + shared="[true]" + /> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/debt/CharacteristicDaoTest/insert_characteristic-result.xml b/sonar-db/src/test/resources/org/sonar/db/debt/CharacteristicDaoTest/insert_characteristic-result.xml new file mode 100644 index 00000000000..f0ac4524f65 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/debt/CharacteristicDaoTest/insert_characteristic-result.xml @@ -0,0 +1,7 @@ +<dataset> + + <characteristics id="1" kee="COMPILER_RELATED_PORTABILITY" name="Compiler related portability" parent_id="[null]" + characteristic_order="1" enabled="[true]" + created_at="2013-11-20" updated_at="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/debt/CharacteristicDaoTest/select_enabled_root_characteristics.xml b/sonar-db/src/test/resources/org/sonar/db/debt/CharacteristicDaoTest/select_enabled_root_characteristics.xml new file mode 100644 index 00000000000..8a6e7472bc4 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/debt/CharacteristicDaoTest/select_enabled_root_characteristics.xml @@ -0,0 +1,24 @@ +<dataset> + + <characteristics id="1" kee="PORTABILITY" name="Portability" parent_id="[null]" characteristic_order="1" + enabled="[true]" + created_at="2013-11-20" updated_at="2013-11-22"/> + + <characteristics id="2" kee="COMPILER_RELATED_PORTABILITY" name="Compiler related portability" parent_id="1" + characteristic_order="[null]" + enabled="[true]" + created_at="2013-11-20" updated_at="2013-11-22"/> + + <!-- requirement --> + <characteristics id="3" kee="[null]" name="[null]" parent_id="2" rule_id="1" + function_key="linear_offset" factor_value="20.0" factor_unit="mn" offset_value="30.0" offset_unit="h" + enabled="[true]" + created_at="2013-11-20" updated_at="[null]"/> + + <!-- disabled characteristics --> + <characteristics id="4" kee="DISABLED_CHARACTERISTIC" name="Disabled characteristic" parent_id="1" + characteristic_order="2" + enabled="[false]" + created_at="2013-11-20" updated_at="2013-11-22"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/debt/CharacteristicDaoTest/select_enabled_root_characteristics_order_by_characteristic_order.xml b/sonar-db/src/test/resources/org/sonar/db/debt/CharacteristicDaoTest/select_enabled_root_characteristics_order_by_characteristic_order.xml new file mode 100644 index 00000000000..59f106fe411 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/debt/CharacteristicDaoTest/select_enabled_root_characteristics_order_by_characteristic_order.xml @@ -0,0 +1,15 @@ +<dataset> + + <characteristics id="1" kee="PORTABILITY" name="Portability" parent_id="[null]" characteristic_order="2" + enabled="[true]" + created_at="2013-11-20" updated_at="2013-11-22"/> + + <characteristics id="2" kee="TESTABILITY" name="Testability" parent_id="[null]" characteristic_order="1" + enabled="[true]" + created_at="2013-11-20" updated_at="2013-11-22"/> + + <characteristics id="3" kee="MAINTAINABILITY" name="Maintainability" parent_id="[null]" characteristic_order="4" + enabled="[true]" + created_at="2013-11-20" updated_at="2013-11-22"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/debt/CharacteristicDaoTest/select_max_characteristic_order_when_characteristics_are_all_disabled.xml b/sonar-db/src/test/resources/org/sonar/db/debt/CharacteristicDaoTest/select_max_characteristic_order_when_characteristics_are_all_disabled.xml new file mode 100644 index 00000000000..d703591428a --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/debt/CharacteristicDaoTest/select_max_characteristic_order_when_characteristics_are_all_disabled.xml @@ -0,0 +1,14 @@ +<dataset> + + <!-- Disabled root characteristic --> + <characteristics id="1" kee="PORTABILITY" name="Portability" parent_id="[null]" characteristic_order="1" + enabled="[false]" + created_at="2013-11-20" updated_at="2013-11-22"/> + + <!-- Disabled root characteristic --> + <characteristics id="2" kee="DISABLED_ROOT_CHARACTERISTIC" name="Disabled root characteristic" parent_id="[null]" + characteristic_order="2" + enabled="[false]" + created_at="2013-11-20" updated_at="2013-11-22"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/debt/CharacteristicDaoTest/select_sub_characteristics_by_parent_id.xml b/sonar-db/src/test/resources/org/sonar/db/debt/CharacteristicDaoTest/select_sub_characteristics_by_parent_id.xml new file mode 100644 index 00000000000..60aa6d6fdfb --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/debt/CharacteristicDaoTest/select_sub_characteristics_by_parent_id.xml @@ -0,0 +1,35 @@ +<dataset> + + <!-- Root characteristic --> + <characteristics id="1" kee="PORTABILITY" name="Portability" parent_id="[null]" characteristic_order="1" + enabled="[true]" + created_at="2013-11-20" updated_at="2013-11-22"/> + + <!-- Sub characteristics of root characteristic --> + <characteristics id="2" kee="COMPILER_RELATED_PORTABILITY" name="Compiler related portability" parent_id="1" + characteristic_order="[null]" + enabled="[true]" + created_at="2013-11-20" updated_at="2013-11-22"/> + <characteristics id="3" kee="HARDWARE_RELATED_PORTABILITY" name="Hardware related portability " parent_id="1" + characteristic_order="[null]" + enabled="[true]" + created_at="2013-11-20" updated_at="2013-11-22"/> + + <!-- Other sub characteristic --> + <characteristics id="4" kee="READABILITY" name="Readability" parent_id="5" characteristic_order="[null]" + enabled="[true]" + created_at="2013-11-20" updated_at="2013-11-22"/> + + <!-- Disabled root characteristic --> + <characteristics id="10" kee="DISABLED_ROOT_CHARACTERISTIC" name="Disabled root characteristic" parent_id="[null]" + characteristic_order="2" + enabled="[false]" + created_at="2013-11-20" updated_at="2013-11-22"/> + + <!-- Disabled characteristic --> + <characteristics id="11" kee="DISABLED_CHARACTERISTIC" name="Disabled characteristic" parent_id="10" + characteristic_order="[null]" + enabled="[false]" + created_at="2013-11-20" updated_at="2013-11-22"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/debt/CharacteristicDaoTest/shared.xml b/sonar-db/src/test/resources/org/sonar/db/debt/CharacteristicDaoTest/shared.xml new file mode 100644 index 00000000000..284d01bed45 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/debt/CharacteristicDaoTest/shared.xml @@ -0,0 +1,26 @@ +<dataset> + + <!-- Root characteristic --> + <characteristics id="1" kee="PORTABILITY" name="Portability" parent_id="[null]" characteristic_order="1" + enabled="[true]" + created_at="2013-11-20" updated_at="2013-11-22"/> + + <!-- Characteristic --> + <characteristics id="2" kee="COMPILER_RELATED_PORTABILITY" name="Compiler related portability" parent_id="1" + characteristic_order="[null]" + enabled="[true]" + created_at="2013-11-20" updated_at="2013-11-22"/> + + <!-- Disabled root characteristic --> + <characteristics id="4" kee="DISABLED_ROOT_CHARACTERISTIC" name="Disabled root characteristic" parent_id="[null]" + characteristic_order="2" + enabled="[false]" + created_at="2013-11-20" updated_at="2013-11-22"/> + + <!-- Disabled characteristic --> + <characteristics id="5" kee="DISABLED_CHARACTERISTIC" name="Disabled characteristic" parent_id="4" + characteristic_order="[null]" + enabled="[false]" + created_at="2013-11-20" updated_at="2013-11-22"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/debt/CharacteristicDaoTest/update_characteristic-result.xml b/sonar-db/src/test/resources/org/sonar/db/debt/CharacteristicDaoTest/update_characteristic-result.xml new file mode 100644 index 00000000000..ff12f94cee6 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/debt/CharacteristicDaoTest/update_characteristic-result.xml @@ -0,0 +1,7 @@ +<dataset> + + <characteristics id="1" kee="COMPILER_RELATED_PORTABILITY" name="New name" parent_id="[null]" characteristic_order="2" + enabled="[false]" + created_at="2013-11-20" updated_at="2014-03-19"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/debt/CharacteristicDaoTest/update_characteristic.xml b/sonar-db/src/test/resources/org/sonar/db/debt/CharacteristicDaoTest/update_characteristic.xml new file mode 100644 index 00000000000..afa53fb186d --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/debt/CharacteristicDaoTest/update_characteristic.xml @@ -0,0 +1,7 @@ +<dataset> + + <characteristics id="1" kee="COMPILER_RELATED_PORTABILITY" name="Compiler related portability" parent_id="[null]" + characteristic_order="1" enabled="[true]" + created_at="2013-11-20" updated_at="2013-11-20"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/debt/RequirementDaoTest/select_requirement.xml b/sonar-db/src/test/resources/org/sonar/db/debt/RequirementDaoTest/select_requirement.xml new file mode 100644 index 00000000000..1a71559a016 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/debt/RequirementDaoTest/select_requirement.xml @@ -0,0 +1,10 @@ +<dataset> + + <!-- Requirement --> + <characteristics id="3" kee="[null]" name="[null]" parent_id="2" root_id="1" rule_id="10" + characteristic_order="[null]" + function_key="linear_offset" factor_value="20.0" factor_unit="mn" offset_value="30.0" offset_unit="h" + enabled="[true]" + created_at="2013-11-20" updated_at="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/debt/RequirementDaoTest/shared.xml b/sonar-db/src/test/resources/org/sonar/db/debt/RequirementDaoTest/shared.xml new file mode 100644 index 00000000000..0ee097f0869 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/debt/RequirementDaoTest/shared.xml @@ -0,0 +1,17 @@ +<dataset> + + <!-- Requirement --> + <characteristics id="3" kee="[null]" name="[null]" parent_id="2" root_id="1" rule_id="10" + characteristic_order="[null]" + function_key="linear_offset" factor_value="20.0" factor_unit="mn" offset_value="30.0" offset_unit="h" + enabled="[true]" + created_at="2013-11-20" updated_at="[null]"/> + + <!-- Disabled requirement --> + <characteristics id="6" kee="[null]" name="[null]" parent_id="5" root_id="4" rule_id="10" + characteristic_order="[null]" + function_key="linear_offset" factor_value="30.0" factor_unit="mn" offset_value="20.0" offset_unit="h" + enabled="[false]" + created_at="2013-11-20" updated_at="2013-11-22"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/duplication/DuplicationDaoTest/shouldGetByHash.xml b/sonar-db/src/test/resources/org/sonar/db/duplication/DuplicationDaoTest/shouldGetByHash.xml new file mode 100644 index 00000000000..37efb6149f0 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/duplication/DuplicationDaoTest/shouldGetByHash.xml @@ -0,0 +1,61 @@ +<dataset> + + <snapshots id="1" project_id="1" status="P" islast="0" purge_status="[null]"/> + <snapshots id="2" project_id="1" status="P" islast="0" purge_status="[null]"/> + <projects id="1" uuid="1" kee="bar-old" enabled="1" scope="FIL" qualifier="CLA" language="java"/> + + <snapshots id="3" project_id="2" status="P" islast="1" purge_status="[null]"/> + <snapshots id="4" project_id="2" status="P" islast="1" purge_status="[null]"/> + <projects id="2" uuid="2" kee="bar-last" enabled="1" scope="FIL" qualifier="CLA" language="java"/> + + <snapshots id="5" project_id="3" status="P" islast="0" purge_status="[null]"/> + <snapshots id="6" project_id="3" status="P" islast="0" purge_status="[null]"/> + <projects id="3" uuid="3" kee="foo-old" enabled="1" scope="FIL" qualifier="CLA" language="java"/> + + <snapshots id="7" project_id="4" status="P" islast="1" purge_status="[null]"/> + <snapshots id="8" project_id="4" status="P" islast="1" purge_status="[null]"/> + <projects id="4" uuid="4" kee="foo-last" enabled="1" scope="FIL" qualifier="CLA" language="java"/> + + <snapshots id="9" project_id="5" status="U" islast="0" purge_status="[null]"/> + <snapshots id="10" project_id="5" status="U" islast="0" purge_status="[null]"/> + <projects id="5" uuid="5" kee="foo" enabled="1" scope="FIL" qualifier="CLA" language="java"/> + + <snapshots id="11" project_id="6" purge_status="[null]" status="P" islast="1"/> + <projects id="6" uuid="6" kee="baz" enabled="1" scope="FIL" qualifier="CLA" language="grvy"/> + + <!-- Old snapshot of another project --> + <!-- bar-old --> + <duplications_index id="1" project_snapshot_id="1" snapshot_id="2" hash="bb" index_in_file="0" start_line="0" + end_line="0"/> + + <!-- Last snapshot of another project --> + <!-- bar-last --> + <duplications_index id="2" project_snapshot_id="3" snapshot_id="4" hash="aa" index_in_file="0" start_line="1" + end_line="2"/> + + <!-- Old snapshot of current project --> + <!-- foo-old --> + <duplications_index id="3" project_snapshot_id="5" snapshot_id="6" hash="bb" index_in_file="0" start_line="0" + end_line="0"/> + + <!-- Last snapshot of current project --> + <!-- foo-last --> + <duplications_index id="4" project_snapshot_id="7" snapshot_id="8" hash="aa" index_in_file="0" start_line="0" + end_line="0"/> + + <!-- New snapshot of current project --> + <!-- foo --> + <duplications_index id="5" project_snapshot_id="9" snapshot_id="10" hash="aa" index_in_file="0" start_line="0" + end_line="0"/> + + <!-- Note that there is two blocks with same hash for current analysis to verify that we use "SELECT DISTINCT", --> + <!-- without "DISTINCT" we will select block from "bar-last" two times. --> + <duplications_index id="6" project_snapshot_id="9" snapshot_id="10" hash="aa" index_in_file="1" start_line="1" + end_line="1"/> + + <!-- Last snapshot of project with another language --> + <!-- baz --> + <duplications_index id="7" project_snapshot_id="1" snapshot_id="11" hash="aa" index_in_file="0" start_line="0" + end_line="0"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/duplication/DuplicationDaoTest/shouldInsert-result.xml b/sonar-db/src/test/resources/org/sonar/db/duplication/DuplicationDaoTest/shouldInsert-result.xml new file mode 100644 index 00000000000..797be8db59d --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/duplication/DuplicationDaoTest/shouldInsert-result.xml @@ -0,0 +1,10 @@ +<dataset> + + <snapshots purge_status="[null]" id="1" status="U" islast="0" project_id="0"/> + <snapshots purge_status="[null]" id="2" status="U" islast="0" project_id="1"/> + <projects id="1" uuid="1" kee="foo" enabled="1" scope="FIL" qualifier="CLA"/> + + <duplications_index id="1" project_snapshot_id="1" snapshot_id="2" hash="bb" index_in_file="0" start_line="1" + end_line="2"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/duplication/DuplicationDaoTest/shouldInsert.xml b/sonar-db/src/test/resources/org/sonar/db/duplication/DuplicationDaoTest/shouldInsert.xml new file mode 100644 index 00000000000..fd4fdc7b948 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/duplication/DuplicationDaoTest/shouldInsert.xml @@ -0,0 +1,7 @@ +<dataset> + + <snapshots purge_status="[null]" id="1" status="U" islast="0" project_id="0"/> + <snapshots purge_status="[null]" id="2" status="U" islast="0" project_id="1"/> + <projects id="1" uuid="1" kee="foo" enabled="1" scope="FIL" qualifier="CLA"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/ActionPlanDaoTest/shared.xml b/sonar-db/src/test/resources/org/sonar/db/issue/ActionPlanDaoTest/shared.xml new file mode 100644 index 00000000000..7e2de0d8076 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/ActionPlanDaoTest/shared.xml @@ -0,0 +1,5 @@ +<dataset> + + <projects id="1" kee="org.sonar.Sample" root_id="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/ActionPlanDaoTest/should_delete_action_plan-result.xml b/sonar-db/src/test/resources/org/sonar/db/issue/ActionPlanDaoTest/should_delete_action_plan-result.xml new file mode 100644 index 00000000000..2b855c97f05 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/ActionPlanDaoTest/should_delete_action_plan-result.xml @@ -0,0 +1,6 @@ +<dataset> + + <action_plans id="1" kee="ABC" project_id="1" name="Long term" description="Long term action plan" deadline="[null]" + user_login="arthur" status="OPEN" created_at="[null]" updated_at="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/ActionPlanDaoTest/should_delete_action_plan.xml b/sonar-db/src/test/resources/org/sonar/db/issue/ActionPlanDaoTest/should_delete_action_plan.xml new file mode 100644 index 00000000000..eaa959cccf9 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/ActionPlanDaoTest/should_delete_action_plan.xml @@ -0,0 +1,9 @@ +<dataset> + + <action_plans id="1" kee="ABC" project_id="1" name="Long term" description="Long term action plan" deadline="[null]" + user_login="arthur" status="OPEN" created_at="[null]" updated_at="[null]"/> + + <action_plans id="2" kee="BCD" project_id="1" name="Short term" description="Short term action plan" deadline="[null]" + user_login="arthur" status="CLOSED" created_at="[null]" updated_at="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/ActionPlanDaoTest/should_find_by_key.xml b/sonar-db/src/test/resources/org/sonar/db/issue/ActionPlanDaoTest/should_find_by_key.xml new file mode 100644 index 00000000000..c21cd9325e4 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/ActionPlanDaoTest/should_find_by_key.xml @@ -0,0 +1,6 @@ +<dataset> + + <action_plans id="1" kee="ABC" project_id="1" name="SHORT_TERM" description="[null]" deadline="[null]" + user_login="igor" status="[null]" created_at="[null]" updated_at="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/ActionPlanDaoTest/should_find_by_keys.xml b/sonar-db/src/test/resources/org/sonar/db/issue/ActionPlanDaoTest/should_find_by_keys.xml new file mode 100644 index 00000000000..a682d59fd17 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/ActionPlanDaoTest/should_find_by_keys.xml @@ -0,0 +1,12 @@ +<dataset> + + <action_plans id="1" kee="ABC" project_id="1" name="SHORT_TERM" description="[null]" deadline="[null]" + user_login="igor" status="[null]" created_at="[null]" updated_at="[null]"/> + + <action_plans id="2" kee="ABD" project_id="1" name="SHORT_TERM" description="[null]" deadline="[null]" + user_login="igor" status="[null]" created_at="[null]" updated_at="[null]"/> + + <action_plans id="3" kee="ABE" project_id="1" name="SHORT_TERM" description="[null]" deadline="[null]" + user_login="igor" status="[null]" created_at="[null]" updated_at="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/ActionPlanDaoTest/should_find_by_name_and_project_id.xml b/sonar-db/src/test/resources/org/sonar/db/issue/ActionPlanDaoTest/should_find_by_name_and_project_id.xml new file mode 100644 index 00000000000..e99d5b3eb3a --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/ActionPlanDaoTest/should_find_by_name_and_project_id.xml @@ -0,0 +1,12 @@ +<dataset> + + <action_plans id="1" kee="ABC" project_id="1" name="SHORT_TERM" description="[null]" deadline="[null]" + user_login="igor" status="OPEN" created_at="[null]" updated_at="[null]"/> + + <action_plans id="2" kee="ABD" project_id="1" name="SHORT_TERM" description="[null]" deadline="[null]" + user_login="igor" status="OPEN" created_at="[null]" updated_at="[null]"/> + + <action_plans id="3" kee="ABE" project_id="2" name="SHORT_TERM" description="[null]" deadline="[null]" + user_login="igor" status="OPEN" created_at="[null]" updated_at="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/ActionPlanDaoTest/should_find_open_by_project_id.xml b/sonar-db/src/test/resources/org/sonar/db/issue/ActionPlanDaoTest/should_find_open_by_project_id.xml new file mode 100644 index 00000000000..e15d4d0bbec --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/ActionPlanDaoTest/should_find_open_by_project_id.xml @@ -0,0 +1,12 @@ +<dataset> + + <action_plans id="1" kee="ABC" project_id="1" name="SHORT_TERM" description="[null]" deadline="[null]" + user_login="igor" status="OPEN" created_at="[null]" updated_at="[null]"/> + + <action_plans id="2" kee="ABD" project_id="1" name="SHORT_TERM" description="[null]" deadline="[null]" + user_login="igor" status="OPEN" created_at="[null]" updated_at="[null]"/> + + <action_plans id="3" kee="ABE" project_id="1" name="SHORT_TERM" description="[null]" deadline="[null]" + user_login="igor" status="CLOSED" created_at="[null]" updated_at="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/ActionPlanDaoTest/should_insert_new_action_plan-result.xml b/sonar-db/src/test/resources/org/sonar/db/issue/ActionPlanDaoTest/should_insert_new_action_plan-result.xml new file mode 100644 index 00000000000..2b855c97f05 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/ActionPlanDaoTest/should_insert_new_action_plan-result.xml @@ -0,0 +1,6 @@ +<dataset> + + <action_plans id="1" kee="ABC" project_id="1" name="Long term" description="Long term action plan" deadline="[null]" + user_login="arthur" status="OPEN" created_at="[null]" updated_at="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/ActionPlanDaoTest/should_update_action_plan-result.xml b/sonar-db/src/test/resources/org/sonar/db/issue/ActionPlanDaoTest/should_update_action_plan-result.xml new file mode 100644 index 00000000000..2b855c97f05 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/ActionPlanDaoTest/should_update_action_plan-result.xml @@ -0,0 +1,6 @@ +<dataset> + + <action_plans id="1" kee="ABC" project_id="1" name="Long term" description="Long term action plan" deadline="[null]" + user_login="arthur" status="OPEN" created_at="[null]" updated_at="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/ActionPlanDaoTest/should_update_action_plan.xml b/sonar-db/src/test/resources/org/sonar/db/issue/ActionPlanDaoTest/should_update_action_plan.xml new file mode 100644 index 00000000000..3da5c2083b5 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/ActionPlanDaoTest/should_update_action_plan.xml @@ -0,0 +1,6 @@ +<dataset> + + <action_plans id="1" kee="ABC" project_id="1" name="Old name" description="Old desc" deadline="[null]" + user_login="[null]" status="CLOSED" created_at="[null]" updated_at="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/ActionPlanStatsDaoTest/shared.xml b/sonar-db/src/test/resources/org/sonar/db/issue/ActionPlanStatsDaoTest/shared.xml new file mode 100644 index 00000000000..7e2de0d8076 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/ActionPlanStatsDaoTest/shared.xml @@ -0,0 +1,5 @@ +<dataset> + + <projects id="1" kee="org.sonar.Sample" root_id="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/ActionPlanStatsDaoTest/should_find_by_project.xml b/sonar-db/src/test/resources/org/sonar/db/issue/ActionPlanStatsDaoTest/should_find_by_project.xml new file mode 100644 index 00000000000..f38c53fea63 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/ActionPlanStatsDaoTest/should_find_by_project.xml @@ -0,0 +1,81 @@ +<dataset> + + <action_plans id="1" kee="ABC" project_id="1" name="SHORT_TERM" description="[null]" deadline="[null]" + user_login="igor" status="OPEN" created_at="[null]" updated_at="[null]"/> + + <issues + id="100" + kee="ABCDE" + component_uuid="uuid-400" + project_uuid="uuid-400" + rule_id="500" + severity="BLOCKER" + manual_severity="[false]" + message="[null]" + line="200" + status="OPEN" + resolution="[null]" + checksum="XXX" + reporter="arthur" + assignee="perceval" + author_login="[null]" + issue_attributes="JIRA=FOO-1234" + action_plan_key="ABC" + issue_creation_date="1366063200000" + issue_update_date="1366063200000" + issue_close_date="1366063200000" + created_at="1400000000000" + updated_at="1400000000000" + /> + + <issues + id="101" + kee="ABCDF" + component_uuid="uuid-400" + project_uuid="uuid-400" + rule_id="500" + severity="BLOCKER" + manual_severity="[false]" + message="[null]" + line="200" + status="CLOSED" + resolution="FIXED" + checksum="XXX" + reporter="arthur" + assignee="perceval" + author_login="[null]" + issue_attributes="JIRA=FOO-1234" + action_plan_key="ABC" + issue_creation_date="1366063200000" + issue_update_date="1366063200000" + issue_close_date="1366063200000" + created_at="1400000000000" + updated_at="1400000000000" + /> + + <issues + id="102" + kee="ABCDG" + component_uuid="uuid-400" + project_uuid="uuid-400" + rule_id="500" + severity="BLOCKER" + manual_severity="[false]" + message="[null]" + line="200" + status="CLOSED" + resolution="FIXED" + checksum="XXX" + reporter="arthur" + assignee="perceval" + author_login="[null]" + issue_attributes="JIRA=FOO-1234" + action_plan_key="ABC" + issue_creation_date="1366063200000" + issue_update_date="1366063200000" + issue_close_date="1366063200000" + created_at="1400000000000" + updated_at="1400000000000" + /> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueChangeDaoTest/delete-result.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueChangeDaoTest/delete-result.xml new file mode 100644 index 00000000000..be1549d36f1 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueChangeDaoTest/delete-result.xml @@ -0,0 +1,42 @@ +<dataset> + + <issue_changes + id="100" + kee="COMMENT-1" + issue_key="ISSUE-1" + user_login="arthur" + change_type="comment" + change_data="old comment" + created_at="1356994800000" + updated_at="1356994800000" + issue_change_creation_date="[null]" + /> + + <issue_changes + id="101" + kee="[null]" + issue_key="1000" + user_login="arthur" + change_type="diff" + change_data="severity=MAJOR|BLOCKER" + created_at="1359759600000" + updated_at="1359759600000" + issue_change_creation_date="1359759600000" + /> + + <!-- + DELETED + + <issue_changes + id="102" + kee="COMMENT-2" + issue_key="ISSUE-1" + user_login="arthur" + change_type="comment" + change_data="recent comment" + created_at="1367704800000" + updated_at="1367704800000" + issue_change_creation_date="1367704800000" + /> + --> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueChangeDaoTest/delete.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueChangeDaoTest/delete.xml new file mode 100644 index 00000000000..3277acb54ca --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueChangeDaoTest/delete.xml @@ -0,0 +1,38 @@ +<dataset> + + <issue_changes + id="100" + kee="COMMENT-1" + issue_key="ISSUE-1" + user_login="arthur" + change_type="comment" + change_data="old comment" + created_at="1356994800000" + updated_at="1356994800000" + issue_change_creation_date="[null]" + /> + + <issue_changes + id="101" + kee="[null]" + issue_key="1000" + user_login="arthur" + change_type="diff" + change_data="severity=MAJOR|BLOCKER" + created_at="1359759600000" + updated_at="1359759600000" + issue_change_creation_date="1359759600000" + /> + + <issue_changes + id="102" + kee="COMMENT-2" + issue_key="ISSUE-1" + user_login="arthur" + change_type="comment" + change_data="recent comment" + created_at="1367704800000" + updated_at="1367704800000" + issue_change_creation_date="1367704800000" + /> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueChangeDaoTest/empty.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueChangeDaoTest/empty.xml new file mode 100644 index 00000000000..871dedcb5e9 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueChangeDaoTest/empty.xml @@ -0,0 +1,3 @@ +<dataset> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueChangeDaoTest/insert-result.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueChangeDaoTest/insert-result.xml new file mode 100644 index 00000000000..06468bff8a8 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueChangeDaoTest/insert-result.xml @@ -0,0 +1,15 @@ +<dataset> + + <issue_changes + id="1" + kee="EFGH" + issue_key="ABCDE" + user_login="emmerik" + change_type="comment" + change_data="Some text" + created_at="1500000000000" + updated_at="1501000000000" + issue_change_creation_date="1502000000000" + /> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueChangeDaoTest/selectChangelogOfNonClosedIssuesByComponent.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueChangeDaoTest/selectChangelogOfNonClosedIssuesByComponent.xml new file mode 100644 index 00000000000..ef1c47fe020 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueChangeDaoTest/selectChangelogOfNonClosedIssuesByComponent.xml @@ -0,0 +1,182 @@ +<dataset> + + <!-- Unresolved. To be included --> + <issues + id="1" + kee="UNRESOLVED_ON_FILE_1" + component_uuid="FILE_1" + project_uuid="PROJECT_1" + resolution="[null]" + status="OPEN" + rule_id="500" + severity="BLOCKER" + manual_severity="[false]" + message="[null]" + line="200" + effort_to_fix="[null]" + checksum="[null]" + reporter="user" + assignee="user" + author_login="[null]" + issue_attributes="[null]" + issue_creation_date="1366063200000" + issue_update_date="1366063200000" + issue_close_date="1366063200000" + created_at="1400000000000" + updated_at="[null]" + /> + + <!-- diff --> + <issue_changes + id="100" + kee="100" + issue_key="UNRESOLVED_ON_FILE_1" + user_login="arthur" + change_type="diff" + change_data="severity=MAJOR|BLOCKER" + created_at="1410213600000" + updated_at="1410213600000" + issue_change_creation_date="1410213600000" + /> + + <!-- comment --> + <issue_changes + id="102" + kee="102" + issue_key="UNRESOLVED_ON_FILE_1" + user_login="arthur" + change_type="comment" + change_data="recent comment" + created_at="1410213600000" + updated_at="1410213600000" + issue_change_creation_date="[null]" + /> + + <!-- Resolved but not closed. To be included --> + <issues + id="2" + kee="RESOLVED_ON_FILE_1" + component_uuid="FILE_1" + project_uuid="PROJECT_1" + resolution="FIXED" + status="RESOLVED" + rule_id="501" + severity="MAJOR" + manual_severity="[false]" + message="[null]" + line="120" + effort_to_fix="[null]" + checksum="[null]" + reporter="[null]" + assignee="user" + author_login="[null]" + issue_attributes="[null]" + issue_creation_date="1366063200000" + issue_update_date="1366063200000" + issue_close_date="1366063200000" + created_at="1400000000000" + updated_at="[null]" + /> + + <issue_changes + id="103" + kee="103" + issue_key="RESOLVED_ON_FILE_1" + user_login="arthur" + change_type="diff" + change_data="severity=MAJOR|BLOCKER" + created_at="1410213600000" + updated_at="1410213600000" + issue_change_creation_date="1410213600000" + /> + + <!-- Closed. To be excluded --> + <issues + id="3" + kee="CLOSED_ON_FILE_1" + component_uuid="FILE_1" + project_uuid="PROJECT_1" + resolution="FIXED" + status="CLOSED" + rule_id="501" + severity="MAJOR" + manual_severity="[false]" + message="[null]" + line="120" + effort_to_fix="[null]" + checksum="[null]" + reporter="[null]" + assignee="user" + author_login="[null]" + issue_attributes="[null]" + issue_creation_date="1366063200000" + issue_update_date="1366063200000" + issue_close_date="1366063200000" + created_at="1400000000000" + updated_at="[null]" + /> + + <issue_changes + id="104" + kee="104" + issue_key="CLOSED_ON_FILE_1" + user_login="arthur" + change_type="diff" + change_data="severity=MAJOR|BLOCKER" + created_at="1410213600000" + updated_at="1410213600000" + issue_change_creation_date="1410213600000" + /> + + <!-- Unresolved on other file --> + <issues + id="4" + kee="UNRESOLVED_ON_FILE_2" + component_uuid="FILE_2" + project_uuid="PROJECT_1" + resolution="[null]" + status="OPEN" + rule_id="500" + severity="BLOCKER" + manual_severity="[false]" + message="[null]" + line="200" + effort_to_fix="[null]" + checksum="[null]" + reporter="user" + assignee="user" + author_login="[null]" + issue_attributes="[null]" + issue_creation_date="1366063200000" + issue_update_date="1366063200000" + issue_close_date="1366063200000" + created_at="1400000000000" + updated_at="[null]" + /> + + <!-- diff --> + <issue_changes + id="105" + kee="105" + issue_key="UNRESOLVED_ON_FILE_2" + user_login="arthur" + change_type="diff" + change_data="severity=MAJOR|BLOCKER" + created_at="1410213600000" + updated_at="1410213600000" + issue_change_creation_date="1410213600000" + /> + + <!-- comment --> + <issue_changes + id="106" + kee="106" + issue_key="UNRESOLVED_ON_FILE_2" + user_login="arthur" + change_type="comment" + change_data="recent comment" + created_at="1410213600000" + updated_at="1410213600000" + issue_change_creation_date="[null]" + /> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueChangeDaoTest/shared.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueChangeDaoTest/shared.xml new file mode 100644 index 00000000000..0b181deb146 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueChangeDaoTest/shared.xml @@ -0,0 +1,63 @@ +<dataset> + + <issue_changes + id="100" + kee="ABCDE" + issue_key="1000" + user_login="arthur" + change_type="comment" + change_data="old comment" + created_at="1356994800000" + updated_at="1356994800000" + issue_change_creation_date="[null]" + /> + + <issue_changes + id="101" + kee="[null]" + issue_key="1000" + user_login="arthur" + change_type="diff" + change_data="severity=MAJOR|BLOCKER" + created_at="1359759600000" + updated_at="1359759600000" + issue_change_creation_date="1359759600000" + /> + + <issue_changes + id="102" + kee="FGHIJ" + issue_key="1000" + user_login="arthur" + change_type="comment" + change_data="recent comment" + created_at="1367704800000" + updated_at="1367704800000" + issue_change_creation_date="[null]" + /> + + <issue_changes + id="103" + kee="KLMN" + issue_key="1001" + user_login="arthur" + change_type="diff" + change_data="actionPlan=1.0|1.1" + created_at="1359759600000" + updated_at="1359759600000" + issue_change_creation_date="1359759600000" + /> + + <issue_changes + id="104" + kee="OPQR" + issue_key="1001" + user_login="henry" + change_type="diff" + change_data="severity=MAJOR|BLOCKER" + created_at="1356994800000" + updated_at="1356994800000" + issue_change_creation_date="1356994800000" + /> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueChangeDaoTest/update-result.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueChangeDaoTest/update-result.xml new file mode 100644 index 00000000000..a1c436a6622 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueChangeDaoTest/update-result.xml @@ -0,0 +1,38 @@ +<dataset> + + <issue_changes + id="100" + kee="COMMENT-1" + issue_key="ISSUE-1" + user_login="arthur" + change_type="comment" + change_data="old comment" + created_at="1356994800000" + updated_at="1356994800000" + issue_change_creation_date="[null]" + /> + + <issue_changes + id="101" + kee="[null]" + issue_key="1000" + user_login="arthur" + change_type="diff" + change_data="severity=MAJOR|BLOCKER" + created_at="1359759600000" + updated_at="1359759600000" + issue_change_creation_date="1359759600000" + /> + + <issue_changes + id="102" + kee="COMMENT-2" + issue_key="ISSUE-1" + user_login="arthur" + change_type="comment" + change_data="new comment" + created_at="1367704800000" + updated_at="1500000000000" + issue_change_creation_date="[null]" + /> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueChangeDaoTest/update.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueChangeDaoTest/update.xml new file mode 100644 index 00000000000..641f333faa3 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueChangeDaoTest/update.xml @@ -0,0 +1,38 @@ +<dataset> + + <issue_changes + id="100" + kee="COMMENT-1" + issue_key="ISSUE-1" + user_login="arthur" + change_type="comment" + change_data="old comment" + created_at="1356994800000" + updated_at="1356994800000" + issue_change_creation_date="[null]" + /> + + <issue_changes + id="101" + kee="[null]" + issue_key="1000" + user_login="arthur" + change_type="diff" + change_data="severity=MAJOR|BLOCKER" + created_at="1359759600000" + updated_at="1359759600000" + issue_change_creation_date="1359759600000" + /> + + <issue_changes + id="102" + kee="COMMENT-2" + issue_key="ISSUE-1" + user_login="arthur" + change_type="comment" + change_data="old value" + created_at="1367704800000" + updated_at="1367704800000" + issue_change_creation_date="[null]" + /> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueChangeMapperTest/insert_comment-result.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueChangeMapperTest/insert_comment-result.xml new file mode 100644 index 00000000000..ed763c2952a --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueChangeMapperTest/insert_comment-result.xml @@ -0,0 +1,13 @@ +<dataset> + <issue_changes + id="1" + kee="COMMENT-1234" + issue_key="ABCDE" + user_login="emmerik" + change_type="comment" + change_data="the comment" + created_at="1500000000000" + updated_at="1500000000000" + issue_change_creation_date="[null]" + /> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueChangeMapperTest/insert_diff-result.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueChangeMapperTest/insert_diff-result.xml new file mode 100644 index 00000000000..bbc0741292f --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueChangeMapperTest/insert_diff-result.xml @@ -0,0 +1,13 @@ +<dataset> + <issue_changes + id="1" + kee="[null]" + issue_key="ABCDE" + user_login="emmerik" + change_type="diff" + change_data="severity=INFO|BLOCKER" + created_at="1500000000000" + updated_at="1500000000000" + issue_change_creation_date="1500000000000" + /> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/find_severities_by_component.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/find_severities_by_component.xml new file mode 100644 index 00000000000..deb88387a4a --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/find_severities_by_component.xml @@ -0,0 +1,80 @@ +<dataset> + + <!-- rule 500 --> + <issues + id="100" + kee="ABCDE-1" + component_uuid="CDEF" + project_uuid="ABCD" + rule_id="500" + severity="BLOCKER" + manual_severity="[false]" + message="[null]" + line="200" + effort_to_fix="4.2" + status="OPEN" + resolution="[null]" + checksum="XXX" + reporter="arthur" + assignee="perceval" + author_login="[null]" + issue_attributes="JIRA=FOO-1234" + issue_creation_date="1366063200000" + issue_update_date="1366063200000" + issue_close_date="1366063200000" + created_at="1400000000000" + updated_at="1400000000000" + /> + + <issues + id="101" + kee="ABCDE-2" + component_uuid="CDEF" + project_uuid="ABCD" + rule_id="500" + severity="MAJOR" + manual_severity="[false]" + message="[null]" + line="200" + effort_to_fix="4.2" + status="OPEN" + resolution="[null]" + checksum="XXX" + reporter="arthur" + assignee="perceval" + author_login="[null]" + issue_attributes="JIRA=FOO-1234" + issue_creation_date="1366149600000" + issue_update_date="1366149600000" + issue_close_date="1366149600000" + created_at="1400000000000" + updated_at="1400000000000" + /> + + + <!-- rule 501 --> + <issues + id="102" + kee="ABCDE-3" + component_uuid="CDEF" + project_uuid="ABCD" + rule_id="501" + severity="BLOCKER" + manual_severity="[false]" + message="[null]" + line="200" + effort_to_fix="4.2" + status="OPEN" + resolution="[null]" + checksum="XXX" + reporter="arthur" + assignee="perceval" + author_login="[null]" + issue_attributes="JIRA=FOO-1234" + issue_creation_date="1366063200000" + issue_update_date="1366063200000" + issue_close_date="1366063200000" + created_at="1400000000000" + updated_at="1400000000000" + /> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/shared.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/shared.xml new file mode 100644 index 00000000000..353f9651342 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/shared.xml @@ -0,0 +1,26 @@ +<dataset> + + <group_roles id="1" group_id="[null]" resource_id="399" role="user"/> + + <projects id="399" uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" module_uuid_path="." kee="struts" + root_id="[null]" qualifier="TRK" scope="PRJ"/> + <projects id="400" uuid="BCDE" project_uuid="ABCD" module_uuid="[null]" module_uuid_path=".ABCD." kee="struts-core" + root_id="399" qualifier="BRC" scope="PRJ"/> + <projects id="401" uuid="CDEF" project_uuid="ABCD" module_uuid="BCDE" module_uuid_path=".ABCD.BCDE." kee="Action.java" + root_id="400" qualifier="CLA" scope="PRJ"/> + <projects id="402" uuid="DEFG" project_uuid="ABCD" module_uuid="BCDE" module_uuid_path=".ABCD.BCDE." kee="Filter.java" + root_id="400" qualifier="CLA" scope="PRJ"/> + + <snapshots id="100" project_id="399" root_snapshot_id="[null]" parent_snapshot_id="[null]" root_project_id="399" + path="" islast="[true]"/> + <snapshots id="101" project_id="400" root_snapshot_id="100" parent_snapshot_id="100" root_project_id="399" path="100." + islast="[true]"/> + <snapshots id="102" project_id="401" root_snapshot_id="100" parent_snapshot_id="101" root_project_id="399" + path="100.101." islast="[true]"/> + <snapshots id="103" project_id="402" root_snapshot_id="100" parent_snapshot_id="101" root_project_id="399" + path="100.101." islast="[true]"/> + + <rules id="500" tags="[null]" system_tags="[null]" plugin_rule_key="AvoidCycle" plugin_name="squid" language="java"/> + <rules id="501" tags="[null]" system_tags="[null]" plugin_rule_key="NullRef" plugin_name="squid" language="xoo"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/should_select_issue_and_component_ids.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/should_select_issue_and_component_ids.xml new file mode 100644 index 00000000000..f92b8328c21 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/should_select_issue_and_component_ids.xml @@ -0,0 +1,80 @@ +<dataset> + + <!-- rule 500 --> + <issues + id="100" + kee="ABCDE-1" + component_uuid="CDEF" + project_uuid="ABCD" + rule_id="500" + severity="BLOCKER" + manual_severity="[false]" + message="[null]" + line="200" + effort_to_fix="4.2" + status="OPEN" + resolution="FIXED" + checksum="XXX" + reporter="arthur" + assignee="perceval" + author_login="[null]" + issue_attributes="JIRA=FOO-1234" + issue_creation_date="1366063200000" + issue_update_date="1366063200000" + issue_close_date="1366063200000" + created_at="1400000000000" + updated_at="1400000000000" + /> + + <issues + id="101" + kee="ABCDE-2" + component_uuid="CDEF" + project_uuid="ABCD" + rule_id="500" + severity="BLOCKER" + manual_severity="[false]" + message="[null]" + line="200" + effort_to_fix="4.2" + status="OPEN" + resolution="FIXED" + checksum="XXX" + reporter="arthur" + assignee="perceval" + author_login="[null]" + issue_attributes="JIRA=FOO-1234" + issue_creation_date="1366063200000" + issue_update_date="1366063200000" + issue_close_date="1366063200000" + created_at="1400000000000" + updated_at="1400000000000" + /> + + + <!-- rule 501 --> + <issues + id="102" + kee="ABCDE-3" + component_uuid="CDEF" + project_uuid="ABCD" + rule_id="501" + severity="BLOCKER" + manual_severity="[false]" + message="[null]" + line="200" + effort_to_fix="4.2" + status="OPEN" + resolution="FIXED" + checksum="XXX" + reporter="arthur" + assignee="perceval" + author_login="[null]" + issue_attributes="JIRA=FOO-1234" + issue_creation_date="1366063200000" + issue_update_date="1366063200000" + issue_close_date="1366063200000" + created_at="1400000000000" + updated_at="1400000000000" + /> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/should_select_non_closed_issues_by_module.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/should_select_non_closed_issues_by_module.xml new file mode 100644 index 00000000000..b3575610bd1 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/should_select_non_closed_issues_by_module.xml @@ -0,0 +1,133 @@ +<dataset> + + <!-- Open Issue on a file --> + <issues + id="100" + kee="100" + component_uuid="CDEF" + project_uuid="ABCD" + rule_id="500" + severity="BLOCKER" + manual_severity="[false]" + message="[null]" + line="200" + effort_to_fix="[null]" + status="OPEN" + resolution="[null]" + checksum="[null]" + reporter="user" + assignee="user" + author_login="[null]" + issue_attributes="[null]" + issue_creation_date="1366063200000" + issue_update_date="1366063200000" + issue_close_date="1366063200000" + created_at="1400000000000" + updated_at="[null]" + /> + + <!-- Open Issue on a file --> + <issues + id="101" + kee="101" + component_uuid="DEFG" + project_uuid="ABCD" + rule_id="501" + severity="MAJOR" + manual_severity="[false]" + message="[null]" + line="120" + effort_to_fix="[null]" + status="OPEN" + resolution="[null]" + checksum="[null]" + reporter="[null]" + assignee="user" + author_login="[null]" + issue_attributes="[null]" + issue_creation_date="1366063200000" + issue_update_date="1366063200000" + issue_close_date="1366063200000" + created_at="1400000000000" + updated_at="[null]" + /> + + <!-- Closed Issue on a file --> + <issues + id="102" + kee="102" + component_uuid="DEFG" + project_uuid="ABCD" + rule_id="501" + severity="MAJOR" + manual_severity="[false]" + message="[null]" + line="120" + effort_to_fix="[null]" + status="CLOSED" + resolution="FIXED" + checksum="[null]" + reporter="[null]" + assignee="user" + author_login="[null]" + issue_attributes="[null]" + issue_creation_date="1366063200000" + issue_update_date="1366063200000" + issue_close_date="1366063200000" + created_at="1400000000000" + updated_at="[null]" + /> + + <!-- Open Issue on a sub module --> + <issues + id="103" + kee="103" + component_uuid="BCDE" + project_uuid="ABCD" + rule_id="501" + severity="MAJOR" + manual_severity="[false]" + message="[null]" + line="[null]" + effort_to_fix="[null]" + status="OPEN" + resolution="[null]" + checksum="[null]" + reporter="[null]" + assignee="user" + author_login="[null]" + issue_attributes="[null]" + issue_creation_date="1366063200000" + issue_update_date="1366063200000" + issue_close_date="1366063200000" + created_at="1400000000000" + updated_at="[null]" + /> + + <!-- Open Issue on a root module --> + <issues + id="104" + kee="104" + component_uuid="ABCD" + project_uuid="ABCD" + rule_id="501" + severity="MAJOR" + manual_severity="[false]" + message="[null]" + line="[null]" + effort_to_fix="[null]" + status="OPEN" + resolution="[null]" + checksum="[null]" + reporter="[null]" + assignee="user" + author_login="[null]" + issue_attributes="[null]" + issue_creation_date="1366063200000" + issue_update_date="1366063200000" + issue_close_date="1366063200000" + created_at="1400000000000" + updated_at="[null]" + /> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/should_select_non_closed_issues_by_module_on_removed_project.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/should_select_non_closed_issues_by_module_on_removed_project.xml new file mode 100644 index 00000000000..b7fa286ffca --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/should_select_non_closed_issues_by_module_on_removed_project.xml @@ -0,0 +1,127 @@ +<!-- + ~ SonarQube, open source software quality management tool. + ~ Copyright (C) 2008-2014 SonarSource + ~ mailto:contact AT sonarsource DOT com + ~ + ~ SonarQube 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. + ~ + ~ SonarQube 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. + --> + +<dataset> + + <!-- Open Issue on a file --> + <issues + id="100" + kee="100" + component_uuid="CDEF" + project_uuid="uuid-111" + rule_id="500" + severity="BLOCKER" + manual_severity="[false]" + message="[null]" + line="200" + effort_to_fix="[null]" + status="OPEN" + resolution="[null]" + checksum="[null]" + reporter="user" + assignee="user" + author_login="[null]" + issue_attributes="[null]" + issue_creation_date="1366063200000" + issue_update_date="1366063200000" + issue_close_date="1366063200000" + created_at="1400000000000" + updated_at="[null]" + /> + + <!-- Open Issue on a file --> + <issues + id="101" + kee="101" + component_uuid="DEFG" + project_uuid="uuid-111" + rule_id="501" + severity="MAJOR" + manual_severity="[false]" + message="[null]" + line="120" + effort_to_fix="[null]" + status="OPEN" + resolution="[null]" + checksum="[null]" + reporter="[null]" + assignee="user" + author_login="[null]" + issue_attributes="[null]" + issue_creation_date="1366063200000" + issue_update_date="1366063200000" + issue_close_date="1366063200000" + created_at="1400000000000" + updated_at="[null]" + /> + + <!-- Closed Issue on a file --> + <issues + id="102" + kee="102" + component_uuid="DEFG" + project_uuid="uuid-111" + rule_id="501" + severity="MAJOR" + manual_severity="[false]" + message="[null]" + line="120" + effort_to_fix="[null]" + status="CLOSED" + resolution="FIXED" + checksum="[null]" + reporter="[null]" + assignee="user" + author_login="[null]" + issue_attributes="[null]" + issue_creation_date="1366063200000" + issue_update_date="1366063200000" + issue_close_date="1366063200000" + created_at="1400000000000" + updated_at="[null]" + /> + + <!-- Open Issue on a sub module --> + <issues + id="103" + kee="103" + component_uuid="BCDE" + project_uuid="uuid-111" + rule_id="501" + severity="MAJOR" + manual_severity="[false]" + message="[null]" + line="[null]" + effort_to_fix="[null]" + status="OPEN" + resolution="[null]" + checksum="[null]" + reporter="[null]" + assignee="user" + author_login="[null]" + issue_attributes="[null]" + issue_creation_date="1366063200000" + issue_update_date="1366063200000" + issue_close_date="1366063200000" + created_at="1400000000000" + updated_at="[null]" + /> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueFilterDaoTest/shared.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueFilterDaoTest/shared.xml new file mode 100644 index 00000000000..68f9cdc6615 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueFilterDaoTest/shared.xml @@ -0,0 +1,23 @@ +<dataset> + + <issue_filters + id="1" + name="Sonar Issues" + user_login="stephane" + shared="[true]" + description="All issues of Sonar" + data="componentRoots=org.codehaus.sonar" + created_at="2013-06-10" + updated_at="2013-06-10"/> + + <issue_filters + id="2" + name="Open issues" + user_login="michael" + shared="[false]" + description="All open issues" + data="statuses=OPEN" + created_at="2013-06-10" + updated_at="2013-06-10"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueFilterDaoTest/should_delete-result.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueFilterDaoTest/should_delete-result.xml new file mode 100644 index 00000000000..7933167cf9a --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueFilterDaoTest/should_delete-result.xml @@ -0,0 +1,13 @@ +<dataset> + + <issue_filters + id="2" + name="Open issues" + user_login="michael" + shared="[false]" + description="All open issues" + data="statuses=OPEN" + created_at="2013-06-10" + updated_at="2013-06-10"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueFilterDaoTest/should_insert-result.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueFilterDaoTest/should_insert-result.xml new file mode 100644 index 00000000000..869df62a337 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueFilterDaoTest/should_insert-result.xml @@ -0,0 +1,34 @@ +<dataset> + + <issue_filters + id="1" + name="Sonar Issues" + user_login="stephane" + shared="[true]" + description="All issues of Sonar" + data="componentRoots=org.codehaus.sonar" + created_at="2013-06-10" + updated_at="2013-06-10"/> + + <issue_filters + id="2" + name="Open issues" + user_login="michael" + shared="[false]" + description="All open issues" + data="statuses=OPEN" + created_at="2013-06-10" + updated_at="2013-06-10"/> + + + <issue_filters + id="3" + name="Sonar Open issues" + user_login="michael" + shared="[true]" + description="All open issues on Sonar" + data="statuses=OPEN|componentRoots=org.codehaus.sonar" + created_at="2013-06-10" + updated_at="2013-06-10"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueFilterDaoTest/should_select_by_user.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueFilterDaoTest/should_select_by_user.xml new file mode 100644 index 00000000000..0f91cec3cdd --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueFilterDaoTest/should_select_by_user.xml @@ -0,0 +1,33 @@ +<dataset> + + <issue_filters + id="1" + name="Sonar Issues" + user_login="stephane" + shared="[true]" + description="All issues of Sonar" + data="componentRoots=org.codehaus.sonar" + created_at="2013-06-10" + updated_at="2013-06-10"/> + + <issue_filters + id="2" + name="Open issues" + user_login="michael" + shared="[false]" + description="All open issues" + data="statuses=OPEN" + created_at="2013-06-10" + updated_at="2013-06-10"/> + + <issue_filters + id="3" + name="Sonar Open issues" + user_login="michael" + shared="[true]" + description="All open issues on Sonar" + data="statuses=OPEN|componentRoots=org.codehaus.sonar" + created_at="2013-06-10" + updated_at="2013-06-10"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueFilterDaoTest/should_select_by_user_with_only_favorite_filters.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueFilterDaoTest/should_select_by_user_with_only_favorite_filters.xml new file mode 100644 index 00000000000..47d558307c3 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueFilterDaoTest/should_select_by_user_with_only_favorite_filters.xml @@ -0,0 +1,39 @@ +<dataset> + + <issue_filters + id="1" + name="Sonar Issues" + user_login="stephane" + shared="[true]" + description="All issues of Sonar" + data="componentRoots=org.codehaus.sonar" + created_at="2013-06-10" + updated_at="2013-06-10"/> + + <issue_filters + id="2" + name="Open issues" + user_login="michael" + shared="[false]" + description="All open issues" + data="statuses=OPEN" + created_at="2013-06-10" + updated_at="2013-06-10"/> + + <issue_filters + id="3" + name="Sonar Open issues" + user_login="michael" + shared="[true]" + description="All open issues on Sonar" + data="statuses=OPEN|componentRoots=org.codehaus.sonar" + created_at="2013-06-10" + updated_at="2013-06-10"/> + + <issue_filter_favourites + id="10" + user_login="michael" + issue_filter_id="2" + created_at="2013-06-10"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueFilterDaoTest/should_select_provided_by_name.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueFilterDaoTest/should_select_provided_by_name.xml new file mode 100644 index 00000000000..81bf84aee21 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueFilterDaoTest/should_select_provided_by_name.xml @@ -0,0 +1,58 @@ +<dataset> + + <!-- This one must be found --> + <issue_filters + id="1" + name="Unresolved Issues" + user_login="[null]" + shared="[true]" + description="[null]" + data="resolved=false" + created_at="2011-04-25 01:15:00" + updated_at="2011-04-25 01:15:00"/> + + <!-- This one must NOT be found: belongs to admin --> + <issue_filters + id="2" + name="Unresolved Issues" + user_login="admin" + shared="[true]" + description="[null]" + data="resolved=false" + created_at="2011-04-25 01:15:00" + updated_at="2011-04-25 01:15:00"/> + + <!-- This one must NOT be found: not shared --> + <issue_filters + id="3" + name="Unresolved Issues" + user_login="[null]" + shared="[false]" + description="[null]" + data="resolved=false" + created_at="2011-04-25 01:15:00" + updated_at="2011-04-25 01:15:00"/> + + <!-- This one must be found --> + <issue_filters + id="4" + name="My Unresolved Issues" + user_login="[null]" + shared="[true]" + description="[null]" + data="resolved=false|assignees=__me__" + created_at="2011-04-25 01:15:00" + updated_at="2011-04-25 01:15:00"/> + + <!-- This one must NOT be found: not shared --> + <issue_filters + id="5" + name="Unknown Filter" + user_login="[null]" + shared="[false]" + description="[null]" + data="resolved=false" + created_at="2011-04-25 01:15:00" + updated_at="2011-04-25 01:15:00"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueFilterDaoTest/should_update-result.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueFilterDaoTest/should_update-result.xml new file mode 100644 index 00000000000..0916ece3f0a --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueFilterDaoTest/should_update-result.xml @@ -0,0 +1,23 @@ +<dataset> + + <issue_filters + id="1" + name="Sonar Issues" + user_login="stephane" + shared="[true]" + description="All issues of Sonar" + data="componentRoots=org.codehaus.sonar" + created_at="2013-06-10" + updated_at="2013-06-10"/> + + <issue_filters + id="2" + name="Closed issues" + user_login="bernard" + shared="[false]" + description="All closed issues" + data="statuses=CLOSED" + created_at="2013-06-10" + updated_at="2013-06-11"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueFilterFavouriteDaoTest/shared.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueFilterFavouriteDaoTest/shared.xml new file mode 100644 index 00000000000..07d23d9fce6 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueFilterFavouriteDaoTest/shared.xml @@ -0,0 +1,21 @@ +<dataset> + + <issue_filter_favourites + id="1" + user_login="stephane" + issue_filter_id="10" + created_at="2013-06-10"/> + + <issue_filter_favourites + id="2" + user_login="stephane" + issue_filter_id="11" + created_at="2013-06-10"/> + + <issue_filter_favourites + id="3" + user_login="arthur" + issue_filter_id="10" + created_at="2013-06-10"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueFilterFavouriteDaoTest/should_delete-result.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueFilterFavouriteDaoTest/should_delete-result.xml new file mode 100644 index 00000000000..b3f03e6724e --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueFilterFavouriteDaoTest/should_delete-result.xml @@ -0,0 +1,15 @@ +<dataset> + + <issue_filter_favourites + id="1" + user_login="stephane" + issue_filter_id="10" + created_at="2013-06-10"/> + + <issue_filter_favourites + id="2" + user_login="stephane" + issue_filter_id="11" + created_at="2013-06-10"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueFilterFavouriteDaoTest/should_delete_by_issue_filter_id-result.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueFilterFavouriteDaoTest/should_delete_by_issue_filter_id-result.xml new file mode 100644 index 00000000000..c2a7f43e9e4 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueFilterFavouriteDaoTest/should_delete_by_issue_filter_id-result.xml @@ -0,0 +1,9 @@ +<dataset> + + <issue_filter_favourites + id="2" + user_login="stephane" + issue_filter_id="11" + created_at="2013-06-10"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueFilterFavouriteDaoTest/should_insert-result.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueFilterFavouriteDaoTest/should_insert-result.xml new file mode 100644 index 00000000000..f9b8e27974d --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueFilterFavouriteDaoTest/should_insert-result.xml @@ -0,0 +1,27 @@ +<dataset> + + <issue_filter_favourites + id="1" + user_login="stephane" + issue_filter_id="10" + created_at="2013-06-10"/> + + <issue_filter_favourites + id="2" + user_login="stephane" + issue_filter_id="11" + created_at="2013-06-10"/> + + <issue_filter_favourites + id="3" + user_login="arthur" + issue_filter_id="10" + created_at="2013-06-10"/> + + <issue_filter_favourites + id="4" + user_login="arthur" + issue_filter_id="11" + created_at="2013-06-18"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueMapperTest/testInsert-result.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueMapperTest/testInsert-result.xml new file mode 100644 index 00000000000..816b527458c --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueMapperTest/testInsert-result.xml @@ -0,0 +1,29 @@ +<dataset> + <issues + id="100" + kee="ABCDE" + component_uuid="uuid-123" + project_uuid="uuid-100" + rule_id="200" + severity="BLOCKER" + manual_severity="[false]" + message="the message" + line="500" + effort_to_fix="3.14" + technical_debt="10" + status="RESOLVED" + resolution="FIXED" + checksum="123456789" + reporter="emmerik" + author_login="morgan" + assignee="karadoc" + issue_attributes="JIRA=FOO-1234" + tags="[null]" + issue_creation_date="1401000000000" + issue_update_date="1402000000000" + issue_close_date="1403000000000" + created_at="1400000000000" + updated_at="1500000000000" + action_plan_key="current_sprint" + /> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueMapperTest/testUpdate-result.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueMapperTest/testUpdate-result.xml new file mode 100644 index 00000000000..afce8a1ed86 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueMapperTest/testUpdate-result.xml @@ -0,0 +1,29 @@ +<dataset> + <issues + id="100" + kee="ABCDE" + component_uuid="uuid-123" + project_uuid="uuid-101" + rule_id="200" + severity="BLOCKER" + manual_severity="[false]" + message="the message" + line="500" + effort_to_fix="3.14" + technical_debt="10" + status="RESOLVED" + resolution="FIXED" + checksum="123456789" + reporter="emmerik" + author_login="morgan" + assignee="karadoc" + issue_attributes="JIRA=FOO-1234" + tags="[null]" + issue_creation_date="1401000000000" + issue_update_date="1402000000000" + issue_close_date="1403000000000" + created_at="1400000000000" + updated_at="1500000000000" + action_plan_key="current_sprint" + /> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueMapperTest/testUpdate.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueMapperTest/testUpdate.xml new file mode 100644 index 00000000000..5cb05d1dd96 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueMapperTest/testUpdate.xml @@ -0,0 +1,27 @@ +<dataset> + <issues + id="100" + kee="ABCDE" + component_uuid="uuid-123" + project_uuid="uuid-100" + rule_id="200" + severity="INFO" + manual_severity="[false]" + message="old" + line="[null]" + effort_to_fix="[null]" + technical_debt="[null]" + status="OPEN" + resolution="[null]" + checksum="[null]" + reporter="[null]" + author_login="[null]" + assignee="[null]" + issue_creation_date="1401000000000" + issue_update_date="1402000000000" + issue_close_date="1403000000000" + created_at="1400000000000" + updated_at="1500000000000" + action_plan_key="[null]" + /> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueMapperTest/updateBeforeSelectedDate_with_conflict-result.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueMapperTest/updateBeforeSelectedDate_with_conflict-result.xml new file mode 100644 index 00000000000..ecb26c85603 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueMapperTest/updateBeforeSelectedDate_with_conflict-result.xml @@ -0,0 +1,30 @@ +<dataset> + <!-- not updated --> + <issues + id="100" + kee="ABCDE" + component_uuid="uuid-123" + project_uuid="uuid-100" + rule_id="200" + severity="INFO" + manual_severity="[false]" + message="old" + line="[null]" + effort_to_fix="[null]" + technical_debt="[null]" + status="OPEN" + resolution="[null]" + checksum="[null]" + reporter="[null]" + author_login="[null]" + assignee="[null]" + issue_attributes="[null]" + tags="[null]" + issue_creation_date="[null]" + issue_update_date="[null]" + issue_close_date="[null]" + created_at="1400000000000" + updated_at="1450000000000" + action_plan_key="[null]" + /> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueMapperTest/updateBeforeSelectedDate_with_conflict.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueMapperTest/updateBeforeSelectedDate_with_conflict.xml new file mode 100644 index 00000000000..0264dc2bd7b --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueMapperTest/updateBeforeSelectedDate_with_conflict.xml @@ -0,0 +1,28 @@ +<dataset> + <issues + id="100" + kee="ABCDE" + component_uuid="uuid-123" + project_uuid="uuid-100" + rule_id="200" + severity="INFO" + manual_severity="[false]" + message="old" + line="[null]" + effort_to_fix="[null]" + technical_debt="[null]" + status="OPEN" + resolution="[null]" + checksum="[null]" + reporter="[null]" + author_login="[null]" + assignee="[null]" + issue_attributes="[null]" + issue_creation_date="[null]" + issue_update_date="[null]" + issue_close_date="[null]" + created_at="1400000000000" + updated_at="1450000000000" + action_plan_key="[null]" + /> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueStatsDaoTest/should_select_assignees.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueStatsDaoTest/should_select_assignees.xml new file mode 100644 index 00000000000..4cc9d077a16 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueStatsDaoTest/should_select_assignees.xml @@ -0,0 +1,80 @@ +<dataset> + + <group_roles id="1" group_id="[null]" resource_id="399" role="user"/> + <projects id="399" kee="my.project:kee" root_id="[null]" qualifier="TRK" scope="PRJ"/> + + <issues + id="100" + kee="ABCDE-1" + component_uuid="uuid-401" + project_uuid="uuid-399" + rule_id="500" + severity="BLOCKER" + manual_severity="[false]" + message="[null]" + line="200" + effort_to_fix="4.2" + status="OPEN" + resolution="FIXED" + checksum="XXX" + reporter="arthur" + assignee="perceval" + author_login="[null]" + issue_attributes="JIRA=FOO-1234" + issue_creation_date="1366063200000" + issue_update_date="1366063200000" + issue_close_date="1366063200000" + created_at="2013-04-16" + updated_at="2013-04-16" + /> + + <issues + id="101" + kee="ABCDE-2" + component_uuid="uuid-401" + project_uuid="uuid-399" + rule_id="500" + severity="BLOCKER" + manual_severity="[false]" + message="[null]" + line="200" + effort_to_fix="4.2" + status="OPEN" + resolution="FIXED" + checksum="XXX" + reporter="arthur" + assignee="[null]" + author_login="[null]" + issue_attributes="JIRA=FOO-1234" + issue_creation_date="1366063200000" + issue_update_date="1366063200000" + issue_close_date="1366063200000" + created_at="2013-04-16" + updated_at="2013-04-16" + /> + + <issues + id="102" + kee="ABCDE-3" + component_uuid="uuid-401" + project_uuid="uuid-399" + rule_id="501" + severity="BLOCKER" + manual_severity="[false]" + message="[null]" + line="200" + effort_to_fix="4.2" + status="OPEN" + resolution="FIXED" + checksum="XXX" + reporter="arthur" + assignee="perceval" + author_login="[null]" + issue_attributes="JIRA=FOO-1234" + issue_creation_date="1366063200000" + issue_update_date="1366063200000" + issue_close_date="1366063200000" + created_at="2013-04-16" + updated_at="2013-04-16" + /> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/loadedtemplate/LoadedTemplateDaoTest/shouldCountByTypeAndKey.xml b/sonar-db/src/test/resources/org/sonar/db/loadedtemplate/LoadedTemplateDaoTest/shouldCountByTypeAndKey.xml new file mode 100644 index 00000000000..f4b6b01f4ab --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/loadedtemplate/LoadedTemplateDaoTest/shouldCountByTypeAndKey.xml @@ -0,0 +1,8 @@ +<dataset> + + <loaded_templates + id="1" + kee="HOTSPOTS" + template_type="DASHBOARD"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/loadedtemplate/LoadedTemplateDaoTest/shouldInsert-result.xml b/sonar-db/src/test/resources/org/sonar/db/loadedtemplate/LoadedTemplateDaoTest/shouldInsert-result.xml new file mode 100644 index 00000000000..6881dd82799 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/loadedtemplate/LoadedTemplateDaoTest/shouldInsert-result.xml @@ -0,0 +1,8 @@ +<dataset> + + <loaded_templates + id="1" + kee="SQALE" + template_type="DASHBOARD"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/loadedtemplate/LoadedTemplateDaoTest/shouldInsert.xml b/sonar-db/src/test/resources/org/sonar/db/loadedtemplate/LoadedTemplateDaoTest/shouldInsert.xml new file mode 100644 index 00000000000..871dedcb5e9 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/loadedtemplate/LoadedTemplateDaoTest/shouldInsert.xml @@ -0,0 +1,3 @@ +<dataset> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/measure/MeasureFilterDaoTest/shared.xml b/sonar-db/src/test/resources/org/sonar/db/measure/MeasureFilterDaoTest/shared.xml new file mode 100644 index 00000000000..8814a1c894d --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/measure/MeasureFilterDaoTest/shared.xml @@ -0,0 +1,23 @@ +<dataset> + + <measure_filters + id="1" + name="Projects" + user_id="[null]" + shared="[true]" + description="All projects" + data="qualifiers=TRK" + created_at="2012-12-25" + updated_at="2012-12-25"/> + + <measure_filters + id="2" + name="Files" + user_id="[null]" + shared="[true]" + description="All files" + data="qualifiers=FIL" + created_at="2012-01-25" + updated_at="2012-01-25"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/measure/MeasureFilterDaoTest/shouldInsert-result.xml b/sonar-db/src/test/resources/org/sonar/db/measure/MeasureFilterDaoTest/shouldInsert-result.xml new file mode 100644 index 00000000000..1100b166b82 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/measure/MeasureFilterDaoTest/shouldInsert-result.xml @@ -0,0 +1,34 @@ +<dataset> + + <measure_filters + id="1" + name="Projects" + user_id="[null]" + shared="[true]" + description="All projects" + data="qualifiers=TRK" + created_at="2012-12-25" + updated_at="2012-12-25"/> + + <measure_filters + id="2" + name="Files" + user_id="[null]" + shared="[true]" + description="All files" + data="qualifiers=FIL" + created_at="2012-01-25" + updated_at="2012-01-25"/> + + + <measure_filters + id="3" + name="Project Treemap" + user_id="123" + shared="[true]" + description="Treemap of projects" + data="qualifiers=TRK|display=treemap" + created_at="2012-12-25" + updated_at="2012-12-25"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/notification/NotificationQueueDaoTest/should_delete_notification-result.xml b/sonar-db/src/test/resources/org/sonar/db/notification/NotificationQueueDaoTest/should_delete_notification-result.xml new file mode 100644 index 00000000000..81662a5913d --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/notification/NotificationQueueDaoTest/should_delete_notification-result.xml @@ -0,0 +1,13 @@ +<dataset> + + <notifications id="2" data="rO0ABXNyAChvcmcuc29uYXIuYXBpLm5vdGlmaWNhdGlvbnMuTm90aWZpY2F0aW9uTppHnJFK4aAC +AAJMAAZmaWVsZHN0AA9MamF2YS91dGlsL01hcDtMAAR0eXBldAASTGphdmEvbGFuZy9TdHJpbmc7 +eHBzcgARamF2YS51dGlsLkhhc2hNYXAFB9rBwxZg0QMAAkYACmxvYWRGYWN0b3JJAAl0aHJlc2hv +bGR4cD9AAAAAAAAMdwgAAAAQAAAAAHh0AAZlbWFpbDI="/> + + <notifications id="4" data="rO0ABXNyAChvcmcuc29uYXIuYXBpLm5vdGlmaWNhdGlvbnMuTm90aWZpY2F0aW9uTppHnJFK4aAC +AAJMAAZmaWVsZHN0AA9MamF2YS91dGlsL01hcDtMAAR0eXBldAASTGphdmEvbGFuZy9TdHJpbmc7 +eHBzcgARamF2YS51dGlsLkhhc2hNYXAFB9rBwxZg0QMAAkYACmxvYWRGYWN0b3JJAAl0aHJlc2hv +bGR4cD9AAAAAAAAMdwgAAAAQAAAAAHh0AAZlbWFpbDQ="/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/notification/NotificationQueueDaoTest/should_delete_notification.xml b/sonar-db/src/test/resources/org/sonar/db/notification/NotificationQueueDaoTest/should_delete_notification.xml new file mode 100644 index 00000000000..6611a054610 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/notification/NotificationQueueDaoTest/should_delete_notification.xml @@ -0,0 +1,23 @@ +<dataset> + + <notifications id="1" data="rO0ABXNyAChvcmcuc29uYXIuYXBpLm5vdGlmaWNhdGlvbnMuTm90aWZpY2F0aW9uTppHnJFK4aAC +AAJMAAZmaWVsZHN0AA9MamF2YS91dGlsL01hcDtMAAR0eXBldAASTGphdmEvbGFuZy9TdHJpbmc7 +eHBzcgARamF2YS51dGlsLkhhc2hNYXAFB9rBwxZg0QMAAkYACmxvYWRGYWN0b3JJAAl0aHJlc2hv +bGR4cD9AAAAAAAAMdwgAAAAQAAAAAHh0AAZlbWFpbDE="/> + + <notifications id="2" data="rO0ABXNyAChvcmcuc29uYXIuYXBpLm5vdGlmaWNhdGlvbnMuTm90aWZpY2F0aW9uTppHnJFK4aAC +AAJMAAZmaWVsZHN0AA9MamF2YS91dGlsL01hcDtMAAR0eXBldAASTGphdmEvbGFuZy9TdHJpbmc7 +eHBzcgARamF2YS51dGlsLkhhc2hNYXAFB9rBwxZg0QMAAkYACmxvYWRGYWN0b3JJAAl0aHJlc2hv +bGR4cD9AAAAAAAAMdwgAAAAQAAAAAHh0AAZlbWFpbDI="/> + + <notifications id="3" data="rO0ABXNyAChvcmcuc29uYXIuYXBpLm5vdGlmaWNhdGlvbnMuTm90aWZpY2F0aW9uTppHnJFK4aAC +AAJMAAZmaWVsZHN0AA9MamF2YS91dGlsL01hcDtMAAR0eXBldAASTGphdmEvbGFuZy9TdHJpbmc7 +eHBzcgARamF2YS51dGlsLkhhc2hNYXAFB9rBwxZg0QMAAkYACmxvYWRGYWN0b3JJAAl0aHJlc2hv +bGR4cD9AAAAAAAAMdwgAAAAQAAAAAHh0AAZlbWFpbDM="/> + + <notifications id="4" data="rO0ABXNyAChvcmcuc29uYXIuYXBpLm5vdGlmaWNhdGlvbnMuTm90aWZpY2F0aW9uTppHnJFK4aAC +AAJMAAZmaWVsZHN0AA9MamF2YS91dGlsL01hcDtMAAR0eXBldAASTGphdmEvbGFuZy9TdHJpbmc7 +eHBzcgARamF2YS51dGlsLkhhc2hNYXAFB9rBwxZg0QMAAkYACmxvYWRGYWN0b3JJAAl0aHJlc2hv +bGR4cD9AAAAAAAAMdwgAAAAQAAAAAHh0AAZlbWFpbDQ="/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/notification/NotificationQueueDaoTest/should_findOldest.xml b/sonar-db/src/test/resources/org/sonar/db/notification/NotificationQueueDaoTest/should_findOldest.xml new file mode 100644 index 00000000000..6611a054610 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/notification/NotificationQueueDaoTest/should_findOldest.xml @@ -0,0 +1,23 @@ +<dataset> + + <notifications id="1" data="rO0ABXNyAChvcmcuc29uYXIuYXBpLm5vdGlmaWNhdGlvbnMuTm90aWZpY2F0aW9uTppHnJFK4aAC +AAJMAAZmaWVsZHN0AA9MamF2YS91dGlsL01hcDtMAAR0eXBldAASTGphdmEvbGFuZy9TdHJpbmc7 +eHBzcgARamF2YS51dGlsLkhhc2hNYXAFB9rBwxZg0QMAAkYACmxvYWRGYWN0b3JJAAl0aHJlc2hv +bGR4cD9AAAAAAAAMdwgAAAAQAAAAAHh0AAZlbWFpbDE="/> + + <notifications id="2" data="rO0ABXNyAChvcmcuc29uYXIuYXBpLm5vdGlmaWNhdGlvbnMuTm90aWZpY2F0aW9uTppHnJFK4aAC +AAJMAAZmaWVsZHN0AA9MamF2YS91dGlsL01hcDtMAAR0eXBldAASTGphdmEvbGFuZy9TdHJpbmc7 +eHBzcgARamF2YS51dGlsLkhhc2hNYXAFB9rBwxZg0QMAAkYACmxvYWRGYWN0b3JJAAl0aHJlc2hv +bGR4cD9AAAAAAAAMdwgAAAAQAAAAAHh0AAZlbWFpbDI="/> + + <notifications id="3" data="rO0ABXNyAChvcmcuc29uYXIuYXBpLm5vdGlmaWNhdGlvbnMuTm90aWZpY2F0aW9uTppHnJFK4aAC +AAJMAAZmaWVsZHN0AA9MamF2YS91dGlsL01hcDtMAAR0eXBldAASTGphdmEvbGFuZy9TdHJpbmc7 +eHBzcgARamF2YS51dGlsLkhhc2hNYXAFB9rBwxZg0QMAAkYACmxvYWRGYWN0b3JJAAl0aHJlc2hv +bGR4cD9AAAAAAAAMdwgAAAAQAAAAAHh0AAZlbWFpbDM="/> + + <notifications id="4" data="rO0ABXNyAChvcmcuc29uYXIuYXBpLm5vdGlmaWNhdGlvbnMuTm90aWZpY2F0aW9uTppHnJFK4aAC +AAJMAAZmaWVsZHN0AA9MamF2YS91dGlsL01hcDtMAAR0eXBldAASTGphdmEvbGFuZy9TdHJpbmc7 +eHBzcgARamF2YS51dGlsLkhhc2hNYXAFB9rBwxZg0QMAAkYACmxvYWRGYWN0b3JJAAl0aHJlc2hv +bGR4cD9AAAAAAAAMdwgAAAAQAAAAAHh0AAZlbWFpbDQ="/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/notification/NotificationQueueDaoTest/should_insert_new_notification_queue-result.xml b/sonar-db/src/test/resources/org/sonar/db/notification/NotificationQueueDaoTest/should_insert_new_notification_queue-result.xml new file mode 100644 index 00000000000..7afce2d8263 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/notification/NotificationQueueDaoTest/should_insert_new_notification_queue-result.xml @@ -0,0 +1,8 @@ +<dataset> + + <notifications id="1" data="rO0ABXNyAChvcmcuc29uYXIuYXBpLm5vdGlmaWNhdGlvbnMuTm90aWZpY2F0aW9uTppHnJFK4aAC +AAJMAAZmaWVsZHN0AA9MamF2YS91dGlsL01hcDtMAAR0eXBldAASTGphdmEvbGFuZy9TdHJpbmc7 +eHBzcgARamF2YS51dGlsLkhhc2hNYXAFB9rBwxZg0QMAAkYACmxvYWRGYWN0b3JJAAl0aHJlc2hv +bGR4cD9AAAAAAAAMdwgAAAAQAAAAAHh0AAVlbWFpbA=="/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/GroupWithPermissionDaoTest/groups_with_permissions.xml b/sonar-db/src/test/resources/org/sonar/db/permission/GroupWithPermissionDaoTest/groups_with_permissions.xml new file mode 100644 index 00000000000..418d5e69fac --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/GroupWithPermissionDaoTest/groups_with_permissions.xml @@ -0,0 +1,20 @@ +<dataset> + + <groups id="200" name="sonar-administrators" description="System administrators"/> + <groups id="201" name="sonar-users" description="Any new users created will automatically join this group"/> + <groups id="202" name="sonar-reviewers" description="Reviewers"/> + + <!-- Project permissions --> + <group_roles id="1" group_id="200" resource_id="100" role="user"/> + <group_roles id="2" group_id="200" resource_id="100" role="admin"/> + <group_roles id="3" group_id="200" resource_id="100" role="codeviewer"/> + + <group_roles id="4" group_id="201" resource_id="100" role="user"/> + + <!-- Permission 'user' for Anyone group --> + <group_roles id="5" group_id="[null]" resource_id="100" role="user"/> + + <!-- Global permission --> + <group_roles id="10" group_id="200" resource_id="[null]" role="admin"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/GroupWithPermissionDaoTest/groups_with_permissions_should_be_sorted_by_group_name.xml b/sonar-db/src/test/resources/org/sonar/db/permission/GroupWithPermissionDaoTest/groups_with_permissions_should_be_sorted_by_group_name.xml new file mode 100644 index 00000000000..10ab0e21e3f --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/GroupWithPermissionDaoTest/groups_with_permissions_should_be_sorted_by_group_name.xml @@ -0,0 +1,15 @@ +<dataset> + + <groups id="200" name="sonar-reviewers" description="Reviewers"/> + <groups id="201" name="sonar-users" description="Any new users created will automatically join this group"/> + <groups id="202" name="sonar-administrators" description="System administrators"/> + + <!-- Project permissions --> + <group_roles id="1" group_id="200" resource_id="100" role="user"/> + <group_roles id="2" group_id="200" resource_id="100" role="admin"/> + <group_roles id="3" group_id="200" resource_id="100" role="codeviewer"/> + + <!-- Permission for Anyone group --> + <group_roles id="4" group_id="[null]" resource_id="100" role="user"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/GroupWithPermissionTemplateDaoTest/groups_with_permissions.xml b/sonar-db/src/test/resources/org/sonar/db/permission/GroupWithPermissionTemplateDaoTest/groups_with_permissions.xml new file mode 100644 index 00000000000..8d6592cbc11 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/GroupWithPermissionTemplateDaoTest/groups_with_permissions.xml @@ -0,0 +1,16 @@ +<dataset> + + <groups id="200" name="sonar-administrators" description="System administrators"/> + <groups id="201" name="sonar-users" description="Any new users created will automatically join this group"/> + <groups id="202" name="sonar-reviewers" description="Reviewers"/> + + <perm_templates_groups id="1" group_id="200" permission_reference="user" template_id="50"/> + <perm_templates_groups id="2" group_id="200" permission_reference="admin" template_id="50"/> + <perm_templates_groups id="3" group_id="200" permission_reference="codeviewer" template_id="50"/> + + <perm_templates_groups id="4" group_id="201" permission_reference="user" template_id="50"/> + + <!-- Permission 'user' for Anyone group --> + <perm_templates_groups id="5" group_id="[null]" permission_reference="user" template_id="50"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/GroupWithPermissionTemplateDaoTest/groups_with_permissions_should_be_sorted_by_group_name.xml b/sonar-db/src/test/resources/org/sonar/db/permission/GroupWithPermissionTemplateDaoTest/groups_with_permissions_should_be_sorted_by_group_name.xml new file mode 100644 index 00000000000..baf745a5028 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/GroupWithPermissionTemplateDaoTest/groups_with_permissions_should_be_sorted_by_group_name.xml @@ -0,0 +1,16 @@ +<dataset> + + <groups id="200" name="sonar-reviewers"/> + <groups id="201" name="sonar-users"/> + <groups id="202" name="sonar-administrators"/> + + <perm_templates_groups id="1" group_id="200" permission_reference="user" template_id="50"/> + <perm_templates_groups id="2" group_id="200" permission_reference="admin" template_id="50"/> + <perm_templates_groups id="3" group_id="200" permission_reference="codeviewer" template_id="50"/> + + <perm_templates_groups id="4" group_id="201" permission_reference="user" template_id="50"/> + + <!-- Permission 'user' for Anyone group --> + <perm_templates_groups id="5" group_id="[null]" permission_reference="user" template_id="50"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_add_user_permission-result.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_add_user_permission-result.xml new file mode 100644 index 00000000000..793d16b3bae --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_add_user_permission-result.xml @@ -0,0 +1,13 @@ +<dataset> + + <users id="200" login="dave.loper" name="Dave Loper" email="dave.loper@company.net" active="[true]"/> + + <user_roles id="1" user_id="200" resource_id="123" role="user"/> + <user_roles id="2" user_id="200" resource_id="123" role="admin"/> + + <projects id="100" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" + description="the description" long_name="Apache Struts" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + authorization_updated_at="123456789"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_add_user_permission.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_add_user_permission.xml new file mode 100644 index 00000000000..8f079ec590c --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_add_user_permission.xml @@ -0,0 +1,12 @@ +<dataset> + + <users id="200" login="dave.loper" name="Dave Loper" email="dave.loper@company.net" active="[true]"/> + + <user_roles id="1" user_id="200" resource_id="123" role="user"/> + + <projects id="123" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" + description="the description" long_name="Apache Struts" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + authorization_updated_at="123456789"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_apply_permission_template-result.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_apply_permission_template-result.xml new file mode 100644 index 00000000000..b70b4ac31a0 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_apply_permission_template-result.xml @@ -0,0 +1,36 @@ +<dataset> + + <groups id="100" name="sonar-administrators"/> + <groups id="101" name="sonar-users"/> + + <users id="200" login="marius" name="Marius" email="[null]" active="[true]"/> + + <!-- on other resources --> + <group_roles id="1" group_id="100" resource_id="1" role="admin"/> + <group_roles id="2" group_id="101" resource_id="1" role="user"/> + <user_roles id="1" user_id="200" resource_id="1" role="admin"/> + + <!-- new groups permissions : sonar-administrators (admin), sonar-users (user & codeviewer), Anyone (user & codeviewer) --> + <group_roles id="3" group_id="100" resource_id="123" role="admin"/> + <group_roles id="4" group_id="101" resource_id="123" role="user"/> + <group_roles id="5" group_id="[null]" resource_id="123" role="user"/> + <group_roles id="6" group_id="101" resource_id="123" role="codeviewer"/> + <group_roles id="7" group_id="[null]" resource_id="123" role="codeviewer"/> + <group_roles id="8" group_id="100" resource_id="123" role="issueadmin"/> + + <!-- new user permission : marius (admin) --> + <user_roles id="2" user_id="200" resource_id="123" role="admin"/> + + <!-- default permission template for all qualifiers --> + <permission_templates id="1" name="default" kee="default_20130101_010203"/> + + <perm_templates_groups id="1" template_id="1" group_id="100" permission_reference="admin"/> + <perm_templates_groups id="2" template_id="1" group_id="101" permission_reference="user"/> + <perm_templates_groups id="3" template_id="1" group_id="[null]" permission_reference="user"/> + <perm_templates_groups id="4" template_id="1" group_id="101" permission_reference="codeviewer"/> + <perm_templates_groups id="5" template_id="1" group_id="[null]" permission_reference="codeviewer"/> + <perm_templates_groups id="6" template_id="1" group_id="100" permission_reference="issueadmin"/> + + <perm_templates_users id="1" template_id="1" user_id="200" permission_reference="admin"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_apply_permission_template.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_apply_permission_template.xml new file mode 100644 index 00000000000..ef9212b8087 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_apply_permission_template.xml @@ -0,0 +1,31 @@ +<dataset> + + <projects id="123" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" + description="the description" long_name="Apache Struts" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + authorization_updated_at="123456789"/> + + <groups id="100" name="sonar-administrators"/> + <groups id="101" name="sonar-users"/> + + <users id="200" login="marius" name="Marius" email="[null]" active="[true]"/> + + <!-- on other resources --> + <group_roles id="1" group_id="100" resource_id="1" role="admin"/> + <group_roles id="2" group_id="101" resource_id="1" role="user"/> + <user_roles id="1" user_id="200" resource_id="1" role="admin"/> + + + <!-- default permission template for all qualifiers --> + <permission_templates id="1" name="default" kee="default_20130101_010203"/> + + <perm_templates_groups id="1" template_id="1" group_id="100" permission_reference="admin"/> + <perm_templates_groups id="2" template_id="1" group_id="101" permission_reference="user"/> + <perm_templates_groups id="3" template_id="1" group_id="[null]" permission_reference="user"/> + <perm_templates_groups id="4" template_id="1" group_id="101" permission_reference="codeviewer"/> + <perm_templates_groups id="5" template_id="1" group_id="[null]" permission_reference="codeviewer"/> + <perm_templates_groups id="6" template_id="1" group_id="100" permission_reference="issueadmin"/> + + <perm_templates_users id="1" template_id="1" user_id="200" permission_reference="admin"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_count_component_permissions.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_count_component_permissions.xml new file mode 100644 index 00000000000..aea672478c6 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_count_component_permissions.xml @@ -0,0 +1,11 @@ +<dataset> + + <users id="200" login="dave.loper" name="Dave Loper" email="dave.loper@company.net" active="[true]"/> + + <groups id="100" name="devs"/> + + <user_roles id="1" user_id="200" resource_id="123" role="user"/> + + <group_roles id="1" group_id="100" resource_id="123" role="codeviewer"/> + +</dataset>
\ No newline at end of file diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_delete_group_permission-result.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_delete_group_permission-result.xml new file mode 100644 index 00000000000..e77f558dc36 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_delete_group_permission-result.xml @@ -0,0 +1,12 @@ +<dataset> + + <groups id="100" name="devs"/> + + <group_roles id="1" group_id="100" resource_id="123" role="admin"/> + + <projects id="123" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" + description="the description" long_name="Apache Struts" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + authorization_updated_at="123456789"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_delete_group_permission.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_delete_group_permission.xml new file mode 100644 index 00000000000..9c3bcfce197 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_delete_group_permission.xml @@ -0,0 +1,13 @@ +<dataset> + + <groups id="100" name="devs"/> + + <group_roles id="1" group_id="100" resource_id="123" role="admin"/> + <group_roles id="2" group_id="100" resource_id="123" role="user"/> + + <projects id="123" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" + description="the description" long_name="Apache Struts" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + authorization_updated_at="123456789"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_delete_user_permission-result.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_delete_user_permission-result.xml new file mode 100644 index 00000000000..8f079ec590c --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_delete_user_permission-result.xml @@ -0,0 +1,12 @@ +<dataset> + + <users id="200" login="dave.loper" name="Dave Loper" email="dave.loper@company.net" active="[true]"/> + + <user_roles id="1" user_id="200" resource_id="123" role="user"/> + + <projects id="123" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" + description="the description" long_name="Apache Struts" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + authorization_updated_at="123456789"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_delete_user_permission.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_delete_user_permission.xml new file mode 100644 index 00000000000..fe3e01186db --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_delete_user_permission.xml @@ -0,0 +1,13 @@ +<dataset> + + <users id="200" login="dave.loper" name="Dave Loper" email="dave.loper@company.net" active="[true]"/> + + <user_roles id="1" user_id="200" resource_id="123" role="user"/> + <user_roles id="2" user_id="200" resource_id="123" role="admin"/> + + <projects id="123" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" + description="the description" long_name="Apache Struts" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + authorization_updated_at="123456789"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_insert_anyone_group_permission-result.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_insert_anyone_group_permission-result.xml new file mode 100644 index 00000000000..276e8d7da3f --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_insert_anyone_group_permission-result.xml @@ -0,0 +1,14 @@ +<dataset> + + <groups id="100" name="devs"/> + + <group_roles id="1" group_id="100" resource_id="123" role="admin"/> + <group_roles id="2" group_id="[null]" resource_id="123" role="user"/> + + <projects id="123" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" + description="the description" long_name="Apache Struts" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + authorization_updated_at="123456789"/> + + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_insert_anyone_group_permission.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_insert_anyone_group_permission.xml new file mode 100644 index 00000000000..4552a5339ee --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_insert_anyone_group_permission.xml @@ -0,0 +1,13 @@ +<dataset> + + <groups id="100" name="devs"/> + + <group_roles id="1" group_id="100" resource_id="123" role="admin"/> + + <projects id="123" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" + description="the description" long_name="Apache Struts" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + authorization_updated_at="123456789"/> + + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_insert_group_permission-result.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_insert_group_permission-result.xml new file mode 100644 index 00000000000..9c3bcfce197 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_insert_group_permission-result.xml @@ -0,0 +1,13 @@ +<dataset> + + <groups id="100" name="devs"/> + + <group_roles id="1" group_id="100" resource_id="123" role="admin"/> + <group_roles id="2" group_id="100" resource_id="123" role="user"/> + + <projects id="123" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" + description="the description" long_name="Apache Struts" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + authorization_updated_at="123456789"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_insert_group_permission.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_insert_group_permission.xml new file mode 100644 index 00000000000..e77f558dc36 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_insert_group_permission.xml @@ -0,0 +1,12 @@ +<dataset> + + <groups id="100" name="devs"/> + + <group_roles id="1" group_id="100" resource_id="123" role="admin"/> + + <projects id="123" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" + description="the description" long_name="Apache Struts" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + authorization_updated_at="123456789"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_remove_all_permissions-result.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_remove_all_permissions-result.xml new file mode 100644 index 00000000000..38def462ed1 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_remove_all_permissions-result.xml @@ -0,0 +1,11 @@ +<dataset> + + <users id="200" login="dave.loper" name="Dave Loper" email="dave.loper@company.net" active="[true]"/> + + <groups id="100" name="devs"/> + + <user_roles/> + + <group_roles/> + +</dataset>
\ No newline at end of file diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_remove_all_permissions.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_remove_all_permissions.xml new file mode 100644 index 00000000000..aea672478c6 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionFacadeTest/should_remove_all_permissions.xml @@ -0,0 +1,11 @@ +<dataset> + + <users id="200" login="dave.loper" name="Dave Loper" email="dave.loper@company.net" active="[true]"/> + + <groups id="100" name="devs"/> + + <user_roles id="1" user_id="200" resource_id="123" role="user"/> + + <group_roles id="1" group_id="100" resource_id="123" role="codeviewer"/> + +</dataset>
\ No newline at end of file diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/addGroupPermissionToTemplate-result.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/addGroupPermissionToTemplate-result.xml new file mode 100644 index 00000000000..c80216743b1 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/addGroupPermissionToTemplate-result.xml @@ -0,0 +1,5 @@ +<dataset> + <permission_templates id="1" name="my template" kee="my_template_20130102_030405" description="my description"/> + <perm_templates_users/> + <perm_templates_groups id="1" template_id="1" group_id="1" permission_reference="new_permission"/> +</dataset>
\ No newline at end of file diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/addGroupPermissionToTemplate.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/addGroupPermissionToTemplate.xml new file mode 100644 index 00000000000..6645e851711 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/addGroupPermissionToTemplate.xml @@ -0,0 +1,5 @@ +<dataset> + <permission_templates id="1" name="my template" kee="my_template_20130102_030405" description="my description"/> + <perm_templates_users/> + <perm_templates_groups/> +</dataset>
\ No newline at end of file diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/addNullGroupPermissionToTemplate-result.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/addNullGroupPermissionToTemplate-result.xml new file mode 100644 index 00000000000..7d42701d39f --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/addNullGroupPermissionToTemplate-result.xml @@ -0,0 +1,5 @@ +<dataset> + <permission_templates id="1" name="my template" kee="my_template_20130102_030405" description="my description"/> + <perm_templates_users/> + <perm_templates_groups id="1" template_id="1" group_id="[null]" permission_reference="new_permission"/> +</dataset>
\ No newline at end of file diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/addNullGroupPermissionToTemplate.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/addNullGroupPermissionToTemplate.xml new file mode 100644 index 00000000000..6645e851711 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/addNullGroupPermissionToTemplate.xml @@ -0,0 +1,5 @@ +<dataset> + <permission_templates id="1" name="my template" kee="my_template_20130102_030405" description="my description"/> + <perm_templates_users/> + <perm_templates_groups/> +</dataset>
\ No newline at end of file diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/addUserPermissionToTemplate-result.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/addUserPermissionToTemplate-result.xml new file mode 100644 index 00000000000..40bf5d45d4e --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/addUserPermissionToTemplate-result.xml @@ -0,0 +1,5 @@ +<dataset> + <permission_templates id="1" name="my template" kee="my_template_20130102_030405" description="my description"/> + <perm_templates_users id="1" template_id="1" user_id="1" permission_reference="new_permission"/> + <perm_templates_groups/> +</dataset>
\ No newline at end of file diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/addUserPermissionToTemplate.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/addUserPermissionToTemplate.xml new file mode 100644 index 00000000000..6645e851711 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/addUserPermissionToTemplate.xml @@ -0,0 +1,5 @@ +<dataset> + <permission_templates id="1" name="my template" kee="my_template_20130102_030405" description="my description"/> + <perm_templates_users/> + <perm_templates_groups/> +</dataset>
\ No newline at end of file diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/createNonAsciiPermissionTemplate-result.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/createNonAsciiPermissionTemplate-result.xml new file mode 100644 index 00000000000..8596137c817 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/createNonAsciiPermissionTemplate-result.xml @@ -0,0 +1,4 @@ +<dataset> + <permission_templates id="1" name="Môü Gnô Gnèçà ß" kee="mou_gno_gneca_20130102_010405" description="my description" + key_pattern="[null]"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/createNonAsciiPermissionTemplate.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/createNonAsciiPermissionTemplate.xml new file mode 100644 index 00000000000..5ed00ba028b --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/createNonAsciiPermissionTemplate.xml @@ -0,0 +1 @@ +<dataset></dataset>
\ No newline at end of file diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/createPermissionTemplate-result.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/createPermissionTemplate-result.xml new file mode 100644 index 00000000000..4f889d5ba48 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/createPermissionTemplate-result.xml @@ -0,0 +1,4 @@ +<dataset> + <permission_templates id="1" name="my template" kee="my_template_20130102_010405" description="my description" + key_pattern="myregexp"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/createPermissionTemplate.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/createPermissionTemplate.xml new file mode 100644 index 00000000000..5ed00ba028b --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/createPermissionTemplate.xml @@ -0,0 +1 @@ +<dataset></dataset>
\ No newline at end of file diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/deletePermissionTemplate-result.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/deletePermissionTemplate-result.xml new file mode 100644 index 00000000000..115b732cb64 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/deletePermissionTemplate-result.xml @@ -0,0 +1,8 @@ +<dataset> + <permission_templates id="2" name="other template" kee="my_template_20130102_030405" description="other description" + created_at="[null]" updated_at="[null]"/> + + <perm_templates_users/> + + <perm_templates_groups/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/deletePermissionTemplate.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/deletePermissionTemplate.xml new file mode 100644 index 00000000000..0520355af31 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/deletePermissionTemplate.xml @@ -0,0 +1,14 @@ +<dataset> + <permission_templates id="1" name="my template" kee="my_template_20130102_030405" description="my description" + created_at="[null]" updated_at="[null]"/> + <permission_templates id="2" name="other template" kee="my_template_20130102_030405" description="other description" + created_at="[null]" updated_at="[null]"/> + + <perm_templates_users id="1" template_id="1" user_id="1" permission_reference="user_permission1"/> + <perm_templates_users id="2" template_id="1" user_id="2" permission_reference="user_permission1"/> + <perm_templates_users id="3" template_id="1" user_id="2" permission_reference="user_permission2"/> + + <perm_templates_groups id="1" template_id="1" group_id="1" permission_reference="group_permission1"/> + <perm_templates_groups id="2" template_id="1" group_id="2" permission_reference="group_permission1"/> + <perm_templates_groups id="3" template_id="1" group_id="[null]" permission_reference="group_permission2"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/removeGroupPermissionFromTemplate-result.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/removeGroupPermissionFromTemplate-result.xml new file mode 100644 index 00000000000..140738df7db --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/removeGroupPermissionFromTemplate-result.xml @@ -0,0 +1,6 @@ +<dataset> + <permission_templates id="1" name="my template" kee="my_template_20130102_030405" description="my description"/> + <perm_templates_users/> + <perm_templates_groups id="1" template_id="1" group_id="1" permission_reference="remaining_permission_other_group"/> + <perm_templates_groups id="3" template_id="1" group_id="2" permission_reference="remaining_permission_same_group"/> +</dataset>
\ No newline at end of file diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/removeGroupPermissionFromTemplate.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/removeGroupPermissionFromTemplate.xml new file mode 100644 index 00000000000..3258dcc22e5 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/removeGroupPermissionFromTemplate.xml @@ -0,0 +1,7 @@ +<dataset> + <permission_templates id="1" name="my template" kee="my_template_20130102_030405" description="my description"/> + <perm_templates_users/> + <perm_templates_groups id="1" template_id="1" group_id="1" permission_reference="remaining_permission_other_group"/> + <perm_templates_groups id="2" template_id="1" group_id="2" permission_reference="permission_to_remove"/> + <perm_templates_groups id="3" template_id="1" group_id="2" permission_reference="remaining_permission_same_group"/> +</dataset>
\ No newline at end of file diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/removeNullGroupPermissionFromTemplate-result.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/removeNullGroupPermissionFromTemplate-result.xml new file mode 100644 index 00000000000..c37bf10135a --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/removeNullGroupPermissionFromTemplate-result.xml @@ -0,0 +1,7 @@ +<dataset> + <permission_templates id="1" name="my template" kee="my_template_20130102_030405" description="my description"/> + <perm_templates_users/> + <perm_templates_groups id="1" template_id="1" group_id="1" permission_reference="remaining_permission_other_group"/> + <perm_templates_groups id="3" template_id="1" group_id="[null]" + permission_reference="remaining_permission_same_group"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/removeNullGroupPermissionFromTemplate.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/removeNullGroupPermissionFromTemplate.xml new file mode 100644 index 00000000000..9e28fa9e458 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/removeNullGroupPermissionFromTemplate.xml @@ -0,0 +1,8 @@ +<dataset> + <permission_templates id="1" name="my template" kee="my_template_20130102_030405" description="my description"/> + <perm_templates_users/> + <perm_templates_groups id="1" template_id="1" group_id="1" permission_reference="remaining_permission_other_group"/> + <perm_templates_groups id="2" template_id="1" group_id="[null]" permission_reference="permission_to_remove"/> + <perm_templates_groups id="3" template_id="1" group_id="[null]" + permission_reference="remaining_permission_same_group"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/removeUserPermissionFromTemplate-result.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/removeUserPermissionFromTemplate-result.xml new file mode 100644 index 00000000000..89983781b67 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/removeUserPermissionFromTemplate-result.xml @@ -0,0 +1,8 @@ +<dataset> + <permission_templates id="1" name="my template" kee="my_template_20130102_030405" description="my description"/> + + <perm_templates_users id="1" template_id="1" user_id="1" permission_reference="remaining_permission_other_user"/> + <perm_templates_users id="3" template_id="1" user_id="2" permission_reference="remaining_permission_same_user"/> + + <perm_templates_groups/> +</dataset>
\ No newline at end of file diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/removeUserPermissionFromTemplate.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/removeUserPermissionFromTemplate.xml new file mode 100644 index 00000000000..779bd770de8 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/removeUserPermissionFromTemplate.xml @@ -0,0 +1,9 @@ +<dataset> + <permission_templates id="1" name="my template" kee="my_template_20130102_030405" description="my description"/> + + <perm_templates_users id="1" template_id="1" user_id="1" permission_reference="remaining_permission_other_user"/> + <perm_templates_users id="2" template_id="1" user_id="2" permission_reference="permission_to_remove"/> + <perm_templates_users id="3" template_id="1" user_id="2" permission_reference="remaining_permission_same_user"/> + + <perm_templates_groups/> +</dataset>
\ No newline at end of file diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/remove_by_group-result.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/remove_by_group-result.xml new file mode 100644 index 00000000000..94ab2fde7ed --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/remove_by_group-result.xml @@ -0,0 +1,5 @@ +<dataset> + <permission_templates id="1" name="my template" kee="my_template_20130102_030405" description="my description"/> + <perm_templates_users/> + <perm_templates_groups id="1" template_id="1" group_id="1" permission_reference="remaining_permission_other_group"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/remove_by_group.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/remove_by_group.xml new file mode 100644 index 00000000000..2ff5815d855 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/remove_by_group.xml @@ -0,0 +1,7 @@ +<dataset> + <permission_templates id="1" name="my template" kee="my_template_20130102_030405" description="my description"/> + <perm_templates_users/> + <perm_templates_groups id="1" template_id="1" group_id="1" permission_reference="remaining_permission_other_group"/> + <perm_templates_groups id="2" template_id="1" group_id="2" permission_reference="permission_to_remove"/> + <perm_templates_groups id="3" template_id="1" group_id="2" permission_reference="permission_to_remove2"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/selectAllPermissionTemplates.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/selectAllPermissionTemplates.xml new file mode 100644 index 00000000000..e2e93914e09 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/selectAllPermissionTemplates.xml @@ -0,0 +1,8 @@ +<dataset> + <permission_templates id="1" name="template1" kee="template1_20130102_030405" description="description1" + created_at="[null]" updated_at="[null]"/> + <permission_templates id="2" name="template2" kee="template2_20130102_030405" description="description2" + created_at="[null]" updated_at="[null]"/> + <permission_templates id="3" name="template3" kee="template3_20130102_030405" description="description3" + created_at="[null]" updated_at="[null]"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/selectEmptyPermissionTemplate.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/selectEmptyPermissionTemplate.xml new file mode 100644 index 00000000000..ab25dd40192 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/selectEmptyPermissionTemplate.xml @@ -0,0 +1,10 @@ +<dataset> + <permission_templates id="1" name="my template" kee="my_template_20130102_030405" description="my description" + created_at="[null]" updated_at="[null]"/> + + <users id="1" login="user1" name="user1"/> + <users id="2" login="user2" name="user2"/> + + <groups id="1" name="group1"/> + <groups id="2" name="group2"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/selectPermissionTemplate.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/selectPermissionTemplate.xml new file mode 100644 index 00000000000..2c82c31400e --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/selectPermissionTemplate.xml @@ -0,0 +1,21 @@ +<dataset> + <permission_templates id="1" name="my template" kee="my_template_20130102_030405" description="my description" + created_at="[null]" updated_at="[null]"/> + + <perm_templates_users id="1" template_id="1" user_id="1" permission_reference="user_permission1"/> + <perm_templates_users id="2" template_id="1" user_id="2" permission_reference="user_permission1"/> + <perm_templates_users id="3" template_id="1" user_id="2" permission_reference="user_permission2"/> + + <users id="1" login="login1" name="user1"/> + <users id="2" login="login2" name="user2"/> + + <perm_templates_groups id="1" template_id="1" group_id="1" permission_reference="group_permission1"/> + <perm_templates_groups id="2" template_id="1" group_id="2" permission_reference="group_permission1"/> + <!-- Anyone group --> + <perm_templates_groups id="3" template_id="1" group_id="[null]" permission_reference="group_permission2"/> + <!-- Unmatched group --> + <perm_templates_groups id="4" template_id="1" group_id="999999" permission_reference="group_permission2"/> + + <groups id="1" name="group1"/> + <groups id="2" name="group2"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/updatePermissionTemplate-result.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/updatePermissionTemplate-result.xml new file mode 100644 index 00000000000..2449862a0a8 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/updatePermissionTemplate-result.xml @@ -0,0 +1,6 @@ +<dataset> + <permission_templates id="1" name="new_name" kee="template1_20130102_030405" description="new_description" + key_pattern="new_regexp" created_at="[null]" updated_at="[null]"/> + <permission_templates id="2" name="template2" kee="template2_20130102_030405" description="description2" + key_pattern="barregexp" created_at="[null]" updated_at="[null]"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/updatePermissionTemplate.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/updatePermissionTemplate.xml new file mode 100644 index 00000000000..c14e8b61e8b --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionTemplateDaoTest/updatePermissionTemplate.xml @@ -0,0 +1,6 @@ +<dataset> + <permission_templates id="1" name="template1" kee="template1_20130102_030405" description="description1" + key_pattern="fooregexp" created_at="[null]" updated_at="[null]"/> + <permission_templates id="2" name="template2" kee="template2_20130102_030405" description="description2" + key_pattern="barregexp" created_at="[null]" updated_at="[null]"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/UserWithPermissionDaoTest/select_only_enable_users.xml b/sonar-db/src/test/resources/org/sonar/db/permission/UserWithPermissionDaoTest/select_only_enable_users.xml new file mode 100644 index 00000000000..662af1a0a8c --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/UserWithPermissionDaoTest/select_only_enable_users.xml @@ -0,0 +1,18 @@ +<dataset> + + <users id="200" login="user1" name="User1" active="[true]"/> + <users id="201" login="user2" name="User2" active="[true]"/> + <users id="202" login="user3" name="User3" active="[true]"/> + <users id="999" login="disabledUser" name="disabledUser" active="[false]"/> + + <!-- Project permissions --> + <user_roles id="1" user_id="200" resource_id="100" role="user"/> + <user_roles id="2" user_id="200" resource_id="100" role="admin"/> + <user_roles id="3" user_id="200" resource_id="100" role="codeviewer"/> + + <user_roles id="4" user_id="201" resource_id="100" role="user"/> + + <!-- Global permission --> + <user_roles id="10" user_id="200" resource_id="[null]" role="admin"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/UserWithPermissionDaoTest/users_with_permissions.xml b/sonar-db/src/test/resources/org/sonar/db/permission/UserWithPermissionDaoTest/users_with_permissions.xml new file mode 100644 index 00000000000..6f40d31f21d --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/UserWithPermissionDaoTest/users_with_permissions.xml @@ -0,0 +1,17 @@ +<dataset> + + <users id="200" login="user1" name="User1" active="[true]"/> + <users id="201" login="user2" name="User2" active="[true]"/> + <users id="202" login="user3" name="User3" active="[true]"/> + + <!-- Project permissions --> + <user_roles id="1" user_id="200" resource_id="100" role="user"/> + <user_roles id="2" user_id="200" resource_id="100" role="admin"/> + <user_roles id="3" user_id="200" resource_id="100" role="codeviewer"/> + + <user_roles id="4" user_id="201" resource_id="100" role="user"/> + + <!-- Global permission --> + <user_roles id="10" user_id="200" resource_id="[null]" role="admin"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/UserWithPermissionDaoTest/users_with_permissions_should_be_sorted_by_user_name.xml b/sonar-db/src/test/resources/org/sonar/db/permission/UserWithPermissionDaoTest/users_with_permissions_should_be_sorted_by_user_name.xml new file mode 100644 index 00000000000..6b39124ce6c --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/UserWithPermissionDaoTest/users_with_permissions_should_be_sorted_by_user_name.xml @@ -0,0 +1,11 @@ +<dataset> + + <users id="200" login="user3" name="User3" active="[true]"/> + <users id="201" login="user1" name="User1" active="[true]"/> + <users id="202" login="user2" name="User2" active="[true]"/> + + <user_roles id="1" user_id="200" resource_id="100" role="user"/> + <user_roles id="2" user_id="200" resource_id="100" role="admin"/> + <user_roles id="3" user_id="200" resource_id="100" role="codeviewer"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/UserWithPermissionTemplateDaoTest/select_only_enable_users.xml b/sonar-db/src/test/resources/org/sonar/db/permission/UserWithPermissionTemplateDaoTest/select_only_enable_users.xml new file mode 100644 index 00000000000..14833919475 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/UserWithPermissionTemplateDaoTest/select_only_enable_users.xml @@ -0,0 +1,14 @@ +<dataset> + + <users id="200" login="user1" name="User1" active="[true]"/> + <users id="201" login="user2" name="User2" active="[true]"/> + <users id="202" login="user3" name="User3" active="[true]"/> + <users id="999" login="disabledUser" name="disabledUser" active="[false]"/> + + <perm_templates_users id="1" user_id="200" permission_reference="user" template_id="50"/> + <perm_templates_users id="2" user_id="200" permission_reference="admin" template_id="50"/> + <perm_templates_users id="3" user_id="200" permission_reference="codeviewer" template_id="50"/> + + <perm_templates_users id="4" user_id="201" permission_reference="user" template_id="50"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/UserWithPermissionTemplateDaoTest/users_with_permissions.xml b/sonar-db/src/test/resources/org/sonar/db/permission/UserWithPermissionTemplateDaoTest/users_with_permissions.xml new file mode 100644 index 00000000000..e886636bd9b --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/UserWithPermissionTemplateDaoTest/users_with_permissions.xml @@ -0,0 +1,13 @@ +<dataset> + + <users id="200" login="user1" name="User1" active="[true]"/> + <users id="201" login="user2" name="User2" active="[true]"/> + <users id="202" login="user3" name="User3" active="[true]"/> + + <perm_templates_users id="1" user_id="200" permission_reference="user" template_id="50"/> + <perm_templates_users id="2" user_id="200" permission_reference="admin" template_id="50"/> + <perm_templates_users id="3" user_id="200" permission_reference="codeviewer" template_id="50"/> + + <perm_templates_users id="4" user_id="201" permission_reference="user" template_id="50"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/UserWithPermissionTemplateDaoTest/users_with_permissions_should_be_sorted_by_user_name.xml b/sonar-db/src/test/resources/org/sonar/db/permission/UserWithPermissionTemplateDaoTest/users_with_permissions_should_be_sorted_by_user_name.xml new file mode 100644 index 00000000000..fd8b981c203 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/permission/UserWithPermissionTemplateDaoTest/users_with_permissions_should_be_sorted_by_user_name.xml @@ -0,0 +1,13 @@ +<dataset> + + <users id="200" login="user3" name="User3" active="[true]"/> + <users id="201" login="user1" name="User1" active="[true]"/> + <users id="202" login="user2" name="User2" active="[true]"/> + + <perm_templates_users id="1" user_id="200" permission_reference="user" template_id="50"/> + <perm_templates_users id="2" user_id="200" permission_reference="admin" template_id="50"/> + <perm_templates_users id="3" user_id="200" permission_reference="codeviewer" template_id="50"/> + + <perm_templates_users id="4" user_id="201" permission_reference="user" template_id="50"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/deleteAllProperties-result.xml b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/deleteAllProperties-result.xml new file mode 100644 index 00000000000..ba4619fbedd --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/deleteAllProperties-result.xml @@ -0,0 +1,15 @@ +<dataset> + + <!-- global --> + <!-- <properties id="1" prop_key="to_be_deleted" text_value="new_global" resource_id="[null]" user_id="[null]"/> --> + <properties id="2" prop_key="global.key" text_value="new_global" resource_id="[null]" user_id="[null]"/> + + <!-- project --> + <!-- <properties id="3" prop_key="to_be_deleted" text_value="new_project" resource_id="10" user_id="[null]"/> --> + <properties id="4" prop_key="project.key" text_value="new_project" resource_id="10" user_id="[null]"/> + + <!-- user --> + <!-- <properties id="5" prop_key="to_be_deleted" text_value="new_user" resource_id="[null]" user_id="100"/> --> + <properties id="6" prop_key="user.key" text_value="new_user" resource_id="[null]" user_id="100"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/deleteAllProperties.xml b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/deleteAllProperties.xml new file mode 100644 index 00000000000..0953b0ecd9f --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/deleteAllProperties.xml @@ -0,0 +1,15 @@ +<dataset> + + <!-- global --> + <properties id="1" prop_key="to_be_deleted" text_value="new_global" resource_id="[null]" user_id="[null]"/> + <properties id="2" prop_key="global.key" text_value="new_global" resource_id="[null]" user_id="[null]"/> + + <!-- project --> + <properties id="3" prop_key="to_be_deleted" text_value="new_project" resource_id="10" user_id="[null]"/> + <properties id="4" prop_key="project.key" text_value="new_project" resource_id="10" user_id="[null]"/> + + <!-- user --> + <properties id="5" prop_key="to_be_deleted" text_value="new_user" resource_id="[null]" user_id="100"/> + <properties id="6" prop_key="user.key" text_value="new_user" resource_id="[null]" user_id="100"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/deleteGlobalProperties-result.xml b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/deleteGlobalProperties-result.xml new file mode 100644 index 00000000000..a5cfed3378b --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/deleteGlobalProperties-result.xml @@ -0,0 +1,12 @@ +<dataset> + + <!-- global --> + <!--<properties id="1" prop_key="global.key" text_value="new_global" resource_id="[null]" user_id="[null]"/>--> + + <!-- project --> + <properties id="2" prop_key="project.key" text_value="new_project" resource_id="10" user_id="[null]"/> + + <!-- user --> + <properties id="3" prop_key="user.key" text_value="new_user" resource_id="[null]" user_id="100"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/deleteGlobalProperties.xml b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/deleteGlobalProperties.xml new file mode 100644 index 00000000000..3e5eb87705c --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/deleteGlobalProperties.xml @@ -0,0 +1,12 @@ +<dataset> + + <!-- global --> + <properties id="1" prop_key="global.key" text_value="new_global" resource_id="[null]" user_id="[null]"/> + + <!-- project --> + <properties id="2" prop_key="project.key" text_value="new_project" resource_id="10" user_id="[null]"/> + + <!-- user --> + <properties id="3" prop_key="user.key" text_value="new_user" resource_id="[null]" user_id="100"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/deleteGlobalProperty-result.xml b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/deleteGlobalProperty-result.xml new file mode 100644 index 00000000000..0428139feb6 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/deleteGlobalProperty-result.xml @@ -0,0 +1,13 @@ +<dataset> + + <!-- global --> + <properties id="1" prop_key="global.key" text_value="new_global" resource_id="[null]" user_id="[null]"/> + <!--<properties id="2" prop_key="to_be_deleted" text_value="xxx" resource_id="[null]" user_id="[null]"/>--> + + <!-- project --> + <properties id="3" prop_key="to_be_deleted" text_value="new_project" resource_id="10" user_id="[null]"/> + + <!-- user --> + <properties id="4" prop_key="user.key" text_value="new_user" resource_id="[null]" user_id="100"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/deleteGlobalProperty.xml b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/deleteGlobalProperty.xml new file mode 100644 index 00000000000..aaf0fd642d3 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/deleteGlobalProperty.xml @@ -0,0 +1,13 @@ +<dataset> + + <!-- global --> + <properties id="1" prop_key="global.key" text_value="new_global" resource_id="[null]" user_id="[null]"/> + <properties id="2" prop_key="to_be_deleted" text_value="xxx" resource_id="[null]" user_id="[null]"/> + + <!-- project - do not delete this project property that has the same key --> + <properties id="3" prop_key="to_be_deleted" text_value="new_project" resource_id="10" user_id="[null]"/> + + <!-- user --> + <properties id="4" prop_key="user.key" text_value="new_user" resource_id="[null]" user_id="100"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/delete_project_properties-result.xml b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/delete_project_properties-result.xml new file mode 100644 index 00000000000..97b8b6f02b3 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/delete_project_properties-result.xml @@ -0,0 +1,12 @@ +<dataset> + + <!--<properties id="1" prop_key="sonar.profile.java" text_value="Sonar Way" resource_id="1" user_id="[null]"/>--> + <!--<properties id="2" prop_key="sonar.profile.java" text_value="Sonar Way" resource_id="2" user_id="[null]"/>--> + + <properties id="3" prop_key="sonar.profile.java" text_value="Sonar Way" resource_id="[null]" user_id="[null]"/> + + <properties id="4" prop_key="sonar.profile.js" text_value="Sonar Way" resource_id="1" user_id="[null]"/> + <properties id="5" prop_key="sonar.profile.js" text_value="Sonar Way" resource_id="2" user_id="[null]"/> + <properties id="6" prop_key="sonar.profile.js" text_value="Sonar Way" resource_id="[null]" user_id="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/delete_project_properties.xml b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/delete_project_properties.xml new file mode 100644 index 00000000000..4e07f27e283 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/delete_project_properties.xml @@ -0,0 +1,13 @@ +<dataset> + + <properties id="1" prop_key="sonar.profile.java" text_value="Sonar Way" resource_id="1" user_id="[null]"/> + <properties id="2" prop_key="sonar.profile.java" text_value="Sonar Way" resource_id="2" user_id="[null]"/> + + <properties id="3" prop_key="sonar.profile.java" text_value="Sonar Way" resource_id="[null]" user_id="[null]"/> + + <properties id="4" prop_key="sonar.profile.js" text_value="Sonar Way" resource_id="1" user_id="[null]"/> + <properties id="5" prop_key="sonar.profile.js" text_value="Sonar Way" resource_id="2" user_id="[null]"/> + <properties id="6" prop_key="sonar.profile.js" text_value="Sonar Way" resource_id="[null]" user_id="[null]"/> + + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/delete_project_property-result.xml b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/delete_project_property-result.xml new file mode 100644 index 00000000000..0b889b14bb3 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/delete_project_property-result.xml @@ -0,0 +1,22 @@ +<dataset> + + <!-- global --> + <properties id="1" prop_key="global.one" text_value="one" resource_id="[null]" user_id="[null]"/> + <properties id="2" prop_key="global.two" text_value="two" resource_id="[null]" user_id="[null]"/> + + <!-- struts --> + <!--<properties id="3" prop_key="struts.one" text_value="one" resource_id="10" user_id="[null]"/>--> + + <!-- commons --> + <properties id="4" prop_key="commonslang.one" text_value="two" resource_id="11" user_id="[null]"/> + + <!-- user --> + <properties id="5" prop_key="user.one" text_value="one" resource_id="[null]" user_id="100"/> + <properties id="6" prop_key="user.two" text_value="two" resource_id="10" user_id="100"/> + + <properties id="7" prop_key="commonslang.one" text_value="one" resource_id="12" user_id="[null]"/> + + <projects id="10" uuid="A" kee="org.struts:struts"/> + <projects id="11" uuid="B" kee="org.apache:commons-lang"/> + <projects id="12" uuid="C" kee="other"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/delete_project_property.xml b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/delete_project_property.xml new file mode 100644 index 00000000000..99bd75917c1 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/delete_project_property.xml @@ -0,0 +1,22 @@ +<dataset> + + <!-- global --> + <properties id="1" prop_key="global.one" text_value="one" resource_id="[null]" user_id="[null]"/> + <properties id="2" prop_key="global.two" text_value="two" resource_id="[null]" user_id="[null]"/> + + <!-- struts --> + <properties id="3" prop_key="struts.one" text_value="one" resource_id="10" user_id="[null]"/> + + <!-- commons --> + <properties id="4" prop_key="commonslang.one" text_value="two" resource_id="11" user_id="[null]"/> + + <!-- user --> + <properties id="5" prop_key="user.one" text_value="one" resource_id="[null]" user_id="100"/> + <properties id="6" prop_key="user.two" text_value="two" resource_id="10" user_id="100"/> + + <properties id="7" prop_key="commonslang.one" text_value="one" resource_id="12" user_id="[null]"/> + + <projects id="10" uuid="A" kee="org.struts:struts"/> + <projects id="11" uuid="B" kee="org.apache:commons-lang"/> + <projects id="12" uuid="C" kee="other"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/findNotificationSubscribers.xml b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/findNotificationSubscribers.xml new file mode 100644 index 00000000000..9bfd1dc3001 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/findNotificationSubscribers.xml @@ -0,0 +1,55 @@ +<dataset> + + <users + id="1" + login="eric" + /> + + <users + id="2" + login="simon" + /> + + <projects id="42" uuid="PROJECT_A" kee="org.apache:struts"/> + + <!-- global subscription --> + <properties + id="1" + prop_key="notification.DispatcherWithGlobalSubscribers.Email" + text_value="true" + resource_id="[null]" + user_id="2"/> + + <!-- project subscription --> + <properties + id="2" + prop_key="notification.DispatcherWithProjectSubscribers.Email" + text_value="true" + resource_id="42" + user_id="1"/> + + <!-- project subscription --> + <properties + id="3" + prop_key="notification.DispatcherWithGlobalAndProjectSubscribers.Email" + text_value="true" + resource_id="56" + user_id="1"/> + + <!-- project subscription --> + <properties + id="4" + prop_key="notification.DispatcherWithGlobalAndProjectSubscribers.Email" + text_value="true" + resource_id="42" + user_id="1"/> + + <!-- global subscription --> + <properties + id="5" + prop_key="notification.DispatcherWithGlobalAndProjectSubscribers.Email" + text_value="true" + resource_id="[null]" + user_id="2"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/insert-result.xml b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/insert-result.xml new file mode 100644 index 00000000000..3e5eb87705c --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/insert-result.xml @@ -0,0 +1,12 @@ +<dataset> + + <!-- global --> + <properties id="1" prop_key="global.key" text_value="new_global" resource_id="[null]" user_id="[null]"/> + + <!-- project --> + <properties id="2" prop_key="project.key" text_value="new_project" resource_id="10" user_id="[null]"/> + + <!-- user --> + <properties id="3" prop_key="user.key" text_value="new_user" resource_id="[null]" user_id="100"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/insert.xml b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/insert.xml new file mode 100644 index 00000000000..5ed00ba028b --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/insert.xml @@ -0,0 +1 @@ +<dataset></dataset>
\ No newline at end of file diff --git a/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/insertGlobalProperties-result.xml b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/insertGlobalProperties-result.xml new file mode 100644 index 00000000000..5594180c370 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/insertGlobalProperties-result.xml @@ -0,0 +1,5 @@ +<dataset> + + <properties prop_key="to_be_inserted" text_value="inserted" resource_id="[null]" user_id="[null]"/> + +</dataset>
\ No newline at end of file diff --git a/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/insertGlobalProperties.xml b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/insertGlobalProperties.xml new file mode 100644 index 00000000000..871dedcb5e9 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/insertGlobalProperties.xml @@ -0,0 +1,3 @@ +<dataset> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/renamePropertyKey-result.xml b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/renamePropertyKey-result.xml new file mode 100644 index 00000000000..0877b0035fe --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/renamePropertyKey-result.xml @@ -0,0 +1,6 @@ +<dataset> + + <properties id="1" prop_key="foo" text_value="bar" resource_id="[null]" user_id="[null]"/> + <properties id="2" prop_key="sonar.license" text_value="the license" resource_id="[null]" user_id="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/renamePropertyKey.xml b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/renamePropertyKey.xml new file mode 100644 index 00000000000..6ab761e2c6f --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/renamePropertyKey.xml @@ -0,0 +1,6 @@ +<dataset> + + <properties id="1" prop_key="foo" text_value="bar" resource_id="[null]" user_id="[null]"/> + <properties id="2" prop_key="sonar.license.secured" text_value="the license" resource_id="[null]" user_id="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/selectGlobalProperties.xml b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/selectGlobalProperties.xml new file mode 100644 index 00000000000..e5aa737e9a0 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/selectGlobalProperties.xml @@ -0,0 +1,14 @@ +<dataset> + + <!-- global --> + <properties id="1" prop_key="global.one" text_value="one" resource_id="[null]" user_id="[null]"/> + <properties id="2" prop_key="global.two" text_value="two" resource_id="[null]" user_id="[null]"/> + + <!-- project --> + <properties id="3" prop_key="project.one" text_value="one" resource_id="10" user_id="[null]"/> + + <!-- user --> + <properties id="4" prop_key="user.one" text_value="one" resource_id="[null]" user_id="100"/> + <properties id="5" prop_key="user.two" text_value="two" resource_id="10" user_id="100"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/selectProjectProperties.xml b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/selectProjectProperties.xml new file mode 100644 index 00000000000..99bd75917c1 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/selectProjectProperties.xml @@ -0,0 +1,22 @@ +<dataset> + + <!-- global --> + <properties id="1" prop_key="global.one" text_value="one" resource_id="[null]" user_id="[null]"/> + <properties id="2" prop_key="global.two" text_value="two" resource_id="[null]" user_id="[null]"/> + + <!-- struts --> + <properties id="3" prop_key="struts.one" text_value="one" resource_id="10" user_id="[null]"/> + + <!-- commons --> + <properties id="4" prop_key="commonslang.one" text_value="two" resource_id="11" user_id="[null]"/> + + <!-- user --> + <properties id="5" prop_key="user.one" text_value="one" resource_id="[null]" user_id="100"/> + <properties id="6" prop_key="user.two" text_value="two" resource_id="10" user_id="100"/> + + <properties id="7" prop_key="commonslang.one" text_value="one" resource_id="12" user_id="[null]"/> + + <projects id="10" uuid="A" kee="org.struts:struts"/> + <projects id="11" uuid="B" kee="org.apache:commons-lang"/> + <projects id="12" uuid="C" kee="other"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/selectProjectPropertiesByResourceId.xml b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/selectProjectPropertiesByResourceId.xml new file mode 100644 index 00000000000..52fec852a8d --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/selectProjectPropertiesByResourceId.xml @@ -0,0 +1,22 @@ +<dataset> + + <!-- global --> + <properties id="1" prop_key="global.one" text_value="one" resource_id="[null]" user_id="[null]"/> + <properties id="2" prop_key="global.two" text_value="two" resource_id="[null]" user_id="[null]"/> + + <!-- struts --> + <properties id="3" prop_key="struts.one" text_value="one" resource_id="10" user_id="[null]"/> + + <!-- commons --> + <properties id="4" prop_key="commonslang.one" text_value="two" resource_id="11" user_id="[null]"/> + + <!-- user --> + <properties id="5" prop_key="user.one" text_value="one" resource_id="[null]" user_id="100"/> + <properties id="6" prop_key="user.two" text_value="two" resource_id="10" user_id="[null]"/> + + <properties id="7" prop_key="commonslang.one" text_value="one" resource_id="12" user_id="[null]"/> + + <projects id="10" uuid="A" kee="org.struts:struts"/> + <projects id="11" uuid="B" kee="org.apache:commons-lang"/> + <projects id="12" uuid="C" kee="other"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/select_by_query.xml b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/select_by_query.xml new file mode 100644 index 00000000000..2873d69a5bc --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/select_by_query.xml @@ -0,0 +1,19 @@ +<dataset> + + <!-- global --> + <properties id="1" prop_key="global.one" text_value="one" resource_id="[null]" user_id="[null]"/> + <properties id="2" prop_key="global.two" text_value="two" resource_id="[null]" user_id="[null]"/> + + <!-- struts --> + <properties id="3" prop_key="struts.one" text_value="one" resource_id="10" user_id="[null]"/> + + <!-- commons --> + <properties id="4" prop_key="commonslang.one" text_value="two" resource_id="11" user_id="[null]"/> + + <!-- user --> + <properties id="5" prop_key="user.one" text_value="one" resource_id="[null]" user_id="100"/> + <properties id="6" prop_key="user.two" text_value="two" resource_id="10" user_id="100"/> + + <properties id="7" prop_key="commonslang.one" text_value="one" resource_id="12" user_id="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/select_module_properties_tree.xml b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/select_module_properties_tree.xml new file mode 100644 index 00000000000..938910a0e01 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/select_module_properties_tree.xml @@ -0,0 +1,61 @@ +<dataset> + + <!-- global --> + <properties id="1" prop_key="global.one" text_value="one" resource_id="[null]" user_id="[null]"/> + <properties id="2" prop_key="global.two" text_value="two" resource_id="[null]" user_id="[null]"/> + + <!-- org.struts:struts --> + <properties id="3" prop_key="struts.one" text_value="one" resource_id="1" user_id="[null]"/> + + <!-- org.struts:struts-core --> + <properties id="4" prop_key="core.one" text_value="one" resource_id="2" user_id="[null]"/> + <properties id="7" prop_key="core.two" text_value="two" resource_id="2" user_id="[null]"/> + + <!-- org.struts:struts-data --> + <properties id="8" prop_key="data.one" text_value="one" resource_id="3" user_id="[null]"/> + + <!-- user --> + <properties id="5" prop_key="user.one" text_value="one" resource_id="[null]" user_id="100"/> + <properties id="6" prop_key="user.two" text_value="two" resource_id="1" user_id="102"/> + + + <!-- root project --> + <projects id="1" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" + uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" module_uuid_path="." + description="the description" long_name="Apache Struts" + enabled="[true]" language="[null]" copy_resource_id="[null]" person_id="[null]" path="[null]" + authorization_updated_at="[null]"/> + + <!-- module --> + <projects id="2" root_id="1" kee="org.struts:struts-core" name="Struts Core" + uuid="EFGH" project_uuid="ABCD" module_uuid="[null]" module_uuid_path=".ABCD." + scope="PRJ" qualifier="BRC" long_name="Struts Core" + description="[null]" enabled="[true]" language="[null]" copy_resource_id="[null]" person_id="[null]" + authorization_updated_at="[null]"/> + + <!-- sub module --> + <projects id="3" root_id="1" kee="org.struts:struts-data" name="Struts Data" + uuid="FGHI" project_uuid="ABCD" module_uuid="EFGH" module_uuid_path=".ABCD.EFGH." + scope="PRJ" qualifier="BRC" long_name="Struts Data" + description="[null]" enabled="[true]" language="[null]" copy_resource_id="[null]" person_id="[null]" + authorization_updated_at="[null]"/> + + <!-- directory --> + <projects long_name="org.struts" id="4" scope="DIR" qualifier="DIR" kee="org.struts:struts-core:src/org/struts" + uuid="GHIJ" project_uuid="ABCD" module_uuid="FGHI" module_uuid_path=".ABCD.EFGH.FGHI." + name="src/org/struts" root_id="3" + description="[null]" + enabled="[true]" language="[null]" copy_resource_id="[null]" person_id="[null]" path="src/org/struts" + authorization_updated_at="[null]"/> + + <!-- file --> + <projects long_name="org.struts.RequestContext" id="5" scope="FIL" qualifier="FIL" + kee="org.struts:struts-core:src/org/struts/RequestContext.java" + uuid="HIJK" project_uuid="ABCD" module_uuid="GHIJ" module_uuid_path=".ABCD.EFGH.FGHI." + name="RequestContext.java" root_id="3" + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" + path="src/org/struts/RequestContext.java" authorization_updated_at="[null]"/> + + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/shouldFindUsersForNotification.xml b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/shouldFindUsersForNotification.xml new file mode 100644 index 00000000000..891d895d7f2 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/shouldFindUsersForNotification.xml @@ -0,0 +1,46 @@ +<dataset> + + <projects id="45" uuid="uuid_45"/> + <projects id="56" uuid="uuid_56"/> + + <properties + id="1" + prop_key="notification.NewViolations.Email" + text_value="true" + resource_id="45" + user_id="2"/> + + <properties + id="2" + prop_key="notification.NewViolations.Twitter" + text_value="true" + resource_id="[null]" + user_id="3"/> + + <properties + id="3" + prop_key="notification.NewViolations.Twitter" + text_value="true" + resource_id="56" + user_id="1"/> + + <properties + id="4" + prop_key="notification.NewViolations.Twitter" + text_value="true" + resource_id="56" + user_id="3"/> + + <users + id="1" + login="user1"/> + + <users + id="2" + login="user2"/> + + <users + id="3" + login="user3"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/should_not_rename_if_same_key-result.xml b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/should_not_rename_if_same_key-result.xml new file mode 100644 index 00000000000..b4fc11a8cdb --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/should_not_rename_if_same_key-result.xml @@ -0,0 +1,5 @@ +<dataset> + + <properties id="1" prop_key="foo" text_value="bar" resource_id="[null]" user_id="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/should_not_rename_if_same_key.xml b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/should_not_rename_if_same_key.xml new file mode 100644 index 00000000000..b4fc11a8cdb --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/should_not_rename_if_same_key.xml @@ -0,0 +1,5 @@ +<dataset> + + <properties id="1" prop_key="foo" text_value="bar" resource_id="[null]" user_id="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/update-result.xml b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/update-result.xml new file mode 100644 index 00000000000..c3268596de3 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/update-result.xml @@ -0,0 +1,15 @@ +<dataset> + + <!-- global --> + <properties id="1" prop_key="global.key" text_value="new_global" resource_id="[null]" user_id="[null]"/> + + <!-- project --> + <properties id="2" prop_key="project.key" text_value="new_project" resource_id="10" user_id="[null]"/> + + <!-- user --> + <properties id="3" prop_key="user.key" text_value="new_user" resource_id="[null]" user_id="100"/> + + <!-- null value --> + <properties id="4" prop_key="null.value" text_value="[null]" resource_id="[null]" user_id="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/update.xml b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/update.xml new file mode 100644 index 00000000000..5229a2b791a --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/update.xml @@ -0,0 +1,14 @@ +<dataset> + + <!-- global --> + <properties id="1" prop_key="global.key" text_value="global" resource_id="[null]" user_id="[null]"/> + + <!-- project --> + <properties id="2" prop_key="project.key" text_value="project" resource_id="10" user_id="[null]"/> + + <!-- user --> + <properties id="3" prop_key="user.key" text_value="user" resource_id="[null]" user_id="100"/> + + <!-- null value --> + <properties id="4" prop_key="null.value" text_value="not null" resource_id="[null]" user_id="[null]"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/updateGlobalProperties-result.xml b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/updateGlobalProperties-result.xml new file mode 100644 index 00000000000..12033fdc629 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/updateGlobalProperties-result.xml @@ -0,0 +1,5 @@ +<dataset> + + <properties prop_key="to_be_updated" text_value="updated" resource_id="[null]" user_id="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/updateGlobalProperties.xml b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/updateGlobalProperties.xml new file mode 100644 index 00000000000..4616072f3d9 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/updateGlobalProperties.xml @@ -0,0 +1,5 @@ +<dataset> + + <properties id="1" prop_key="to_be_updated" text_value="old value" resource_id="[null]" user_id="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/updatePropertiesFromKeyAndValueToNewValue-result.xml b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/updatePropertiesFromKeyAndValueToNewValue-result.xml new file mode 100644 index 00000000000..194761a6b2d --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/updatePropertiesFromKeyAndValueToNewValue-result.xml @@ -0,0 +1,9 @@ +<dataset> + + <properties id="1" prop_key="sonar.profile.java" text_value="Default" resource_id="[null]" user_id="[null]"/> + <properties id="2" prop_key="sonar.profile.java" text_value="Default" resource_id="1" user_id="[null]"/> + + <properties id="3" prop_key="sonar.profile.js" text_value="Sonar Way" resource_id="[null]" user_id="[null]"/> + <properties id="4" prop_key="sonar.profile.js" text_value="Sonar Way" resource_id="2" user_id="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/updatePropertiesFromKeyAndValueToNewValue.xml b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/updatePropertiesFromKeyAndValueToNewValue.xml new file mode 100644 index 00000000000..5567744e146 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/property/PropertiesDaoTest/updatePropertiesFromKeyAndValueToNewValue.xml @@ -0,0 +1,9 @@ +<dataset> + + <properties id="1" prop_key="sonar.profile.java" text_value="Sonar Way" resource_id="[null]" user_id="[null]"/> + <properties id="2" prop_key="sonar.profile.java" text_value="Sonar Way" resource_id="1" user_id="[null]"/> + + <properties id="3" prop_key="sonar.profile.js" text_value="Sonar Way" resource_id="[null]" user_id="[null]"/> + <properties id="4" prop_key="sonar.profile.js" text_value="Sonar Way" resource_id="2" user_id="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldDeleteResource.xml b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldDeleteResource.xml new file mode 100644 index 00000000000..02a88004d9b --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldDeleteResource.xml @@ -0,0 +1,38 @@ +<dataset> + + <projects id="1" uuid="1" enabled="[true]" root_id="[null]" + long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project" + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]"/> + + <snapshots id="1" project_id="1" parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" + status="P" islast="[false]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" + build_date="1228222680000" + version="[null]" path="[null]"/> + + <events id="1" name="Version 1.0" component_uuid="1" snapshot_id="1" category="VERSION" description="[null]" + event_date="1228222680000" created_at="1228222680000" event_data="[null]"/> + + <issues id="1" kee="ABCDE" component_uuid="1" project_uuid="1" status="CLOSED" resolution="[null]" line="200" + severity="BLOCKER" + reporter="perceval" assignee="arthur" rule_id="500" + manual_severity="[false]" + message="[null]" + issue_creation_date="1366063200000" + issue_update_date="1366063200000" + issue_close_date="1366063200000" + created_at="[null]" + updated_at="[null]" + /> + + <issue_changes id="1" kee="ABDA" issue_key="ABCDE" created_at="[null]" updated_at="[null]" user_login="admin" + change_type="comment" change_data="this is a comment"/> + + <authors id="1" person_id="1" login="tartanpion" created_at="[null]" updated_at="[null]"/> + <authors id="2" person_id="1" login="fanfoue" created_at="[null]" updated_at="[null]"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldDeleteSnapshot-result.xml b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldDeleteSnapshot-result.xml new file mode 100644 index 00000000000..f17226a159a --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldDeleteSnapshot-result.xml @@ -0,0 +1,29 @@ +<dataset> + + <!-- snapshot to keep --> + <snapshots id="1" purge_status="[null]" period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" + period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" + scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" + version="[null]" + project_id="1" + parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="[false]" + path="[null]"/> + + <project_measures ID="1" characteristic_id="[null]" url="[null]" variation_value_1="[null]" variation_value_2="[null]" + variation_value_3="[null]" variation_value_4="[null]" + variation_value_5="[null]" + rule_priority="[null]" + alert_text="[null]" VALUE="10.0" METRIC_ID="1" SNAPSHOT_ID="1" rules_category_id="[null]" + RULE_ID="1" + person_id="[null]" + text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]" + alert_status="[null]" description="[null]" measure_data="[null]"/> + <events id="1" name="Version 1.0" component_uuid="1" snapshot_id="1" category="VERSION" description="[null]" + event_date="1228222680000" created_at="1228222680000" event_data="[null]"/> + <duplications_index id="1" project_snapshot_id="1" snapshot_id="1" hash="bb" index_in_file="0" start_line="0" + end_line="0"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldDeleteSnapshot.xml b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldDeleteSnapshot.xml new file mode 100644 index 00000000000..3f756fc37d3 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldDeleteSnapshot.xml @@ -0,0 +1,57 @@ +<dataset> + + <!-- snapshot to keep --> + <snapshots id="1" project_id="1" parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" + status="P" islast="[false]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" + build_date="1228222680000" + version="[null]" path="[null]"/> + + <project_measures ID="1" characteristic_id="[null]" url="[null]" variation_value_1="[null]" variation_value_2="[null]" + variation_value_3="[null]" variation_value_4="[null]" + variation_value_5="[null]" + rule_priority="[null]" + alert_text="[null]" VALUE="10.0" METRIC_ID="1" SNAPSHOT_ID="1" rules_category_id="[null]" + RULE_ID="1" + person_id="[null]" + text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]" + alert_status="[null]" description="[null]" measure_data="[null]"/> + <events id="1" name="Version 1.0" component_uuid="1" snapshot_id="1" category="VERSION" description="[null]" + event_date="1228222680000" created_at="1228222680000" event_data="[null]"/> + <duplications_index id="1" project_snapshot_id="1" snapshot_id="1" hash="bb" index_in_file="0" start_line="0" + end_line="0"/> + + + <!-- snapshot to remove, id 5 on resource 5--> + <snapshots id="5" project_id="5" parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" + build_date="1228222680000" + version="[null]" path="[null]"/> + + <project_measures ID="2" characteristic_id="[null]" url="[null]" variation_value_1="[null]" variation_value_2="[null]" + variation_value_3="[null]" variation_value_4="[null]" + variation_value_5="[null]" + rule_priority="[null]" + alert_text="[null]" VALUE="10.0" METRIC_ID="1" SNAPSHOT_ID="5" rules_category_id="[null]" + RULE_ID="1" + person_id="[null]" + text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]" + alert_status="[null]" description="[null]" measure_data="[null]"/> + <events id="2" name="Version 1.0" component_uuid="5" snapshot_id="5" category="VERSION" description="[null]" + event_date="1228222680000" created_at="1228222680000" event_data="[null]"/> + <duplications_index id="2" project_snapshot_id="5" snapshot_id="5" hash="bb" index_in_file="0" start_line="0" + end_line="0"/> + + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldDeleteWastedMeasuresWhenPurgingSnapshot-result.xml b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldDeleteWastedMeasuresWhenPurgingSnapshot-result.xml new file mode 100644 index 00000000000..c59e34d5c8b --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldDeleteWastedMeasuresWhenPurgingSnapshot-result.xml @@ -0,0 +1,87 @@ +<dataset> + + <metrics id="1" delete_historical_data="[null]" + name="ncloc" val_type="INT" description="[null]" domain="[null]" short_name="" enabled="[true]" + worst_value="[null]" optimized_best_value="[null]" best_value="[null]" + direction="0" hidden="[false]"/> + + <metrics id="2" delete_historical_data="[true]" + name="coverage" val_type="INT" description="[null]" domain="[null]" short_name="" enabled="[true]" + worst_value="0" optimized_best_value="[true]" best_value="100" + direction="1" hidden="[false]"/> + + <characteristics id="1" kee="M1C1" name="M1C1" parent_id="[null]" characteristic_order="1" enabled="[true]"/> + <characteristics id="2" kee="M1C2" name="M1C1" parent_id="1" characteristic_order="[null]" enabled="[true]"/> + <characteristics id="3" kee="M1C3" name="M1C3" parent_id="2" characteristic_order="[null]" enabled="[true]"/> + + <snapshots id="1" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" + build_date="1228222680000" version="[null]" path="[null]"/> + + <!-- do not delete standard measure --> + <project_measures id="1" project_id="1" snapshot_id="1" rule_id="[null]" characteristic_id="[null]" metric_id="1" + url="[null]" variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" + variation_value_4="[null]" + variation_value_5="[null]" rule_priority="[null]" alert_text="[null]" value="10.0" + rules_category_id="[null]" + person_id="[null]" + text_value="[null]" tendency="[null]" measure_date="[null]" alert_status="[null]" + description="[null]" measure_data="[null]"/> + + <!-- delete measure on rule --> + <!--<project_measures ID="2" project_id="1" SNAPSHOT_ID="1" RULE_ID="33" characteristic_id="[null]" METRIC_ID="1" + url="[null]" variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" + variation_value_4="[null]" + variation_value_5="[null]" rule_priority="[null]" alert_text="[null]" VALUE="10.0" + rules_category_id="[null]" + person_id="[null]" + text_value="[null]" tendency="[null]" measure_date="[null]" alert_status="[null]" + description="[null]" measure_data="[null]"/>--> + + <!-- do not delete measure on characteristic --> + <project_measures id="3" project_id="1" snapshot_id="1" rule_id="[null]" characteristic_id="1" metric_id="1" + url="[null]" variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" + variation_value_4="[null]" + variation_value_5="[null]" rule_priority="[null]" alert_text="[null]" value="10.0" + rules_category_id="[null]" + person_id="[null]" + text_value="[null]" tendency="[null]" measure_date="[null]" alert_status="[null]" + description="[null]" measure_data="[null]"/> + + <!-- do not delete measure on characteristic --> + <project_measures id="4" project_id="1" snapshot_id="1" rule_id="[null]" characteristic_id="2" metric_id="1" + url="[null]" variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" + variation_value_4="[null]" + variation_value_5="[null]" rule_priority="[null]" alert_text="[null]" value="10.0" + rules_category_id="[null]" + person_id="[null]" + text_value="[null]" tendency="[null]" measure_date="[null]" alert_status="[null]" + description="[null]" measure_data="[null]"/> + + <!-- delete measure on metrics that are flagged with delete_historical_data=true --> + <!--<project_measures ID="6" project_id="1" SNAPSHOT_ID="1" RULE_ID="[null]" characteristic_id="[null]" METRIC_ID="2" + url="[null]" variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" + variation_value_4="[null]" + variation_value_5="[null]" rule_priority="[null]" alert_text="[null]" VALUE="10.0" + rules_category_id="[null]" + person_id="[null]" + text_value="[null]" tendency="[null]" measure_date="[null]" alert_status="[null]" + description="[null]" measure_data="[null]"/>--> + + <!-- delete measure on developers --> + <!--<project_measures id="7" project_id="1" snapshot_id="1" rule_id="[null]" characteristic_id="[null]" metric_id="2" + url="[null]" variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" + person_id="123456" + variation_value_4="[null]" + variation_value_5="[null]" rule_priority="[null]" alert_text="[null]" value="10.0" + rules_category_id="[null]" + text_value="[null]" tendency="[null]" measure_date="[null]" alert_status="[null]" + description="[null]" measure_data="[null]"/>--> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldDeleteWastedMeasuresWhenPurgingSnapshot.xml b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldDeleteWastedMeasuresWhenPurgingSnapshot.xml new file mode 100644 index 00000000000..d4931b9a343 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldDeleteWastedMeasuresWhenPurgingSnapshot.xml @@ -0,0 +1,87 @@ +<dataset> + + <metrics id="1" delete_historical_data="[null]" + name="ncloc" val_type="INT" description="[null]" domain="[null]" short_name="" enabled="[true]" + worst_value="[null]" optimized_best_value="[null]" best_value="[null]" + direction="0" hidden="[false]"/> + + <metrics id="2" delete_historical_data="[true]" + name="coverage" val_type="INT" description="[null]" domain="[null]" short_name="" enabled="[true]" + worst_value="0" optimized_best_value="[true]" best_value="100" + direction="1" hidden="[false]"/> + + <characteristics id="1" kee="M1C1" name="M1C1" parent_id="[null]" characteristic_order="1" enabled="[true]"/> + <characteristics id="2" kee="M1C2" name="M1C1" parent_id="1" characteristic_order="[null]" enabled="[true]"/> + <characteristics id="3" kee="M1C3" name="M1C3" parent_id="2" characteristic_order="[null]" enabled="[true]"/> + + <snapshots id="1" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" + build_date="1228222680000" version="[null]" path="[null]"/> + + <!-- do not delete standard measure --> + <project_measures id="1" project_id="1" snapshot_id="1" rule_id="[null]" characteristic_id="[null]" metric_id="1" + url="[null]" variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" + variation_value_4="[null]" + variation_value_5="[null]" rule_priority="[null]" alert_text="[null]" value="10.0" + rules_category_id="[null]" + person_id="[null]" + text_value="[null]" tendency="[null]" measure_date="[null]" alert_status="[null]" + description="[null]" measure_data="[null]"/> + + <!-- delete measure on rule --> + <project_measures id="2" project_id="1" snapshot_id="1" rule_id="33" characteristic_id="[null]" metric_id="1" + url="[null]" variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" + variation_value_4="[null]" + variation_value_5="[null]" rule_priority="[null]" alert_text="[null]" value="10.0" + rules_category_id="[null]" + person_id="[null]" + text_value="[null]" tendency="[null]" measure_date="[null]" alert_status="[null]" + description="[null]" measure_data="[null]"/> + + <!-- do not delete measure on root characteristic --> + <project_measures id="3" project_id="1" snapshot_id="1" rule_id="[null]" characteristic_id="1" metric_id="1" + url="[null]" variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" + variation_value_4="[null]" + variation_value_5="[null]" rule_priority="[null]" alert_text="[null]" value="10.0" + rules_category_id="[null]" + person_id="[null]" + text_value="[null]" tendency="[null]" measure_date="[null]" alert_status="[null]" + description="[null]" measure_data="[null]"/> + + <!-- do not delete measure on characteristic --> + <project_measures id="4" project_id="1" snapshot_id="1" rule_id="[null]" characteristic_id="2" metric_id="1" + url="[null]" variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" + variation_value_4="[null]" + variation_value_5="[null]" rule_priority="[null]" alert_text="[null]" value="10.0" + rules_category_id="[null]" + person_id="[null]" + text_value="[null]" tendency="[null]" measure_date="[null]" alert_status="[null]" + description="[null]" measure_data="[null]"/> + + <!-- delete measure on metrics that are flagged with delete_historical_data=true --> + <project_measures id="6" project_id="1" snapshot_id="1" rule_id="[null]" characteristic_id="[null]" metric_id="2" + url="[null]" variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" + variation_value_4="[null]" + variation_value_5="[null]" rule_priority="[null]" alert_text="[null]" value="10.0" + rules_category_id="[null]" + person_id="[null]" + text_value="[null]" tendency="[null]" measure_date="[null]" alert_status="[null]" + description="[null]" measure_data="[null]"/> + + <!-- delete measure on developers --> + <project_measures id="7" project_id="1" snapshot_id="1" rule_id="[null]" characteristic_id="[null]" metric_id="2" + url="[null]" variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" + person_id="123456" + variation_value_4="[null]" + variation_value_5="[null]" rule_priority="[null]" alert_text="[null]" value="10.0" + rules_category_id="[null]" + text_value="[null]" tendency="[null]" measure_date="[null]" alert_status="[null]" + description="[null]" measure_data="[null]"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldPurgeSnapshot-result.xml b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldPurgeSnapshot-result.xml new file mode 100644 index 00000000000..370f4d3ab34 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldPurgeSnapshot-result.xml @@ -0,0 +1,75 @@ +<!-- + +Changes: +* snapshot.purge_status=1 +* commented-out rows are deleted + +Note that measures, events and reviews are not deleted. + +--> +<dataset> + <snapshots id="1" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[false]" purge_status="1" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" + build_date="1228222680000" version="[null]" path="[null]"/> + + <!--switched_off="[null]" permanent_id="[null]" RULE_ID="1" FAILURE_LEVEL="2"--> + <!--MESSAGE="msg1" LINE="[null]" COST="[null]"--> + <!--created_at="2008-12-02 13:58:00.00"--> + <!--checksum="[null]" person_id="[null]"/>--> + + <project_measures ID="1" project_id="1" SNAPSHOT_ID="1" RULE_ID="[null]" characteristic_id="[null]" + url="[null]" variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" + variation_value_4="[null]" + variation_value_5="[null]" rule_priority="[null]" alert_text="[null]" VALUE="10.0" METRIC_ID="1" + rules_category_id="[null]" + person_id="[null]" + text_value="[null]" tendency="[null]" measure_date="[null]" alert_status="[null]" + description="[null]" measure_data="[null]"/> + + <events id="1" component_uuid="1" snapshot_id="1" + category="VERSION" description="[null]" name="Version 1.0" event_date="1228222680000" + created_at="1228222680000" + event_data="[null]"/> + + <!--<duplications_index id="1" project_snapshot_id="1" snapshot_id="1"--> + <!--hash="bb" index_in_file="0" start_line="0" end_line="0"/>--> + + + <!-- The following is not purged but is kept for DBUnit --> + <snapshots id="2" + project_id="2" parent_snapshot_id="[null]" root_project_id="2" root_snapshot_id="[null]" + status="P" islast="[false]" purge_status="1" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" + build_date="1228222680000" version="[null]" path="[null]"/> + + + <project_measures ID="2" project_id="2" SNAPSHOT_ID="2" RULE_ID="[null]" characteristic_id="[null]" + url="[null]" variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" + variation_value_4="[null]" + variation_value_5="[null]" rule_priority="[null]" alert_text="[null]" VALUE="10.0" METRIC_ID="1" + rules_category_id="[null]" + person_id="[null]" + text_value="[null]" tendency="[null]" measure_date="[null]" alert_status="[null]" + description="[null]" measure_data="[null]"/> + + <events id="2" component_uuid="2" snapshot_id="2" + category="VERSION" description="[null]" name="Version 1.0" event_date="1228222680000" + created_at="1228222680000" + event_data="[null]"/> + + <duplications_index id="2" project_snapshot_id="2" snapshot_id="2" + hash="bb" index_in_file="0" start_line="0" end_line="0"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldPurgeSnapshot.xml b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldPurgeSnapshot.xml new file mode 100644 index 00000000000..53144869569 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldPurgeSnapshot.xml @@ -0,0 +1,59 @@ +<dataset> + + <snapshots id="1" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[false]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" + build_date="1228222680000" version="[null]" path="[null]"/> + + <project_measures ID="1" project_id="1" SNAPSHOT_ID="1" RULE_ID="[null]" characteristic_id="[null]" + url="[null]" variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" + variation_value_4="[null]" variation_value_5="[null]" rule_priority="[null]" alert_text="[null]" + VALUE="10.0" METRIC_ID="1" rules_category_id="[null]" person_id="[null]" text_value="[null]" + tendency="[null]" measure_date="[null]" alert_status="[null]" description="[null]" + measure_data="[null]"/> + + <events id="1" component_uuid="1" snapshot_id="1" + category="VERSION" description="[null]" name="Version 1.0" event_date="1228222680000" + created_at="1228222680000" + event_data="[null]"/> + + <duplications_index id="1" project_snapshot_id="1" snapshot_id="1" + hash="bb" index_in_file="0" start_line="0" end_line="0"/> + + + <!-- The following is not purged but is kept for DBUnit --> + <snapshots id="2" + project_id="2" parent_snapshot_id="[null]" root_project_id="2" root_snapshot_id="[null]" + status="P" islast="[false]" purge_status="1" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" + build_date="1228222680000" version="[null]" path="[null]"/> + + <project_measures ID="2" project_id="2" SNAPSHOT_ID="2" RULE_ID="[null]" characteristic_id="[null]" + url="[null]" variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" + variation_value_4="[null]" + variation_value_5="[null]" rule_priority="[null]" alert_text="[null]" VALUE="10.0" METRIC_ID="1" + rules_category_id="[null]" + person_id="[null]" + text_value="[null]" tendency="[null]" measure_date="[null]" alert_status="[null]" + description="[null]" measure_data="[null]"/> + + <events id="2" component_uuid="2" snapshot_id="2" + category="VERSION" description="[null]" name="Version 1.0" event_date="1228222680000" + created_at="1228222680000" + event_data="[null]"/> + + <duplications_index id="2" project_snapshot_id="2" snapshot_id="2" + hash="bb" index_in_file="0" start_line="0" end_line="0"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/delete_file_sources_of_disabled_resources-result.xml b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/delete_file_sources_of_disabled_resources-result.xml new file mode 100644 index 00000000000..2cb6b58826f --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/delete_file_sources_of_disabled_resources-result.xml @@ -0,0 +1,9 @@ +<dataset> + + <file_sources id="2" project_uuid="ABCD" file_uuid="KLMN" binary_data="[null]" line_hashes="[null]" + data_hash="321654988" + created_at="123456789" updated_at="123456789" src_hash="123456" data_type="SOURCE"/> + <file_sources id="4" project_uuid="ABCD" file_uuid="KLMN" binary_data="[null]" line_hashes="[null]" + data_hash="321654988" + created_at="123456789" updated_at="123456789" src_hash="123456" data_type="TEST"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/delete_file_sources_of_disabled_resources.xml b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/delete_file_sources_of_disabled_resources.xml new file mode 100644 index 00000000000..5307fc8219a --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/delete_file_sources_of_disabled_resources.xml @@ -0,0 +1,87 @@ +<dataset> + + <!-- the project --> + <projects id="1" enabled="[true]" root_id="[null]" uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" + module_uuid_path="." created_at="[null]" + long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project" + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + deprecated_kee="[null]" authorization_updated_at="[null]"/> + + <!-- the directory --> + <projects id="2" enabled="[true]" root_id="1" uuid="EFGH" project_uuid="ABCD" module_uuid="ABCD" + module_uuid_path="." created_at="[null]" + long_name="[null]" scope="DIR" qualifier="DIR" kee="project:my/dir" name="my/dir" + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + deprecated_kee="[null]" authorization_updated_at="[null]"/> + + <!-- the files --> + <projects id="3" enabled="[true]" root_id="1" uuid="GHIJ" project_uuid="ABCD" module_uuid="ABCD" + module_uuid_path=".ABCD." created_at="[null]" + long_name="[null]" scope="FIL" qualifier="FIL" kee="project:my/dir/File.java" name="my/dir/File.java" + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + deprecated_kee="[null]" authorization_updated_at="[null]"/> + <projects id="4" enabled="[true]" root_id="1" uuid="KLMN" project_uuid="ABCD" module_uuid="ABCD" + module_uuid_path=".ABCD." created_at="[null]" + long_name="[null]" scope="FIL" qualifier="FIL" kee="project:my/dir/DeletedFile.java" + name="my/dir/DeletedFile.java" + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + deprecated_kee="[null]" authorization_updated_at="[null]"/> + + <snapshots id="1" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[false]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" + build_date="1228222680000" version="[null]" path="[null]"/> + + <snapshots id="2" + project_id="2" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1" + status="P" islast="[false]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" + build_date="1228222680000" version="[null]" path="[null]"/> + + <snapshots id="3" + project_id="3" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1" + status="P" islast="[false]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" + build_date="1228222680000" version="[null]" path="[null]"/> + + <!-- isLast is true, don't want to delete associated source lines --> + <snapshots id="4" + project_id="4" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" + build_date="1228222680000" version="[null]" path="[null]"/> + + <file_sources id="1" project_uuid="ABCD" file_uuid="GHIJ" binary_data="[null]" line_hashes="[null]" + data_hash="321654987" + created_at="123456789" updated_at="123456789" src_hash="12345" data_type="SOURCE"/> + <file_sources id="2" project_uuid="ABCD" file_uuid="KLMN" binary_data="[null]" line_hashes="[null]" + data_hash="321654988" + created_at="123456789" updated_at="123456789" src_hash="123456" data_type="SOURCE"/> + <file_sources id="3" project_uuid="ABCD" file_uuid="GHIJ" binary_data="[null]" line_hashes="[null]" + data_hash="321654987" + created_at="123456789" updated_at="123456789" src_hash="12345" data_type="TEST"/> + <file_sources id="4" project_uuid="ABCD" file_uuid="KLMN" binary_data="[null]" line_hashes="[null]" + data_hash="321654988" + created_at="123456789" updated_at="123456789" src_hash="123456" data_type="TEST"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/disable_resources_without_last_snapshot-result.xml b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/disable_resources_without_last_snapshot-result.xml new file mode 100644 index 00000000000..530dafeedaa --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/disable_resources_without_last_snapshot-result.xml @@ -0,0 +1,118 @@ +<!-- + +What has been changed : +* enabled=false on projects +* purge_status=1 on snapshots +* resolve not already resolved issues on all components + +--> +<dataset> + + <!-- the project --> + <projects id="1" enabled="[false]" root_id="[null]" uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" + module_uuid_path="." created_at="[null]" + long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project" + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + deprecated_kee="[null]" authorization_updated_at="[null]"/> + + <!-- the directory --> + <projects id="2" enabled="[false]" root_id="1" uuid="EFGH" project_uuid="ABCD" module_uuid="ABCD" module_uuid_path="." + created_at="[null]" + long_name="[null]" scope="DIR" qualifier="DIR" kee="project:my/dir" name="my/dir" + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + deprecated_kee="[null]" authorization_updated_at="[null]"/> + + <!-- the file --> + <projects id="3" enabled="[false]" root_id="1" uuid="GHIJ" project_uuid="ABCD" module_uuid="ABCD" + module_uuid_path=".ABCD." created_at="[null]" + long_name="[null]" scope="FIL" qualifier="FIL" kee="project:my/dir/File.java" name="my/dir/File.java" + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + deprecated_kee="[null]" authorization_updated_at="[null]"/> + + <snapshots id="1" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[false]" purge_status="1" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" + build_date="1228222680000" version="[null]" path="[null]"/> + + <snapshots id="2" + project_id="2" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1" + status="P" islast="[false]" purge_status="1" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" + build_date="1228222680000" version="[null]" path="[null]"/> + + + <snapshots id="3" + project_id="3" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1" + status="P" islast="[false]" purge_status="1" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" + build_date="1228222680000" version="[null]" path="[null]"/> + + <!-- Open issue on file --> + <issues id="1" kee="ISSUE-1" + component_uuid="GHIJ" + project_uuid="ABCD" + status="CLOSED" + issue_close_date="1396994400000" + resolution="REMOVED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" + manual_severity="[false]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" + issue_attributes="[null]" checksum="[null]" author_login="[null]" + updated_at="1450000000000" issue_creation_date="1366063200000" issue_update_date="1396994400000" + created_at="1450000000000" tags="[null]"/> + + <!-- Open issue on directory --> + <issues id="2" kee="ISSUE-2" + component_uuid="EFGH" + project_uuid="ABCD" + status="CLOSED" + issue_close_date="1396994400000" + resolution="REMOVED" line="[null]" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" + manual_severity="[false]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" + issue_attributes="[null]" checksum="[null]" author_login="[null]" + updated_at="1450000000000" issue_creation_date="1366063200000" issue_update_date="1396994400000" + created_at="1450000000000" tags="[null]"/> + + <!-- Open issue on project --> + <issues id="3" kee="ISSUE-3" + component_uuid="ABCD" + project_uuid="ABCD" + status="CLOSED" + issue_close_date="1396994400000" + resolution="REMOVED" line="[null]" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" + manual_severity="[false]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" + issue_attributes="[null]" checksum="[null]" author_login="[null]" + updated_at="1450000000000" issue_creation_date="1366063200000" issue_update_date="1396994400000" + created_at="1450000000000" tags="[null]"/> + + <!-- Resolved issue on file -> not to be updated --> + <issues id="4" kee="ISSUE-4" + component_uuid="GHIJ" + project_uuid="ABCD" + status="CLOSED" + issue_close_date="1449529200000" + resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" + manual_severity="[false]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" + issue_attributes="[null]" checksum="[null]" author_login="[null]" + updated_at="1450000000000" issue_creation_date="1366063200000" issue_update_date="1396908000000" + created_at="1450000000000" tags="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/disable_resources_without_last_snapshot.xml b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/disable_resources_without_last_snapshot.xml new file mode 100644 index 00000000000..0cfef24e585 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/disable_resources_without_last_snapshot.xml @@ -0,0 +1,110 @@ +<dataset> + + <!-- the project --> + <projects id="1" enabled="[true]" root_id="[null]" uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" + module_uuid_path="." created_at="[null]" + long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project" + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + deprecated_kee="[null]" authorization_updated_at="[null]"/> + + <!-- the directory --> + <projects id="2" enabled="[true]" root_id="1" uuid="EFGH" project_uuid="ABCD" module_uuid="ABCD" module_uuid_path="." + created_at="[null]" + long_name="[null]" scope="DIR" qualifier="DIR" kee="project:my/dir" name="my/dir" + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + deprecated_kee="[null]" authorization_updated_at="[null]"/> + + <!-- the file --> + <projects id="3" enabled="[true]" root_id="1" uuid="GHIJ" project_uuid="ABCD" module_uuid="ABCD" + module_uuid_path=".ABCD." created_at="[null]" + long_name="[null]" scope="FIL" qualifier="FIL" kee="project:my/dir/File.java" name="my/dir/File.java" + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + deprecated_kee="[null]" authorization_updated_at="[null]"/> + + <snapshots id="1" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[false]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="[null]"/> + + <snapshots id="2" + project_id="2" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1" + status="P" islast="[false]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="[null]"/> + + + <snapshots id="3" + project_id="3" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1" + status="P" islast="[false]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="[null]"/> + + <!-- Open issue on file --> + <issues id="1" kee="ISSUE-1" + component_uuid="GHIJ" + project_uuid="ABCD" + status="OPEN" + issue_close_date="[null]" + resolution="[null]" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" + manual_severity="[false]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" + issue_attributes="[null]" checksum="[null]" author_login="[null]" + updated_at="[null]" issue_creation_date="1366063200000" issue_update_date="1366063200000" + created_at="1450000000000"/> + + <!-- Open issue on directory --> + <issues id="2" kee="ISSUE-2" + component_uuid="EFGH" + project_uuid="ABCD" + status="OPEN" + issue_close_date="[null]" + resolution="[null]" line="[null]" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" + manual_severity="[false]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" + issue_attributes="[null]" checksum="[null]" author_login="[null]" + updated_at="[null]" issue_creation_date="1366063200000" issue_update_date="1366063200000" + created_at="1450000000000"/> + + <!-- Open issue on project --> + <issues id="3" kee="ISSUE-3" + component_uuid="ABCD" + project_uuid="ABCD" + status="CONFIRM" + issue_close_date="[null]" + resolution="[null]" line="[null]" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" + manual_severity="[false]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" + issue_attributes="[null]" checksum="[null]" author_login="[null]" + updated_at="[null]" issue_creation_date="1366063200000" issue_update_date="1366063200000" + created_at="1450000000000"/> + + <!-- Resolved issue on file -> not to be updated --> + <issues id="4" kee="ISSUE-4" + component_uuid="GHIJ" + project_uuid="ABCD" + status="CLOSED" + issue_close_date="1449529200000" + resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" + manual_severity="[false]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" + issue_attributes="[null]" checksum="[null]" author_login="[null]" + updated_at="1450000000000" issue_creation_date="1366063200000" issue_update_date="1396908000000" + created_at="1450000000000"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/select_purgeable_file_uuids.xml b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/select_purgeable_file_uuids.xml new file mode 100644 index 00000000000..b3bca4514fb --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/select_purgeable_file_uuids.xml @@ -0,0 +1,88 @@ +<dataset> + + <!-- the project --> + <projects id="1" enabled="[true]" root_id="[null]" uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" + module_uuid_path="." created_at="[null]" + long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project" + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + deprecated_kee="[null]" authorization_updated_at="[null]"/> + + <!-- the directory --> + <projects id="2" enabled="[true]" root_id="1" uuid="EFGH" project_uuid="ABCD" module_uuid="ABCD" + module_uuid_path="." created_at="[null]" + long_name="[null]" scope="DIR" qualifier="DIR" kee="project:my/dir" name="my/dir" + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + deprecated_kee="[null]" authorization_updated_at="[null]"/> + + <!-- the files --> + <projects id="3" enabled="[true]" root_id="1" uuid="GHIJ" project_uuid="ABCD" module_uuid="ABCD" + module_uuid_path=".ABCD." created_at="[null]" + long_name="[null]" scope="FIL" qualifier="FIL" kee="project:my/dir/File.java" name="my/dir/File.java" + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + deprecated_kee="[null]" authorization_updated_at="[null]"/> + <projects id="4" enabled="[true]" root_id="1" uuid="KLMN" project_uuid="ABCD" module_uuid="ABCD" + module_uuid_path=".ABCD." created_at="[null]" + long_name="[null]" scope="FIL" qualifier="FIL" kee="project:my/dir/File.java" + name="my/dir/File.java" + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + deprecated_kee="[null]" authorization_updated_at="[null]"/> + <!-- the file has already been disabled. It should not be selected --> + <projects id="5" enabled="[false]" root_id="1" uuid="OPQR" project_uuid="ABCD" module_uuid="ABCD" + module_uuid_path=".ABCD." created_at="[null]" + long_name="[null]" scope="FIL" qualifier="FIL" kee="project:my/dir/File.java" + name="my/dir/File.java" + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + deprecated_kee="[null]" authorization_updated_at="[null]"/> + + <snapshots id="1" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" + build_date="1228222680000" version="[null]" path="[null]"/> + + <snapshots id="2" + project_id="2" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" + build_date="1228222680000" version="[null]" path="[null]"/> + + <!-- isLast is false --> + <snapshots id="3" + project_id="3" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1" + status="P" islast="[false]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" + build_date="1228222680000" version="[null]" path="[null]"/> + + <snapshots id="4" + project_id="4" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" + build_date="1228222680000" version="[null]" path="[null]"/> + + <file_sources id="1" project_uuid="ABCD" file_uuid="GHIJ" binary_data="[null]" line_hashes="[null]" + data_hash="321654987" + created_at="123456789" updated_at="123456789" data_type="SOURCE"/> + <file_sources id="2" project_uuid="ABCD" file_uuid="KLMN" binary_data="[null]" line_hashes="[null]" + data_hash="321654988" + created_at="123456789" updated_at="123456789" data_type="SOURCE"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldDeleteAbortedBuilds-result.xml b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldDeleteAbortedBuilds-result.xml new file mode 100644 index 00000000000..041565fc171 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldDeleteAbortedBuilds-result.xml @@ -0,0 +1,49 @@ +<!-- + +Snapshot 2 has been deleted + +--> +<dataset> + + <!-- the project --> + <projects id="1" enabled="[true]" root_id="[null]" + long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project" + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" + authorization_updated_at="[null]"/> + + <!-- past snapshot with status "processed" and already purged --> + <snapshots id="1" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[false]" purge_status="1" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="[null]"/> + + <!-- snapshot with status "unprocessed" -> to be deleted --> + <!--<snapshots id="2"--> + <!--project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"--> + <!--status="U" islast="[false]" purge_status="0"--> + <!--period1_mode="[null]" period1_param="[null]" period1_date="[null]"--> + <!--period2_mode="[null]" period2_param="[null]" period2_date="[null]"--> + <!--period3_mode="[null]" period3_param="[null]" period3_date="[null]"--> + <!--period4_mode="[null]" period4_param="[null]" period4_date="[null]"--> + <!--period5_mode="[null]" period5_param="[null]" period5_date="[null]"--> + <!--depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" version="[null]" path="[null]"/>--> + + <!-- snapshot with status "processed" and flagged as "last" -> do not purge and do not delete --> + <snapshots id="3" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[true]" purge_status="0" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldDeleteAbortedBuilds.xml b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldDeleteAbortedBuilds.xml new file mode 100644 index 00000000000..0c821011796 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldDeleteAbortedBuilds.xml @@ -0,0 +1,45 @@ +<dataset> + + <!-- the project --> + <projects id="1" enabled="[true]" root_id="[null]" + long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project" + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" + authorization_updated_at="[null]"/> + + <!-- past snapshot with status "processed" and already purged --> + <snapshots id="1" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[false]" purge_status="1" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="[null]"/> + + <!-- snapshot with status "unprocessed" -> to be deleted --> + <snapshots id="2" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="U" islast="[false]" purge_status="0" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="[null]"/> + + <!-- snapshot with status "processed" and flagged as "last" -> do not purge and do not delete --> + <snapshots id="3" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[true]" purge_status="0" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldDeleteHistoricalDataOfDirectoriesAndFiles-result.xml b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldDeleteHistoricalDataOfDirectoriesAndFiles-result.xml new file mode 100644 index 00000000000..a43778f76a0 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldDeleteHistoricalDataOfDirectoriesAndFiles-result.xml @@ -0,0 +1,98 @@ +<!-- + +What has been changed : purge_status=1 on snapshot 4 (PRJ) and snapshots 5 and 6 (DIR/FIL) are deleted + +--> + +<dataset> + + <!-- the project --> + <projects id="1" enabled="[true]" root_id="[null]" uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" + module_uuid_path="." created_at="[null]" + long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project" + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + deprecated_kee="[null]" authorization_updated_at="[null]"/> + + <!-- the directory --> + <projects id="2" enabled="[true]" root_id="1" uuid="EFGH" project_uuid="ABCD" module_uuid="ABCD" module_uuid_path="." + created_at="[null]" + long_name="[null]" scope="DIR" qualifier="DIR" kee="project:my/dir" name="my/dir" + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + deprecated_kee="[null]" authorization_updated_at="[null]"/> + + <!-- the file --> + <projects id="3" enabled="[true]" root_id="1" uuid="GHIJ" project_uuid="ABCD" module_uuid="ABCD" + module_uuid_path=".ABCD." created_at="[null]" + long_name="[null]" scope="FIL" qualifier="FIL" kee="project:my/dir/File.java" name="my/dir/File.java" + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + deprecated_kee="[null]" authorization_updated_at="[null]"/> + + <!-- do not purge last snapshots --> + <snapshots id="1" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="[null]"/> + + <snapshots id="2" + project_id="2" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="DIR" qualifier="DIR" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="[null]"/> + + + <snapshots id="3" + project_id="3" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="FIL" qualifier="FIL" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="[null]"/> + + <!-- snapshots to be purged --> + <snapshots id="4" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[false]" purge_status="1" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="[null]"/> + + <!--<snapshots id="5"--> + <!--project_id="2" parent_snapshot_id="4" root_project_id="1" root_snapshot_id="4"--> + <!--status="P" islast="[false]" purge_status="1"--> + <!--period1_mode="[null]" period1_param="[null]" period1_date="[null]"--> + <!--period2_mode="[null]" period2_param="[null]" period2_date="[null]"--> + <!--period3_mode="[null]" period3_param="[null]" period3_date="[null]"--> + <!--period4_mode="[null]" period4_param="[null]" period4_date="[null]"--> + <!--period5_mode="[null]" period5_param="[null]" period5_date="[null]"--> + <!--depth="[null]" scope="DIR" qualifier="DIR" created_at="1228222680000" build_date="1228222680000" version="[null]" path="[null]"/>--> + + + <!--<snapshots id="6"--> + <!--project_id="3" parent_snapshot_id="5" root_project_id="1" root_snapshot_id="4"--> + <!--status="P" islast="[false]" purge_status="1"--> + <!--period1_mode="[null]" period1_param="[null]" period1_date="[null]"--> + <!--period2_mode="[null]" period2_param="[null]" period2_date="[null]"--> + <!--period3_mode="[null]" period3_param="[null]" period3_date="[null]"--> + <!--period4_mode="[null]" period4_param="[null]" period4_date="[null]"--> + <!--period5_mode="[null]" period5_param="[null]" period5_date="[null]"--> + <!--depth="[null]" scope="FIL" qualifier="FIL" created_at="1228222680000" build_date="1228222680000" version="[null]" path="[null]"/>--> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldDeleteHistoricalDataOfDirectoriesAndFiles.xml b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldDeleteHistoricalDataOfDirectoriesAndFiles.xml new file mode 100644 index 00000000000..b7089187ced --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldDeleteHistoricalDataOfDirectoriesAndFiles.xml @@ -0,0 +1,94 @@ +<dataset> + + <!-- the project --> + <projects id="1" enabled="[true]" root_id="[null]" uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" + module_uuid_path="." created_at="[null]" + long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project" + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + deprecated_kee="[null]" authorization_updated_at="[null]"/> + + <!-- the directory --> + <projects id="2" enabled="[true]" root_id="1" uuid="EFGH" project_uuid="ABCD" module_uuid="ABCD" module_uuid_path="." + created_at="[null]" + long_name="[null]" scope="DIR" qualifier="DIR" kee="project:my/dir" name="my/dir" + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + deprecated_kee="[null]" authorization_updated_at="[null]"/> + + <!-- the file --> + <projects id="3" enabled="[true]" root_id="1" uuid="GHIJ" project_uuid="ABCD" module_uuid="ABCD" + module_uuid_path=".ABCD." created_at="[null]" + long_name="[null]" scope="FIL" qualifier="FIL" kee="project:my/dir/File.java" name="my/dir/File.java" + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + deprecated_kee="[null]" authorization_updated_at="[null]"/> + + <!-- do not purge last snapshots --> + <snapshots id="1" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="[null]"/> + + <snapshots id="2" + project_id="2" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="DIR" qualifier="DIR" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="[null]"/> + + + <snapshots id="3" + project_id="3" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="FIL" qualifier="FIL" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="[null]"/> + + <!-- snapshots to be purged --> + <snapshots id="4" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[false]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="[null]"/> + + <snapshots id="5" + project_id="2" parent_snapshot_id="4" root_project_id="1" root_snapshot_id="4" + status="P" islast="[false]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="DIR" qualifier="DIR" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="[null]"/> + + + <snapshots id="6" + project_id="3" parent_snapshot_id="5" root_project_id="1" root_snapshot_id="4" + status="P" islast="[false]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="FIL" qualifier="FIL" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldDeleteProject.xml b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldDeleteProject.xml new file mode 100644 index 00000000000..1f554aded5d --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldDeleteProject.xml @@ -0,0 +1,108 @@ +<dataset> + + <!-- root --> + <projects id="1" enabled="[true]" root_id="[null]" + uuid="A" project_uuid="A" module_uuid="[null]" module_uuid_path="." + long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project" + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" + authorization_updated_at="[null]"/> + + <snapshots id="1" project_id="1" parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" + status="P" islast="[false]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" + build_date="1228222680000" + version="[null]" path="[null]"/> + + <action_plans id="1" kee="ABCD" project_id="1" name="SHORT_TERM" description="[null]" deadline="[null]" + user_login="igor" status="[null]" created_at="[null]" updated_at="[null]"/> + + <issues id="1" kee="ABCDE" component_uuid="A" project_uuid="A" status="CLOSED" resolution="[null]" line="200" + severity="BLOCKER" + reporter="perceval" assignee="arthur" rule_id="500" + manual_severity="[false]" + message="[null]" + action_plan_key="[null]" + created_at="[null]" + updated_at="[null]" + issue_creation_date="1366063200000" + issue_update_date="1366063200000" + issue_close_date="1366063200000" + /> + + <issues id="2" kee="ABCDF" component_uuid="A" project_uuid="A" status="CLOSED" resolution="[null]" line="200" + severity="BLOCKER" + reporter="perceval" assignee="arthur" rule_id="500" + manual_severity="[false]" + message="[null]" + action_plan_key="[null]" + created_at="[null]" + updated_at="[null]" + issue_creation_date="1366063200000" + issue_update_date="1366063200000" + issue_close_date="1366063200000" + /> + + <issue_changes id="1" kee="[null]" issue_key="ABCDF" created_at="[null]" updated_at="[null]" user_login="admin" + change_type="comment" change_data="abc"/> + + <!-- modules --> + <projects id="2" enabled="[true]" root_id="1" + uuid="B" project_uuid="A" module_uuid="A" module_uuid_path=".A." + long_name="[null]" scope="PRJ" qualifier="BRC" kee="module1" name="module1" + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" + authorization_updated_at="[null]"/> + + <snapshots id="2" project_id="2" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1" + status="P" islast="[false]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="BRC" created_at="1228222680000" + build_date="1228222680000" + version="[null]" path="[null]"/> + + + <projects id="3" enabled="[false]" root_id="1" + uuid="C" project_uuid="A" module_uuid="A" module_uuid_path=".A." + long_name="[null]" scope="PRJ" qualifier="BRC" kee="module2" name="module2" + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" + authorization_updated_at="[null]"/> + + <snapshots id="3" project_id="3" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="BRC" created_at="1228222680000" + build_date="1228222680000" + version="[null]" path="[null]"/> + + <!-- file of module 2--> + <projects id="4" enabled="[false]" root_id="3" + uuid="D" project_uuid="A" module_uuid="C" module_uuid_path=".A.C." + long_name="[null]" scope="FIL" qualifier="FIL" kee="module2:File.java" name="File" + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" + authorization_updated_at="[null]"/> + + <snapshots id="4" project_id="4" parent_snapshot_id="3" root_project_id="1" root_snapshot_id="1" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="FIL" qualifier="FIL" created_at="1228222680000" + build_date="1228222680000" + version="[null]" path="[null]"/> + <file_sources id="1" project_uuid="A" file_uuid="D" binary_data="[null]" line_hashes="[null]" data_hash="321654987" + created_at="123456789" updated_at="123456789" data_type="SOURCE"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldDeleteSnapshots-result.xml b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldDeleteSnapshots-result.xml new file mode 100644 index 00000000000..18f56865b25 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldDeleteSnapshots-result.xml @@ -0,0 +1,37 @@ +<dataset> + + <!-- do not delete if islast=true --> + <snapshots id="1" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="[null]"/> + + <!-- delete only resource 1 --> + <snapshots id="2" + project_id="2" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1" + status="P" islast="[false]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="[null]"/> + + <!-- to be deleted --> + <!--<snapshots id="3" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[false]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" version="[null]" path="[null]"/>--> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldDeleteSnapshots.xml b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldDeleteSnapshots.xml new file mode 100644 index 00000000000..b22f1e45c20 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldDeleteSnapshots.xml @@ -0,0 +1,38 @@ +<dataset> + + <!-- do not delete if islast=true --> + <snapshots id="1" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="[null]"/> + + <!-- delete only resource 1 --> + <snapshots id="2" + project_id="2" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1" + status="P" islast="[false]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="[null]"/> + + <!-- to be deleted --> + <snapshots id="3" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[false]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="[null]"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldPurgeProject-result.xml b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldPurgeProject-result.xml new file mode 100644 index 00000000000..1072cf24714 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldPurgeProject-result.xml @@ -0,0 +1,49 @@ +<dataset> + + <!-- the project --> + <projects id="1" uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" module_uuid_path="." enabled="[true]" + created_at="[null]" + long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project" + root_id="[null]" description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" + path="[null]" deprecated_kee="[null]" + authorization_updated_at="[null]"/> + + + <!-- snapshot already purged --> + <snapshots id="1" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[false]" purge_status="1" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="[null]"/> + + + <!-- do not purge snapshot with islast=true--> + <snapshots id="2" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="[null]"/> + + <!-- snapshot to be purged --> + <snapshots id="3" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[false]" purge_status="1" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldPurgeProject.xml b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldPurgeProject.xml new file mode 100644 index 00000000000..034d3856aaf --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldPurgeProject.xml @@ -0,0 +1,49 @@ +<dataset> + + <!-- the project --> + <projects id="1" uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" module_uuid_path="." enabled="[true]" + created_at="[null]" + long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project" + root_id="[null]" description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" + path="[null]" deprecated_kee="[null]" + authorization_updated_at="[null]"/> + + + <!-- snapshot already purged --> + <snapshots id="1" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[false]" purge_status="1" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="[null]"/> + + + <!-- do not purge snapshot with islast=true--> + <snapshots id="2" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="[null]"/> + + <!-- snapshot to be purged --> + <snapshots id="3" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[false]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldSelectPurgeableSnapshots.xml b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldSelectPurgeableSnapshots.xml new file mode 100644 index 00000000000..d523d563dc7 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldSelectPurgeableSnapshots.xml @@ -0,0 +1,68 @@ +<dataset> + + <!-- last -> select --> + <snapshots id="1" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="[null]"/> + + <!-- not processed -> exclude --> + <snapshots id="2" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="U" islast="[false]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="[null]"/> + + <!-- on other resource -> exclude --> + <snapshots id="3" + project_id="222" parent_snapshot_id="[null]" root_project_id="222" root_snapshot_id="[null]" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="[null]"/> + + <!-- without event -> select --> + <snapshots id="4" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[false]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="[null]"/> + + <!-- with event -> select --> + <snapshots id="5" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[false]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="[null]"/> + + <events id="2" component_uuid="1" snapshot_id="5" + category="Version" description="[null]" name="Version 1.0" event_date="1228222680000" + created_at="1228222680000" + event_data="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/should_delete_all_closed_issues-result.xml b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/should_delete_all_closed_issues-result.xml new file mode 100644 index 00000000000..142d23dcfe0 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/should_delete_all_closed_issues-result.xml @@ -0,0 +1,89 @@ +<!-- + + EXACTLY THE SAME FILE. NO ROWS HAVE BEEN DELETED. + +--> +<dataset> + + <projects id="1" uuid="1" enabled="[true]" root_id="[null]" created_at="[null]" + long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project" + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" + authorization_updated_at="[null]"/> + + <snapshots id="1" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" + build_date="1228222680000" version="[null]" path="[null]"/> + + + <!-- old closed issues on file and project --> + <!-- + <issues id="1" kee="ISSUE-1" + component_uuid="100" + project_uuid="1" + status="CLOSED" + issue_close_date="1262300400000" + resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" + updated_at="[null]" issue_creation_date="1366063200000" issue_update_date="1366063200000" created_at="2013-04-16"/> + <issue_changes id="1" kee="[null]" issue_key="ISSUE-1" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/> + + <issues id="2" kee="ISSUE-2" + component_uuid="1" + project_uuid="1" + status="CLOSED" + issue_close_date="1262300400000" + resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" + updated_at="[null]" issue_creation_date="1366063200000" issue_update_date="1366063200000" created_at="2013-04-16"/> + <issue_changes id="2" kee="[null]" issue_key="ISSUE-2" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/> + --> + + <!-- old open issues --> + <issues id="3" kee="ISSUE-3" + component_uuid="1" + project_uuid="1" + status="OPEN" + issue_close_date="[null]" + resolution="[null]" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" + manual_severity="[false]" tags="[null]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" + issue_attributes="[null]" checksum="[null]" author_login="[null]" + updated_at="[null]" issue_creation_date="1366063200000" issue_update_date="1366063200000" + created_at="1400000000000"/> + <issue_changes id="3" kee="[null]" issue_key="ISSUE-3" created_at="[null]" updated_at="[null]" user_login="admin" + change_type="comment" change_data="abc" issue_change_creation_date="[null]"/> + + <!-- recent open and closed issues --> + <issues id="4" kee="ISSUE-4" + component_uuid="100" + project_uuid="1" + status="OPEN" + issue_close_date="[null]" + resolution="[null]" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" + manual_severity="[false]" tags="[null]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" + issue_attributes="[null]" checksum="[null]" author_login="[null]" + updated_at="[null]" issue_creation_date="1366063200000" issue_update_date="1366063200000" + created_at="1400000000000"/> + <issue_changes id="4" kee="[null]" issue_key="ISSUE-4" created_at="[null]" updated_at="[null]" user_login="admin" + change_type="comment" change_data="abc" issue_change_creation_date="[null]"/> + + <!-- + <issues id="5" kee="ISSUE-5" + component_uuid="100" + project_uuid="1" + status="CLOSED" + issue_close_date="1735686000000" + resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" + updated_at="[null]" issue_creation_date="1366063200000" issue_update_date="1366063200000" created_at="2013-04-16"/> + <issue_changes id="5" kee="[null]" issue_key="ISSUE-5" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/> + --> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/should_delete_all_closed_issues.xml b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/should_delete_all_closed_issues.xml new file mode 100644 index 00000000000..9fe05024ebd --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/should_delete_all_closed_issues.xml @@ -0,0 +1,94 @@ +<dataset> + + <projects id="1" uuid="1" enabled="[true]" root_id="[null]" created_at="[null]" + long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project" + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" + authorization_updated_at="[null]"/> + + <snapshots id="1" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" + build_date="1228222680000" version="[null]" path="[null]"/> + + + <!-- old closed issues on file and project --> + <issues id="1" kee="ISSUE-1" + component_uuid="100" + project_uuid="1" + status="CLOSED" + issue_close_date="1262300400000" + resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" + manual_severity="[false]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" + issue_attributes="[null]" checksum="[null]" author_login="[null]" + updated_at="[null]" issue_creation_date="1366063200000" issue_update_date="1366063200000" + created_at="1400000000000"/> + <issue_changes id="1" kee="[null]" issue_key="ISSUE-1" created_at="[null]" updated_at="[null]" user_login="admin" + change_type="comment" change_data="abc" issue_change_creation_date="[null]"/> + + <issues id="2" kee="ISSUE-2" + component_uuid="1" + project_uuid="1" + status="CLOSED" + issue_close_date="1262300400000" + resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" + manual_severity="[false]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" + issue_attributes="[null]" checksum="[null]" author_login="[null]" + updated_at="[null]" issue_creation_date="1366063200000" issue_update_date="1366063200000" + created_at="1400000000000"/> + <issue_changes id="2" kee="[null]" issue_key="ISSUE-2" created_at="[null]" updated_at="[null]" user_login="admin" + change_type="comment" change_data="abc" issue_change_creation_date="[null]"/> + + + <!-- old open issues --> + <issues id="3" kee="ISSUE-3" + component_uuid="1" + project_uuid="1" + status="OPEN" + issue_close_date="[null]" + resolution="[null]" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" + manual_severity="[false]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" + issue_attributes="[null]" checksum="[null]" author_login="[null]" + updated_at="[null]" issue_creation_date="1366063200000" issue_update_date="1366063200000" + created_at="1400000000000"/> + <issue_changes id="3" kee="[null]" issue_key="ISSUE-3" created_at="[null]" updated_at="[null]" user_login="admin" + change_type="comment" change_data="abc" issue_change_creation_date="[null]"/> + + <!-- recent open and closed issues --> + <issues id="4" kee="ISSUE-4" + component_uuid="100" + project_uuid="1" + status="OPEN" + issue_close_date="[null]" + resolution="[null]" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" + manual_severity="[false]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" + issue_attributes="[null]" checksum="[null]" author_login="[null]" + updated_at="[null]" issue_creation_date="1366063200000" issue_update_date="1366063200000" + created_at="1400000000000"/> + <issue_changes id="4" kee="[null]" issue_key="ISSUE-4" created_at="[null]" updated_at="[null]" user_login="admin" + change_type="comment" change_data="abc" issue_change_creation_date="[null]"/> + + <issues id="5" kee="ISSUE-5" + component_uuid="100" + project_uuid="1" + status="CLOSED" + issue_close_date="1735686000000" + resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" + manual_severity="[false]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" + issue_attributes="[null]" checksum="[null]" author_login="[null]" + updated_at="[null]" issue_creation_date="1366063200000" issue_update_date="1366063200000" + created_at="1400000000000"/> + <issue_changes id="5" kee="[null]" issue_key="ISSUE-5" created_at="[null]" updated_at="[null]" user_login="admin" + change_type="comment" change_data="abc" issue_change_creation_date="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/should_delete_old_closed_issues-result.xml b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/should_delete_old_closed_issues-result.xml new file mode 100644 index 00000000000..7b79eaacc03 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/should_delete_old_closed_issues-result.xml @@ -0,0 +1,86 @@ +<dataset> + + <projects id="1" uuid="1" enabled="[true]" root_id="[null]" created_at="[null]" + long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project" + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" + authorization_updated_at="[null]"/> + + <snapshots id="1" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="[null]"/> + + <!-- old closed issues on file and project -> to be purged --> + <!-- + <issues id="1" kee="ISSUE-1" + component_uuid="100" + project_uuid="1" + status="CLOSED" + issue_close_date="1262300400000" + resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" + updated_at="[null]" issue_creation_date="1366063200000" issue_update_date="1366063200000" created_at="2013-04-16"/> + <issue_changes id="1" kee="[null]" issue_key="ISSUE-1" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/> + + <issues id="2" kee="ISSUE-2" + component_uuid="1" + project_uuid="1" + status="CLOSED" + issue_close_date="1262300400000" + resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" + updated_at="[null]" issue_creation_date="1366063200000" issue_update_date="1366063200000" created_at="2013-04-16"/> + <issue_changes id="2" kee="[null]" issue_key="ISSUE-2" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/> + --> + + <!-- old open issues -> do not purge --> + <issues id="3" kee="ISSUE-3" + component_uuid="1" + project_uuid="1" + status="OPEN" + issue_close_date="[null]" + resolution="[null]" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" + manual_severity="[false]" tags="[null]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" + issue_attributes="[null]" checksum="[null]" author_login="[null]" + updated_at="[null]" issue_creation_date="1366063200000" issue_update_date="1366063200000" + created_at="1400000000000"/> + <issue_changes id="3" kee="[null]" issue_key="ISSUE-3" created_at="[null]" updated_at="[null]" user_login="admin" + change_type="comment" change_data="abc" issue_change_creation_date="[null]"/> + + <!-- recent open and closed issues -> do not purge --> + <issues id="4" kee="ISSUE-4" + component_uuid="100" + project_uuid="1" + status="OPEN" + issue_close_date="[null]" + resolution="[null]" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" + manual_severity="[false]" tags="[null]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" + issue_attributes="[null]" checksum="[null]" author_login="[null]" + updated_at="[null]" issue_creation_date="1366063200000" issue_update_date="1366063200000" + created_at="1400000000000"/> + <issue_changes id="4" kee="[null]" issue_key="ISSUE-4" created_at="[null]" updated_at="[null]" user_login="admin" + change_type="comment" change_data="abc" issue_change_creation_date="[null]"/> + + <issues id="5" kee="ISSUE-5" + component_uuid="100" + project_uuid="1" + status="CLOSED" + issue_close_date="1735686000000" + resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" + manual_severity="[false]" tags="[null]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" + issue_attributes="[null]" checksum="[null]" author_login="[null]" + updated_at="[null]" issue_creation_date="1366063200000" issue_update_date="1366063200000" + created_at="1400000000000"/> + <issue_changes id="5" kee="[null]" issue_key="ISSUE-5" created_at="[null]" updated_at="[null]" user_login="admin" + change_type="comment" change_data="abc" issue_change_creation_date="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/should_delete_old_closed_issues.xml b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/should_delete_old_closed_issues.xml new file mode 100644 index 00000000000..95d56051843 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/purge/PurgeDaoTest/should_delete_old_closed_issues.xml @@ -0,0 +1,93 @@ +<dataset> + + <projects id="1" uuid="1" enabled="[true]" root_id="[null]" created_at="[null]" + long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project" + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" + authorization_updated_at="[null]"/> + + <snapshots id="1" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" + build_date="1228222680000" version="[null]" path="[null]"/> + + <!-- old closed issues on file and project -> to be purged --> + <issues id="1" kee="ISSUE-1" + component_uuid="100" + project_uuid="1" + status="CLOSED" + issue_close_date="1262300400000" + resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" + manual_severity="[false]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" + issue_attributes="[null]" checksum="[null]" author_login="[null]" + updated_at="[null]" issue_creation_date="1366063200000" issue_update_date="1366063200000" + created_at="1400000000000"/> + <issue_changes id="1" kee="[null]" issue_key="ISSUE-1" created_at="[null]" updated_at="[null]" user_login="admin" + change_type="comment" change_data="abc" issue_change_creation_date="[null]"/> + + <issues id="2" kee="ISSUE-2" + component_uuid="1" + project_uuid="1" + status="CLOSED" + issue_close_date="1262300400000" + resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" + manual_severity="[false]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" + issue_attributes="[null]" checksum="[null]" author_login="[null]" + updated_at="[null]" issue_creation_date="1366063200000" issue_update_date="1366063200000" + created_at="1400000000000"/> + <issue_changes id="2" kee="[null]" issue_key="ISSUE-2" created_at="[null]" updated_at="[null]" user_login="admin" + change_type="comment" change_data="abc" issue_change_creation_date="[null]"/> + + + <!-- old open issues -> do not purge --> + <issues id="3" kee="ISSUE-3" + component_uuid="1" + project_uuid="1" + status="OPEN" + issue_close_date="[null]" + resolution="[null]" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" + manual_severity="[false]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" + issue_attributes="[null]" checksum="[null]" author_login="[null]" + updated_at="[null]" issue_creation_date="1366063200000" issue_update_date="1366063200000" + created_at="1400000000000"/> + <issue_changes id="3" kee="[null]" issue_key="ISSUE-3" created_at="[null]" updated_at="[null]" user_login="admin" + change_type="comment" change_data="abc" issue_change_creation_date="[null]"/> + + <!-- recent open and closed issues -> do not purge --> + <issues id="4" kee="ISSUE-4" + component_uuid="100" + project_uuid="1" + status="OPEN" + issue_close_date="[null]" + resolution="[null]" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" + manual_severity="[false]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" + issue_attributes="[null]" checksum="[null]" author_login="[null]" + updated_at="[null]" issue_creation_date="1366063200000" issue_update_date="1366063200000" + created_at="1400000000000"/> + <issue_changes id="4" kee="[null]" issue_key="ISSUE-4" created_at="[null]" updated_at="[null]" user_login="admin" + change_type="comment" change_data="abc" issue_change_creation_date="[null]"/> + + <issues id="5" kee="ISSUE-5" + component_uuid="100" + project_uuid="1" + status="CLOSED" + issue_close_date="1735686000000" + resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" + manual_severity="[false]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" + issue_attributes="[null]" checksum="[null]" author_login="[null]" + updated_at="[null]" issue_creation_date="1366063200000" issue_update_date="1366063200000" + created_at="1400000000000"/> + <issue_changes id="5" kee="[null]" issue_key="ISSUE-5" created_at="[null]" updated_at="[null]" user_login="admin" + change_type="comment" change_data="abc" issue_change_creation_date="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/qualitygate/ProjectQgateAssociationDaoTest/shared.xml b/sonar-db/src/test/resources/org/sonar/db/qualitygate/ProjectQgateAssociationDaoTest/shared.xml new file mode 100644 index 00000000000..9fb6b533775 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/qualitygate/ProjectQgateAssociationDaoTest/shared.xml @@ -0,0 +1,46 @@ +<dataset> + + <quality_gates id="42" name="Golden"/> + <quality_gates id="43" name="Ninth"/> + + <projects id="1" uuid="A" name="Project One" qualifier="TRK" scope="PRJ"/> + <projects id="2" uuid="B" name="Project Two" qualifier="TRK" scope="PRJ"/> + <projects id="3" uuid="C" name="Project Three" qualifier="TRK" scope="PRJ"/> + <projects id="4" uuid="D" name="Project Four" qualifier="TRK" scope="PRJ"/> + <projects id="5" uuid="E" name="Project Five" qualifier="TRK" scope="PRJ"/> + <projects id="6" uuid="F" name="View Six" qualifier="VW" scope="PRJ"/> + <projects id="7" uuid="G" name="Project One" qualifier="TRK" scope="FIL"/> + + <resource_index id="1" kee="project one" resource_id="1" root_project_id="1" position="0" name_size="11" + qualifier="TRK"/> + <resource_index id="2" kee="roject one" resource_id="1" root_project_id="1" position="1" name_size="11" + qualifier="TRK"/> + <resource_index id="3" kee="oject one" resource_id="1" root_project_id="1" position="2" name_size="11" + qualifier="TRK"/> + <resource_index id="4" kee="ject one" resource_id="1" root_project_id="1" position="3" name_size="11" + qualifier="TRK"/> + <resource_index id="5" kee="ect one" resource_id="1" root_project_id="1" position="4" name_size="11" qualifier="TRK"/> + <resource_index id="6" kee="ct one" resource_id="1" root_project_id="1" position="5" name_size="11" qualifier="TRK"/> + <resource_index id="7" kee="t one" resource_id="1" root_project_id="1" position="6" name_size="11" qualifier="TRK"/> + <resource_index id="8" kee=" one" resource_id="1" root_project_id="1" position="7" name_size="11" qualifier="TRK"/> + <resource_index id="9" kee="one" resource_id="1" root_project_id="1" position="8" name_size="11" qualifier="TRK"/> + <resource_index id="10" kee="project two" resource_id="2" root_project_id="2" position="0" name_size="11" + qualifier="TRK"/> + <resource_index id="11" kee="roject two" resource_id="2" root_project_id="2" position="1" name_size="11" + qualifier="TRK"/> + <resource_index id="12" kee="oject two" resource_id="2" root_project_id="2" position="2" name_size="11" + qualifier="TRK"/> + <resource_index id="13" kee="ject two" resource_id="2" root_project_id="2" position="3" name_size="11" + qualifier="TRK"/> + <resource_index id="14" kee="ect two" resource_id="2" root_project_id="2" position="4" name_size="11" + qualifier="TRK"/> + <resource_index id="15" kee="ct two" resource_id="2" root_project_id="2" position="5" name_size="11" qualifier="TRK"/> + <resource_index id="16" kee="t two" resource_id="2" root_project_id="2" position="6" name_size="11" qualifier="TRK"/> + <resource_index id="17" kee=" two" resource_id="2" root_project_id="2" position="7" name_size="11" qualifier="TRK"/> + + <properties id="1" prop_key="sonar.qualitygate" resource_id="[null]" text_value="43"/> + <properties id="2" prop_key="sonar.qualitygate" resource_id="1" text_value="42"/> + <properties id="3" prop_key="sonar.qualitygate" resource_id="2" text_value="42"/> + <properties id="4" prop_key="sonar.qualitygate" resource_id="3" text_value="42"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/qualitygate/QualityGateConditionDaoTest/delete-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualitygate/QualityGateConditionDaoTest/delete-result.xml new file mode 100644 index 00000000000..62f82411cd7 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/qualitygate/QualityGateConditionDaoTest/delete-result.xml @@ -0,0 +1,12 @@ +<dataset> + + <quality_gate_conditions id="2" qgate_id="1" metric_id="3" operator="<" value_warning="10" value_error="20" + period="[null]"/> + <quality_gate_conditions id="3" qgate_id="1" metric_id="4" operator="<" value_warning="10" value_error="[null]" + period="1"/> + <quality_gate_conditions id="4" qgate_id="2" metric_id="5" operator="<" value_warning="[null]" value_error="20" + period="3"/> + <quality_gate_conditions id="5" qgate_id="2" metric_id="6" operator="<" value_warning="[null]" value_error="20" + period="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/qualitygate/QualityGateConditionDaoTest/insert-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualitygate/QualityGateConditionDaoTest/insert-result.xml new file mode 100644 index 00000000000..20aa1a86ee7 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/qualitygate/QualityGateConditionDaoTest/insert-result.xml @@ -0,0 +1,6 @@ +<dataset> + + <quality_gate_conditions id="1" qgate_id="1" metric_id="2" operator="GT" value_warning="10" value_error="20" + period="3"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/qualitygate/QualityGateConditionDaoTest/insert.xml b/sonar-db/src/test/resources/org/sonar/db/qualitygate/QualityGateConditionDaoTest/insert.xml new file mode 100644 index 00000000000..871dedcb5e9 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/qualitygate/QualityGateConditionDaoTest/insert.xml @@ -0,0 +1,3 @@ +<dataset> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/qualitygate/QualityGateConditionDaoTest/selectForQualityGate.xml b/sonar-db/src/test/resources/org/sonar/db/qualitygate/QualityGateConditionDaoTest/selectForQualityGate.xml new file mode 100644 index 00000000000..82faf6d5f15 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/qualitygate/QualityGateConditionDaoTest/selectForQualityGate.xml @@ -0,0 +1,14 @@ +<dataset> + + <quality_gate_conditions id="1" qgate_id="1" metric_id="2" operator="<" value_warning="10" value_error="20" + period="3"/> + <quality_gate_conditions id="2" qgate_id="1" metric_id="3" operator="<" value_warning="10" value_error="20" + period="[null]"/> + <quality_gate_conditions id="3" qgate_id="1" metric_id="4" operator="<" value_warning="10" value_error="[null]" + period="1"/> + <quality_gate_conditions id="4" qgate_id="2" metric_id="5" operator="<" value_warning="[null]" value_error="20" + period="3"/> + <quality_gate_conditions id="5" qgate_id="2" metric_id="6" operator="<" value_warning="[null]" value_error="20" + period="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/qualitygate/QualityGateConditionDaoTest/shouldCleanConditions-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualitygate/QualityGateConditionDaoTest/shouldCleanConditions-result.xml new file mode 100644 index 00000000000..7179362495c --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/qualitygate/QualityGateConditionDaoTest/shouldCleanConditions-result.xml @@ -0,0 +1,24 @@ +<dataset> + + <metrics delete_historical_data="false" id="1" name="key1" val_type="INT" description="description" domain="domain" + short_name="name1" qualitative="false" user_managed="false" enabled="true" worst_value="[null]" + optimized_best_value="false" best_value="[null]" direction="1" hidden="false"/> + + <metrics delete_historical_data="false" id="2" name="disabledkey2" val_type="INT" description="description" + domain="domain" + short_name="name2" qualitative="false" user_managed="false" enabled="false" worst_value="[null]" + optimized_best_value="false" best_value="[null]" direction="1" hidden="false"/> + + <!-- ok --> + <quality_gate_conditions id="1" qgate_id="1" metric_id="1" operator="GT" value_error="30" value_warning="[null]" + period="[null]"/> + <quality_gate_conditions id="2" qgate_id="2" metric_id="1" operator="GT" value_error="[null]" value_warning="150" + period="[null]"/> + + <!-- disabled metric --> + <!--<quality_gate_conditions id="3" qgate_id="1" metric_id="2" operator="GT" value_error="30" value_warning="[null]" period="[null]"/>--> + + <!-- unknown metric --> + <!--<quality_gate_conditions id="4" qgate_id="1" metric_id="999" operator="GT" value_error="30" value_warning="[null]" period="[null]"/>--> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/qualitygate/QualityGateConditionDaoTest/shouldCleanConditions.xml b/sonar-db/src/test/resources/org/sonar/db/qualitygate/QualityGateConditionDaoTest/shouldCleanConditions.xml new file mode 100644 index 00000000000..402d75a704c --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/qualitygate/QualityGateConditionDaoTest/shouldCleanConditions.xml @@ -0,0 +1,26 @@ +<dataset> + + <metrics delete_historical_data="false" id="1" name="key1" val_type="INT" description="description" domain="domain" + short_name="name1" qualitative="false" user_managed="false" enabled="true" worst_value="[null]" + optimized_best_value="false" best_value="[null]" direction="1" hidden="false"/> + + <metrics delete_historical_data="false" id="2" name="disabledkey2" val_type="INT" description="description" + domain="domain" + short_name="name2" qualitative="false" user_managed="false" enabled="false" worst_value="[null]" + optimized_best_value="false" best_value="[null]" direction="1" hidden="false"/> + + <!-- ok --> + <quality_gate_conditions id="1" qgate_id="1" metric_id="1" operator="GT" value_error="30" value_warning="[null]" + period="[null]"/> + <quality_gate_conditions id="2" qgate_id="2" metric_id="1" operator="GT" value_error="[null]" value_warning="150" + period="[null]"/> + + <!-- disabled metric --> + <quality_gate_conditions id="3" qgate_id="1" metric_id="2" operator="GT" value_error="30" value_warning="[null]" + period="[null]"/> + + <!-- unknown metric --> + <quality_gate_conditions id="4" qgate_id="1" metric_id="999" operator="GT" value_error="30" value_warning="[null]" + period="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/qualitygate/QualityGateConditionDaoTest/update-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualitygate/QualityGateConditionDaoTest/update-result.xml new file mode 100644 index 00000000000..1364e7c51e9 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/qualitygate/QualityGateConditionDaoTest/update-result.xml @@ -0,0 +1,14 @@ +<dataset> + + <quality_gate_conditions id="1" qgate_id="1" metric_id="7" operator=">" value_warning="50" value_error="80" + period="1"/> + <quality_gate_conditions id="2" qgate_id="1" metric_id="3" operator="<" value_warning="10" value_error="20" + period="[null]"/> + <quality_gate_conditions id="3" qgate_id="1" metric_id="4" operator="<" value_warning="10" value_error="[null]" + period="1"/> + <quality_gate_conditions id="4" qgate_id="2" metric_id="5" operator="<" value_warning="[null]" value_error="20" + period="3"/> + <quality_gate_conditions id="5" qgate_id="2" metric_id="6" operator="<" value_warning="[null]" value_error="20" + period="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/qualitygate/QualityGateDaoTest/delete-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualitygate/QualityGateDaoTest/delete-result.xml new file mode 100644 index 00000000000..3c0ddc793c1 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/qualitygate/QualityGateDaoTest/delete-result.xml @@ -0,0 +1,6 @@ +<dataset> + + <quality_gates id="2" name="Balanced"/> + <quality_gates id="3" name="Lenient"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/qualitygate/QualityGateDaoTest/insert-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualitygate/QualityGateDaoTest/insert-result.xml new file mode 100644 index 00000000000..00881f2945b --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/qualitygate/QualityGateDaoTest/insert-result.xml @@ -0,0 +1,5 @@ +<dataset> + + <quality_gates id="1" name="My Quality Gate"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/qualitygate/QualityGateDaoTest/insert.xml b/sonar-db/src/test/resources/org/sonar/db/qualitygate/QualityGateDaoTest/insert.xml new file mode 100644 index 00000000000..871dedcb5e9 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/qualitygate/QualityGateDaoTest/insert.xml @@ -0,0 +1,3 @@ +<dataset> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/qualitygate/QualityGateDaoTest/selectAll.xml b/sonar-db/src/test/resources/org/sonar/db/qualitygate/QualityGateDaoTest/selectAll.xml new file mode 100644 index 00000000000..6eb3e577e4e --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/qualitygate/QualityGateDaoTest/selectAll.xml @@ -0,0 +1,7 @@ +<dataset> + + <quality_gates id="1" name="Very strict"/> + <quality_gates id="2" name="Balanced"/> + <quality_gates id="3" name="Lenient"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/qualitygate/QualityGateDaoTest/update-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualitygate/QualityGateDaoTest/update-result.xml new file mode 100644 index 00000000000..4f80f313eae --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/qualitygate/QualityGateDaoTest/update-result.xml @@ -0,0 +1,7 @@ +<dataset> + + <quality_gates id="1" name="Not so strict"/> + <quality_gates id="2" name="Balanced"/> + <quality_gates id="3" name="Lenient"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete-result.xml new file mode 100644 index 00000000000..2283bba7d52 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete-result.xml @@ -0,0 +1,11 @@ +<dataset> + + <!--<active_rules created_at="[null]" updated_at="[null]" id="1" profile_id="1" rule_id="10" failure_level="2" inheritance="INHERITED"--> + + <active_rules created_at="[null]" updated_at="[null]" id="2" profile_id="2" rule_id="10" failure_level="0" + inheritance="[null]"/> + + <active_rules created_at="[null]" updated_at="[null]" id="3" profile_id="2" rule_id="11" failure_level="1" + inheritance="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_from_profile-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_from_profile-result.xml new file mode 100644 index 00000000000..617cd7e08b0 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_from_profile-result.xml @@ -0,0 +1,10 @@ +<dataset> + + <active_rules created_at="[null]" updated_at="[null]" id="1" profile_id="1" rule_id="10" failure_level="2" + inheritance="INHERITED"/> + + <!--<active_rules created_at="[null]" updated_at="[null]" id="2" profile_id="2" rule_id="10" failure_level="0" inheritance="[null]"--> + + <!--<active_rules created_at="[null]" updated_at="[null]" id="3" profile_id="2" rule_id="11" failure_level="1" inheritance="[null]"--> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_from_rule-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_from_rule-result.xml new file mode 100644 index 00000000000..a06288e57b6 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_from_rule-result.xml @@ -0,0 +1,11 @@ +<dataset> + + <active_rules created_at="[null]" updated_at="[null]" id="1" profile_id="1" rule_id="10" failure_level="2" + inheritance="INHERITED"/> + + <active_rules created_at="[null]" updated_at="[null]" id="2" profile_id="2" rule_id="10" failure_level="0" + inheritance="[null]"/> + + <!--<active_rules created_at="[null]" updated_at="[null]" id="3" profile_id="2" rule_id="11" failure_level="1" inheritance="[null]"/>--> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameter-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameter-result.xml new file mode 100644 index 00000000000..900eb2c2874 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameter-result.xml @@ -0,0 +1,14 @@ +<dataset> + + <active_rules created_at="[null]" updated_at="[null]" id="1" profile_id="1" rule_id="10" failure_level="2" + inheritance="INHERITED"/> + + <active_rules created_at="[null]" updated_at="[null]" id="2" profile_id="2" rule_id="10" failure_level="0" + inheritance="[null]"/> + + <!--<active_rule_parameters id="1" active_rule_id="1" rules_parameter_id="1" rules_parameter_key="max" value="20"/>--> + <active_rule_parameters id="2" active_rule_id="1" rules_parameter_id="2" rules_parameter_key="format" value="html"/> + + <active_rule_parameters id="3" active_rule_id="2" rules_parameter_id="1" rules_parameter_key="max" value="15"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameters-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameters-result.xml new file mode 100644 index 00000000000..b8aba08833d --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameters-result.xml @@ -0,0 +1,14 @@ +<dataset> + + <active_rules created_at="[null]" updated_at="[null]" id="1" profile_id="1" rule_id="10" failure_level="2" + inheritance="INHERITED"/> + + <active_rules created_at="[null]" updated_at="[null]" id="2" profile_id="2" rule_id="10" failure_level="0" + inheritance="[null]"/> + + <!--<active_rule_parameters id="1" active_rule_id="1" rules_parameter_id="1" rules_parameter_key="max" value="20"/>--> + <!--<active_rule_parameters id="2" active_rule_id="1" rules_parameter_id="2" rules_parameter_key="format" value="html"/>--> + + <active_rule_parameters id="3" active_rule_id="2" rules_parameter_id="1" rules_parameter_key="max" value="15"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameters_from_profile_id-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameters_from_profile_id-result.xml new file mode 100644 index 00000000000..d1bbff5912e --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameters_from_profile_id-result.xml @@ -0,0 +1,19 @@ +<dataset> + + <active_rules created_at="[null]" updated_at="[null]" id="1" profile_id="1" rule_id="10" failure_level="2" + inheritance="INHERITED"/> + + <!-- Parent of Active rule 1 --> + <active_rules created_at="[null]" updated_at="[null]" id="2" profile_id="2" rule_id="10" failure_level="0" + inheritance="[null]"/> + + <active_rules created_at="[null]" updated_at="[null]" id="3" profile_id="2" rule_id="11" failure_level="1" + inheritance="[null]"/> + + <active_rule_parameters id="1" active_rule_id="1" rules_parameter_id="1" rules_parameter_key="max" value="20"/> + <active_rule_parameters id="2" active_rule_id="1" rules_parameter_id="2" rules_parameter_key="format" value="html"/> + + <!--<active_rule_parameters id="3" active_rule_id="2" rules_parameter_id="1" rules_parameter_key="max" value="15"/>--> + <!--<active_rule_parameters id="4" active_rule_id="3" rules_parameter_id="2" rules_parameter_key="format" value="text"/>--> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameters_from_profile_id.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameters_from_profile_id.xml new file mode 100644 index 00000000000..47c6ceeac24 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameters_from_profile_id.xml @@ -0,0 +1,19 @@ +<dataset> + + <active_rules created_at="[null]" updated_at="[null]" id="1" profile_id="1" rule_id="10" failure_level="2" + inheritance="INHERITED"/> + + <!-- Parent of Active rule 1 --> + <active_rules created_at="[null]" updated_at="[null]" id="2" profile_id="2" rule_id="10" failure_level="0" + inheritance="[null]"/> + + <active_rules created_at="[null]" updated_at="[null]" id="3" profile_id="2" rule_id="11" failure_level="1" + inheritance="[null]"/> + + <active_rule_parameters id="1" active_rule_id="1" rules_parameter_id="1" rules_parameter_key="max" value="20"/> + <active_rule_parameters id="2" active_rule_id="1" rules_parameter_id="2" rules_parameter_key="format" value="html"/> + + <active_rule_parameters id="3" active_rule_id="2" rules_parameter_id="1" rules_parameter_key="max" value="15"/> + <active_rule_parameters id="4" active_rule_id="3" rules_parameter_id="2" rules_parameter_key="format" value="text"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/empty.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/empty.xml new file mode 100644 index 00000000000..871dedcb5e9 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/empty.xml @@ -0,0 +1,3 @@ +<dataset> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/insert-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/insert-result.xml new file mode 100644 index 00000000000..574cbabdd56 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/insert-result.xml @@ -0,0 +1,6 @@ +<dataset> + + <active_rules created_at="[null]" updated_at="[null]" id="1" profile_id="1" rule_id="10" failure_level="2" + inheritance="INHERITED"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/insert_parameter-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/insert_parameter-result.xml new file mode 100644 index 00000000000..ed2e17d48d3 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/insert_parameter-result.xml @@ -0,0 +1,5 @@ +<dataset> + + <active_rule_parameters id="1" active_rule_id="1" rules_parameter_id="1" rules_parameter_key="max" value="20"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/shared.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/shared.xml new file mode 100644 index 00000000000..b6d5461c10d --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/shared.xml @@ -0,0 +1,22 @@ +<dataset> + + <active_rules created_at="[null]" updated_at="[null]" id="1" profile_id="1" rule_id="10" failure_level="2" + inheritance="INHERITED"/> + + <!-- Parent of Active rule 1 --> + <active_rules created_at="[null]" updated_at="[null]" id="2" profile_id="2" rule_id="10" failure_level="0" + inheritance="[null]"/> + + <active_rules created_at="[null]" updated_at="[null]" id="3" profile_id="2" rule_id="11" failure_level="1" + inheritance="[null]"/> + + <active_rule_parameters id="1" active_rule_id="1" rules_parameter_id="1" rules_parameter_key="max" value="20"/> + <active_rule_parameters id="2" active_rule_id="1" rules_parameter_id="2" rules_parameter_key="format" value="html"/> + + <active_rule_parameters id="3" active_rule_id="2" rules_parameter_id="1" rules_parameter_key="max" value="15"/> + + <rules_profiles id="1" name="Child" language="java" parent_kee="parent" kee="child" is_default="[false]"/> + + <rules_profiles id="2" name="Parent" language="java" parent_kee="[null]" kee="parent" is_default="[false]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/update-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/update-result.xml new file mode 100644 index 00000000000..30111d636a7 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/update-result.xml @@ -0,0 +1,12 @@ +<dataset> + + <active_rules created_at="[null]" updated_at="[null]" id="1" profile_id="1" rule_id="10" failure_level="4" + inheritance="[null]"/> + + <active_rules created_at="[null]" updated_at="[null]" id="2" profile_id="2" rule_id="10" failure_level="0" + inheritance="[null]"/> + + <active_rules created_at="[null]" updated_at="[null]" id="3" profile_id="2" rule_id="11" failure_level="1" + inheritance="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/update_parameter-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/update_parameter-result.xml new file mode 100644 index 00000000000..289da2f39f2 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/update_parameter-result.xml @@ -0,0 +1,8 @@ +<dataset> + + <active_rule_parameters id="1" active_rule_id="2" rules_parameter_id="3" rules_parameter_key="newMax" value="30"/> + <active_rule_parameters id="2" active_rule_id="1" rules_parameter_id="2" rules_parameter_key="format" value="html"/> + + <active_rule_parameters id="3" active_rule_id="2" rules_parameter_id="1" rules_parameter_key="max" value="15"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/QualityProfileDaoTest/delete-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/QualityProfileDaoTest/delete-result.xml new file mode 100644 index 00000000000..fac2543235e --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/QualityProfileDaoTest/delete-result.xml @@ -0,0 +1,6 @@ +<dataset> + + <rules_profiles id="2" name="Sonar Way" language="js" parent_kee="[null]" kee="js_sonar_way" is_default="[false]" + rules_updated_at="[null]" created_at="[null]" updated_at="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/QualityProfileDaoTest/inheritance.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/QualityProfileDaoTest/inheritance.xml new file mode 100644 index 00000000000..4768bc64707 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/QualityProfileDaoTest/inheritance.xml @@ -0,0 +1,23 @@ +<dataset> + + <rules_profiles id="1" name="Child1" language="java" parent_kee="java_parent" kee="java_child1" is_default="[false]" + rules_updated_at="[null]" created_at="[null]" updated_at="[null]"/> + + <rules_profiles id="2" name="Child2" language="java" parent_kee="java_parent" kee="java_child2" is_default="[false]" + rules_updated_at="[null]" created_at="[null]" updated_at="[null]"/> + + <rules_profiles id="3" name="Parent" language="java" parent_kee="[null]" kee="java_parent" is_default="[false]" + rules_updated_at="[null]" created_at="[null]" updated_at="[null]"/> + + <!-- Same profile for another language --> + + <rules_profiles id="4" name="Child1" language="js" parent_kee="js_parent" kee="js_child1" is_default="[false]" + rules_updated_at="[null]" created_at="[null]" updated_at="[null]"/> + + <rules_profiles id="5" name="Child2" language="js" parent_kee="js_parent" kee="js_child2" is_default="[false]" + rules_updated_at="[null]" created_at="[null]" updated_at="[null]"/> + + <rules_profiles id="6" name="Parent" language="js" parent_kee="[null]" kee="js_parent" is_default="[false]" + rules_updated_at="[null]" created_at="[null]" updated_at="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/QualityProfileDaoTest/insert-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/QualityProfileDaoTest/insert-result.xml new file mode 100644 index 00000000000..8a9e9ce1ada --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/QualityProfileDaoTest/insert-result.xml @@ -0,0 +1,13 @@ +<dataset> + + <rules_profiles id="1" name="Sonar Way" language="java" parent_kee="[null]" kee="java_sonar_way" is_default="[true]" + rules_updated_at="[null]" created_at="[null]" updated_at="[null]"/> + + <rules_profiles id="2" name="Sonar Way" language="js" parent_kee="[null]" kee="js_sonar_way" is_default="[false]" + rules_updated_at="[null]" created_at="[null]" updated_at="[null]"/> + + <rules_profiles id="3" name="ABCDE" language="xoo" parent_kee="[null]" kee="abcde" is_default="[false]" + rules_updated_at="[null]" created_at="[null]" updated_at="[null]"/> + + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/QualityProfileDaoTest/projects.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/QualityProfileDaoTest/projects.xml new file mode 100644 index 00000000000..94df8ad98ee --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/QualityProfileDaoTest/projects.xml @@ -0,0 +1,18 @@ +<dataset> + + <rules_profiles id="1" name="Sonar Way" language="java" parent_kee="[null]" kee="java_sonar_way" is_default="[true]" + rules_updated_at="[null]" created_at="[null]" updated_at="[null]"/> + <rules_profiles id="2" name="Sonar Way" language="js" parent_kee="[null]" kee="js_sonar_way" is_default="[true]" + rules_updated_at="[null]" created_at="[null]" updated_at="[null]"/> + + <projects id="1" uuid="A" kee="org.codehaus.sonar:sonar" name="SonarQube" enabled="[true]"/> + <projects id="2" uuid="B" kee="org.codehaus.sonar-plugins.java:java" name="SonarQube Java" enabled="[true]"/> + <projects id="3" uuid="C" kee="disabled:project" name="Disabled Project" enabled="[false]"/> + + <project_qprofiles id="1" project_uuid="A" profile_key="java_sonar_way"/> + <project_qprofiles id="2" project_uuid="B" profile_key="java_sonar_way"/> + <project_qprofiles id="3" project_uuid="A" profile_key="js_sonar_way"/> + <project_qprofiles id="4" project_uuid="B" profile_key="js_sonar_way"/> + <project_qprofiles id="5" project_uuid="C" profile_key="js_sonar_way"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/QualityProfileDaoTest/select_all_is_sorted_by_profile_name.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/QualityProfileDaoTest/select_all_is_sorted_by_profile_name.xml new file mode 100644 index 00000000000..94e35a7f936 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/QualityProfileDaoTest/select_all_is_sorted_by_profile_name.xml @@ -0,0 +1,13 @@ +<dataset> + + <rules_profiles id="3" name="Third" language="js" parent_kee="[null]" kee="js_third" is_default="[false]" + rules_updated_at="[null]" created_at="[null]" updated_at="[null]"/> + + <rules_profiles id="1" name="First" language="js" parent_kee="[null]" kee="js_first" is_default="[false]" + rules_updated_at="[null]" created_at="[null]" updated_at="[null]"/> + + <rules_profiles id="2" name="Second" language="js" parent_kee="[null]" kee="js_second" is_default="[false]" + rules_updated_at="[null]" created_at="[null]" updated_at="[null]"/> + + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/QualityProfileDaoTest/select_by_language.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/QualityProfileDaoTest/select_by_language.xml new file mode 100644 index 00000000000..05dbd930efd --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/QualityProfileDaoTest/select_by_language.xml @@ -0,0 +1,14 @@ +<dataset> + + <rules_profiles id="1" name="Sonar Way 1" language="java" parent_kee="[null]" kee="java_sonar_way" + is_default="[false]" + rules_updated_at="[null]" created_at="[null]" updated_at="[null]"/> + + <rules_profiles id="2" name="Sonar Way" language="js" parent_kee="[null]" kee="js_sonar_way" is_default="[false]" + rules_updated_at="[null]" created_at="[null]" updated_at="[null]"/> + + <rules_profiles id="3" name="Sonar Way 2" language="java" parent_kee="[null]" kee="java_sonar_way2" + is_default="[false]" + rules_updated_at="[null]" created_at="[null]" updated_at="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/QualityProfileDaoTest/shared.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/QualityProfileDaoTest/shared.xml new file mode 100644 index 00000000000..bf8e0113b24 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/QualityProfileDaoTest/shared.xml @@ -0,0 +1,9 @@ +<dataset> + + <rules_profiles id="1" name="Sonar Way" language="java" parent_kee="[null]" kee="java_sonar_way" is_default="[true]" + rules_updated_at="[null]" created_at="[null]" updated_at="[null]"/> + + <rules_profiles id="2" name="Sonar Way" language="js" parent_kee="[null]" kee="js_sonar_way" is_default="[false]" + rules_updated_at="[null]" created_at="[null]" updated_at="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/QualityProfileDaoTest/update-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/QualityProfileDaoTest/update-result.xml new file mode 100644 index 00000000000..3d54167f58d --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/QualityProfileDaoTest/update-result.xml @@ -0,0 +1,10 @@ +<dataset> + + <rules_profiles id="1" name="New Name" language="js" parent_kee="fghij" kee="java_sonar_way" is_default="[false]" + rules_updated_at="[null]" created_at="[null]" updated_at="[null]"/> + + <rules_profiles id="2" name="Sonar Way" language="js" parent_kee="[null]" kee="js_sonar_way" is_default="[false]" + rules_updated_at="[null]" created_at="[null]" updated_at="[null]"/> + + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/empty.xml b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/empty.xml new file mode 100644 index 00000000000..871dedcb5e9 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/empty.xml @@ -0,0 +1,3 @@ +<dataset> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/insert-result.xml b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/insert-result.xml new file mode 100644 index 00000000000..708daeb2aa8 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/insert-result.xml @@ -0,0 +1,15 @@ +<dataset> + + <rules tags="[null]" system_tags="[null]" id="1" plugin_rule_key="NewRuleKey" plugin_name="plugin" name="new name" + description="new description" status="DEPRECATED" + plugin_config_key="NewConfigKey" priority="0" is_template="[true]" language="dart" created_at="2013-12-16" + updated_at="2013-12-17" template_id="3" + note_data="[null]" note_user_login="[null]" note_created_at="[null]" note_updated_at="[null]" + characteristic_id="100" default_characteristic_id="101" + remediation_function="linear" default_remediation_function="linear_offset" + remediation_coeff="1h" default_remediation_coeff="5d" + remediation_offset="5min" default_remediation_offset="10h" + effort_to_fix_description="squid.S115.effortToFix" + /> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/insert_all-result.xml b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/insert_all-result.xml new file mode 100644 index 00000000000..71c46fb15b7 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/insert_all-result.xml @@ -0,0 +1,47 @@ +<!-- + ~ SonarQube, open source software quality management tool. + ~ Copyright (C) 2008-2014 SonarSource + ~ mailto:contact AT sonarsource DOT com + ~ + ~ SonarQube 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. + ~ + ~ SonarQube 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. + --> + +<dataset> + + <rules tags="[null]" system_tags="[null]" id="1" plugin_rule_key="NewRuleKey" plugin_name="plugin" name="new name" + description="new description" status="DEPRECATED" + plugin_config_key="NewConfigKey" priority="0" is_template="[true]" language="dart" created_at="2013-12-16" + updated_at="2013-12-17" template_id="3" + note_data="[null]" note_user_login="[null]" note_created_at="[null]" note_updated_at="[null]" + characteristic_id="100" default_characteristic_id="101" + remediation_function="linear" default_remediation_function="linear_offset" + remediation_coeff="1h" default_remediation_coeff="5d" + remediation_offset="5min" default_remediation_offset="10h" + effort_to_fix_description="squid.S115.effortToFix" + /> + + <rules tags="[null]" system_tags="[null]" id="2" plugin_rule_key="NewRuleKey2" plugin_name="plugin2" name="new name2" + description="new description2" status="BETA" + plugin_config_key="NewConfigKey2" priority="2" is_template="[false]" language="js" created_at="2013-12-14" + updated_at="2013-12-15" template_id="[null]" + note_data="[null]" note_user_login="[null]" note_created_at="[null]" note_updated_at="[null]" + characteristic_id="102" default_characteristic_id="103" + remediation_function="linear_offset" default_remediation_function="linear" + remediation_coeff="5d" default_remediation_coeff="1h" + remediation_offset="10h" default_remediation_offset="5min" + effort_to_fix_description="squid.S115.effortToFix2" + /> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/insert_parameter-result.xml b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/insert_parameter-result.xml new file mode 100644 index 00000000000..5208b7a4a4c --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/insert_parameter-result.xml @@ -0,0 +1,3 @@ +<dataset> + <rules_parameters id="1" rule_id="1" name="max" param_type="INTEGER" default_value="30" description="My Parameter"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/insert_parameter.xml b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/insert_parameter.xml new file mode 100644 index 00000000000..871dedcb5e9 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/insert_parameter.xml @@ -0,0 +1,3 @@ +<dataset> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/selectAll.xml b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/selectAll.xml new file mode 100644 index 00000000000..d957463ec95 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/selectAll.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<dataset> + + <rules tags="[null]" system_tags="[null]" id="1" plugin_rule_key="AvoidNull" plugin_name="checkstyle" + name="Avoid Null" description="Should avoid NULL" status="READY" + note_data="Rule note with accents éèà " note_user_login="polop.palap" note_created_at="2013-12-25" + characteristic_id="100" default_characteristic_id="101" + remediation_function="linear" default_remediation_function="linear_offset" + remediation_coeff="1h" default_remediation_coeff="5d" + remediation_offset="5min" default_remediation_offset="10h" + effort_to_fix_description="squid.S115.effortToFix" + /> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/selectById.xml b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/selectById.xml new file mode 100644 index 00000000000..b4a2a04621d --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/selectById.xml @@ -0,0 +1,8 @@ +<dataset> + + <rules tags="[null]" system_tags="[null]" id="1" plugin_rule_key="AvoidComparison" plugin_name="checkstyle" + name="Avoid Comparison" description="Should avoid ==" status="READY"/> + <rules tags="[null]" system_tags="[null]" id="2" plugin_rule_key="AvoidNull" plugin_name="checkstyle" + name="Avoid Null" description="Should avoid NULL" status="READY"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/selectNonManual.xml b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/selectNonManual.xml new file mode 100644 index 00000000000..22f7c745985 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/selectNonManual.xml @@ -0,0 +1,8 @@ +<dataset> + + <rules tags="[null]" system_tags="[null]" id="1" plugin_rule_key="AvoidNull" plugin_name="checkstyle" + name="Avoid Null" description="Should avoid NULL" status="READY"/> + <rules tags="[null]" system_tags="[null]" id="2" plugin_rule_key="AvoidNull" plugin_name="manual" name="Manual Rule" + description="Should not appear" status="READY"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/selectParameters.xml b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/selectParameters.xml new file mode 100644 index 00000000000..8f5e8a92b95 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/selectParameters.xml @@ -0,0 +1,8 @@ +<dataset> + + <rules tags="[null]" system_tags="[null]" id="1" plugin_rule_key="AvoidNull" plugin_name="checkstyle" + name="Avoid Null" description="Should avoid NULL" status="READY"/> + <rules_parameters id="1" rule_id="1" name="myParameter" param_type="plop" default_value="plouf" + description="My Parameter"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/select_by_name.xml b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/select_by_name.xml new file mode 100644 index 00000000000..b4a2a04621d --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/select_by_name.xml @@ -0,0 +1,8 @@ +<dataset> + + <rules tags="[null]" system_tags="[null]" id="1" plugin_rule_key="AvoidComparison" plugin_name="checkstyle" + name="Avoid Comparison" description="Should avoid ==" status="READY"/> + <rules tags="[null]" system_tags="[null]" id="2" plugin_rule_key="AvoidNull" plugin_name="checkstyle" + name="Avoid Null" description="Should avoid NULL" status="READY"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/select_by_rule_key.xml b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/select_by_rule_key.xml new file mode 100644 index 00000000000..b4a2a04621d --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/select_by_rule_key.xml @@ -0,0 +1,8 @@ +<dataset> + + <rules tags="[null]" system_tags="[null]" id="1" plugin_rule_key="AvoidComparison" plugin_name="checkstyle" + name="Avoid Comparison" description="Should avoid ==" status="READY"/> + <rules tags="[null]" system_tags="[null]" id="2" plugin_rule_key="AvoidNull" plugin_name="checkstyle" + name="Avoid Null" description="Should avoid NULL" status="READY"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/select_by_sub_characteristic_id.xml b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/select_by_sub_characteristic_id.xml new file mode 100644 index 00000000000..1dbd55a539f --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/select_by_sub_characteristic_id.xml @@ -0,0 +1,74 @@ +<dataset> + + <!-- Root characteristic --> + <characteristics id="1" kee="PORTABILITY" name="Portability" parent_id="[null]" characteristic_order="1" + enabled="[true]" + created_at="2013-11-20" updated_at="2013-11-22"/> + + <!-- Sub characteristics of root characteristic --> + <characteristics id="2" kee="COMPILER_RELATED_PORTABILITY" name="Compiler related portability" parent_id="1" + characteristic_order="[null]" + enabled="[true]" + created_at="2013-11-20" updated_at="2013-11-22"/> + <characteristics id="3" kee="HARDWARE_RELATED_PORTABILITY" name="Hardware related portability " parent_id="1" + characteristic_order="[null]" + enabled="[true]" + created_at="2013-11-20" updated_at="2013-11-22"/> + + <!-- Disabled root characteristic --> + <characteristics id="10" kee="DISABLED_ROOT_CHARACTERISTIC" name="Disabled root characteristic" parent_id="[null]" + characteristic_order="2" + enabled="[false]" + created_at="2013-11-20" updated_at="2013-11-22"/> + + <!-- Disabled characteristic --> + <characteristics id="11" kee="DISABLED_CHARACTERISTIC" name="Disabled characteristic" parent_id="10" + characteristic_order="[null]" + enabled="[false]" + created_at="2013-11-20" updated_at="2013-11-22"/> + + <!-- Rule linked to a sub characteristic --> + <rules tags="[null]" system_tags="[null]" id="1" plugin_rule_key="UselessImportCheck" plugin_name="squid" + name="UselessImportCheck" description="Useless imports should be removed" status="READY" + characteristic_id="2" default_characteristic_id="50" + remediation_function="LINEAR_OFFSET" default_remediation_function="LINEAR_OFFSET" + remediation_coeff="5d" default_remediation_coeff="5d" + remediation_offset="10h" default_remediation_offset="10h" updated_at="2014-02-19"/> + + <!-- Rule linked to a sub characteristic --> + <rules tags="[null]" system_tags="[null]" id="2" plugin_rule_key="LeftCurlyBraceStartLineCheck" plugin_name="squid" + name="LeftCurlyBraceStartLineCheck" + description="Left curly braces should be located at the beginning of lines of code" status="READY" + characteristic_id="3" default_characteristic_id="50" + remediation_function="LINEAR_OFFSET" default_remediation_function="LINEAR_OFFSET" + remediation_coeff="5d" default_remediation_coeff="5d" + remediation_offset="10h" default_remediation_offset="10h" updated_at="2014-02-19"/> + + <!-- Rule linked to a disabled sub characteristic -> should never be returned --> + <rules tags="[null]" system_tags="[null]" id="3" plugin_rule_key="CallToFileDeleteOnExitMethod" plugin_name="squid" + name="CallToFileDeleteOnExitMethod" description="CallToFileDeleteOnExitMethod" status="READY" + characteristic_id="11" default_characteristic_id="50" + remediation_function="LINEAR" default_remediation_function="LINEAR_OFFSET" + remediation_coeff="5d" default_remediation_coeff="5d" + remediation_offset="[null]" default_remediation_offset="10h" updated_at="2014-02-19"/> + + <!-- Removed rule linked to one enable sub characteristic --> + <rules tags="[null]" system_tags="[null]" id="4" plugin_rule_key="ObjectFinalizeOverridenCallsSuperFinalizeCheck" + plugin_name="squid" name="ObjectFinalizeOverridenCallsSuperFinalizeCheck" + description="super.finalize() should be called at the end of Object.finalize() implementations" + status="REMOVED" + characteristic_id="3" default_characteristic_id="50" + remediation_function="LINEAR" default_remediation_function="LINEAR_OFFSET" + remediation_coeff="5d" default_remediation_coeff="5min" + remediation_offset="[null]" default_remediation_offset="10h" updated_at="2014-02-19"/> + + <!-- Rule linked to a sub characteristic, but only default characteristic is linked --> + <rules tags="[null]" system_tags="[null]" id="5" plugin_rule_key="RightCurlyBraceStartLineCheck" plugin_name="squid" + name="RightCurlyBraceStartLineCheck" + description="Right curly braces should be located at the beginning of lines of code" status="READY" + characteristic_id="[null]" default_characteristic_id="3" + remediation_function="[null]" default_remediation_function="LINEAR" + remediation_coeff="[null]" default_remediation_coeff="5d" + remediation_offset="[null]" default_remediation_offset="[null]" updated_at="2014-02-19"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/select_enables_and_non_manual.xml b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/select_enables_and_non_manual.xml new file mode 100644 index 00000000000..9d7df0a738b --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/select_enables_and_non_manual.xml @@ -0,0 +1,31 @@ +<dataset> + + <rules tags="[null]" system_tags="[null]" id="1" plugin_rule_key="AvoidNull" plugin_name="checkstyle" + name="Avoid Null" description="Should avoid NULL" status="READY" + note_data="Rule note with accents éèà " note_user_login="polop.palap" note_created_at="2013-12-25" + description_format="HTML" + characteristic_id="100" default_characteristic_id="101" + remediation_function="LINEAR" default_remediation_function="LINEAR_OFFSET" + remediation_coeff="1h" default_remediation_coeff="5d" + remediation_offset="5min" default_remediation_offset="10h" + effort_to_fix_description="squid.S115.effortToFix"/> + + <rules tags="[null]" system_tags="[null]" id="2" plugin_rule_key="AvoidNull" plugin_name="squid" name="Avoid Null" + description="Should avoid NULL" status="REMOVED" + note_data="[null]" note_user_login="[null]" note_created_at="[null]" description_format="HTML" + characteristic_id="[null]" default_characteristic_id="[null]" + remediation_function="[null]" default_remediation_function="[null]" + remediation_coeff="[null]" default_remediation_coeff="[null]" + remediation_offset="[null]" default_remediation_offset="[null]" + effort_to_fix_description="[null]"/> + + <rules tags="[null]" system_tags="[null]" id="3" plugin_rule_key="AvoidNull" plugin_name="manual" name="Manual Rule" + description="Should not appear" status="READY" + note_data="[null]" note_user_login="[null]" note_created_at="[null]" description_format="HTML" + characteristic_id="[null]" default_characteristic_id="[null]" + remediation_function="[null]" default_remediation_function="[null]" + remediation_coeff="[null]" default_remediation_coeff="[null]" + remediation_offset="[null]" default_remediation_offset="[null]" + effort_to_fix_description="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/select_parameters_by_rule_id.xml b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/select_parameters_by_rule_id.xml new file mode 100644 index 00000000000..c137ab0e4cf --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/select_parameters_by_rule_id.xml @@ -0,0 +1,12 @@ +<dataset> + + <rules tags="[null]" system_tags="[null]" id="1" plugin_rule_key="AvoidNull" plugin_name="checkstyle" + name="Avoid Null" description="Should avoid NULL" status="READY"/> + <rules_parameters id="1" rule_id="1" name="myParameter" param_type="plop" default_value="plouf" + description="My Parameter"/> + <rules tags="[null]" system_tags="[null]" id="2" plugin_rule_key="Unused" plugin_name="unused" name="Unused Rule" + description="Not used" status="REMOVED"/> + <rules_parameters id="2" rule_id="2" name="otherParam" param_type="plop" default_value="plouf" + description="Other Parameter"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/select_parameters_by_rule_ids.xml b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/select_parameters_by_rule_ids.xml new file mode 100644 index 00000000000..f2c208ef87b --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/select_parameters_by_rule_ids.xml @@ -0,0 +1,9 @@ +<dataset> + + <rules_parameters id="1" rule_id="1" name="myParameter" param_type="plop" default_value="plouf" + description="My Parameter"/> + + <rules_parameters id="2" rule_id="2" name="otherParam" param_type="plop" default_value="plouf" + description="Other Parameter"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/update-result.xml b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/update-result.xml new file mode 100644 index 00000000000..13a9ef4b6eb --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/update-result.xml @@ -0,0 +1,27 @@ +<dataset> + + <rules tags="[null]" system_tags="[null]" id="1" plugin_rule_key="NewRuleKey" plugin_name="plugin" name="new name" + description="new description" status="DEPRECATED" + plugin_config_key="NewConfigKey" priority="0" is_template="[true]" language="dart" + created_at="2011-04-25 01:05:00" updated_at="2013-12-17" template_id="3" + note_data="My note" note_user_login="admin" note_created_at="2013-12-19" note_updated_at="2013-12-20" + characteristic_id="100" default_characteristic_id="101" + remediation_function="linear" default_remediation_function="linear_offset" + remediation_coeff="1h" default_remediation_coeff="5d" + remediation_offset="5min" default_remediation_offset="10h" + effort_to_fix_description="squid.S115.effortToFix" + /> + + <rules tags="[null]" system_tags="[null]" id="2" plugin_rule_key="Parent1" plugin_name="checkstyle" + name="Parent Rule 1" description="Parent Rule 1" status="READY" + plugin_config_key="Parent1" priority="2" is_template="[false]" language="golo" created_at="1981-10-24 15:20:00" + updated_at="[null]" template_id="[null]" + note_created_at="[null]" note_data="[null]" note_updated_at="[null]" note_user_login="[null]"/> + + <rules tags="[null]" system_tags="[null]" id="3" plugin_rule_key="Parent2" plugin_name="checkstyle" + name="Parent Rule 2" description="Parent Rule 2" status="READY" + plugin_config_key="Parent2" priority="2" is_template="[false]" language="dart" created_at="1982-12-14 03:15:00" + updated_at="[null]" template_id="[null]" + note_created_at="[null]" note_data="[null]" note_updated_at="[null]" note_user_login="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/update.xml b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/update.xml new file mode 100644 index 00000000000..5813974016a --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/update.xml @@ -0,0 +1,18 @@ +<dataset> + + <rules tags="[null]" system_tags="[null]" id="1" plugin_rule_key="AvoidNull" plugin_name="checkstyle" + name="Avoid Null" description="Should avoid NULL" status="READY" + plugin_config_key="AvoidNull" priority="2" is_template="[false]" language="golo" + created_at="2011-04-25 01:05:00" template_id="2"/> + + <rules tags="[null]" system_tags="[null]" id="2" plugin_rule_key="Parent1" plugin_name="checkstyle" + name="Parent Rule 1" description="Parent Rule 1" status="READY" + plugin_config_key="Parent1" priority="2" is_template="[false]" language="golo" + created_at="1981-10-24 15:20:00"/> + + <rules tags="[null]" system_tags="[null]" id="3" plugin_rule_key="Parent2" plugin_name="checkstyle" + name="Parent Rule 2" description="Parent Rule 2" status="READY" + plugin_config_key="Parent2" priority="2" is_template="[false]" language="dart" + created_at="1982-12-14 03:15:00"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/update_parameter-result.xml b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/update_parameter-result.xml new file mode 100644 index 00000000000..25188f3a97e --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/update_parameter-result.xml @@ -0,0 +1,4 @@ +<dataset> + <rules_parameters id="1" rule_id="1" name="format" param_type="STRING" default_value="^[a-z]+(\.[a-z][a-z0-9]*)*$" + description="Regular expression used to check the package names against."/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/update_parameter.xml b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/update_parameter.xml new file mode 100644 index 00000000000..5208b7a4a4c --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/update_parameter.xml @@ -0,0 +1,3 @@ +<dataset> + <rules_parameters id="1" rule_id="1" name="max" param_type="INTEGER" default_value="30" description="My Parameter"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/semaphore/SemaphoreDaoTest/old_semaphore.xml b/sonar-db/src/test/resources/org/sonar/db/semaphore/SemaphoreDaoTest/old_semaphore.xml new file mode 100644 index 00000000000..ac6cf63ee0e --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/semaphore/SemaphoreDaoTest/old_semaphore.xml @@ -0,0 +1,4 @@ +<dataset> + <semaphores id="1" name="foo" checksum="acbd18db4cc2f85cedef654fccc4a4d8" created_at="1264374000000" + updated_at="1264374000000" locked_at="1264374000000"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/AuthorDaoTest/add_missing_module_uuid_path-result.xml b/sonar-db/src/test/resources/org/sonar/db/user/AuthorDaoTest/add_missing_module_uuid_path-result.xml new file mode 100644 index 00000000000..912c502b3f9 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/AuthorDaoTest/add_missing_module_uuid_path-result.xml @@ -0,0 +1,9 @@ +<dataset> + <projects id="1" name="developer@company.net" qualifier="DEV" uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" + module_uuid_path=".ABCD."/> + <authors id="1" person_id="1" login="developer@company.net"/> + + <projects id="2" name="developer2@company.net" qualifier="DEV" uuid="BCDE" project_uuid="BCDE" module_uuid="[null]" + module_uuid_path=".BCDE."/> + <authors id="2" person_id="2" login="developer2@company.net"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/AuthorDaoTest/add_missing_module_uuid_path.xml b/sonar-db/src/test/resources/org/sonar/db/user/AuthorDaoTest/add_missing_module_uuid_path.xml new file mode 100644 index 00000000000..fb0854fccbe --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/AuthorDaoTest/add_missing_module_uuid_path.xml @@ -0,0 +1,2 @@ +<dataset> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/AuthorDaoTest/countDeveloperLogins.xml b/sonar-db/src/test/resources/org/sonar/db/user/AuthorDaoTest/countDeveloperLogins.xml new file mode 100644 index 00000000000..42776255866 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/AuthorDaoTest/countDeveloperLogins.xml @@ -0,0 +1,7 @@ +<dataset> + + <authors id="1" person_id="1" login="godin"/> + <authors id="2" person_id="1" login="evgeny"/> + <authors id="3" person_id="2" login="simon"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/AuthorDaoTest/shouldInsertAuthor-result.xml b/sonar-db/src/test/resources/org/sonar/db/user/AuthorDaoTest/shouldInsertAuthor-result.xml new file mode 100644 index 00000000000..40e855c7588 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/AuthorDaoTest/shouldInsertAuthor-result.xml @@ -0,0 +1,8 @@ +<dataset> + + <authors + id="1" + person_id="13" + login="godin"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/AuthorDaoTest/shouldInsertAuthor.xml b/sonar-db/src/test/resources/org/sonar/db/user/AuthorDaoTest/shouldInsertAuthor.xml new file mode 100644 index 00000000000..fb0854fccbe --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/AuthorDaoTest/shouldInsertAuthor.xml @@ -0,0 +1,2 @@ +<dataset> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/AuthorDaoTest/shouldInsertAuthorAndDeveloper-result.xml b/sonar-db/src/test/resources/org/sonar/db/user/AuthorDaoTest/shouldInsertAuthorAndDeveloper-result.xml new file mode 100644 index 00000000000..c7c3436d390 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/AuthorDaoTest/shouldInsertAuthorAndDeveloper-result.xml @@ -0,0 +1,5 @@ +<dataset> + <projects id="1" name="developer@company.net" qualifier="DEV" uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" + module_uuid_path="."/> + <authors id="1" person_id="1" login="developer@company.net"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/AuthorDaoTest/shouldInsertAuthorAndDeveloper.xml b/sonar-db/src/test/resources/org/sonar/db/user/AuthorDaoTest/shouldInsertAuthorAndDeveloper.xml new file mode 100644 index 00000000000..fb0854fccbe --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/AuthorDaoTest/shouldInsertAuthorAndDeveloper.xml @@ -0,0 +1,2 @@ +<dataset> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/AuthorDaoTest/shouldPreventAuthorsAndDevelopersDuplication-result.xml b/sonar-db/src/test/resources/org/sonar/db/user/AuthorDaoTest/shouldPreventAuthorsAndDevelopersDuplication-result.xml new file mode 100644 index 00000000000..ddca7b45c66 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/AuthorDaoTest/shouldPreventAuthorsAndDevelopersDuplication-result.xml @@ -0,0 +1,8 @@ +<dataset> + + <projects id="1" name="developer@company.net" qualifier="DEV" uuid="[null]" project_uuid="[null]" module_uuid="[null]" + module_uuid_path="."/> + + <authors id="1" person_id="1" login="developer@company.net"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/AuthorDaoTest/shouldPreventAuthorsAndDevelopersDuplication.xml b/sonar-db/src/test/resources/org/sonar/db/user/AuthorDaoTest/shouldPreventAuthorsAndDevelopersDuplication.xml new file mode 100644 index 00000000000..ddca7b45c66 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/AuthorDaoTest/shouldPreventAuthorsAndDevelopersDuplication.xml @@ -0,0 +1,8 @@ +<dataset> + + <projects id="1" name="developer@company.net" qualifier="DEV" uuid="[null]" project_uuid="[null]" module_uuid="[null]" + module_uuid_path="."/> + + <authors id="1" person_id="1" login="developer@company.net"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/AuthorDaoTest/shouldPreventAuthorsDuplication-result.xml b/sonar-db/src/test/resources/org/sonar/db/user/AuthorDaoTest/shouldPreventAuthorsDuplication-result.xml new file mode 100644 index 00000000000..8203f8edbc2 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/AuthorDaoTest/shouldPreventAuthorsDuplication-result.xml @@ -0,0 +1,5 @@ +<dataset> + + <authors id="1" person_id="10" login="godin"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/AuthorDaoTest/shouldPreventAuthorsDuplication.xml b/sonar-db/src/test/resources/org/sonar/db/user/AuthorDaoTest/shouldPreventAuthorsDuplication.xml new file mode 100644 index 00000000000..8203f8edbc2 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/AuthorDaoTest/shouldPreventAuthorsDuplication.xml @@ -0,0 +1,5 @@ +<dataset> + + <authors id="1" person_id="10" login="godin"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/AuthorDaoTest/shouldSelectByLogin.xml b/sonar-db/src/test/resources/org/sonar/db/user/AuthorDaoTest/shouldSelectByLogin.xml new file mode 100644 index 00000000000..40e855c7588 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/AuthorDaoTest/shouldSelectByLogin.xml @@ -0,0 +1,8 @@ +<dataset> + + <authors + id="1" + person_id="13" + login="godin"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/anonymous_should_be_authorized.xml b/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/anonymous_should_be_authorized.xml new file mode 100644 index 00000000000..f5730087a21 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/anonymous_should_be_authorized.xml @@ -0,0 +1,14 @@ +<dataset> + + <user_roles id="1" user_id="100" resource_id="999" role="user"/> + <groups_users user_id="100" group_id="200"/> + <group_roles id="1" group_id="[null]" resource_id="300" role="user"/> + <group_roles id="2" group_id="[null]" resource_id="400" role="user"/> + + <projects id="301" kee="pj-w-snapshot:package" root_id="300" uuid="ABCD" module_uuid="EDFG"/> + <projects id="302" kee="pj-w-snapshot:file" root_id="300" uuid="BCDE" module_uuid="EDFG"/> + <projects id="303" kee="pj-w-snapshot:other" root_id="300" uuid="CDEF" module_uuid="EDFG"/> + <projects id="300" kee="pj-w-snapshot" uuid="EDFG" module_uuid="[null]"/> + <projects id="400" kee="pj-wo-snapshot" uuid="FGHI" project_uuid="FGHI"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/group_should_be_authorized.xml b/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/group_should_be_authorized.xml new file mode 100644 index 00000000000..7ffca0d6f5e --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/group_should_be_authorized.xml @@ -0,0 +1,16 @@ +<dataset> + + <!-- user 100 has no direct grant access, but is in the group 200 that has the role "user" + on the project 300 --> + <user_roles id="1" user_id="100" resource_id="999" role="user"/> + <groups_users user_id="100" group_id="200"/> + <group_roles id="1" group_id="200" resource_id="300" role="user"/> + <group_roles id="2" group_id="200" resource_id="400" role="user"/> + + <projects id="301" kee="pj-w-snapshot:package" root_id="300" uuid="ABCD" module_uuid="DEFG"/> + <projects id="302" kee="pj-w-snapshot:file" root_id="300" uuid="BCDE" module_uuid="DEFG"/> + <projects id="303" kee="pj-w-snapshot:other" root_id="300" uuid="CDEF" module_uuid="DEFG"/> + <projects id="300" kee="pj-w-snapshot" uuid="DEFG" module_uuid="[null]"/> + <projects id="400" kee="pj-wo-snapshot" uuid="EFGH" module_uuid="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/is_authorized_component_key_for_global_permission.xml b/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/is_authorized_component_key_for_global_permission.xml new file mode 100644 index 00000000000..c5cd325ea5e --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/is_authorized_component_key_for_global_permission.xml @@ -0,0 +1,15 @@ +<dataset> + + <!-- user 100 has no direct grant access, but is in the group 200 that has the role "user" + on the all the projects --> + <user_roles id="1" user_id="100" resource_id="999" role="user"/> + <groups_users user_id="100" group_id="200"/> + <group_roles id="1" group_id="200" resource_id="[null]" role="user"/> + + <projects id="301" kee="pj-w-snapshot:package" root_id="300" uuid="ABCD" module_uuid="DEFG"/> + <projects id="302" kee="pj-w-snapshot:file" root_id="300" uuid="BCDE" module_uuid="DEFG"/> + <projects id="303" kee="pj-w-snapshot:other" root_id="300" uuid="CDEF" module_uuid="DEFG"/> + <projects id="300" kee="pj-w-snapshot" uuid="DEFG" module_uuid="[null]"/> + <projects id="400" kee="pj-wo-snapshot" uuid="EFGH" module_uuid="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/keep_authorized_project_ids_for_anonymous.xml b/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/keep_authorized_project_ids_for_anonymous.xml new file mode 100644 index 00000000000..1c21104a7b6 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/keep_authorized_project_ids_for_anonymous.xml @@ -0,0 +1,10 @@ +<dataset> + + <groups_users user_id="100" group_id="200"/> + <group_roles id="1" group_id="[null]" resource_id="300" role="user"/> + <group_roles id="2" group_id="200" resource_id="400" role="codeviewer"/> + + <projects id="300" kee="pj-w-snapshot" uuid="DEFG" module_uuid="[null]" enabled="[true]"/> + <projects id="400" kee="pj-wo-snapshot" uuid="EFGH" module_uuid="[null]" enabled="[true]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/keep_authorized_project_ids_for_group.xml b/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/keep_authorized_project_ids_for_group.xml new file mode 100644 index 00000000000..17e6323ccd6 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/keep_authorized_project_ids_for_group.xml @@ -0,0 +1,10 @@ +<dataset> + + <groups_users user_id="100" group_id="200"/> + <group_roles id="1" group_id="200" resource_id="300" role="user"/> + <group_roles id="2" group_id="200" resource_id="400" role="codeviewer"/> + + <projects id="300" kee="pj-w-snapshot" uuid="DEFG" module_uuid="[null]" enabled="[true]"/> + <projects id="400" kee="pj-wo-snapshot" uuid="EFGH" module_uuid="[null]" enabled="[true]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/keep_authorized_project_ids_for_user.xml b/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/keep_authorized_project_ids_for_user.xml new file mode 100644 index 00000000000..515adaa8f48 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/keep_authorized_project_ids_for_user.xml @@ -0,0 +1,10 @@ +<dataset> + + <!-- user 100 has the role "user" on the project 300 --> + <user_roles id="1" user_id="100" resource_id="300" role="user"/> + <user_roles id="2" user_id="100" resource_id="400" role="codeviewer"/> + + <projects id="300" kee="pj-w-snapshot" uuid="DEFG" module_uuid="[null]" enabled="[true]"/> + <projects id="400" kee="pj-wo-snapshot" uuid="EFGH" module_uuid="[null]" enabled="[true]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/should_return_global_permissions_for_anonymous.xml b/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/should_return_global_permissions_for_anonymous.xml new file mode 100644 index 00000000000..515b647b270 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/should_return_global_permissions_for_anonymous.xml @@ -0,0 +1,11 @@ +<dataset> + + <user_roles id="1" user_id="100" resource_id="[null]" role="user"/> + + <groups_users user_id="1" group_id="200"/> + <groups_users user_id="1" group_id="201"/> + + <group_roles id="200" group_id="[null]" resource_id="[null]" role="user"/> + <group_roles id="201" group_id="[null]" resource_id="[null]" role="admin"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/should_return_global_permissions_for_group_anyone.xml b/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/should_return_global_permissions_for_group_anyone.xml new file mode 100644 index 00000000000..bd166a7e669 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/should_return_global_permissions_for_group_anyone.xml @@ -0,0 +1,11 @@ +<dataset> + + <users id="10" login="anyone_user"/> + + <user_roles id="1" user_id="10" resource_id="[null]" role="user"/> + + <groups_users user_id="10" group_id="[null]"/> + + <group_roles id="1" group_id="[null]" resource_id="[null]" role="profileadmin"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/should_return_group_global_permissions.xml b/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/should_return_group_global_permissions.xml new file mode 100644 index 00000000000..0ff49e9417c --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/should_return_group_global_permissions.xml @@ -0,0 +1,18 @@ +<dataset> + + <!-- user 10 has no direct grant access, but is in the 'user' group 200 and in the 'admin' group 201 --> + <users id="10" login="john"/> + <!-- user 11 has no direct grant access, but is in the 'user' group 200 --> + <users id="11" login="arthur"/> + + <user_roles id="1" user_id="999" resource_id="[null]" role="user"/> + <user_roles id="2" user_id="999" resource_id="[null]" role="user"/> + + <groups_users user_id="10" group_id="200"/> + <groups_users user_id="10" group_id="201"/> + <groups_users user_id="11" group_id="200"/> + + <group_roles id="1" group_id="200" resource_id="[null]" role="user"/> + <group_roles id="2" group_id="201" resource_id="[null]" role="admin"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/should_return_root_project_keys_for_anonymous.xml b/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/should_return_root_project_keys_for_anonymous.xml new file mode 100644 index 00000000000..a1aa1f05a76 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/should_return_root_project_keys_for_anonymous.xml @@ -0,0 +1,16 @@ +<dataset> + + <user_roles id="1" user_id="100" resource_id="999" role="user"/> + <groups_users user_id="100" group_id="200"/> + <group_roles id="1" group_id="[null]" resource_id="300" role="user"/> + + <projects id="300" uuid="ABCD" module_uuid="[null]" kee="pj-w-snapshot" scope="PRJ" qualifier="TRK" enabled="[true]"/> + <projects id="301" uuid="BCDE" module_uuid="[null]" kee="pj-w-snapshot1" scope="PRJ" qualifier="TRK" + enabled="[true]"/> + <projects id="302" uuid="CDEF" module_uuid="[null]" kee="pj-w-snapshot2" scope="PRJ" qualifier="TRK" + enabled="[true]"/> + + <projects id="303" uuid="DEFG" module_uuid="[null]" kee="pj-w-snapshot3" scope="PRJ" qualifier="TRK" + enabled="[true]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/should_return_root_project_keys_for_group.xml b/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/should_return_root_project_keys_for_group.xml new file mode 100644 index 00000000000..93682166701 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/should_return_root_project_keys_for_group.xml @@ -0,0 +1,18 @@ +<dataset> + + <!-- user 100 has no direct grant access, but is in the group 200 that has the role "user" + on the project 300 --> + <user_roles id="1" user_id="100" resource_id="999" role="user"/> + <groups_users user_id="100" group_id="200"/> + <group_roles id="1" group_id="200" resource_id="300" role="user"/> + + <projects id="300" uuid="ABCD" module_uuid="[null]" kee="pj-w-snapshot" scope="PRJ" qualifier="TRK" enabled="[true]"/> + <projects id="301" uuid="BCDE" module_uuid="[null]" kee="pj-w-snapshot1" scope="PRJ" qualifier="TRK" + enabled="[true]"/> + <projects id="302" uuid="CDEF" module_uuid="[null]" kee="pj-w-snapshot2" scope="PRJ" qualifier="TRK" + enabled="[true]"/> + + <projects id="303" uuid="DEFG" module_uuid="[null]" kee="pj-w-snapshot3" scope="PRJ" qualifier="TRK" + enabled="[true]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/should_return_root_project_keys_for_user.xml b/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/should_return_root_project_keys_for_user.xml new file mode 100644 index 00000000000..060223cdfbd --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/should_return_root_project_keys_for_user.xml @@ -0,0 +1,17 @@ +<dataset> + + <!-- user 100 has the role "user" on the project 300 and in group 200 --> + <user_roles id="1" user_id="100" resource_id="300" role="user"/> + <groups_users user_id="100" group_id="200"/> + <group_roles id="1" group_id="200" resource_id="999" role="user"/> + + <projects id="300" uuid="ABCD" module_uuid="[null]" kee="pj-w-snapshot" scope="PRJ" qualifier="TRK" enabled="[true]"/> + <projects id="301" uuid="BCDE" module_uuid="[null]" kee="pj-w-snapshot1" scope="PRJ" qualifier="TRK" + enabled="[true]"/> + <projects id="302" uuid="CDEF" module_uuid="[null]" kee="pj-w-snapshot2" scope="PRJ" qualifier="TRK" + enabled="[true]"/> + + <projects id="303" uuid="DEFG" module_uuid="[null]" kee="pj-w-snapshot3" scope="PRJ" qualifier="TRK" + enabled="[true]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/should_return_user_global_permissions.xml b/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/should_return_user_global_permissions.xml new file mode 100644 index 00000000000..5b8e83ba208 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/should_return_user_global_permissions.xml @@ -0,0 +1,18 @@ +<dataset> + + <!-- user 10 has no group, but has direct role 'user' and 'admin' --> + <users id="10" login="john"/> + <!-- user 11 has no group, but has direct role 'user' --> + <users id="11" login="arthur"/> + + <user_roles id="1" user_id="10" resource_id="[null]" role="user"/> + <user_roles id="2" user_id="10" resource_id="[null]" role="admin"/> + <user_roles id="3" user_id="11" resource_id="[null]" role="user"/> + + <groups_users user_id="999" group_id="200"/> + <groups_users user_id="999" group_id="201"/> + + <group_roles id="200" group_id="200" resource_id="[null]" role="user"/> + <group_roles id="201" group_id="200" resource_id="[null]" role="admin"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/user_should_be_authorized.xml b/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/user_should_be_authorized.xml new file mode 100644 index 00000000000..3771e09738d --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/AuthorizationDaoTest/user_should_be_authorized.xml @@ -0,0 +1,11 @@ +<dataset> + + <!-- user 100 has the role "user" on the project 300 and in group 200 --> + <user_roles id="1" user_id="100" resource_id="300" role="user"/> + <user_roles id="2" user_id="100" resource_id="400" role="user"/> + <groups_users user_id="100" group_id="200"/> + <group_roles id="1" group_id="200" resource_id="999" role="user"/> + + <projects id="300" kee="pj-w-snapshot" uuid="DEFG" module_uuid="[null]"/> + <projects id="400" kee="pj-wo-snapshot" uuid="EFGH" module_uuid="[null]"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/GroupMembershipDaoTest/select_user_group.xml b/sonar-db/src/test/resources/org/sonar/db/user/GroupMembershipDaoTest/select_user_group.xml new file mode 100644 index 00000000000..5993aae1121 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/GroupMembershipDaoTest/select_user_group.xml @@ -0,0 +1,7 @@ +<dataset> + + <groups id="101" name="sonar-users" description="Any new users created will automatically join this group"/> + + <groups_users user_id="201" group_id="101"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/GroupMembershipDaoTest/shared.xml b/sonar-db/src/test/resources/org/sonar/db/user/GroupMembershipDaoTest/shared.xml new file mode 100644 index 00000000000..a882f396f6c --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/GroupMembershipDaoTest/shared.xml @@ -0,0 +1,19 @@ +<dataset> + + <groups id="100" name="sonar-administrators" description="System administrators"/> + <groups id="101" name="sonar-users" description="Any new users created will automatically join this group"/> + <groups id="102" name="sonar-reviewers" description="Reviewers"/> + + <!-- user 200 is in all groups --> + <groups_users user_id="200" group_id="100"/> + <groups_users user_id="200" group_id="101"/> + <groups_users user_id="200" group_id="102"/> + + <!-- user 201 is in users group --> + <groups_users user_id="201" group_id="101"/> + + <users id="200" login="two-hundred"/> + <users id="201" login="two-hundred-one"/> + <users id="202" login="two-hundred-two"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/GroupMembershipDaoTest/shared_plus_empty_group.xml b/sonar-db/src/test/resources/org/sonar/db/user/GroupMembershipDaoTest/shared_plus_empty_group.xml new file mode 100644 index 00000000000..36b89224326 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/GroupMembershipDaoTest/shared_plus_empty_group.xml @@ -0,0 +1,20 @@ +<dataset> + + <groups id="100" name="sonar-administrators" description="System administrators"/> + <groups id="101" name="sonar-users" description="Any new users created will automatically join this group"/> + <groups id="102" name="sonar-reviewers" description="Reviewers"/> + <groups id="103" name="sonar-nobody" description="Nobody in this group"/> + + <!-- user 200 is in all groups --> + <groups_users user_id="200" group_id="100"/> + <groups_users user_id="200" group_id="101"/> + <groups_users user_id="200" group_id="102"/> + + <!-- user 201 is in users group --> + <groups_users user_id="201" group_id="101"/> + + <users id="200" login="admin" name="Admin" active="[true]"/> + <users id="201" login="not.admin" name="Not Admin" active="[true]"/> + <users id="202" login="inactive" name="Inactive" active="[false]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/GroupMembershipDaoTest/should_be_sorted_by_group_name.xml b/sonar-db/src/test/resources/org/sonar/db/user/GroupMembershipDaoTest/should_be_sorted_by_group_name.xml new file mode 100644 index 00000000000..baaecdb40d4 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/GroupMembershipDaoTest/should_be_sorted_by_group_name.xml @@ -0,0 +1,12 @@ +<dataset> + + <groups id="100" name="sonar-users" description="Any new users created will automatically join this group"/> + <groups id="101" name="sonar-administrators" description="System administrators"/>/> + <groups id="102" name="sonar-reviewers" description="Reviewers"/> + + <!-- user 200 is in all groups --> + <groups_users user_id="200" group_id="100"/> + <groups_users user_id="200" group_id="101"/> + <groups_users user_id="200" group_id="102"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/RoleDaoTest/deleteGroupPermissionsByGroupId-result.xml b/sonar-db/src/test/resources/org/sonar/db/user/RoleDaoTest/deleteGroupPermissionsByGroupId-result.xml new file mode 100644 index 00000000000..a9effb1ea47 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/RoleDaoTest/deleteGroupPermissionsByGroupId-result.xml @@ -0,0 +1,13 @@ +<dataset> + + <groups id="100" name="sonar-administrators"/> + <groups id="101" name="sonar-users"/> + + <group_roles id="4" group_id="101" role="shareDashboard" resource_id="[null]"/> + + <group_roles id="5" group_id="[null]" role="scan" resource_id="[null]"/> + <group_roles id="6" group_id="[null]" role="dryRunScan" resource_id="[null]"/> + + <group_roles id="7" group_id="102" role="admin" resource_id="1"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/RoleDaoTest/deleteGroupPermissionsByGroupId.xml b/sonar-db/src/test/resources/org/sonar/db/user/RoleDaoTest/deleteGroupPermissionsByGroupId.xml new file mode 100644 index 00000000000..f05b0aebecf --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/RoleDaoTest/deleteGroupPermissionsByGroupId.xml @@ -0,0 +1,18 @@ +<dataset> + + <groups id="100" name="sonar-administrators"/> + <groups id="101" name="sonar-users"/> + + <!-- All 3 lines with group_id 100 will be deleted --> + <group_roles id="1" group_id="100" role="admin" resource_id="[null]"/> + <group_roles id="2" group_id="100" role="profileadmin" resource_id="1"/> + <group_roles id="3" group_id="100" role="shareDashboard" resource_id="[null]"/> + + <group_roles id="4" group_id="101" role="shareDashboard" resource_id="[null]"/> + + <group_roles id="5" group_id="[null]" role="scan" resource_id="[null]"/> + <group_roles id="6" group_id="[null]" role="dryRunScan" resource_id="[null]"/> + + <group_roles id="7" group_id="102" role="admin" resource_id="1"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/RoleDaoTest/globalGroupPermissions-result.xml b/sonar-db/src/test/resources/org/sonar/db/user/RoleDaoTest/globalGroupPermissions-result.xml new file mode 100644 index 00000000000..d87bfe95e07 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/RoleDaoTest/globalGroupPermissions-result.xml @@ -0,0 +1,16 @@ +<dataset> + + <groups id="100" name="sonar-administrators"/> + <groups id="101" name="sonar-users"/> + + <group_roles id="1" group_id="100" role="admin" resource_id="[null]"/> + <group_roles id="3" group_id="100" role="shareDashboard" resource_id="[null]"/> + <group_roles id="4" group_id="101" role="shareDashboard" resource_id="[null]"/> + + <!-- Group 'anyone' has a NULL group_id --> + <group_roles id="5" group_id="[null]" role="scan" resource_id="[null]"/> + <group_roles id="6" group_id="[null]" role="dryRunScan" resource_id="[null]"/> + + <group_roles id="7" group_id="102" role="admin" resource_id="1"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/RoleDaoTest/globalGroupPermissions.xml b/sonar-db/src/test/resources/org/sonar/db/user/RoleDaoTest/globalGroupPermissions.xml new file mode 100644 index 00000000000..2e76afcd3be --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/RoleDaoTest/globalGroupPermissions.xml @@ -0,0 +1,18 @@ +<dataset> + + <groups id="100" name="sonar-administrators"/> + <groups id="101" name="sonar-users"/> + + <group_roles id="1" group_id="100" role="admin" resource_id="[null]"/> + <group_roles id="2" group_id="100" role="profileadmin" resource_id="[null]"/> + <group_roles id="3" group_id="100" role="shareDashboard" resource_id="[null]"/> + <group_roles id="4" group_id="101" role="shareDashboard" resource_id="[null]"/> + + <!-- Group 'anyone' has a NULL group_id --> + <group_roles id="5" group_id="[null]" role="scan" resource_id="[null]"/> + <group_roles id="6" group_id="[null]" role="dryRunScan" resource_id="[null]"/> + + <!-- Component permission, it should not be returned with global permissions --> + <group_roles id="7" group_id="102" role="admin" resource_id="1"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/RoleDaoTest/globalUserPermissions-result.xml b/sonar-db/src/test/resources/org/sonar/db/user/RoleDaoTest/globalUserPermissions-result.xml new file mode 100644 index 00000000000..5fd4509c330 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/RoleDaoTest/globalUserPermissions-result.xml @@ -0,0 +1,11 @@ +<dataset> + + <users id="200" login="admin_user" name="admin_user" active="[true]"/> + <users id="201" login="profile_admin_user" name="profile_admin_user" active="[true]"/> + + <user_roles id="1" user_id="200" role="admin" resource_id="[null]"/> + <user_roles id="3" user_id="201" role="profileadmin" resource_id="[null]"/> + + <user_roles id="4" user_id="200" role="admin" resource_id="1"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/RoleDaoTest/globalUserPermissions.xml b/sonar-db/src/test/resources/org/sonar/db/user/RoleDaoTest/globalUserPermissions.xml new file mode 100644 index 00000000000..4d95c91f03d --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/RoleDaoTest/globalUserPermissions.xml @@ -0,0 +1,13 @@ +<dataset> + + <users id="200" login="admin_user" name="admin_user" active="[true]"/> + <users id="201" login="profile_admin_user" name="profile_admin_user" active="[true]"/> + + <user_roles id="1" user_id="200" role="admin" resource_id="[null]"/> + <user_roles id="2" user_id="200" role="profileadmin" resource_id="[null]"/> + <user_roles id="3" user_id="201" role="profileadmin" resource_id="[null]"/> + + <!-- Component permission, it should not be returned with global permissions --> + <user_roles id="4" user_id="200" role="admin" resource_id="1"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/RoleDaoTest/resourceGroupPermissions-result.xml b/sonar-db/src/test/resources/org/sonar/db/user/RoleDaoTest/resourceGroupPermissions-result.xml new file mode 100644 index 00000000000..71650eb675a --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/RoleDaoTest/resourceGroupPermissions-result.xml @@ -0,0 +1,14 @@ +<dataset> + + <groups id="100" name="sonar-administrators"/> + <groups id="101" name="sonar-users"/> + + <group_roles id="1" group_id="100" role="admin" resource_id="1"/> + <group_roles id="3" group_id="101" role="codeviewer" resource_id="1"/> + + <!-- Group 'anyone' has a NULL group_id --> + <group_roles id="4" group_id="[null]" role="user" resource_id="1"/> + + <group_roles id="5" group_id="100" role="admin" resource_id="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/RoleDaoTest/resourceGroupPermissions.xml b/sonar-db/src/test/resources/org/sonar/db/user/RoleDaoTest/resourceGroupPermissions.xml new file mode 100644 index 00000000000..8fb07128af7 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/RoleDaoTest/resourceGroupPermissions.xml @@ -0,0 +1,16 @@ +<dataset> + + <groups id="100" name="sonar-administrators"/> + <groups id="101" name="sonar-users"/> + + <group_roles id="1" group_id="100" role="admin" resource_id="1"/> + <group_roles id="2" group_id="100" role="codeviewer" resource_id="1"/> + <group_roles id="3" group_id="101" role="codeviewer" resource_id="1"/> + + <!-- Group 'anyone' has a NULL group_id --> + <group_roles id="4" group_id="[null]" role="user" resource_id="1"/> + + <!-- Global permission, it should not be returned with component permissions --> + <group_roles id="5" group_id="100" role="admin" resource_id="[null]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/RoleDaoTest/resourceUserPermissions-result.xml b/sonar-db/src/test/resources/org/sonar/db/user/RoleDaoTest/resourceUserPermissions-result.xml new file mode 100644 index 00000000000..7e0ac55287b --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/RoleDaoTest/resourceUserPermissions-result.xml @@ -0,0 +1,11 @@ +<dataset> + + <users id="200" login="admin_user" name="admin_user" active="[true]"/> + <users id="201" login="browse_admin_user" name="browse_admin_user" active="[true]"/> + + <user_roles id="1" user_id="200" role="admin" resource_id="1"/> + <user_roles id="3" user_id="201" role="user" resource_id="1"/> + + <user_roles id="4" user_id="200" role="admin"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/RoleDaoTest/resourceUserPermissions.xml b/sonar-db/src/test/resources/org/sonar/db/user/RoleDaoTest/resourceUserPermissions.xml new file mode 100644 index 00000000000..a5f72708fb6 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/RoleDaoTest/resourceUserPermissions.xml @@ -0,0 +1,13 @@ +<dataset> + + <users id="200" login="admin_user" name="admin_user" active="[true]"/> + <users id="201" login="browse_admin_user" name="browse_admin_user" active="[true]"/> + + <user_roles id="1" user_id="200" role="admin" resource_id="1"/> + <user_roles id="2" user_id="200" role="user" resource_id="1"/> + <user_roles id="3" user_id="201" role="user" resource_id="1"/> + + <!-- Global permission, it should not be returned with component permissions --> + <user_roles id="4" user_id="200" role="admin"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/RoleMapperTest/countRoles.xml b/sonar-db/src/test/resources/org/sonar/db/user/RoleMapperTest/countRoles.xml new file mode 100644 index 00000000000..ec1ed3b076f --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/RoleMapperTest/countRoles.xml @@ -0,0 +1,14 @@ +<dataset> + <groups id="100" name="sonar-administrators"/> + <groups id="101" name="sonar-users"/> + <users id="200" login="marius" name="Marius" email="[null]" active="[true]"/> + + <group_roles id="1" group_id="100" resource_id="123" role="admin"/> + <group_roles id="2" group_id="[null]" resource_id="123" role="user"/> + <user_roles id="1" user_id="200" resource_id="123" role="codeviewer"/> + + <!-- other resource --> + <group_roles id="3" group_id="101" resource_id="999" role="codeviewer"/> + <user_roles id="2" user_id="200" resource_id="999" role="codeviewer"/> + +</dataset>
\ No newline at end of file diff --git a/sonar-db/src/test/resources/org/sonar/db/user/RoleMapperTest/deleteRolesByResourceId-result.xml b/sonar-db/src/test/resources/org/sonar/db/user/RoleMapperTest/deleteRolesByResourceId-result.xml new file mode 100644 index 00000000000..dae82ddd8f8 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/RoleMapperTest/deleteRolesByResourceId-result.xml @@ -0,0 +1,14 @@ +<dataset> + <groups id="100" name="sonar-administrators"/> + <groups id="101" name="sonar-users"/> + <users id="200" login="marius" name="Marius" email="[null]" active="[true]"/> + + <!--<group_roles id="1" group_id="100" resource_id="123" role="admin"/>--> + <!--<group_roles id="2" group_id="[null]" resource_id="123" role="user"/>--> + <!--<user_roles id="1" user_id="200" resource_id="123" role="codeviewer"/>--> + + <!-- other resource --> + <group_roles id="3" group_id="101" resource_id="999" role="codeviewer"/> + <user_roles id="2" user_id="200" resource_id="999" role="codeviewer"/> + +</dataset>
\ No newline at end of file diff --git a/sonar-db/src/test/resources/org/sonar/db/user/RoleMapperTest/deleteRolesByResourceId.xml b/sonar-db/src/test/resources/org/sonar/db/user/RoleMapperTest/deleteRolesByResourceId.xml new file mode 100644 index 00000000000..ec1ed3b076f --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/RoleMapperTest/deleteRolesByResourceId.xml @@ -0,0 +1,14 @@ +<dataset> + <groups id="100" name="sonar-administrators"/> + <groups id="101" name="sonar-users"/> + <users id="200" login="marius" name="Marius" email="[null]" active="[true]"/> + + <group_roles id="1" group_id="100" resource_id="123" role="admin"/> + <group_roles id="2" group_id="[null]" resource_id="123" role="user"/> + <user_roles id="1" user_id="200" resource_id="123" role="codeviewer"/> + + <!-- other resource --> + <group_roles id="3" group_id="101" resource_id="999" role="codeviewer"/> + <user_roles id="2" user_id="200" resource_id="999" role="codeviewer"/> + +</dataset>
\ No newline at end of file diff --git a/sonar-db/src/test/resources/org/sonar/db/user/RoleMapperTest/insertRoles-result.xml b/sonar-db/src/test/resources/org/sonar/db/user/RoleMapperTest/insertRoles-result.xml new file mode 100644 index 00000000000..7a7e6f8e196 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/RoleMapperTest/insertRoles-result.xml @@ -0,0 +1,11 @@ +<dataset> + <groups id="100" name="sonar-administrators"/> + <groups id="101" name="sonar-users"/> + <users id="200" login="marius" name="Marius" email="[null]" active="[true]"/> + + <group_roles id="1" group_id="100" resource_id="123" role="admin"/> + <group_roles id="2" group_id="[null]" resource_id="123" role="user"/> + <user_roles id="1" user_id="200" resource_id="123" role="codeviewer"/> + + +</dataset>
\ No newline at end of file diff --git a/sonar-db/src/test/resources/org/sonar/db/user/RoleMapperTest/insertRoles.xml b/sonar-db/src/test/resources/org/sonar/db/user/RoleMapperTest/insertRoles.xml new file mode 100644 index 00000000000..b99df83bc15 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/RoleMapperTest/insertRoles.xml @@ -0,0 +1,5 @@ +<dataset> + <groups id="100" name="sonar-administrators"/> + <groups id="101" name="sonar-users"/> + <users id="200" login="marius" name="Marius" email="[null]" active="[true]"/> +</dataset>
\ No newline at end of file diff --git a/sonar-db/src/test/resources/org/sonar/db/user/UserDaoTest/deactivate_user-result.xml b/sonar-db/src/test/resources/org/sonar/db/user/UserDaoTest/deactivate_user-result.xml new file mode 100644 index 00000000000..60e55e6494f --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/UserDaoTest/deactivate_user-result.xml @@ -0,0 +1,45 @@ +<dataset> + <!-- deactivated --> + <users id="100" login="marius" name="Marius" email="marius@lesbronzes.fr" created_at="1418215735482" + updated_at="1500000000000" active="[false]"/> + + <!-- deleted + <dashboards id="1" user_id="100" NAME="[null]" COLUMN_LAYOUT="[null]" CREATED_AT="[null]" DESCRIPTION="[null]" IS_GLOBAL="[false]" SHARED="[false]" UPDATED_AT="[null]"/> + <active_dashboards id="1" user_id="100" dashboard_id="1" ORDER_INDEX="[null]"/> + <issue_filters id="1" user_login="marius" name="My issues" CREATED_AT="[null]" DATA="[null]" DESCRIPTION="[null]" SHARED="[false]" UPDATED_AT="[null]"/> + <issue_filter_favourites id="1" user_login="marius" issue_filter_id="1" CREATED_AT="[null]"/> + <measure_filters id="1" user_id="100" name="My measures" CREATED_AT="[null]" DATA="[null]" DESCRIPTION="[null]" SHARED="[false]" UPDATED_AT="[null]"/> + <measure_filter_favourites id="1" user_id="100" measure_filter_id="1" CREATED_AT="[null]"/> + <properties id="1" user_id="100" PROP_KEY="[null]" RESOURCE_ID="[null]" TEXT_VALUE="[null]" /> + <groups_users user_id="100" group_id="200"/> + <user_roles id="1" user_id="100" role="admin" RESOURCE_ID="[null]"/> + --> + + <users id="101" login="jcdus" name="Jean-Claude Dus" email="jcdus@lesbronzes.fr" created_at="1418215735482" + updated_at="1418215735485" active="[true]"/> + <dashboards id="2" user_id="101" NAME="[null]" COLUMN_LAYOUT="[null]" CREATED_AT="[null]" DESCRIPTION="[null]" + IS_GLOBAL="[false]" SHARED="[false]" UPDATED_AT="[null]"/> + <active_dashboards id="2" user_id="101" dashboard_id="2" ORDER_INDEX="[null]"/> + <active_dashboards id="4" user_id="101" dashboard_id="3" ORDER_INDEX="[null]"/> + <issue_filters id="2" user_login="jcdus" name="My issues" CREATED_AT="[null]" DATA="[null]" DESCRIPTION="[null]" + SHARED="[false]" UPDATED_AT="[null]"/> + <issue_filter_favourites id="2" user_login="jcdus" issue_filter_id="2" CREATED_AT="[null]"/> + <issue_filter_favourites id="4" user_login="jcdus" issue_filter_id="3" CREATED_AT="[null]"/> + <measure_filters id="2" user_id="101" name="My measures" CREATED_AT="[null]" DATA="[null]" DESCRIPTION="[null]" + SHARED="[false]" UPDATED_AT="[null]"/> + <measure_filter_favourites id="2" user_id="101" measure_filter_id="2" CREATED_AT="[null]"/> + <measure_filter_favourites id="4" user_id="101" measure_filter_id="3" CREATED_AT="[null]"/> + <properties id="2" user_id="101" PROP_KEY="[null]" RESOURCE_ID="[null]" TEXT_VALUE="[null]"/> + <groups_users user_id="101" group_id="200"/> + <user_roles id="2" user_id="101" role="admin" RESOURCE_ID="[null]"/> + + <!-- Not deleted because shared --> + <dashboards id="3" user_id="100" NAME="[null]" COLUMN_LAYOUT="[null]" CREATED_AT="[null]" DESCRIPTION="[null]" + IS_GLOBAL="[false]" SHARED="[true]" UPDATED_AT="[null]"/> + <issue_filters id="3" user_login="marius" name="My shared issues" CREATED_AT="[null]" DATA="[null]" + DESCRIPTION="[null]" SHARED="[true]" UPDATED_AT="[null]"/> + <measure_filters id="3" user_id="100" name="My shared measures" CREATED_AT="[null]" DATA="[null]" DESCRIPTION="[null]" + SHARED="[true]" UPDATED_AT="[null]"/> + + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/UserDaoTest/deactivate_user.xml b/sonar-db/src/test/resources/org/sonar/db/user/UserDaoTest/deactivate_user.xml new file mode 100644 index 00000000000..804838dfa2a --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/UserDaoTest/deactivate_user.xml @@ -0,0 +1,43 @@ +<dataset> + <users id="100" login="marius" name="Marius" email="marius@lesbronzes.fr" created_at="1418215735482" + updated_at="1418215735485" active="[true]"/> + <dashboards id="1" user_id="100" NAME="[null]" COLUMN_LAYOUT="[null]" CREATED_AT="[null]" DESCRIPTION="[null]" + IS_GLOBAL="[false]" SHARED="[false]" UPDATED_AT="[null]"/> + <dashboards id="3" user_id="100" NAME="[null]" COLUMN_LAYOUT="[null]" CREATED_AT="[null]" DESCRIPTION="[null]" + IS_GLOBAL="[false]" SHARED="[true]" UPDATED_AT="[null]"/> + <active_dashboards id="1" user_id="100" dashboard_id="1" ORDER_INDEX="[null]"/> + <active_dashboards id="3" user_id="100" dashboard_id="3" ORDER_INDEX="[null]"/> + <issue_filters id="1" user_login="marius" name="My issues" CREATED_AT="[null]" DATA="[null]" DESCRIPTION="[null]" + SHARED="[false]" UPDATED_AT="[null]"/> + <issue_filters id="3" user_login="marius" name="My shared issues" CREATED_AT="[null]" DATA="[null]" + DESCRIPTION="[null]" SHARED="[true]" UPDATED_AT="[null]"/> + <issue_filter_favourites id="1" user_login="marius" issue_filter_id="1" CREATED_AT="[null]"/> + <issue_filter_favourites id="3" user_login="marius" issue_filter_id="3" CREATED_AT="[null]"/> + <measure_filters id="1" user_id="100" name="My measures" CREATED_AT="[null]" DATA="[null]" DESCRIPTION="[null]" + SHARED="[false]" UPDATED_AT="[null]"/> + <measure_filters id="3" user_id="100" name="My shared measures" CREATED_AT="[null]" DATA="[null]" DESCRIPTION="[null]" + SHARED="[true]" UPDATED_AT="[null]"/> + <measure_filter_favourites id="1" user_id="100" measure_filter_id="1" CREATED_AT="[null]"/> + <measure_filter_favourites id="3" user_id="100" measure_filter_id="3" CREATED_AT="[null]"/> + <properties id="1" user_id="100" PROP_KEY="[null]" RESOURCE_ID="[null]" TEXT_VALUE="[null]"/> + <groups_users user_id="100" group_id="200"/> + <user_roles id="1" user_id="100" role="admin" RESOURCE_ID="[null]"/> + + <users id="101" login="jcdus" name="Jean-Claude Dus" email="jcdus@lesbronzes.fr" created_at="1418215735482" + updated_at="1418215735485" active="[true]"/> + <dashboards id="2" user_id="101" NAME="[null]" COLUMN_LAYOUT="[null]" CREATED_AT="[null]" DESCRIPTION="[null]" + IS_GLOBAL="[false]" SHARED="[false]" UPDATED_AT="[null]"/> + <active_dashboards id="2" user_id="101" dashboard_id="2" ORDER_INDEX="[null]"/> + <active_dashboards id="4" user_id="101" dashboard_id="3" ORDER_INDEX="[null]"/> + <issue_filters id="2" user_login="jcdus" name="My issues" CREATED_AT="[null]" DATA="[null]" DESCRIPTION="[null]" + SHARED="[false]" UPDATED_AT="[null]"/> + <issue_filter_favourites id="2" user_login="jcdus" issue_filter_id="2" CREATED_AT="[null]"/> + <issue_filter_favourites id="4" user_login="jcdus" issue_filter_id="3" CREATED_AT="[null]"/> + <measure_filters id="2" user_id="101" name="My measures" CREATED_AT="[null]" DATA="[null]" DESCRIPTION="[null]" + SHARED="[false]" UPDATED_AT="[null]"/> + <measure_filter_favourites id="2" user_id="101" measure_filter_id="2" CREATED_AT="[null]"/> + <measure_filter_favourites id="4" user_id="101" measure_filter_id="3" CREATED_AT="[null]"/> + <properties id="2" user_id="101" PROP_KEY="[null]" RESOURCE_ID="[null]" TEXT_VALUE="[null]"/> + <groups_users user_id="101" group_id="200"/> + <user_roles id="2" user_id="101" role="admin" RESOURCE_ID="[null]"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/UserDaoTest/insert-result.xml b/sonar-db/src/test/resources/org/sonar/db/user/UserDaoTest/insert-result.xml new file mode 100644 index 00000000000..621e018f88b --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/UserDaoTest/insert-result.xml @@ -0,0 +1,4 @@ +<dataset> + <users id="1" login="john" name="John" email="jo@hn.com" created_at="1418215735482" updated_at="1418215735482" + active="[true]"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/UserDaoTest/selectActiveUserByLogin.xml b/sonar-db/src/test/resources/org/sonar/db/user/UserDaoTest/selectActiveUserByLogin.xml new file mode 100644 index 00000000000..dc029ad46d6 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/UserDaoTest/selectActiveUserByLogin.xml @@ -0,0 +1,14 @@ +<dataset> + <!-- inactive --> + <users id="50" login="inactive_user" name="Disabled" email="inactive@lesbronzes.fr" created_at="1418215735482" + updated_at="1418215735485" active="[false]"/> + + <!-- active --> + <users id="101" login="marius" name="Marius" email="marius@lesbronzes.fr" created_at="1418215735482" + updated_at="1418215735485" active="[true]"/> + + <users id="102" login="jcdus" name="Jean-Claude Dus" email="jcdus@lesbronzes.fr" created_at="1418215735482" + updated_at="1418215735485" active="[true]"/> + + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/UserDaoTest/selectGroupByName.xml b/sonar-db/src/test/resources/org/sonar/db/user/UserDaoTest/selectGroupByName.xml new file mode 100644 index 00000000000..4148c50491d --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/UserDaoTest/selectGroupByName.xml @@ -0,0 +1,5 @@ +<dataset> + <groups id="1" name="sonar-users" description="Sonar Users" created_at="2011-05-18" updated_at="2012-07-21"/> + <groups id="2" name="sonar-administrators" description="Sonar Administrators" created_at="2011-05-18" + updated_at="2012-07-21"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/UserDaoTest/selectUsersByLogins.xml b/sonar-db/src/test/resources/org/sonar/db/user/UserDaoTest/selectUsersByLogins.xml new file mode 100644 index 00000000000..3be84a27b69 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/UserDaoTest/selectUsersByLogins.xml @@ -0,0 +1,9 @@ +<dataset> + <users id="100" login="inactive_user" name="Disabled" email="inactive@lesbronzes.fr" created_at="1418215735482" + updated_at="1418215735485" active="[false]"/> + <users id="101" login="marius" name="Marius" email="marius@lesbronzes.fr" created_at="1418215735482" + updated_at="1418215735485" active="[true]"/> + <users id="102" login="jcdus" name="Jean-Claude Dus" email="jcdus@lesbronzes.fr" created_at="1418215735482" + updated_at="1418215735485" active="[true]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/UserDaoTest/selectUsersByQuery.xml b/sonar-db/src/test/resources/org/sonar/db/user/UserDaoTest/selectUsersByQuery.xml new file mode 100644 index 00000000000..7107ad4ed36 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/UserDaoTest/selectUsersByQuery.xml @@ -0,0 +1,7 @@ +<dataset> + <users id="100" login="inactive_user" name="Disabled" email="inactive@lesbronzes.fr" created_at="1418215735482" + updated_at="1418215735485" active="[false]"/> + <users id="101" login="marius" name="Marius" email="marius@lesbronzes.fr" created_at="1418215735482" + updated_at="1418215735485" active="[true]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/UserDaoTest/selectUsersByText.xml b/sonar-db/src/test/resources/org/sonar/db/user/UserDaoTest/selectUsersByText.xml new file mode 100644 index 00000000000..1c685cc787c --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/UserDaoTest/selectUsersByText.xml @@ -0,0 +1,7 @@ +<dataset> + <users id="101" login="marius" name="Marius" email="marius@lesbronzes.fr" created_at="1418215735482" + updated_at="1418215735485" active="[true]"/> + <users id="102" login="sbrandhof" name="Simon Brandhof" email="marius@lesbronzes.fr" created_at="1418215735482" + updated_at="1418215735485" active="[true]"/> + +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/user/UserDaoTest/update_user.xml b/sonar-db/src/test/resources/org/sonar/db/user/UserDaoTest/update_user.xml new file mode 100644 index 00000000000..621e018f88b --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/user/UserDaoTest/update_user.xml @@ -0,0 +1,4 @@ +<dataset> + <users id="1" login="john" name="John" email="jo@hn.com" created_at="1418215735482" updated_at="1418215735482" + active="[true]"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/version/DatabaseVersionTest/getVersion.xml b/sonar-db/src/test/resources/org/sonar/db/version/DatabaseVersionTest/getVersion.xml new file mode 100644 index 00000000000..867616dc080 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/version/DatabaseVersionTest/getVersion.xml @@ -0,0 +1,8 @@ +<dataset> + + <schema_migrations version="1"/> + <schema_migrations version="2"/> + <schema_migrations version="4"/> + <schema_migrations version="123"/> + <schema_migrations version="50"/> +</dataset> diff --git a/sonar-db/src/test/resources/org/sonar/db/version/DatabaseVersionTest/getVersion_no_rows.xml b/sonar-db/src/test/resources/org/sonar/db/version/DatabaseVersionTest/getVersion_no_rows.xml new file mode 100644 index 00000000000..5ed00ba028b --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/version/DatabaseVersionTest/getVersion_no_rows.xml @@ -0,0 +1 @@ +<dataset></dataset>
\ No newline at end of file diff --git a/sonar-db/src/test/resources/org/sonar/jpa/dao/ProfilesDaoTest/shouldGetProfiles.xml b/sonar-db/src/test/resources/org/sonar/jpa/dao/ProfilesDaoTest/shouldGetProfiles.xml new file mode 100644 index 00000000000..aeb851beb8e --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/jpa/dao/ProfilesDaoTest/shouldGetProfiles.xml @@ -0,0 +1,7 @@ +<dataset> + + <rules_profiles id="1" name="profile one" language="java" is_default="[false]"/> + <rules_profiles id="2" name="profile two" language="java" is_default="[false]"/> + <rules_profiles id="3" name="profile three" language="plsql" is_default="[false]"/> + +</dataset>
\ No newline at end of file |