}
public List<String> selectProjectsFromView(DbSession session, String viewUuid, String projectViewUuid) {
- return mapper(session).selectProjectsFromView("%." + viewUuid + ".%", projectViewUuid, Qualifiers.SUBVIEW);
+ return mapper(session).selectProjectsFromView("%." + viewUuid + ".%", projectViewUuid);
}
}
.lookupIndex(ViewIndexDefinition.INDEX)
.lookupType(ViewIndexDefinition.TYPE_VIEW)
.lookupId(viewUuid)
- .lookupPath(ViewIndexDefinition.FIELD_PROJECTS));
+ .lookupPath(ViewIndexDefinition.FIELD_PROJECTS))
+ .cacheKey(cacheKey(viewUuid));
}
return viewsFilter;
}
+ public static String cacheKey(String viewUuid) {
+ return IssueIndexDefinition.TYPE_ISSUE + viewUuid + ViewIndexDefinition.TYPE_VIEW;
+ }
+
private FilterBuilder getAuthorizationFilter(QueryContext options) {
String user = options.getUserLogin();
Set<String> groups = options.getUserGroups();
package org.sonar.server.component;
+import com.google.common.base.Preconditions;
import org.sonar.api.resources.Qualifiers;
import org.sonar.api.resources.Scopes;
import org.sonar.api.utils.internal.Uuids;
}
public static ComponentDto newFileDto(ComponentDto module, String fileUuid) {
- return newComponent(fileUuid, module)
+ return newChildComponent(fileUuid, module)
.setKey("KEY_" + fileUuid)
.setName("NAME_" + fileUuid)
.setLongName("LONG_NAME_" + fileUuid)
public static ComponentDto newDirectory(ComponentDto module, String path) {
String uuid = Uuids.create();
- return newComponent(uuid, module)
+ return newChildComponent(uuid, module)
.setKey(!path.equals("/") ? module.getKey() + ":" + path : module.getKey() + ":/")
.setName(path)
.setLongName(path)
}
public static ComponentDto newModuleDto(String uuid, ComponentDto subProjectOrProject) {
- return newComponent(uuid, subProjectOrProject)
+ return newChildComponent(uuid, subProjectOrProject)
.setKey("KEY_" + uuid)
.setName("NAME_" + uuid)
.setLongName("LONG_NAME_" + uuid)
.setEnabled(true);
}
- private static ComponentDto newComponent(String uuid, ComponentDto module) {
+ public static ComponentDto newView(String uuid) {
+ return newProjectDto(uuid)
+ .setUuid(uuid)
+ .setScope(Scopes.PROJECT)
+ .setQualifier(Qualifiers.VIEW);
+ }
+
+ public static ComponentDto newTechnicalProject(ComponentDto project, ComponentDto view) {
+ return newTechnicalProject(Uuids.create(), project, view);
+ }
+
+ public static ComponentDto newTechnicalProject(String uuid, ComponentDto project, ComponentDto view) {
+ Preconditions.checkNotNull(project.getId(), "The project need to be persisted before creating this technical project.");
+ return newChildComponent(uuid, view)
+ .setUuid(uuid)
+ .setKey(view.key() + project.key())
+ .setName(project.name())
+ .setLongName(project.longName())
+ .setCopyResourceId(project.getId())
+ .setScope(Scopes.FILE)
+ .setQualifier(Qualifiers.PROJECT)
+ .setPath(null)
+ .setLanguage(null);
+ }
+
+ private static ComponentDto newChildComponent(String uuid, ComponentDto module) {
return new ComponentDto()
.setUuid(uuid)
.setProjectUuid(module.projectUuid())
.setLanguage("java")
.setPath("src/org/struts/RequestContext.java")
.setParentProjectId(3L)
+ .setCopyResourceId(5L)
.setEnabled(true)
.setAuthorizationUpdatedAt(123456789L);
@Test(expected = IllegalStateException.class)
public void update() {
dao.update(session, new ComponentDto()
- .setId(1L)
- .setKey("org.struts:struts-core:src/org/struts/RequestContext.java")
- );
+ .setId(1L)
+ .setKey("org.struts:struts-core:src/org/struts/RequestContext.java")
+ );
}
@Test
setupData("shared");
dao.delete(session, new ComponentDto()
- .setId(1L)
- .setKey("org.struts:struts-core:src/org/struts/RequestContext.java")
- );
+ .setId(1L)
+ .setKey("org.struts:struts-core:src/org/struts/RequestContext.java")
+ );
session.commit();
checkTable("delete", "projects");
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.server.computation.step;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.security.DefaultGroups;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.issue.db.IssueDto;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.rule.RuleDto;
+import org.sonar.server.component.ComponentTesting;
+import org.sonar.server.component.db.ComponentDao;
+import org.sonar.server.computation.ComputationContext;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.issue.IssueQuery;
+import org.sonar.server.issue.IssueTesting;
+import org.sonar.server.issue.db.IssueDao;
+import org.sonar.server.issue.index.IssueIndex;
+import org.sonar.server.issue.index.IssueIndexer;
+import org.sonar.server.permission.InternalPermissionService;
+import org.sonar.server.permission.PermissionChange;
+import org.sonar.server.rule.RuleTesting;
+import org.sonar.server.rule.db.RuleDao;
+import org.sonar.server.search.QueryContext;
+import org.sonar.server.tester.ServerTester;
+import org.sonar.server.user.MockUserSession;
+import org.sonar.server.view.index.ViewIndexer;
+
+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;
+
+/**
+ * It's still not possible to only used EsTester as IssueIndex does not support it yet.
+ */
+public class IndexViewsStepMediumTest {
+
+ ComputationContext context;
+
+ DbSession dbSession;
+
+ ViewIndexer indexer;
+
+ IndexViewsStep step;
+
+ @ClassRule
+ public static ServerTester tester = new ServerTester().addComponents(IndexViewsStep.class);
+
+ IssueIndex index;
+
+ @Before
+ public void setUp() throws Exception {
+ tester.clearIndexes();
+ context = mock(ComputationContext.class);
+ dbSession = tester.get(DbClient.class).openSession(false);
+ index = tester.get(IssueIndex.class);
+ step = tester.get(IndexViewsStep.class);
+ }
+
+ @After
+ public void after() {
+ dbSession.close();
+ }
+
+ @Test
+ public void clear_cache_of_issue_on_view_filter() throws Exception {
+ String viewUuid = "ABCD";
+ when(context.getProject()).thenReturn(ComponentTesting.newProjectDto(viewUuid).setQualifier(Qualifiers.VIEW));
+
+ RuleDto rule = RuleTesting.newXooX1();
+ tester.get(RuleDao.class).insert(dbSession, rule);
+ ComponentDto project1 = addProjectWithIssue(rule);
+
+ ComponentDto view = ComponentTesting.newView("ABCD");
+ ComponentDto techProject1 = ComponentTesting.newTechnicalProject("CDEF", project1, view);
+ tester.get(ComponentDao.class).insert(dbSession, view, techProject1);
+ dbSession.commit();
+ tester.get(ViewIndexer.class).index(viewUuid);
+
+ // Execute issue query on view -> 1 issue on view (and filter on view will be set in cache)
+ assertThat(tester.get(IssueIndex.class).search(IssueQuery.builder().viewUuids(newArrayList(viewUuid)).build(), new QueryContext()).getHits()).hasSize(1);
+
+ // Add a project to the view
+ ComponentDto project2 = addProjectWithIssue(rule);
+ ComponentDto techProject2 = ComponentTesting.newTechnicalProject("EFGH", project2, view);
+ tester.get(ComponentDao.class).insert(dbSession, techProject2);
+ dbSession.commit();
+
+ // Execute issue query on view -> Still 1 issue on view, issue on project2 is not yet visible
+ assertThat(tester.get(IssueIndex.class).search(IssueQuery.builder().viewUuids(newArrayList(viewUuid)).build(), new QueryContext()).getHits()).hasSize(1);
+
+ step.execute(context);
+
+ // Execute issue query on view -> issue of project2 are well taken into account
+ assertThat(tester.get(IssueIndex.class).search(IssueQuery.builder().viewUuids(newArrayList(viewUuid)).build(), new QueryContext()).getHits()).hasSize(2);
+ }
+
+ private ComponentDto addProjectWithIssue(RuleDto rule) {
+ ComponentDto project = ComponentTesting.newProjectDto();
+ ComponentDto file = ComponentTesting.newFileDto(project);
+ tester.get(ComponentDao.class).insert(dbSession, project, file);
+
+ IssueDto issue = IssueTesting.newDto(rule, file, project);
+ tester.get(IssueDao.class).insert(dbSession, issue);
+ dbSession.commit();
+
+ setDefaultProjectPermission(project);
+ tester.get(IssueIndexer.class).indexAll();
+
+ return project;
+ }
+
+ private void setDefaultProjectPermission(ComponentDto project) {
+ // project can be seen by anyone and by code viewer
+ MockUserSession.set().setLogin("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+ tester.get(InternalPermissionService.class).addPermission(new PermissionChange().setComponentKey(project.getKey()).setGroup(DefaultGroups.ANYONE).setPermission(UserRole.USER));
+ MockUserSession.set();
+ }
+}
name="RequestContext.java" long_name="org.struts.RequestContext"
uuid="GHIJ" project_uuid="ABCD" module_uuid="EFGH" module_uuid_path=".ABCD.EFGH."
qualifier="FIL" scope="FIL" language="java" path="src/org/struts/RequestContext.java" root_id="3"
- description="[null]" enabled="[true]" copy_resource_id="[null]" person_id="[null]"
+ description="[null]" enabled="[true]" copy_resource_id="5" person_id="[null]"
authorization_updated_at="123456789" created_at="2014-06-18"
/>
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 Long parentProjectId;
private boolean enabled = true;
private Long authorizationUpdatedAt;
return this;
}
+ public Long getCopyResourceId() {
+ return copyResourceId;
+ }
+
+ public ComponentDto setCopyResourceId(Long copyResourceId) {
+ this.copyResourceId = copyResourceId;
+ return this;
+ }
+
/**
* Only available on projects
*/
/**
* Return technical projects from a view or a sub-view
*/
- List<String> selectProjectsFromView(@Param("viewUuidLikeQuery") String viewUuidLikeQuery, @Param("projectViewUuid") String projectViewUuid,
- @Param("subViewQualifier") String subViewQualifier);
+ List<String> selectProjectsFromView(@Param("viewUuidLikeQuery") String viewUuidLikeQuery, @Param("projectViewUuid") String projectViewUuid);
long countById(long id);
</select>
<sql id="insertColumns">
- (kee, deprecated_kee, uuid, project_uuid, module_uuid, module_uuid_path, name, long_name, qualifier, scope, language, root_id, path, enabled, created_at, authorization_updated_at)
+ (kee, deprecated_kee, uuid, project_uuid, module_uuid, module_uuid_path, name, long_name, qualifier, scope, language, root_id, path, copy_resource_id, enabled,
+ created_at, authorization_updated_at)
</sql>
<insert id="insert" parameterType="Component" keyColumn="id" useGeneratedKeys="true" keyProperty="id">
insert into projects <include refid="insertColumns"/>
values (#{kee}, #{deprecatedKey}, #{uuid}, #{projectUuid}, #{moduleUuid}, #{moduleUuidPath}, #{name}, #{longName}, #{qualifier}, #{scope},
- #{language}, #{parentProjectId}, #{path}, #{enabled}, #{createdAt}, #{authorizationUpdatedAt})
+ #{language}, #{parentProjectId}, #{path}, #{copyResourceId}, #{enabled}, #{createdAt}, #{authorizationUpdatedAt})
</insert>
<delete id="deleteByKey" parameterType="String">
.setScope("FIL")
.setLanguage("java")
.setPath("src/org/struts/RequestContext.java")
+ .setCopyResourceId(5L)
.setParentProjectId(3L)
.setAuthorizationUpdatedAt(123456789L);
assertThat(componentDto.path()).isEqualTo("src/org/struts/RequestContext.java");
assertThat(componentDto.language()).isEqualTo("java");
assertThat(componentDto.parentProjectId()).isEqualTo(3L);
+ assertThat(componentDto.getCopyResourceId()).isEqualTo(5L);
assertThat(componentDto.getAuthorizationUpdatedAt()).isEqualTo(123456789L);
}