diff options
26 files changed, 389 insertions, 303 deletions
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java index c876dd10c87..41e3477bf26 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java @@ -27,6 +27,7 @@ import org.sonar.api.SonarPlugin; import org.sonar.api.checks.NoSonarFilter; import org.sonar.api.resources.Java; import org.sonar.plugins.core.batch.ExcludedResourceFilter; +import org.sonar.plugins.core.batch.IndexProjectPostJob; import org.sonar.plugins.core.batch.MavenInitializer; import org.sonar.plugins.core.batch.ProjectFileSystemLogger; import org.sonar.plugins.core.charts.DistributionAreaChart; @@ -289,6 +290,7 @@ public class CorePlugin extends SonarPlugin { extensions.add(ManualViolationInjector.class); extensions.add(UpdateReviewsDecorator.class); extensions.add(ViolationSeverityUpdater.class); + extensions.add(IndexProjectPostJob.class); // time machine extensions.add(TendencyDecorator.class); diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/batch/IndexProjectPostJob.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/batch/IndexProjectPostJob.java new file mode 100644 index 00000000000..5beb4ac709a --- /dev/null +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/batch/IndexProjectPostJob.java @@ -0,0 +1,44 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2011 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.core.batch; + +import org.sonar.api.batch.PostJob; +import org.sonar.api.batch.SensorContext; +import org.sonar.api.resources.Project; +import org.sonar.core.NotDryRun; +import org.sonar.core.resource.ResourceIndexerDao; + +/** + * @since 2.13 + */ +@NotDryRun +public class IndexProjectPostJob implements PostJob { + private ResourceIndexerDao indexer; + + public IndexProjectPostJob(ResourceIndexerDao indexer) { + this.indexer = indexer; + } + + public void executeOn(Project project, SensorContext context) { + if (project.getId() != null) { + indexer.indexProject(project.getId()); + } + } +} diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/batch/IndexProjectPostJobTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/batch/IndexProjectPostJobTest.java new file mode 100644 index 00000000000..cdb23d6fd6e --- /dev/null +++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/batch/IndexProjectPostJobTest.java @@ -0,0 +1,53 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2011 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.core.batch; + +import org.junit.Test; +import org.sonar.api.resources.Project; +import org.sonar.core.resource.ResourceIndexerDao; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; + +public class IndexProjectPostJobTest { + @Test + public void shouldIndexProject() { + ResourceIndexerDao indexer = mock(ResourceIndexerDao.class); + IndexProjectPostJob job = new IndexProjectPostJob(indexer); + Project project = new Project("foo"); + project.setId(123); + + job.executeOn(project, null); + + verify(indexer).indexProject(123); + } + + @Test + public void shouldNotIndexProjectIfMissingId() { + ResourceIndexerDao indexer = mock(ResourceIndexerDao.class); + IndexProjectPostJob job = new IndexProjectPostJob(indexer); + + job.executeOn(new Project("foo"), null); + + verifyZeroInteractions(indexer); + } + +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapModule.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapModule.java index b40aa67a45a..21f6824c713 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapModule.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapModule.java @@ -27,7 +27,6 @@ import org.sonar.batch.MavenPluginExecutor; import org.sonar.batch.ServerMetadata; import org.sonar.batch.config.BatchSettings; import org.sonar.batch.config.BatchSettingsEnhancer; -import org.sonar.core.resource.ResourceIndexer; import org.sonar.jpa.session.DatabaseSessionProvider; import org.sonar.jpa.session.DefaultDatabaseConnector; import org.sonar.jpa.session.ThreadLocalDatabaseSessionFactory; @@ -67,7 +66,6 @@ public class BootstrapModule extends Module { addCoreSingleton(BatchDatabase.class); addCoreSingleton(MyBatis.class); - addCoreSingleton(ResourceIndexer.class); addCoreSingleton(DefaultDatabaseConnector.class); addCoreSingleton(ThreadLocalDatabaseSessionFactory.class); for (Class daoClass : DaoUtils.getDaoClasses()) { diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/DefaultResourcePersister.java b/sonar-batch/src/main/java/org/sonar/batch/index/DefaultResourcePersister.java index 5386b61414d..57037c987fd 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/index/DefaultResourcePersister.java +++ b/sonar-batch/src/main/java/org/sonar/batch/index/DefaultResourcePersister.java @@ -27,8 +27,6 @@ import org.sonar.api.database.model.ResourceModel; import org.sonar.api.database.model.Snapshot; import org.sonar.api.resources.*; import org.sonar.api.utils.SonarException; -import org.sonar.core.resource.ResourceIndexer; -import org.sonar.core.resource.ResourceIndexerDao; import javax.persistence.NonUniqueResultException; import javax.persistence.Query; @@ -41,11 +39,9 @@ public final class DefaultResourcePersister implements ResourcePersister { private DatabaseSession session; private Map<Resource, Snapshot> snapshotsByResource = Maps.newHashMap(); - private ResourceIndexer indexer; - public DefaultResourcePersister(DatabaseSession session, ResourceIndexer indexer) { + public DefaultResourcePersister(DatabaseSession session) { this.session = session; - this.indexer = indexer; } public Snapshot saveProject(Project project, Project parent) { @@ -84,7 +80,6 @@ public final class DefaultResourcePersister implements ResourcePersister { snapshot.setCreatedAt(project.getAnalysisDate()); snapshot = session.save(snapshot); session.commit(); - indexer.index(project.getName(), snapshot.getQualifier(), snapshot.getResourceId(), snapshot.getRootProjectId()); return snapshot; } @@ -134,7 +129,6 @@ public final class DefaultResourcePersister implements ResourcePersister { } else { snapshot = persistFileOrDirectory(project, resource, parent); } - indexer.index(resource.getName(), snapshot.getQualifier(), snapshot.getResourceId(), snapshot.getRootProjectId()); return snapshot; } diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/DefaultResourcePersisterTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/DefaultResourcePersisterTest.java index 35277ff3436..3491738c922 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/index/DefaultResourcePersisterTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/index/DefaultResourcePersisterTest.java @@ -26,7 +26,6 @@ import org.sonar.api.resources.JavaPackage; import org.sonar.api.resources.Library; import org.sonar.api.resources.Project; import org.sonar.jpa.test.AbstractDbUnitTestCase; -import org.sonar.core.resource.ResourceIndexer; import java.text.ParseException; import java.text.SimpleDateFormat; @@ -34,7 +33,6 @@ import java.text.SimpleDateFormat; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.notNullValue; -import static org.mockito.Mockito.mock; public class DefaultResourcePersisterTest extends AbstractDbUnitTestCase { @@ -67,7 +65,7 @@ public class DefaultResourcePersisterTest extends AbstractDbUnitTestCase { public void shouldSaveNewProject() { setupData("shared"); - ResourcePersister persister = new DefaultResourcePersister(getSession(), mock(ResourceIndexer.class)); + ResourcePersister persister = new DefaultResourcePersister(getSession()); persister.saveProject(singleProject, null); checkTables("shouldSaveNewProject", "projects", "snapshots"); @@ -77,7 +75,7 @@ public class DefaultResourcePersisterTest extends AbstractDbUnitTestCase { public void shouldSaveNewMultiModulesProject() throws ParseException { setupData("shared"); - ResourcePersister persister = new DefaultResourcePersister(getSession(), mock(ResourceIndexer.class)); + ResourcePersister persister = new DefaultResourcePersister(getSession()); persister.saveProject(multiModuleProject, null); persister.saveProject(moduleA, multiModuleProject); persister.saveProject(moduleB, multiModuleProject); @@ -90,7 +88,7 @@ public class DefaultResourcePersisterTest extends AbstractDbUnitTestCase { public void shouldSaveNewDirectory() { setupData("shared"); - ResourcePersister persister = new DefaultResourcePersister(getSession(), mock(ResourceIndexer.class)); + ResourcePersister persister = new DefaultResourcePersister(getSession()); persister.saveProject(singleProject, null); persister.saveResource(singleProject, new JavaPackage("org.foo").setEffectiveKey("foo:org.foo")); @@ -102,7 +100,7 @@ public class DefaultResourcePersisterTest extends AbstractDbUnitTestCase { public void shouldSaveNewLibrary() { setupData("shared"); - ResourcePersister persister = new DefaultResourcePersister(getSession(), mock(ResourceIndexer.class)); + ResourcePersister persister = new DefaultResourcePersister(getSession()); persister.saveProject(singleProject, null); persister.saveResource(singleProject, new Library("junit:junit", "4.8.2").setEffectiveKey("junit:junit")); persister.saveResource(singleProject, new Library("junit:junit", "4.8.2").setEffectiveKey("junit:junit"));// do nothing, already saved @@ -115,7 +113,7 @@ public class DefaultResourcePersisterTest extends AbstractDbUnitTestCase { public void shouldClearResourcesExceptProjects() { setupData("shared"); - DefaultResourcePersister persister = new DefaultResourcePersister(getSession(), mock(ResourceIndexer.class)); + DefaultResourcePersister persister = new DefaultResourcePersister(getSession()); persister.saveProject(multiModuleProject, null); persister.saveProject(moduleA, multiModuleProject); persister.saveResource(moduleA, new JavaPackage("org.foo").setEffectiveKey("a:org.foo")); @@ -131,7 +129,7 @@ public class DefaultResourcePersisterTest extends AbstractDbUnitTestCase { public void shouldUpdateExistingResource() { setupData("shouldUpdateExistingResource"); - ResourcePersister persister = new DefaultResourcePersister(getSession(), mock(ResourceIndexer.class)); + ResourcePersister persister = new DefaultResourcePersister(getSession()); singleProject.setName("new name"); singleProject.setDescription("new description"); persister.saveProject(singleProject, null); diff --git a/sonar-batch/src/test/java/org/sonar/batch/phases/UpdateStatusJobTest.java b/sonar-batch/src/test/java/org/sonar/batch/phases/UpdateStatusJobTest.java index 21b784d1ff3..320db8e9608 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/phases/UpdateStatusJobTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/phases/UpdateStatusJobTest.java @@ -24,7 +24,6 @@ import org.sonar.api.database.DatabaseSession; import org.sonar.api.database.model.Snapshot; import org.sonar.batch.ServerMetadata; import org.sonar.batch.index.DefaultResourcePersister; -import org.sonar.core.resource.ResourceIndexer; import org.sonar.jpa.test.AbstractDbUnitTestCase; import javax.persistence.Query; @@ -51,7 +50,7 @@ public class UpdateStatusJobTest extends AbstractDbUnitTestCase { private void assertAnalysis(int snapshotId, String fixture) { setupData("sharedFixture", fixture); DatabaseSession session = getSession(); - UpdateStatusJob sensor = new UpdateStatusJob(mock(ServerMetadata.class), session, new DefaultResourcePersister(session, mock(ResourceIndexer.class)), loadSnapshot(snapshotId)); + UpdateStatusJob sensor = new UpdateStatusJob(mock(ServerMetadata.class), session, new DefaultResourcePersister(session), loadSnapshot(snapshotId)); sensor.execute(); getSession().stop(); diff --git a/sonar-core/src/main/java/org/sonar/core/resource/ResourceIndexer.java b/sonar-core/src/main/java/org/sonar/core/resource/ResourceIndexer.java deleted file mode 100644 index d184792df99..00000000000 --- a/sonar-core/src/main/java/org/sonar/core/resource/ResourceIndexer.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2011 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * Sonar is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.core.resource; - -import com.google.common.annotations.Beta; -import org.apache.commons.lang.ArrayUtils; -import org.sonar.api.BatchComponent; -import org.sonar.api.ServerComponent; -import org.sonar.api.resources.Qualifiers; -import org.sonar.api.resources.Scopes; - -/** - * This component will be automatically called in v3.0 when a resource is created or updated. - * It means that it will not be exposed to plugin API. - * - * @since 2.13 - */ -@Beta -public class ResourceIndexer implements BatchComponent, ServerComponent { - private ResourceIndexerDao dao; - - /** - * Hardcoded list of qualifiers to index. Need to be configurable. - * Directories and packages are explicitly excluded. - */ - static final String[] INDEXABLE_QUALIFIERS = { - Qualifiers.VIEW, - Qualifiers.SUBVIEW, - Qualifiers.PROJECT, - Qualifiers.MODULE, - Qualifiers.FILE, - Qualifiers.CLASS, - Qualifiers.UNIT_TEST_FILE - }; - - public ResourceIndexer(ResourceIndexerDao dao) { - this.dao = dao; - } - - public ResourceIndexer index(String resourceName, String qualifier, int resourceId, int rootProjectId) { - if (ArrayUtils.contains(INDEXABLE_QUALIFIERS, qualifier)) { - dao.index(resourceName, qualifier, resourceId, rootProjectId); - } - return this; - } - - /** - * Used only for the migration from a version less than 2.13. - */ - public ResourceIndexer indexAll() { - ResourceIndexerFilter filter = ResourceIndexerFilter.create() - .setScopes(new String[]{Scopes.PROJECT, Scopes.FILE}) - .setQualifiers(INDEXABLE_QUALIFIERS); - dao.index(filter); - return this; - } -} diff --git a/sonar-core/src/main/java/org/sonar/core/resource/ResourceIndexerDao.java b/sonar-core/src/main/java/org/sonar/core/resource/ResourceIndexerDao.java index 0aa11816fd6..8e737501011 100644 --- a/sonar-core/src/main/java/org/sonar/core/resource/ResourceIndexerDao.java +++ b/sonar-core/src/main/java/org/sonar/core/resource/ResourceIndexerDao.java @@ -19,123 +19,174 @@ */ package org.sonar.core.resource; -import org.apache.commons.lang.ObjectUtils; +import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.StringUtils; import org.apache.ibatis.session.ExecutorType; 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.core.persistence.MyBatis; public class ResourceIndexerDao { public static final int MINIMUM_KEY_SIZE = 3; + // 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; } - public ResourceIndexerDao index(String resourceName, String qualifier, int resourceId, int rootProjectId) { - SqlSession sqlSession = mybatis.openSession(); + /** + * This method is reentrant. It can be executed even if the project is already indexed. + */ + public ResourceIndexerDao indexProject(final int rootProjectId) { + SqlSession session = mybatis.openSession(ExecutorType.BATCH); try { - ResourceDto resource = new ResourceDto() - .setId(resourceId) - .setQualifier(qualifier) - .setName(resourceName) - .setRootId(rootProjectId); - index(resource, sqlSession, true); + ResourceIndexerMapper mapper = session.getMapper(ResourceIndexerMapper.class); + doIndexProject(rootProjectId, session, mapper); + session.commit(); + return this; } finally { - sqlSession.close(); + session.close(); } - return this; } - - public ResourceIndexerDao index(ResourceIndexerFilter filter) { - final SqlSession sqlSession = mybatis.openSession(ExecutorType.BATCH); + /** + * This method is reentrant. It can be executed even if some projects are already indexed. + */ + public ResourceIndexerDao indexProjects() { + final SqlSession session = mybatis.openSession(ExecutorType.BATCH); try { - sqlSession.select("selectResourcesToIndex", filter, new ResultHandler() { + final ResourceIndexerMapper mapper = session.getMapper(ResourceIndexerMapper.class); + session.select("selectRootProjectIds", /* workaround to get booleans */ResourceIndexerFilter.create(), new ResultHandler() { public void handleResult(ResultContext context) { - ResourceDto resource = (ResourceDto) context.getResultObject(); - - // The column PROJECTS.ROOT_ID references the module but not the root project in a multi-modules project. - boolean correctRootProjectId = false; - - index(resource, sqlSession, correctRootProjectId); + Integer rootProjectId = (Integer) context.getResultObject(); + doIndexProject(rootProjectId, session, mapper); + session.commit(); } }); + return this; + } finally { - sqlSession.close(); + session.close(); } - return this; } - void index(ResourceDto resource, SqlSession session, boolean correctProjectRootId) { - String name = resource.getName(); - if (StringUtils.isBlank(name) || resource.getId() == null) { - return; - } + private void doIndexProject(int rootProjectId, SqlSession session, final ResourceIndexerMapper mapper) { + // non indexed resources + ResourceIndexerFilter filter = ResourceIndexerFilter.create() + .setNonIndexedOnly(true) + .setQualifiers(NOT_RENAMABLE_QUALIFIERS) + .setScopes(NOT_RENAMABLE_SCOPES) + .setRootProjectId(rootProjectId); + + session.select("selectResources", filter, new ResultHandler() { + 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 + filter = ResourceIndexerFilter.create() + .setNonIndexedOnly(false) + .setQualifiers(RENAMABLE_QUALIFIERS) + .setScopes(RENAMABLE_SCOPES) + .setRootProjectId(rootProjectId); + + session.select("selectResources", filter, new ResultHandler() { + public void handleResult(ResultContext context) { + ResourceDto resource = (ResourceDto) context.getResultObject(); + + mapper.deleteByResourceId(resource.getId()); + doIndex(resource, mapper); + } + }); + } - String key = toKey(name); - if (key.length() >= MINIMUM_KEY_SIZE) { - ResourceIndexerMapper mapper = session.getMapper(ResourceIndexerMapper.class); - boolean toBeIndexed = sanitizeIndex(resource, key, mapper); - if (toBeIndexed) { - - ResourceIndexDto dto = new ResourceIndexDto() - .setResourceId(resource.getId()) - .setQualifier(resource.getQualifier()) - .setRootProjectId(loadRootProjectId(resource, mapper, correctProjectRootId)) - .setNameSize(name.length()); - - for (int position = 0; position <= key.length() - MINIMUM_KEY_SIZE; position++) { - dto.setPosition(position); - dto.setKey(StringUtils.substring(key, position)); - mapper.insert(dto); - } - session.commit(); + void doIndex(ResourceDto resource, ResourceIndexerMapper mapper) { + String key = nameToKey(resource.getName()); + if (key.length() >= MINIMUM_KEY_SIZE) { + ResourceIndexDto dto = new ResourceIndexDto() + .setResourceId(resource.getId()) + .setQualifier(resource.getQualifier()) + .setRootProjectId(resource.getRootId()) + .setNameSize(resource.getName().length()); + + for (int position = 0; position <= key.length() - MINIMUM_KEY_SIZE; position++) { + dto.setPosition(position); + dto.setKey(StringUtils.substring(key, position)); + mapper.insert(dto); } } } - private Integer loadRootProjectId(ResourceDto resource, ResourceIndexerMapper mapper, boolean correctProjectRootId) { - if (correctProjectRootId) { - return resource.getRootId(); - } - Integer rootId; - if (resource.getRootId() != null) { - ResourceDto root = mapper.selectRootId(resource.getRootId()); - if (root != null) { - rootId = (Integer) ObjectUtils.defaultIfNull(root.getRootId(), root.getId()); - } else { - rootId = resource.getRootId(); + public boolean indexResource(int id, String name, String qualifier, int rootProjectId) { + boolean indexed = false; + if (isIndexableQualifier(qualifier)) { + SqlSession session = mybatis.openSession(); + try { + String key = nameToKey(name); + if (key.length() >= MINIMUM_KEY_SIZE) { + indexed = true; + ResourceIndexerMapper mapper = session.getMapper(ResourceIndexerMapper.class); + boolean toBeIndexed = sanitizeIndex(id, key, mapper); + if (toBeIndexed) { + ResourceIndexDto dto = new ResourceIndexDto() + .setResourceId(id) + .setQualifier(qualifier) + .setRootProjectId(rootProjectId) + .setNameSize(name.length()); + + for (int position = 0; position <= key.length() - MINIMUM_KEY_SIZE; position++) { + dto.setPosition(position); + dto.setKey(StringUtils.substring(key, position)); + mapper.insert(dto); + } + session.commit(); + } + } + } finally { + session.close(); } - } else { - rootId = resource.getId(); } - return rootId; + return indexed; } + /** * 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(ResourceDto resource, String key, ResourceIndexerMapper mapper) { - ResourceIndexDto masterIndex = mapper.selectMasterIndexByResourceId(resource.getId()); + private boolean sanitizeIndex(int 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(resource.getId()); + mapper.deleteByResourceId(resourceId); masterIndex = null; } return masterIndex == null; } - static String toKey(String input) { - return StringUtils.lowerCase(input); + static String nameToKey(String input) { + return StringUtils.lowerCase(StringUtils.trimToEmpty(input)); + } + + static boolean isIndexableQualifier(String qualifier) { + return ArrayUtils.contains(RENAMABLE_QUALIFIERS, qualifier) || ArrayUtils.contains(NOT_RENAMABLE_QUALIFIERS, qualifier); } } diff --git a/sonar-core/src/main/java/org/sonar/core/resource/ResourceIndexerFilter.java b/sonar-core/src/main/java/org/sonar/core/resource/ResourceIndexerFilter.java index 73b2aea748b..a8a823078db 100644 --- a/sonar-core/src/main/java/org/sonar/core/resource/ResourceIndexerFilter.java +++ b/sonar-core/src/main/java/org/sonar/core/resource/ResourceIndexerFilter.java @@ -20,9 +20,11 @@ package org.sonar.core.resource; public final class ResourceIndexerFilter { - private boolean enabled = true; + private boolean _true = true; + private Integer rootProjectId = null; private String[] scopes = null; private String[] qualifiers = null; + private boolean nonIndexedOnly=false; private ResourceIndexerFilter() { } @@ -31,10 +33,6 @@ public final class ResourceIndexerFilter { return new ResourceIndexerFilter(); } - public boolean isEnabled() { - return enabled; - } - public String[] getScopes() { return scopes; } @@ -52,4 +50,22 @@ public final class ResourceIndexerFilter { this.qualifiers = qualifiers; return this; } + + public Integer getRootProjectId() { + return rootProjectId; + } + + public ResourceIndexerFilter setRootProjectId(Integer i) { + this.rootProjectId = i; + return this; + } + + public boolean isNonIndexedOnly() { + return nonIndexedOnly; + } + + public ResourceIndexerFilter setNonIndexedOnly(boolean b) { + this.nonIndexedOnly = b; + return this; + } } diff --git a/sonar-core/src/main/java/org/sonar/core/resource/ResourceIndexerMapper.java b/sonar-core/src/main/java/org/sonar/core/resource/ResourceIndexerMapper.java index b4d0ef63b0b..a9b044f23fa 100644 --- a/sonar-core/src/main/java/org/sonar/core/resource/ResourceIndexerMapper.java +++ b/sonar-core/src/main/java/org/sonar/core/resource/ResourceIndexerMapper.java @@ -19,9 +19,9 @@ */ package org.sonar.core.resource; -public interface ResourceIndexerMapper { +import java.util.List; - ResourceDto selectRootId(int id); +public interface ResourceIndexerMapper { ResourceIndexDto selectMasterIndexByResourceId(int resourceId); diff --git a/sonar-core/src/main/resources/org/sonar/core/resource/ResourceIndexerMapper.xml b/sonar-core/src/main/resources/org/sonar/core/resource/ResourceIndexerMapper.xml index 4fcf08b84fd..fee6f471405 100644 --- a/sonar-core/src/main/resources/org/sonar/core/resource/ResourceIndexerMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/resource/ResourceIndexerMapper.xml @@ -3,27 +3,47 @@ <mapper namespace="org.sonar.core.resource.ResourceIndexerMapper"> - <select id="selectResourcesToIndex" parameterType="map" resultType="Resource"> - select id, root_id as "rootId", name, scope, qualifier - from projects + <!-- + 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> - enabled=#{enabled} - and copy_resource_id is null - <if test="scopes != null">and scope in + 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 qualifier in - <foreach item="qualifier" index="index" collection="qualifiers" open="(" separator="," close=")">#{qualifier}</foreach> + <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> </select> - <select id="selectRootId" parameterType="int" resultType="Resource"> - select id, root_id as "rootId" - from projects - where id=#{id} + <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="int" resultType="ResourceIndex"> select kee as "key", resource_id as "resourceId" from resource_index diff --git a/sonar-core/src/test/java/org/sonar/core/resource/ResourceIndexerDaoTest.java b/sonar-core/src/test/java/org/sonar/core/resource/ResourceIndexerDaoTest.java index fba523f1efb..2426fdc9166 100644 --- a/sonar-core/src/test/java/org/sonar/core/resource/ResourceIndexerDaoTest.java +++ b/sonar-core/src/test/java/org/sonar/core/resource/ResourceIndexerDaoTest.java @@ -33,28 +33,28 @@ public class ResourceIndexerDaoTest extends DaoTestCase { } @Test - public void shouldIndexSingleResource() { - setupData("shouldIndexSingleResource"); + public void shouldIndexResource() { + setupData("shouldIndexResource"); - dao.index("ZipUtils", "FIL", 10, 8); + dao.indexResource(10, "ZipUtils", "FIL", 8); - checkTables("shouldIndexSingleResource", "resource_index"); + checkTables("shouldIndexResource", "resource_index"); } @Test - public void shouldIndexAllResources() { - setupData("shouldIndexAllResources"); + public void shouldIndexProjects() { + setupData("shouldIndexProjects"); - dao.index(ResourceIndexerFilter.create()); + dao.indexProjects(); - checkTables("shouldIndexAllResources", "resource_index"); + checkTables("shouldIndexProjects", "resource_index"); } @Test public void shouldIndexMultiModulesProject() { setupData("shouldIndexMultiModulesProject"); - dao.index(ResourceIndexerFilter.create()); + dao.indexProject(1); checkTables("shouldIndexMultiModulesProject", "resource_index"); } @@ -63,7 +63,7 @@ public class ResourceIndexerDaoTest extends DaoTestCase { public void shouldReindexProjectAfterRenaming() { setupData("shouldReindexProjectAfterRenaming"); - dao.index(ResourceIndexerFilter.create()); + dao.indexProject(1); checkTables("shouldReindexProjectAfterRenaming", "resource_index"); } diff --git a/sonar-core/src/test/java/org/sonar/core/resource/ResourceIndexerTest.java b/sonar-core/src/test/java/org/sonar/core/resource/ResourceIndexerTest.java deleted file mode 100644 index 7e6d2e5fc0a..00000000000 --- a/sonar-core/src/test/java/org/sonar/core/resource/ResourceIndexerTest.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2011 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * Sonar is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.core.resource; - -import org.hamcrest.BaseMatcher; -import org.hamcrest.Description; -import org.junit.Test; -import org.sonar.api.resources.Qualifiers; - -import static org.mockito.Mockito.*; - -public class ResourceIndexerTest { - - @Test - public void shouldNotIndexDirectories() { - ResourceIndexerDao dao = mock(ResourceIndexerDao.class); - ResourceIndexer indexer = new ResourceIndexer(dao); - indexer.index("org.foo", Qualifiers.DIRECTORY, 12, 9); - - verifyZeroInteractions(dao); - } - - @Test - public void shouldIndexResource() { - ResourceIndexerDao dao = mock(ResourceIndexerDao.class); - ResourceIndexer indexer = new ResourceIndexer(dao); - indexer.index("org.foo.Bar", Qualifiers.FILE, 12, 9); - - verify(dao).index("org.foo.Bar", Qualifiers.FILE, 12, 9); - } - - @Test - public void shouldIndexAll() { - ResourceIndexerDao dao = mock(ResourceIndexerDao.class); - ResourceIndexer indexer = new ResourceIndexer(dao); - indexer.indexAll(); - - verify(dao).index(argThat(new BaseMatcher<ResourceIndexerFilter>() { - public boolean matches(Object o) { - ResourceIndexerFilter filter = (ResourceIndexerFilter) o; - return filter.isEnabled() && filter.getScopes().length == 2 && filter.getQualifiers().length == ResourceIndexer.INDEXABLE_QUALIFIERS.length; - } - - public void describeTo(Description description) { - } - })); - } -} diff --git a/sonar-core/src/test/resources/org/sonar/core/resource/ResourceIndexerDaoTest/shouldIndexAllResources.xml b/sonar-core/src/test/resources/org/sonar/core/resource/ResourceIndexerDaoTest/shouldIndexAllResources.xml deleted file mode 100644 index 66686dff07a..00000000000 --- a/sonar-core/src/test/resources/org/sonar/core/resource/ResourceIndexerDaoTest/shouldIndexAllResources.xml +++ /dev/null @@ -1,13 +0,0 @@ -<dataset> - - <projects long_name="[null]" id="1" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" - root_id="[null]" - description="[null]" - enabled="[true]" language="java" copy_resource_id="[null]"/> - - <projects long_name="org.struts.RequestContext" id="3" scope="FIL" qualifier="FIL" kee="org.struts:struts:org.struts.RequestContext" - name="RequestContext" root_id="1" - description="[null]" - enabled="[true]" language="java" copy_resource_id="[null]"/> - -</dataset> diff --git a/sonar-core/src/test/resources/org/sonar/core/resource/ResourceIndexerDaoTest/shouldIndexMultiModulesProject-result.xml b/sonar-core/src/test/resources/org/sonar/core/resource/ResourceIndexerDaoTest/shouldIndexMultiModulesProject-result.xml index 0bcc35f398b..953290805fe 100644 --- a/sonar-core/src/test/resources/org/sonar/core/resource/ResourceIndexerDaoTest/shouldIndexMultiModulesProject-result.xml +++ b/sonar-core/src/test/resources/org/sonar/core/resource/ResourceIndexerDaoTest/shouldIndexMultiModulesProject-result.xml @@ -1,6 +1,6 @@ <dataset> - <!-- project "struts" -> module "struts-core" -> file "RequestContext" --> + <!-- 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" root_id="[null]" description="[null]" @@ -11,14 +11,39 @@ description="[null]" enabled="[true]" language="java" copy_resource_id="[null]"/> - <projects long_name="org.struts.RequestContext" id="3" scope="FIL" qualifier="FIL" kee="org.struts:struts-core:org.struts.RequestContext" + <!-- 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" + name="org.struts" root_id="2" + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]"/> + + <projects long_name="org.struts.RequestContext" id="4" scope="CLA" qualifier="CLA" + kee="org.struts:struts-core:org.struts.RequestContext" name="RequestContext" root_id="2" description="[null]" enabled="[true]" language="java" copy_resource_id="[null]"/> + <snapshots id="1" islast="[true]" root_project_id="1" project_id="1"/> + <snapshots id="2" islast="[true]" root_project_id="1" project_id="2"/> + <snapshots id="3" islast="[true]" root_project_id="1" project_id="3"/> + <snapshots 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"/> @@ -36,17 +61,5 @@ <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"/> - <!-- RequestContext --> - <resource_index kee="requestcontext" position="0" name_size="14" resource_id="3" root_project_id="1" qualifier="FIL"/> - <resource_index kee="equestcontext" position="1" name_size="14" resource_id="3" root_project_id="1" qualifier="FIL"/> - <resource_index kee="questcontext" position="2" name_size="14" resource_id="3" root_project_id="1" qualifier="FIL"/> - <resource_index kee="uestcontext" position="3" name_size="14" resource_id="3" root_project_id="1" qualifier="FIL"/> - <resource_index kee="estcontext" position="4" name_size="14" resource_id="3" root_project_id="1" qualifier="FIL"/> - <resource_index kee="stcontext" position="5" name_size="14" resource_id="3" root_project_id="1" qualifier="FIL"/> - <resource_index kee="tcontext" position="6" name_size="14" resource_id="3" root_project_id="1" qualifier="FIL"/> - <resource_index kee="context" position="7" name_size="14" resource_id="3" root_project_id="1" qualifier="FIL"/> - <resource_index kee="ontext" position="8" name_size="14" resource_id="3" root_project_id="1" qualifier="FIL"/> - <resource_index kee="ntext" position="9" name_size="14" resource_id="3" root_project_id="1" qualifier="FIL"/> - <resource_index kee="text" position="10" name_size="14" resource_id="3" root_project_id="1" qualifier="FIL"/> - <resource_index kee="ext" position="11" name_size="14" resource_id="3" root_project_id="1" qualifier="FIL"/> + </dataset> diff --git a/sonar-core/src/test/resources/org/sonar/core/resource/ResourceIndexerDaoTest/shouldIndexMultiModulesProject.xml b/sonar-core/src/test/resources/org/sonar/core/resource/ResourceIndexerDaoTest/shouldIndexMultiModulesProject.xml index 3fd51854a75..18ef94a4616 100644 --- a/sonar-core/src/test/resources/org/sonar/core/resource/ResourceIndexerDaoTest/shouldIndexMultiModulesProject.xml +++ b/sonar-core/src/test/resources/org/sonar/core/resource/ResourceIndexerDaoTest/shouldIndexMultiModulesProject.xml @@ -1,6 +1,6 @@ <dataset> - <!-- project "struts" -> module "struts-core" -> file "RequestContext" --> + <!-- 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" root_id="[null]" description="[null]" @@ -11,9 +11,20 @@ description="[null]" enabled="[true]" language="java" copy_resource_id="[null]"/> - <projects long_name="org.struts.RequestContext" id="3" scope="FIL" qualifier="FIL" kee="org.struts:struts-core:org.struts.RequestContext" + <!-- 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" + name="org.struts" root_id="2" + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]"/> + + <projects long_name="org.struts.RequestContext" id="4" scope="FIL" qualifier="CLA" + kee="org.struts:struts-core:org.struts.RequestContext" name="RequestContext" root_id="2" description="[null]" enabled="[true]" language="java" copy_resource_id="[null]"/> + <snapshots id="1" islast="[true]" root_project_id="1" project_id="1"/> + <snapshots id="2" islast="[true]" root_project_id="1" project_id="2"/> + <snapshots id="3" islast="[true]" root_project_id="1" project_id="3"/> + <snapshots id="4" islast="[true]" root_project_id="1" project_id="4"/> </dataset> diff --git a/sonar-core/src/test/resources/org/sonar/core/resource/ResourceIndexerDaoTest/shouldIndexAllResources-result.xml b/sonar-core/src/test/resources/org/sonar/core/resource/ResourceIndexerDaoTest/shouldIndexProjects-result.xml index 2f35b67259d..dcdcec48803 100644 --- a/sonar-core/src/test/resources/org/sonar/core/resource/ResourceIndexerDaoTest/shouldIndexAllResources-result.xml +++ b/sonar-core/src/test/resources/org/sonar/core/resource/ResourceIndexerDaoTest/shouldIndexProjects-result.xml @@ -1,32 +1,46 @@ <dataset> + <!-- project --> <projects long_name="[null]" id="1" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" root_id="[null]" description="[null]" enabled="[true]" language="java" copy_resource_id="[null]"/> - <projects long_name="org.struts.RequestContext" id="3" scope="FIL" qualifier="FIL" kee="org.struts:struts:org.struts.RequestContext" + <!-- directory --> + <projects long_name="org.struts" id="2" scope="DIR" qualifier="PAC" kee="org.struts:struts:org.struts" + name="org.struts" root_id="1" + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]"/> + + <!-- file --> + <projects long_name="org.struts.RequestContext" id="3" scope="CLA" qualifier="CLA" + kee="org.struts:struts:org.struts.RequestContext" name="RequestContext" root_id="1" description="[null]" enabled="[true]" language="java" copy_resource_id="[null]"/> + <snapshots id="1" islast="[true]" root_project_id="1" project_id="1" scope="PRJ" qualifier="TRK"/> + <snapshots id="2" islast="[true]" root_project_id="1" project_id="2" scope="DIR" qualifier="PAC"/> + <snapshots 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"/> - <!-- RequestContext --> - <resource_index kee="requestcontext" position="0" name_size="14" resource_id="3" root_project_id="1" qualifier="FIL"/> - <resource_index kee="equestcontext" position="1" name_size="14" resource_id="3" root_project_id="1" qualifier="FIL"/> - <resource_index kee="questcontext" position="2" name_size="14" resource_id="3" root_project_id="1" qualifier="FIL"/> - <resource_index kee="uestcontext" position="3" name_size="14" resource_id="3" root_project_id="1" qualifier="FIL"/> - <resource_index kee="estcontext" position="4" name_size="14" resource_id="3" root_project_id="1" qualifier="FIL"/> - <resource_index kee="stcontext" position="5" name_size="14" resource_id="3" root_project_id="1" qualifier="FIL"/> - <resource_index kee="tcontext" position="6" name_size="14" resource_id="3" root_project_id="1" qualifier="FIL"/> - <resource_index kee="context" position="7" name_size="14" resource_id="3" root_project_id="1" qualifier="FIL"/> - <resource_index kee="ontext" position="8" name_size="14" resource_id="3" root_project_id="1" qualifier="FIL"/> - <resource_index kee="ntext" position="9" name_size="14" resource_id="3" root_project_id="1" qualifier="FIL"/> - <resource_index kee="text" position="10" name_size="14" resource_id="3" root_project_id="1" qualifier="FIL"/> - <resource_index kee="ext" position="11" name_size="14" resource_id="3" root_project_id="1" qualifier="FIL"/> </dataset> diff --git a/sonar-core/src/test/resources/org/sonar/core/resource/ResourceIndexerDaoTest/shouldIndexProjects.xml b/sonar-core/src/test/resources/org/sonar/core/resource/ResourceIndexerDaoTest/shouldIndexProjects.xml new file mode 100644 index 00000000000..4d463454340 --- /dev/null +++ b/sonar-core/src/test/resources/org/sonar/core/resource/ResourceIndexerDaoTest/shouldIndexProjects.xml @@ -0,0 +1,24 @@ +<dataset> + + <!-- project --> + <projects long_name="[null]" id="1" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" + root_id="[null]" + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]"/> + + <!-- directory --> + <projects long_name="org.struts" id="2" scope="DIR" qualifier="PAC" kee="org.struts:struts:org.struts" + name="org.struts" root_id="1" + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]"/> + + <!-- file --> + <projects long_name="org.struts.RequestContext" id="3" scope="FIL" qualifier="CLA" kee="org.struts:struts:org.struts.RequestContext" + name="RequestContext" root_id="1" + description="[null]" + enabled="[true]" language="java" copy_resource_id="[null]"/> + + <snapshots id="1" islast="[true]" root_project_id="1" project_id="1" scope="PRJ" qualifier="TRK" /> + <snapshots id="2" islast="[true]" root_project_id="1" project_id="2" scope="DIR" qualifier="PAC"/> + <snapshots id="3" islast="[true]" root_project_id="1" project_id="3" scope="FIL" qualifier="CLA"/> +</dataset> diff --git a/sonar-core/src/test/resources/org/sonar/core/resource/ResourceIndexerDaoTest/shouldIndexSingleResource-result.xml b/sonar-core/src/test/resources/org/sonar/core/resource/ResourceIndexerDaoTest/shouldIndexResource-result.xml index f4cf0805ede..f4cf0805ede 100644 --- a/sonar-core/src/test/resources/org/sonar/core/resource/ResourceIndexerDaoTest/shouldIndexSingleResource-result.xml +++ b/sonar-core/src/test/resources/org/sonar/core/resource/ResourceIndexerDaoTest/shouldIndexResource-result.xml diff --git a/sonar-core/src/test/resources/org/sonar/core/resource/ResourceIndexerDaoTest/shouldIndexSingleResource.xml b/sonar-core/src/test/resources/org/sonar/core/resource/ResourceIndexerDaoTest/shouldIndexResource.xml index 5a4a28b7df3..5a4a28b7df3 100644 --- a/sonar-core/src/test/resources/org/sonar/core/resource/ResourceIndexerDaoTest/shouldIndexSingleResource.xml +++ b/sonar-core/src/test/resources/org/sonar/core/resource/ResourceIndexerDaoTest/shouldIndexResource.xml diff --git a/sonar-core/src/test/resources/org/sonar/core/resource/ResourceIndexerDaoTest/shouldReindexProjectAfterRenaming-result.xml b/sonar-core/src/test/resources/org/sonar/core/resource/ResourceIndexerDaoTest/shouldReindexProjectAfterRenaming-result.xml index 6523767aa7c..cda14af38a3 100644 --- a/sonar-core/src/test/resources/org/sonar/core/resource/ResourceIndexerDaoTest/shouldReindexProjectAfterRenaming-result.xml +++ b/sonar-core/src/test/resources/org/sonar/core/resource/ResourceIndexerDaoTest/shouldReindexProjectAfterRenaming-result.xml @@ -5,6 +5,7 @@ description="[null]" enabled="[true]" language="java" copy_resource_id="[null]"/> + <snapshots 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"/> diff --git a/sonar-core/src/test/resources/org/sonar/core/resource/ResourceIndexerDaoTest/shouldReindexProjectAfterRenaming.xml b/sonar-core/src/test/resources/org/sonar/core/resource/ResourceIndexerDaoTest/shouldReindexProjectAfterRenaming.xml index 1c5531156ba..0af2532f6b7 100644 --- a/sonar-core/src/test/resources/org/sonar/core/resource/ResourceIndexerDaoTest/shouldReindexProjectAfterRenaming.xml +++ b/sonar-core/src/test/resources/org/sonar/core/resource/ResourceIndexerDaoTest/shouldReindexProjectAfterRenaming.xml @@ -5,6 +5,8 @@ description="[null]" enabled="[true]" language="java" copy_resource_id="[null]"/> + <snapshots 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 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"/> diff --git a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java index 492e5090f0c..23c2b4cca1a 100644 --- a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java +++ b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java @@ -44,7 +44,6 @@ import org.sonar.core.persistence.DatabaseMigrator; import org.sonar.core.persistence.DefaultDatabase; import org.sonar.core.persistence.MyBatis; import org.sonar.core.qualitymodel.DefaultModelFinder; -import org.sonar.core.resource.ResourceIndexer; import org.sonar.core.rule.DefaultRuleFinder; import org.sonar.core.user.DefaultUserFinder; import org.sonar.jpa.dao.DaoFacade; @@ -135,7 +134,6 @@ public final class Platform { rootContainer.addSingleton(EmbeddedDatabaseFactory.class); rootContainer.addSingleton(DefaultDatabase.class); rootContainer.addSingleton(MyBatis.class); - rootContainer.addSingleton(ResourceIndexer.class); // for the migration 241 rootContainer.addSingleton(DefaultDatabaseConnector.class); rootContainer.addSingleton(DefaultServerUpgradeStatus.class); rootContainer.addSingleton(DatabaseMigrator.class); diff --git a/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java b/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java index 927defeac4c..ed5ec2f7fa2 100644 --- a/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java +++ b/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java @@ -36,7 +36,7 @@ import org.sonar.api.web.*; import org.sonar.core.i18n.RuleI18nManager; import org.sonar.core.persistence.Database; import org.sonar.core.persistence.DatabaseMigrator; -import org.sonar.core.resource.ResourceIndexer; +import org.sonar.core.resource.ResourceIndexerDao; import org.sonar.markdown.Markdown; import org.sonar.server.configuration.Backup; import org.sonar.server.configuration.ProfilesManager; @@ -368,8 +368,8 @@ public final class JRubyFacade { return i18n.getJsDictionnary(rubyLocale); } - public void indexResources() { - getContainer().getComponentByType(ResourceIndexer.class).indexAll(); + public void indexProjects() { + getContainer().getComponentByType(ResourceIndexerDao.class).indexProjects(); } public void logError(String message) { diff --git a/sonar-server/src/main/webapp/WEB-INF/db/migrate/241_index_resources.rb b/sonar-server/src/main/webapp/WEB-INF/db/migrate/241_index_projects.rb index d0e43896e5a..ace26b6fc5b 100644 --- a/sonar-server/src/main/webapp/WEB-INF/db/migrate/241_index_resources.rb +++ b/sonar-server/src/main/webapp/WEB-INF/db/migrate/241_index_projects.rb @@ -23,10 +23,10 @@ # # Sonar 2.13 # -class IndexResources < ActiveRecord::Migration +class IndexProjects < ActiveRecord::Migration def self.up - Java::OrgSonarServerUi::JRubyFacade.getInstance().indexResources() + Java::OrgSonarServerUi::JRubyFacade.getInstance().indexProjects() end end |