@@ -21,11 +21,11 @@ package org.sonar.server.component.persistence; | |||
import com.google.common.annotations.VisibleForTesting; | |||
import org.apache.ibatis.session.SqlSession; | |||
import org.sonar.core.persistence.DaoComponent; | |||
import org.sonar.api.ServerComponent; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.core.component.ComponentDto; | |||
import org.sonar.core.component.db.ComponentMapper; | |||
import org.sonar.core.persistence.DaoComponent; | |||
import org.sonar.core.persistence.DbSession; | |||
import org.sonar.server.db.BaseDao; | |||
@@ -62,21 +62,25 @@ public class ComponentDao extends BaseDao<ComponentMapper, ComponentDto, String> | |||
@Override | |||
protected ComponentDto doInsert(ComponentDto item, DbSession session) { | |||
throw new IllegalStateException("Not implemented yet"); | |||
throw notImplemented(); | |||
} | |||
@Override | |||
protected ComponentDto doUpdate(ComponentDto item, DbSession session) { | |||
throw new IllegalStateException("Not implemented yet"); | |||
throw notImplemented(); | |||
} | |||
@Override | |||
protected void doDeleteByKey(String key, DbSession session) { | |||
throw new IllegalStateException("Not implemented yet"); | |||
throw notImplemented(); | |||
} | |||
@Override | |||
public Iterable<String> keysOfRowsUpdatedAfter(long timestamp, DbSession session) { | |||
throw notImplemented(); | |||
} | |||
private static IllegalStateException notImplemented() { | |||
throw new IllegalStateException("Not implemented yet"); | |||
} | |||
} |
@@ -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.server.duplication.ws; | |||
import com.google.common.annotations.VisibleForTesting; | |||
import org.codehaus.staxmate.SMInputFactory; | |||
import org.codehaus.staxmate.in.SMHierarchicCursor; | |||
import org.codehaus.staxmate.in.SMInputCursor; | |||
import org.sonar.api.ServerComponent; | |||
import org.sonar.api.utils.text.JsonWriter; | |||
import org.sonar.core.component.ComponentDto; | |||
import org.sonar.core.persistence.DbSession; | |||
import org.sonar.server.component.persistence.ComponentDao; | |||
import javax.annotation.Nullable; | |||
import javax.xml.stream.XMLInputFactory; | |||
import javax.xml.stream.XMLStreamException; | |||
import java.io.StringReader; | |||
import java.util.Map; | |||
import static com.google.common.collect.Maps.newHashMap; | |||
public class DuplicationsWriter implements ServerComponent { | |||
private final ComponentDao componentDao; | |||
public DuplicationsWriter(ComponentDao componentDao) { | |||
this.componentDao = componentDao; | |||
} | |||
@VisibleForTesting | |||
void write(@Nullable String duplicationsData, JsonWriter json, DbSession session) { | |||
Map<String, String> refByComponentKey = newHashMap(); | |||
json.name("duplications").beginArray(); | |||
if (duplicationsData != null) { | |||
writeDuplications(duplicationsData, refByComponentKey, json, session); | |||
} | |||
json.endArray(); | |||
json.name("files").beginObject(); | |||
writeFiles(refByComponentKey, json, session); | |||
json.endObject(); | |||
} | |||
private void writeDuplications(String duplicationsData, Map<String, String> refByComponentKey, JsonWriter json, DbSession session) { | |||
try { | |||
SMInputFactory inputFactory = initStax(); | |||
SMHierarchicCursor root = inputFactory.rootElementCursor(new StringReader(duplicationsData)); | |||
root.advance(); // <duplications> | |||
SMInputCursor cursor = root.childElementCursor("g"); | |||
while (cursor.getNext() != null) { | |||
json.beginObject().name("blocks").beginArray(); | |||
SMInputCursor bCursor = cursor.childElementCursor("b"); | |||
while (bCursor.getNext() != null) { | |||
String from = bCursor.getAttrValue("s"); | |||
String size = bCursor.getAttrValue("l"); | |||
String componentKey = bCursor.getAttrValue("r"); | |||
if (from != null && size != null && componentKey != null) { | |||
String ref = refByComponentKey.get(componentKey); | |||
if (ref == null) { | |||
ref = Integer.toString(refByComponentKey.size() + 1); | |||
refByComponentKey.put(componentKey, Integer.toString(refByComponentKey.size() + 1)); | |||
} | |||
json.beginObject(); | |||
json.prop("from", Integer.valueOf(from)); | |||
json.prop("size", Integer.valueOf(size)); | |||
json.prop("_ref", ref); | |||
json.endObject(); | |||
} | |||
} | |||
json.endArray().endObject(); | |||
} | |||
} catch (XMLStreamException e) { | |||
throw new IllegalStateException("XML is not valid", e); | |||
} | |||
} | |||
private void writeFiles(Map<String, String> refByComponentKey, JsonWriter json, DbSession session) { | |||
Map<Long, ComponentDto> projectById = newHashMap(); | |||
for (Map.Entry<String, String> entry : refByComponentKey.entrySet()) { | |||
String componentKey = entry.getKey(); | |||
String ref = entry.getValue(); | |||
ComponentDto file = componentDao.getByKey(componentKey, session); | |||
if (file != null) { | |||
json.name(ref).beginObject(); | |||
json.prop("key", file.key()); | |||
json.prop("name", file.longName()); | |||
ComponentDto project = projectById.get(file.projectId()); | |||
if (project == null) { | |||
project = componentDao.getById(file.projectId(), session); | |||
projectById.put(file.projectId(), project); | |||
} | |||
json.prop("projectName", project != null ? project.longName() : null); | |||
json.endObject(); | |||
} | |||
} | |||
} | |||
private static SMInputFactory initStax() { | |||
XMLInputFactory xmlFactory = XMLInputFactory.newInstance(); | |||
xmlFactory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.TRUE); | |||
xmlFactory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, Boolean.FALSE); | |||
// just so it won't try to load DTD in if there's DOCTYPE | |||
xmlFactory.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE); | |||
xmlFactory.setProperty(XMLInputFactory.IS_VALIDATING, Boolean.FALSE); | |||
return new SMInputFactory(xmlFactory); | |||
} | |||
} |
@@ -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.server.duplication.ws; | |||
import org.sonar.api.server.ws.WebService; | |||
public class DuplicationsWs implements WebService { | |||
private final ShowAction showAction; | |||
public DuplicationsWs(ShowAction showAction) { | |||
this.showAction = showAction; | |||
} | |||
@Override | |||
public void define(Context context) { | |||
NewController controller = context.createController("api/duplications") | |||
.setSince("4.4") | |||
.setDescription("Display duplications information"); | |||
showAction.define(controller); | |||
controller.done(); | |||
} | |||
} |
@@ -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.server.duplication.ws; | |||
import com.google.common.io.Resources; | |||
import org.sonar.api.measures.CoreMetrics; | |||
import org.sonar.api.server.ws.Request; | |||
import org.sonar.api.server.ws.RequestHandler; | |||
import org.sonar.api.server.ws.Response; | |||
import org.sonar.api.server.ws.WebService; | |||
import org.sonar.api.utils.text.JsonWriter; | |||
import org.sonar.api.web.UserRole; | |||
import org.sonar.core.measure.db.MeasureDto; | |||
import org.sonar.core.measure.db.MeasureKey; | |||
import org.sonar.core.persistence.DbSession; | |||
import org.sonar.core.persistence.MyBatis; | |||
import org.sonar.server.db.DbClient; | |||
import org.sonar.server.measure.persistence.MeasureDao; | |||
import org.sonar.server.user.UserSession; | |||
import javax.annotation.CheckForNull; | |||
public class ShowAction implements RequestHandler { | |||
private final DbClient dbClient; | |||
private final MeasureDao measureDao; | |||
private final DuplicationsWriter duplicationsWriter; | |||
public ShowAction(DbClient dbClient, MeasureDao measureDao, DuplicationsWriter duplicationsWriter) { | |||
this.dbClient = dbClient; | |||
this.measureDao = measureDao; | |||
this.duplicationsWriter = duplicationsWriter; | |||
} | |||
void define(WebService.NewController controller) { | |||
WebService.NewAction action = controller.createAction("show") | |||
.setDescription("Get duplications. Require Browse permission on file's project") | |||
.setSince("4.4") | |||
.setHandler(this) | |||
.setResponseExample(Resources.getResource(this.getClass(), "example-show.json")); | |||
action | |||
.createParam("key") | |||
.setRequired(true) | |||
.setDescription("File key") | |||
.setExampleValue("my_project:/src/foo/Bar.php"); | |||
} | |||
@Override | |||
public void handle(Request request, Response response) { | |||
String fileKey = request.mandatoryParam("key"); | |||
UserSession.get().checkComponentPermission(UserRole.CODEVIEWER, fileKey); | |||
DbSession session = dbClient.openSession(false); | |||
try { | |||
JsonWriter json = response.newJsonWriter().beginObject(); | |||
String duplications = findDataFromComponent(fileKey, CoreMetrics.DUPLICATIONS_DATA_KEY, session); | |||
duplicationsWriter.write(duplications, json, session); | |||
json.endObject().close(); | |||
} finally { | |||
MyBatis.closeQuietly(session); | |||
} | |||
} | |||
@CheckForNull | |||
private String findDataFromComponent(String fileKey, String metricKey, DbSession session) { | |||
MeasureDto data = measureDao.getByKey(MeasureKey.of(fileKey, metricKey), session); | |||
if (data != null) { | |||
return data.getData(); | |||
} | |||
return null; | |||
} | |||
} |
@@ -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.server.duplication.ws; | |||
import javax.annotation.ParametersAreNonnullByDefault; |
@@ -52,13 +52,7 @@ import org.sonar.core.measure.db.MeasureFilterDao; | |||
import org.sonar.core.metric.DefaultMetricFinder; | |||
import org.sonar.core.notification.DefaultNotificationManager; | |||
import org.sonar.core.permission.PermissionFacade; | |||
import org.sonar.core.persistence.DaoUtils; | |||
import org.sonar.core.persistence.DatabaseVersion; | |||
import org.sonar.core.persistence.DefaultDatabase; | |||
import org.sonar.core.persistence.MyBatis; | |||
import org.sonar.core.persistence.PreviewDatabaseFactory; | |||
import org.sonar.core.persistence.SemaphoreUpdater; | |||
import org.sonar.core.persistence.SemaphoresImpl; | |||
import org.sonar.core.persistence.*; | |||
import org.sonar.core.preview.PreviewCache; | |||
import org.sonar.core.profiling.Profiling; | |||
import org.sonar.core.purge.PurgeProfiler; | |||
@@ -94,32 +88,12 @@ import org.sonar.server.db.DbClient; | |||
import org.sonar.server.db.EmbeddedDatabaseFactory; | |||
import org.sonar.server.db.migrations.DatabaseMigrations; | |||
import org.sonar.server.db.migrations.DatabaseMigrator; | |||
import org.sonar.server.debt.DebtCharacteristicsXMLImporter; | |||
import org.sonar.server.debt.DebtModelBackup; | |||
import org.sonar.server.debt.DebtModelLookup; | |||
import org.sonar.server.debt.DebtModelOperations; | |||
import org.sonar.server.debt.DebtModelPluginRepository; | |||
import org.sonar.server.debt.DebtModelService; | |||
import org.sonar.server.debt.DebtModelXMLExporter; | |||
import org.sonar.server.debt.DebtRulesXMLImporter; | |||
import org.sonar.server.debt.*; | |||
import org.sonar.server.duplication.ws.DuplicationsWriter; | |||
import org.sonar.server.duplication.ws.DuplicationsWs; | |||
import org.sonar.server.es.ESIndex; | |||
import org.sonar.server.es.ESNode; | |||
import org.sonar.server.issue.ActionService; | |||
import org.sonar.server.issue.AssignAction; | |||
import org.sonar.server.issue.CommentAction; | |||
import org.sonar.server.issue.DefaultIssueFinder; | |||
import org.sonar.server.issue.InternalRubyIssueService; | |||
import org.sonar.server.issue.IssueBulkChangeService; | |||
import org.sonar.server.issue.IssueChangelogFormatter; | |||
import org.sonar.server.issue.IssueChangelogService; | |||
import org.sonar.server.issue.IssueCommentService; | |||
import org.sonar.server.issue.IssueService; | |||
import org.sonar.server.issue.IssueStatsFinder; | |||
import org.sonar.server.issue.PlanAction; | |||
import org.sonar.server.issue.PublicRubyIssueService; | |||
import org.sonar.server.issue.ServerIssueStorage; | |||
import org.sonar.server.issue.SetSeverityAction; | |||
import org.sonar.server.issue.TransitionAction; | |||
import org.sonar.server.issue.*; | |||
import org.sonar.server.issue.actionplan.ActionPlanService; | |||
import org.sonar.server.issue.actionplan.ActionPlanWs; | |||
import org.sonar.server.issue.filter.IssueFilterService; | |||
@@ -141,74 +115,23 @@ import org.sonar.server.permission.ws.PermissionsWs; | |||
import org.sonar.server.platform.ws.RestartHandler; | |||
import org.sonar.server.platform.ws.ServerWs; | |||
import org.sonar.server.platform.ws.SystemWs; | |||
import org.sonar.server.plugins.BatchWs; | |||
import org.sonar.server.plugins.InstalledPluginReferentialFactory; | |||
import org.sonar.server.plugins.PluginDownloader; | |||
import org.sonar.server.plugins.ServerExtensionInstaller; | |||
import org.sonar.server.plugins.ServerPluginJarInstaller; | |||
import org.sonar.server.plugins.ServerPluginJarsInstaller; | |||
import org.sonar.server.plugins.ServerPluginRepository; | |||
import org.sonar.server.plugins.UpdateCenterClient; | |||
import org.sonar.server.plugins.UpdateCenterMatrixFactory; | |||
import org.sonar.server.plugins.*; | |||
import org.sonar.server.qualitygate.QgateProjectFinder; | |||
import org.sonar.server.qualitygate.QualityGates; | |||
import org.sonar.server.qualitygate.RegisterQualityGates; | |||
import org.sonar.server.qualitygate.ws.QGatesAppAction; | |||
import org.sonar.server.qualitygate.ws.QGatesCopyAction; | |||
import org.sonar.server.qualitygate.ws.QGatesCreateAction; | |||
import org.sonar.server.qualitygate.ws.QGatesCreateConditionAction; | |||
import org.sonar.server.qualitygate.ws.QGatesDeleteConditionAction; | |||
import org.sonar.server.qualitygate.ws.QGatesDeselectAction; | |||
import org.sonar.server.qualitygate.ws.QGatesDestroyAction; | |||
import org.sonar.server.qualitygate.ws.QGatesListAction; | |||
import org.sonar.server.qualitygate.ws.QGatesRenameAction; | |||
import org.sonar.server.qualitygate.ws.QGatesSearchAction; | |||
import org.sonar.server.qualitygate.ws.QGatesSelectAction; | |||
import org.sonar.server.qualitygate.ws.QGatesSetAsDefaultAction; | |||
import org.sonar.server.qualitygate.ws.QGatesShowAction; | |||
import org.sonar.server.qualitygate.ws.QGatesUnsetDefaultAction; | |||
import org.sonar.server.qualitygate.ws.QGatesUpdateConditionAction; | |||
import org.sonar.server.qualitygate.ws.QGatesWs; | |||
import org.sonar.server.qualityprofile.ActiveRuleService; | |||
import org.sonar.server.qualityprofile.DefaultProfilesCache; | |||
import org.sonar.server.qualityprofile.ProfilesManager; | |||
import org.sonar.server.qualityprofile.QProfileActiveRuleOperations; | |||
import org.sonar.server.qualityprofile.QProfileBackup; | |||
import org.sonar.server.qualityprofile.QProfileLookup; | |||
import org.sonar.server.qualityprofile.QProfileOperations; | |||
import org.sonar.server.qualityprofile.QProfileProjectLookup; | |||
import org.sonar.server.qualityprofile.QProfileProjectOperations; | |||
import org.sonar.server.qualityprofile.QProfileRepositoryExporter; | |||
import org.sonar.server.qualityprofile.QProfiles; | |||
import org.sonar.server.qualityprofile.QualityProfileService; | |||
import org.sonar.server.qualityprofile.RegisterQualityProfiles; | |||
import org.sonar.server.qualityprofile.RuleActivationContextFactory; | |||
import org.sonar.server.qualitygate.ws.*; | |||
import org.sonar.server.qualityprofile.*; | |||
import org.sonar.server.qualityprofile.index.ActiveRuleIndex; | |||
import org.sonar.server.qualityprofile.index.ActiveRuleNormalizer; | |||
import org.sonar.server.qualityprofile.persistence.ActiveRuleDao; | |||
import org.sonar.server.qualityprofile.ws.BulkRuleActivationActions; | |||
import org.sonar.server.qualityprofile.ws.ProfilesWs; | |||
import org.sonar.server.qualityprofile.ws.QProfileRecreateBuiltInAction; | |||
import org.sonar.server.qualityprofile.ws.QProfilesWs; | |||
import org.sonar.server.qualityprofile.ws.RuleActivationActions; | |||
import org.sonar.server.rule.DeprecatedRulesDefinition; | |||
import org.sonar.server.rule.RubyRuleService; | |||
import org.sonar.server.rule.RuleDefinitionsLoader; | |||
import org.sonar.server.rule.RuleOperations; | |||
import org.sonar.server.rule.RuleRegistry; | |||
import org.sonar.server.rule.RuleRepositories; | |||
import org.sonar.server.rule.Rules; | |||
import org.sonar.server.qualityprofile.ws.*; | |||
import org.sonar.server.rule.*; | |||
import org.sonar.server.rule2.RegisterRules; | |||
import org.sonar.server.rule2.RuleService; | |||
import org.sonar.server.rule2.index.RuleIndex; | |||
import org.sonar.server.rule2.index.RuleNormalizer; | |||
import org.sonar.server.rule2.persistence.RuleDao; | |||
import org.sonar.server.rule2.ws.RuleMapping; | |||
import org.sonar.server.rule2.ws.RulesWebService; | |||
import org.sonar.server.rule2.ws.SearchAction; | |||
import org.sonar.server.rule2.ws.SetNoteAction; | |||
import org.sonar.server.rule2.ws.SetTagsAction; | |||
import org.sonar.server.rule2.ws.TagsAction; | |||
import org.sonar.server.rule2.ws.*; | |||
import org.sonar.server.search.IndexClient; | |||
import org.sonar.server.source.CodeColorizers; | |||
import org.sonar.server.source.DeprecatedSourceDecorator; | |||
@@ -218,20 +141,7 @@ import org.sonar.server.source.ws.ScmAction; | |||
import org.sonar.server.source.ws.ScmWriter; | |||
import org.sonar.server.source.ws.ShowAction; | |||
import org.sonar.server.source.ws.SourcesWs; | |||
import org.sonar.server.startup.CleanPreviewAnalysisCache; | |||
import org.sonar.server.startup.CopyRequirementsFromCharacteristicsToRules; | |||
import org.sonar.server.startup.GeneratePluginIndex; | |||
import org.sonar.server.startup.GwtPublisher; | |||
import org.sonar.server.startup.JdbcDriverDeployer; | |||
import org.sonar.server.startup.LogServerId; | |||
import org.sonar.server.startup.RegisterDashboards; | |||
import org.sonar.server.startup.RegisterDebtModel; | |||
import org.sonar.server.startup.RegisterMetrics; | |||
import org.sonar.server.startup.RegisterNewMeasureFilters; | |||
import org.sonar.server.startup.RegisterPermissionTemplates; | |||
import org.sonar.server.startup.RegisterServletFilters; | |||
import org.sonar.server.startup.RenameDeprecatedPropertyKeys; | |||
import org.sonar.server.startup.ServerMetadataPersister; | |||
import org.sonar.server.startup.*; | |||
import org.sonar.server.test.CoverageService; | |||
import org.sonar.server.test.ws.CoverageShowAction; | |||
import org.sonar.server.test.ws.CoverageWs; | |||
@@ -243,20 +153,9 @@ import org.sonar.server.ui.JRubyProfiling; | |||
import org.sonar.server.ui.PageDecorations; | |||
import org.sonar.server.ui.Views; | |||
import org.sonar.server.updatecenter.ws.UpdateCenterWs; | |||
import org.sonar.server.user.DefaultUserService; | |||
import org.sonar.server.user.DoPrivileged; | |||
import org.sonar.server.user.GroupMembershipFinder; | |||
import org.sonar.server.user.GroupMembershipService; | |||
import org.sonar.server.user.NewUserNotifier; | |||
import org.sonar.server.user.SecurityRealmFactory; | |||
import org.sonar.server.user.*; | |||
import org.sonar.server.user.ws.UsersWs; | |||
import org.sonar.server.util.BooleanTypeValidation; | |||
import org.sonar.server.util.FloatTypeValidation; | |||
import org.sonar.server.util.IntegerTypeValidation; | |||
import org.sonar.server.util.StringListTypeValidation; | |||
import org.sonar.server.util.StringTypeValidation; | |||
import org.sonar.server.util.TextTypeValidation; | |||
import org.sonar.server.util.TypeValidations; | |||
import org.sonar.server.util.*; | |||
import org.sonar.server.ws.ListingWs; | |||
import org.sonar.server.ws.WebServiceEngine; | |||
@@ -566,6 +465,11 @@ class ServerComponents { | |||
pico.addSingleton(ScmWriter.class); | |||
pico.addSingleton(ScmAction.class); | |||
// Duplications | |||
pico.addSingleton(DuplicationsWs.class); | |||
pico.addSingleton(DuplicationsWriter.class); | |||
pico.addSingleton(org.sonar.server.duplication.ws.ShowAction.class); | |||
// text | |||
pico.addSingleton(MacroInterpreter.class); | |||
pico.addSingleton(RubyTextService.class); |
@@ -0,0 +1,54 @@ | |||
{ | |||
"duplications": [ | |||
{ | |||
"blocks": [ | |||
{ | |||
"from": 94, "size": 101, "_ref": "1" | |||
}, | |||
{ | |||
"from": 83, "size": 101, "_ref": "2" | |||
} | |||
] | |||
}, | |||
{ | |||
"blocks": [ | |||
{ | |||
"from": 38, "size": 40, "_ref": "1" | |||
}, | |||
{ | |||
"from": 29, "size": 39, "_ref": "2" | |||
} | |||
] | |||
}, | |||
{ | |||
"blocks": [ | |||
{ | |||
"from": 148, "size": 24, "_ref": "1" | |||
}, | |||
{ | |||
"from": 137, "size": 24, "_ref": "2" | |||
}, | |||
{ | |||
"from": 137, "size": 24, "_ref": "3" | |||
} | |||
] | |||
} | |||
], | |||
"files": { | |||
"1": { | |||
"key": "org.codehaus.sonar:sonar-plugin-api:src/main/java/org/sonar/api/utils/command/CommandExecutor.java", | |||
"name": "CommandExecutor", | |||
"projectName": "SonarQube" | |||
}, | |||
"2": { | |||
"key": "com.sonarsource.orchestrator:sonar-orchestrator:src/main/java/com/sonar/orchestrator/util/CommandExecutor.java", | |||
"name": "CommandExecutor", | |||
"projectName": "SonarSource :: Orchestrator" | |||
}, | |||
"3": { | |||
"key": "org.codehaus.sonar.runner:sonar-runner-api:src/main/java/org/sonar/runner/api/CommandExecutor.java", | |||
"name": "CommandExecutor", | |||
"projectName": "SonarSource Runner" | |||
} | |||
} | |||
} |
@@ -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.server.duplication.ws; | |||
import org.json.JSONException; | |||
import org.junit.Before; | |||
import org.junit.Test; | |||
import org.junit.runner.RunWith; | |||
import org.mockito.Mock; | |||
import org.mockito.runners.MockitoJUnitRunner; | |||
import org.skyscreamer.jsonassert.JSONAssert; | |||
import org.sonar.api.utils.text.JsonWriter; | |||
import org.sonar.core.component.ComponentDto; | |||
import org.sonar.core.persistence.DbSession; | |||
import org.sonar.server.component.persistence.ComponentDao; | |||
import javax.annotation.Nullable; | |||
import java.io.StringWriter; | |||
import static org.mockito.Matchers.anyLong; | |||
import static org.mockito.Matchers.anyString; | |||
import static org.mockito.Matchers.eq; | |||
import static org.mockito.Mockito.*; | |||
@RunWith(MockitoJUnitRunner.class) | |||
public class DuplicationsWriterTest { | |||
@Mock | |||
ComponentDao componentDao; | |||
@Mock | |||
DbSession session; | |||
DuplicationsWriter writer; | |||
@Before | |||
public void setUp() throws Exception { | |||
writer = new DuplicationsWriter(componentDao); | |||
} | |||
@Test | |||
public void write_duplications() throws Exception { | |||
String key1 = "org.codehaus.sonar:sonar-ws-client:src/main/java/org/sonar/wsclient/services/PropertyDeleteQuery.java"; | |||
ComponentDto file1 = new ComponentDto().setId(10L).setQualifier("FIL").setKey(key1).setLongName("PropertyDeleteQuery").setProjectId(1L); | |||
String key2 = "org.codehaus.sonar:sonar-ws-client:src/main/java/org/sonar/wsclient/services/PropertyUpdateQuery.java"; | |||
ComponentDto file2 = new ComponentDto().setId(11L).setQualifier("FIL").setKey(key2).setLongName("PropertyUpdateQuery").setProjectId(1L); | |||
when(componentDao.getByKey(key1, session)).thenReturn(file1); | |||
when(componentDao.getByKey(key2, session)).thenReturn(file2); | |||
when(componentDao.getById(1L, session)).thenReturn(new ComponentDto().setId(1L).setLongName("SonarQube")); | |||
test( | |||
"<duplications>\n" + | |||
"<g>\n" + | |||
"<b s=\"57\" l=\"12\" r=\"org.codehaus.sonar:sonar-ws-client:src/main/java/org/sonar/wsclient/services/PropertyDeleteQuery.java\"/>\n" + | |||
"<b s=\"73\" l=\"12\" r=\"org.codehaus.sonar:sonar-ws-client:src/main/java/org/sonar/wsclient/services/PropertyUpdateQuery.java\"/>\n" + | |||
"</g>\n" + | |||
"</duplications>", | |||
"{\n" + | |||
" \"duplications\": [\n" + | |||
" {\n" + | |||
" \"blocks\": [\n" + | |||
" {\n" + | |||
" \"from\": 57, \"size\": 12, \"_ref\": \"1\"\n" + | |||
" },\n" + | |||
" {\n" + | |||
" \"from\": 73, \"size\": 12, \"_ref\": \"2\"\n" + | |||
" }\n" + | |||
" ]\n" + | |||
" }," + | |||
" ],\n" + | |||
" \"files\": {\n" + | |||
" \"1\": {\n" + | |||
" \"key\": \"org.codehaus.sonar:sonar-ws-client:src/main/java/org/sonar/wsclient/services/PropertyDeleteQuery.java\",\n" + | |||
" \"name\": \"PropertyDeleteQuery\",\n" + | |||
" \"projectName\": \"SonarQube\"\n" + | |||
" },\n" + | |||
" \"2\": {\n" + | |||
" \"key\": \"org.codehaus.sonar:sonar-ws-client:src/main/java/org/sonar/wsclient/services/PropertyUpdateQuery.java\",\n" + | |||
" \"name\": \"PropertyUpdateQuery\",\n" + | |||
" \"projectName\": \"SonarQube\"\n" + | |||
" }\n" + | |||
" }" + | |||
"}" | |||
); | |||
verify(componentDao, times(2)).getByKey(anyString(), eq(session)); | |||
verify(componentDao, times(1)).getById(anyLong(), eq(session)); | |||
} | |||
@Test | |||
public void write_nothing_when_no_data() throws Exception { | |||
test(null, "{\"duplications\": [], \"files\": {}}"); | |||
} | |||
private void test(@Nullable String duplications, String expected) throws JSONException { | |||
StringWriter output = new StringWriter(); | |||
JsonWriter jsonWriter = JsonWriter.of(output); | |||
jsonWriter.beginObject(); | |||
writer.write(duplications, jsonWriter, session); | |||
jsonWriter.endObject(); | |||
JSONAssert.assertEquals(output.toString(), expected, true); | |||
} | |||
} |
@@ -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.server.duplication.ws; | |||
import org.junit.Test; | |||
import org.sonar.api.server.ws.WebService; | |||
import org.sonar.server.db.DbClient; | |||
import org.sonar.server.measure.persistence.MeasureDao; | |||
import org.sonar.server.ws.WsTester; | |||
import static org.fest.assertions.Assertions.assertThat; | |||
import static org.mockito.Mockito.mock; | |||
public class DuplicationsWsTest { | |||
WsTester tester = new WsTester(new DuplicationsWs(new ShowAction(mock(DbClient.class), mock(MeasureDao.class), mock(DuplicationsWriter.class)))); | |||
@Test | |||
public void define_ws() throws Exception { | |||
WebService.Controller controller = tester.controller("api/duplications"); | |||
assertThat(controller).isNotNull(); | |||
assertThat(controller.since()).isEqualTo("4.4"); | |||
assertThat(controller.description()).isNotEmpty(); | |||
WebService.Action show = controller.action("show"); | |||
assertThat(show).isNotNull(); | |||
assertThat(show.handler()).isNotNull(); | |||
assertThat(show.since()).isEqualTo("4.4"); | |||
assertThat(show.isInternal()).isFalse(); | |||
assertThat(show.responseExampleAsString()).isNotEmpty(); | |||
assertThat(show.params()).hasSize(1); | |||
} | |||
} |
@@ -0,0 +1,96 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2014 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with 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.duplication.ws; | |||
import org.junit.Before; | |||
import org.junit.Test; | |||
import org.junit.runner.RunWith; | |||
import org.mockito.Mock; | |||
import org.mockito.runners.MockitoJUnitRunner; | |||
import org.sonar.api.measures.CoreMetrics; | |||
import org.sonar.api.utils.text.JsonWriter; | |||
import org.sonar.api.web.UserRole; | |||
import org.sonar.core.measure.db.MeasureDto; | |||
import org.sonar.core.measure.db.MeasureKey; | |||
import org.sonar.core.persistence.DbSession; | |||
import org.sonar.server.db.DbClient; | |||
import org.sonar.server.measure.persistence.MeasureDao; | |||
import org.sonar.server.user.MockUserSession; | |||
import org.sonar.server.ws.WsTester; | |||
import static org.mockito.Matchers.*; | |||
import static org.mockito.Mockito.verify; | |||
import static org.mockito.Mockito.when; | |||
@RunWith(MockitoJUnitRunner.class) | |||
public class ShowActionTest { | |||
@Mock | |||
DbSession session; | |||
@Mock | |||
DbClient dbClient; | |||
@Mock | |||
MeasureDao measureDao; | |||
@Mock | |||
DuplicationsWriter duplicationsWriter; | |||
WsTester tester; | |||
@Before | |||
public void setUp() throws Exception { | |||
when(dbClient.openSession(false)).thenReturn(session); | |||
tester = new WsTester(new DuplicationsWs(new ShowAction(dbClient, measureDao, duplicationsWriter))); | |||
} | |||
@Test | |||
public void show_duplications() throws Exception { | |||
String componentKey = "src/Foo.java"; | |||
MockUserSession.set().addComponentPermission(UserRole.CODEVIEWER, "org.codehaus.sonar:sonar", componentKey); | |||
MeasureKey measureKey = MeasureKey.of(componentKey, CoreMetrics.DUPLICATIONS_DATA_KEY); | |||
when(measureDao.getByKey(measureKey, session)).thenReturn( | |||
MeasureDto.createFor(measureKey).setTextValue("{duplications}") | |||
); | |||
WsTester.TestRequest request = tester.newGetRequest("api/duplications", "show").setParam("key", componentKey); | |||
request.execute(); | |||
verify(duplicationsWriter).write(eq("{duplications}"), any(JsonWriter.class), eq(session)); | |||
} | |||
@Test | |||
public void no_duplications_when_no_data() throws Exception { | |||
String componentKey = "src/Foo.java"; | |||
MockUserSession.set().addComponentPermission(UserRole.CODEVIEWER, "org.codehaus.sonar:sonar", componentKey); | |||
MeasureKey measureKey = MeasureKey.of(componentKey, CoreMetrics.DUPLICATIONS_DATA_KEY); | |||
when(measureDao.getByKey(measureKey, session)).thenReturn(null); | |||
WsTester.TestRequest request = tester.newGetRequest("api/duplications", "show").setParam("key", componentKey); | |||
request.execute(); | |||
verify(duplicationsWriter).write(isNull(String.class), any(JsonWriter.class), eq(session)); | |||
} | |||
} |