<artifactId>sonar-plugin-api</artifactId>
<scope>provided</scope>
</dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <scope>provided</scope>
+ </dependency>
<!-- unit tests -->
<dependency>
<artifactId>sonar-deprecated</artifactId>
<scope>provided</scope>
</dependency>
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ <scope>provided</scope>
+ </dependency>
<!-- unit tests -->
<dependency>
<artifactId>commons-email</artifactId>
<version>1.3.2</version>
</dependency>
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ <scope>provided</scope>
+ </dependency>
<!-- unit tests -->
<dependency>
--- /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.
+#
+
+#
+# SonarQube 4.5.1
+#
+class MysqlMediumtextToLongtext < ActiveRecord::Migration
+
+ def self.up
+ if dialect()=='mysql'
+ apply 'rules', 'description'
+ apply 'rules', 'note_data'
+ apply 'snapshot_sources', 'data'
+ apply 'properties', 'text_value'
+ apply 'measure_filters', 'data'
+ apply 'graphs', 'data'
+ apply 'snapshot_data', 'snapshot_data'
+ apply 'issue_changes', 'change_data'
+ apply 'issue_filters', 'data'
+ apply 'activities', 'data_field'
+ end
+ end
+
+ def self.apply(table, column)
+ ActiveRecord::Base.connection.execute("alter table #{table} modify #{column} longtext")
+ end
+end
# But we would like the bigger MEDIUMTEXT for the snapshot_sources table (16777215 characters).
# This hack works only for ActiveRecord-JDBC (Jruby use).
# See http://www.headius.com/jrubywiki/index.php/Adding_Datatypes_to_ActiveRecord-JDBC
- tp[:text] = { :name => "mediumtext" }
+ tp[:text] = { :name => "longtext" }
tp[:binary] = { :name => "longblob" }
tp[:big_integer] = { :name => "bigint"}
# /SonarQube
package org.sonar.batch.index;
import com.google.common.collect.Sets;
-import org.sonar.api.database.DatabaseSession;
import org.sonar.api.database.model.Snapshot;
-import org.sonar.api.database.model.SnapshotSource;
import org.sonar.api.resources.DuplicatedSourceException;
import org.sonar.api.resources.Resource;
+import org.sonar.core.source.db.SnapshotSourceDao;
+import org.sonar.core.source.db.SnapshotSourceDto;
+
+import javax.annotation.CheckForNull;
import java.util.Set;
public final class SourcePersister {
- private DatabaseSession session;
private Set<Integer> savedSnapshotIds = Sets.newHashSet();
private ResourcePersister resourcePersister;
+ private final SnapshotSourceDao sourceDao;
- public SourcePersister(DatabaseSession session, ResourcePersister resourcePersister) {
- this.session = session;
+ public SourcePersister(ResourcePersister resourcePersister, SnapshotSourceDao sourceDao) {
this.resourcePersister = resourcePersister;
+ this.sourceDao = sourceDao;
}
public void saveSource(Resource resource, String source) {
if (isCached(snapshot)) {
throw new DuplicatedSourceException(resource);
}
- session.save(new SnapshotSource(snapshot.getId(), source));
- session.commit();
+ SnapshotSourceDto dto = new SnapshotSourceDto();
+ dto.setSnapshotId(snapshot.getId().longValue());
+ dto.setData(source);
+ sourceDao.insert(dto);
addToCache(snapshot);
}
+ @CheckForNull
public String getSource(Resource resource) {
- SnapshotSource source = null;
Snapshot snapshot = resourcePersister.getSnapshot(resource);
- if (snapshot!=null && snapshot.getId()!=null) {
- source = session.getSingleResult(SnapshotSource.class, "snapshotId", snapshot.getId());
+ if (snapshot != null && snapshot.getId() != null) {
+ return sourceDao.selectSnapshotSource(snapshot.getId());
}
- return source!=null ? source.getData() : null;
+ return null;
}
private boolean isCached(Snapshot snapshot) {
*/
package org.sonar.batch.scan;
+import org.apache.commons.lang.StringUtils;
import org.sonar.api.BatchComponent;
-import org.sonar.api.database.DatabaseSession;
-import org.sonar.api.database.model.ResourceModel;
-import org.sonar.api.database.model.Snapshot;
-import org.sonar.api.database.model.SnapshotSource;
import org.sonar.api.resources.Resource;
import org.sonar.api.resources.ResourceUtils;
import org.sonar.api.utils.HttpDownloader;
import org.sonar.batch.bootstrap.AnalysisMode;
import org.sonar.batch.bootstrap.ServerClient;
+import org.sonar.core.source.db.SnapshotSourceDao;
-import javax.persistence.Query;
+import javax.annotation.CheckForNull;
public class LastSnapshots implements BatchComponent {
private final AnalysisMode analysisMode;
- private final DatabaseSession session;
private final ServerClient server;
+ private final SnapshotSourceDao sourceDao;
- public LastSnapshots(AnalysisMode analysisMode, DatabaseSession session, ServerClient server) {
+ public LastSnapshots(AnalysisMode analysisMode, SnapshotSourceDao dao, ServerClient server) {
this.analysisMode = analysisMode;
- this.session = session;
+ this.sourceDao = dao;
this.server = server;
}
+ @CheckForNull
public String getSource(Resource resource) {
- String source = "";
+ String source = null;
if (ResourceUtils.isFile(resource)) {
if (analysisMode.isPreview()) {
source = loadSourceFromWs(resource);
source = loadSourceFromDb(resource);
}
}
- return source;
+ return StringUtils.defaultString(source, "");
}
+ @CheckForNull
private String loadSourceFromWs(Resource resource) {
try {
return server.request("/api/sources?resource=" + resource.getEffectiveKey() + "&format=txt", false, analysisMode.getPreviewReadTimeoutSec() * 1000);
}
}
+ @CheckForNull
private String loadSourceFromDb(Resource resource) {
- Snapshot snapshot = getSnapshot(resource);
- if (snapshot != null) {
- SnapshotSource source = session.getSingleResult(SnapshotSource.class, "snapshotId", snapshot.getId());
- if (source != null) {
- return source.getData();
- }
- }
- return "";
- }
-
- private Snapshot getSnapshot(Resource resource) {
- Query query = session.createQuery("from " + Snapshot.class.getSimpleName() + " s where s.last=:last and s.resourceId=(select r.id from "
- + ResourceModel.class.getSimpleName() + " r where r.key=:key)");
- query.setParameter("key", resource.getEffectiveKey());
- query.setParameter("last", Boolean.TRUE);
- return session.getSingleResult(query, null);
+ return sourceDao.selectSnapshotSourceByComponentKey(resource.getEffectiveKey());
}
}
sonarFile.setDeprecatedKey(pathFromSourceDir);
}
sonarIndex.index(sonarFile);
+
importSources(fs, shouldImportSource, inputFile, sonarFile);
}
}
import org.sonar.api.resources.DuplicatedSourceException;
import org.sonar.api.resources.File;
import org.sonar.api.resources.Resource;
-import org.sonar.jpa.test.AbstractDbUnitTestCase;
+import org.sonar.core.persistence.AbstractDaoTestCase;
+import org.sonar.core.source.db.SnapshotSourceDao;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
-public class SourcePersisterTest extends AbstractDbUnitTestCase {
+public class SourcePersisterTest extends AbstractDaoTestCase {
private SourcePersister sourcePersister;
@Before
public void before() {
setupData("shared");
- Snapshot snapshot = getSession().getSingleResult(Snapshot.class, "id", 1000);
ResourcePersister resourcePersister = mock(ResourcePersister.class);
+ Snapshot snapshot = new Snapshot();
+ snapshot.setId(1000);
when(resourcePersister.getSnapshotOrFail(any(Resource.class))).thenReturn(snapshot);
- sourcePersister = new SourcePersister(getSession(), resourcePersister);
+ sourcePersister = new SourcePersister(resourcePersister, new SnapshotSourceDao(getMyBatis()));
}
@Test
import org.sonar.api.utils.HttpDownloader;
import org.sonar.batch.bootstrap.AnalysisMode;
import org.sonar.batch.bootstrap.ServerClient;
-import org.sonar.jpa.test.AbstractDbUnitTestCase;
+import org.sonar.core.persistence.TestDatabase;
+import org.sonar.core.source.db.SnapshotSourceDao;
import java.net.URI;
import java.net.URISyntaxException;
import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.*;
-public class LastSnapshotsTest extends AbstractDbUnitTestCase {
+public class LastSnapshotsTest {
@Rule
public ExpectedException thrown = ExpectedException.none();
+
+ @Rule
+ public TestDatabase db = new TestDatabase();
+
private AnalysisMode mode;
@Before
@Test
public void should_get_source_of_last_snapshot() {
- setupData("last_snapshot");
- ServerClient server = mock(ServerClient.class);
+ db.prepareDbUnit(getClass(), "last_snapshot.xml");
- LastSnapshots lastSnapshots = new LastSnapshots(mode, getSession(), server);
+ ServerClient server = mock(ServerClient.class);
+ LastSnapshots lastSnapshots = new LastSnapshots(mode, new SnapshotSourceDao(db.myBatis()), server);
assertThat(lastSnapshots.getSource(newFile())).isEqualTo("this is bar");
verifyZeroInteractions(server);
@Test
public void should_return_empty_source_if_no_last_snapshot() {
- setupData("no_last_snapshot");
+ db.prepareDbUnit(getClass(), "no_last_snapshot.xml");
ServerClient server = mock(ServerClient.class);
- LastSnapshots lastSnapshots = new LastSnapshots(mode, getSession(), server);
+ LastSnapshots lastSnapshots = new LastSnapshots(mode, new SnapshotSourceDao(db.myBatis()), server);
assertThat(lastSnapshots.getSource(newFile())).isEqualTo("");
verifyZeroInteractions(server);
@Test
public void should_download_source_from_ws_if_preview_mode() {
- setupData("last_snapshot");
+ db.prepareDbUnit(getClass(), "last_snapshot.xml");
ServerClient server = mock(ServerClient.class);
when(server.request(anyString(), eq(false), eq(30 * 1000))).thenReturn("downloaded source of Bar.c");
when(mode.isPreview()).thenReturn(true);
- LastSnapshots lastSnapshots = new LastSnapshots(mode, getSession(), server);
+ LastSnapshots lastSnapshots = new LastSnapshots(mode, new SnapshotSourceDao(db.myBatis()), server);
String source = lastSnapshots.getSource(newFile());
assertThat(source).isEqualTo("downloaded source of Bar.c");
@Test
public void should_fail_to_download_source_from_ws() throws URISyntaxException {
- setupData("last_snapshot");
+ db.prepareDbUnit(getClass(), "last_snapshot.xml");
ServerClient server = mock(ServerClient.class);
when(server.request(anyString(), eq(false), eq(30 * 1000))).thenThrow(new HttpDownloader.HttpException(new URI(""), 500));
when(mode.isPreview()).thenReturn(true);
- LastSnapshots lastSnapshots = new LastSnapshots(mode, getSession(), server);
+ LastSnapshots lastSnapshots = new LastSnapshots(mode, new SnapshotSourceDao(db.myBatis()), server);
thrown.expect(HttpDownloader.HttpException.class);
lastSnapshots.getSource(newFile());
@Test
public void should_return_empty_source_if_preview_mode_and_no_last_snapshot() throws URISyntaxException {
- setupData("last_snapshot");
+ db.prepareDbUnit(getClass(), "last_snapshot.xml");
ServerClient server = mock(ServerClient.class);
when(server.request(anyString(), eq(false), eq(30 * 1000))).thenThrow(new HttpDownloader.HttpException(new URI(""), 404));
when(mode.isPreview()).thenReturn(true);
- LastSnapshots lastSnapshots = new LastSnapshots(mode, getSession(), server);
+ LastSnapshots lastSnapshots = new LastSnapshots(mode, new SnapshotSourceDao(db.myBatis()), server);
String source = lastSnapshots.getSource(newFile());
assertThat(source).isEqualTo("");
@Test
public void should_not_load_source_of_non_files() throws URISyntaxException {
- setupData("last_snapshot");
+ db.prepareDbUnit(getClass(), "last_snapshot.xml");
ServerClient server = mock(ServerClient.class);
- LastSnapshots lastSnapshots = new LastSnapshots(mode, getSession(), server);
+ LastSnapshots lastSnapshots = new LastSnapshots(mode, new SnapshotSourceDao(db.myBatis()), server);
String source = lastSnapshots.getSource(new Project("my-project"));
assertThat(source).isEqualTo("");
*/
public class DatabaseVersion implements BatchComponent, ServerComponent {
- public static final int LAST_VERSION = 584;
+ public static final int LAST_VERSION = 600;
public static enum Status {
UP_TO_DATE, REQUIRES_UPGRADE, REQUIRES_DOWNGRADE, FRESH_INSTALL
public MySqlWithDecimalDialect() {
super();
registerColumnType(Types.DOUBLE, "decimal precision");
- registerColumnType(Types.VARCHAR, DatabaseProperties.MAX_TEXT_SIZE, "mediumtext");
- registerColumnType(Types.CLOB, "mediumtext");
+ registerColumnType(Types.VARCHAR, DatabaseProperties.MAX_TEXT_SIZE, "longtext");
+ registerColumnType(Types.CLOB, "longtext");
registerColumnType(Types.BLOB, "blob");
}
}
package org.sonar.core.source.db;
import org.apache.ibatis.session.SqlSession;
+import org.sonar.api.BatchComponent;
import org.sonar.api.ServerComponent;
import org.sonar.core.persistence.MyBatis;
/**
* @since 3.6
*/
-public class SnapshotSourceDao implements ServerComponent {
+public class SnapshotSourceDao implements BatchComponent, ServerComponent {
private final MyBatis mybatis;
}
}
+ public void insert(SnapshotSourceDto dto) {
+ SqlSession session = mybatis.openSession(false);
+ try {
+ session.getMapper(SnapshotSourceMapper.class).insert(dto);
+ session.commit();
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
}
--- /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.core.source.db;
+
+public class SnapshotSourceDto {
+ private Long id;
+ private Long snapshotId;
+ private String data;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public Long getSnapshotId() {
+ return snapshotId;
+ }
+
+ public void setSnapshotId(Long snapshotId) {
+ this.snapshotId = snapshotId;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+}
package org.sonar.core.source.db;
+import javax.annotation.CheckForNull;
+
/**
* @since 3.6
*/
public interface SnapshotSourceMapper {
+ @CheckForNull
String selectSnapshotSource(long snapshotId);
+ @CheckForNull
String selectSnapshotSourceByComponentKey(String componentKey);
+
+ void insert(SnapshotSourceDto dto);
}
<class>org.sonar.api.design.DependencyDto</class>
<class>org.sonar.api.measures.Metric</class>
<class>org.sonar.api.database.model.ResourceModel</class>
- <class>org.sonar.api.database.model.SnapshotSource</class>
<class>org.sonar.api.rules.Rule</class>
<class>org.sonar.api.rules.RuleParam</class>
<class>org.sonar.api.resources.ProjectLink</class>
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 USERS(ID, LOGIN, NAME, EMAIL, CRYPTED_PASSWORD, SALT, CREATED_AT, UPDATED_AT, REMEMBER_TOKEN, REMEMBER_TOKEN_EXPIRES_AT) VALUES (1, 'admin', 'Administrator', '', 'a373a0e667abb2604c1fd571eb4ad47fe8cc0878', '48bc4b0d93179b5103fd3885ea9119498e9d161b', '2011-09-26 22:27:48.0', '2011-09-26 22:27:48.0', null, null);
ALTER TABLE USERS ALTER COLUMN ID RESTART WITH 2;
WHERE p.kee = #{componentKey}
</select>
+ <insert id="insert" parameterType="org.sonar.core.source.db.SnapshotSourceDto" useGeneratedKeys="false">
+ insert into snapshot_sources (snapshot_id, data) values (#{snapshotId}, #{data})
+ </insert>
+
</mapper>
+++ /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.api.database.model;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.commons.lang.builder.ToStringBuilder;
-import org.apache.commons.lang.builder.ToStringStyle;
-import org.sonar.api.database.BaseIdentifiable;
-import org.sonar.api.database.DatabaseProperties;
-
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.Lob;
-import javax.persistence.Table;
-
-@Entity
-@Table(name = "snapshot_sources")
-public class SnapshotSource extends BaseIdentifiable {
-
- @Column(name = "snapshot_id")
- private Integer snapshotId;
-
- @Lob
- @Column(name = "data", updatable = true, nullable = true, length = DatabaseProperties.MAX_TEXT_SIZE)
- private String data;
-
- public SnapshotSource() {
- }
-
- public SnapshotSource(Snapshot snapshot, String source) {
- this.snapshotId = snapshot.getId();
- this.data = source;
- }
-
- public SnapshotSource(Integer snapshotId, String source) {
- this.snapshotId = snapshotId;
- this.data = source;
- }
-
- public void setSnapshot(Snapshot snapshot) {
- this.snapshotId = snapshot.getId();
- }
-
- public String getData() {
- return data;
- }
-
- public void setData(String data) {
- this.data = data;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (!(obj instanceof SnapshotSource)) {
- return false;
- }
- if (this == obj) {
- return true;
- }
- SnapshotSource other = (SnapshotSource) obj;
- return snapshotId.equals(other.snapshotId);
- }
-
- @Override
- public int hashCode() {
- return snapshotId.hashCode();
- }
-
- @Override
- public String toString() {
- return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
- .append("snapshot_id", snapshotId)
- .append("data", StringUtils.abbreviate(data, 1000))
- .toString();
- }
-}